Fix readonly file mapping on windows

`CreateFileMapping` tries to extend the file to the size of mapping
which leads to failure if database was opened in readonly and calculated
mmap size is bigger than the file size.
Providing 0 to `MapViewOfFile` will create a view which has size of
mapping, i.e. file-size in read-only mode and full size if file was
truncated.

Also, swap `sizehi` and `sizelo` names to reflect windows API docs.
This was changed in 1c97a490d for seemingly no reason.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
pull/307/head
Evgenii Stratonikov 2022-01-12 18:59:18 +03:00
parent eedea6cb26
commit 52d028ffe9
1 changed files with 6 additions and 4 deletions

View File

@ -62,23 +62,25 @@ func funlock(db *DB) error {
// mmap memory maps a DB's data file.
// Based on: https://github.com/edsrzf/mmap-go
func mmap(db *DB, sz int) error {
var sizelo, sizehi uint32
if !db.readOnly {
// Truncate the database to the size of the mmap.
if err := db.file.Truncate(int64(sz)); err != nil {
return fmt.Errorf("truncate: %s", err)
}
sizehi = uint32(sz >> 32)
sizelo = uint32(sz) & 0xffffffff
}
// Open a file mapping handle.
sizelo := uint32(sz >> 32)
sizehi := uint32(sz) & 0xffffffff
h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizelo, sizehi, nil)
h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizehi, sizelo, nil)
if h == 0 {
return os.NewSyscallError("CreateFileMapping", errno)
}
// Create the memory map.
addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz))
addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, 0)
if addr == 0 {
return os.NewSyscallError("MapViewOfFile", errno)
}