File: mmap_windows.go

package info (click to toggle)
golang-github-oschwald-maxminddb-golang-v2 2.0.0~beta10-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,120 kB
  • sloc: perl: 557; makefile: 3
file content (72 lines) | stat: -rw-r--r-- 1,840 bytes parent folder | download
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
}