From 52d028ffe933a703786b078ca22444e8536d09c5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 12 Jan 2022 18:59:18 +0300 Subject: [PATCH 1/2] 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 --- bolt_windows.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bolt_windows.go b/bolt_windows.go index 09e00b6..afc1a29 100644 --- a/bolt_windows.go +++ b/bolt_windows.go @@ -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) } From 4504feba82e157ea781b603911b90c5786ba268c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 26 Nov 2022 13:20:35 +0300 Subject: [PATCH 2/2] Close `CreateFileMapping` handle after `MapViewOfFile` failure mmap-go does this, see https://github.com/edsrzf/mmap-go/commit/82d537b921ff6268a1e4a1980dc66b9d1546759f Signed-off-by: Evgenii Stratonikov --- bolt_windows.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bolt_windows.go b/bolt_windows.go index afc1a29..6cf07bd 100644 --- a/bolt_windows.go +++ b/bolt_windows.go @@ -82,6 +82,8 @@ func mmap(db *DB, sz int) error { // Create the memory map. addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, 0) if addr == 0 { + // Do our best and report error returned from MapViewOfFile. + _ = syscall.CloseHandle(h) return os.NewSyscallError("MapViewOfFile", errno) }