1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
//go:build windows && !appengine
// +build windows,!appengine
package maxminddb
import (
"errors"
"os"
"unsafe"
"golang.org/x/sys/windows"
)
// mmap maps a file into memory and returns a byte slice.
func mmap(fd, length int) ([]byte, error) {
// Create a file mapping
handle, err := windows.CreateFileMapping(
windows.Handle(fd),
nil,
windows.PAGE_READONLY,
0,
0,
nil,
)
if err != nil {
return nil, os.NewSyscallError("CreateFileMapping", err)
}
defer windows.CloseHandle(handle)
// Map the file into memory
addrUintptr, err := windows.MapViewOfFile(
handle,
windows.FILE_MAP_READ,
0,
0,
0,
)
if err != nil {
return nil, os.NewSyscallError("MapViewOfFile", err)
}
// When there's not enough address space for the whole file (e.g. large
// files on 32-bit systems), MapViewOfFile may return a partial mapping.
// Query the region size and fail on partial mappings.
var info windows.MemoryBasicInformation
if err := windows.VirtualQuery(addrUintptr, &info, unsafe.Sizeof(info)); err != nil {
_ = windows.UnmapViewOfFile(addrUintptr)
return nil, os.NewSyscallError("VirtualQuery", err)
}
if info.RegionSize < uintptr(length) {
_ = windows.UnmapViewOfFile(addrUintptr)
return nil, errors.New("file too large")
}
// Workaround for unsafeptr check in go vet, see
// https://github.com/golang/go/issues/58625
addr := *(*unsafe.Pointer)(unsafe.Pointer(&addrUintptr))
return unsafe.Slice((*byte)(addr), length), nil
}
// munmap unmaps a memory-mapped file and releases associated resources.
func munmap(b []byte) error {
// Convert slice to base address and length
data := unsafe.SliceData(b)
addr := uintptr(unsafe.Pointer(data))
// Unmap the memory
if err := windows.UnmapViewOfFile(addr); err != nil {
return os.NewSyscallError("UnmapViewOfFile", err)
}
return nil
}
|