Yeah, there's an obvious ordering problem there.

I'm still not convinced lmdb/boltdb needs two fds open. The O_SYNC effect can be gotten by calling fdatasync after a meta write; the commit protocol should just be

1. write non-meta pages
2. fdatasync
3. write meta page
4. fdatasync

And Copy doesn't need to open the file, if it uses a SectionReader instead of OS-level file offsets.

With the above, there could be a second API that's enough to let tests simulate failures. Tests would just wrap a real *os.File (so mmap etc work, via Fd()), and basically break things they want to break.

``` go
func OpenFile(f File) (*DB, error)

type File interface {
    ReadAt(b []byte, off int64) (n int, err error)
    WriteAt(b []byte, off int64) (n int, err error)
    Stat() (*os.FileInfo, error)
    Fd() uintptr
    Close() error
}
```

Typical test usage:

``` go
type BrokenFile struct {
    *os.File
}
func (f BrokenFile) WriteAt(b []byte, off int64) (n int, err error)
    return 0, io.ErrShortWrite
}

func TestDBMetaInitWriteError(t *testing.T) {
    // useful helper to create tmp and remove afterward? something liek this
    withTempFile(t, func(tmp *os.File) {
        err := db.OpenFile(BrokenFile{tmp})
        assert.Equal(t, err, io.ErrShortWrite)
    })
}
```