You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
1.8 KiB
85 lines
1.8 KiB
// +build windows,!appengine |
|
|
|
package maxminddb |
|
|
|
// Windows support largely borrowed from mmap-go. |
|
// |
|
// Copyright 2011 Evan Shaw. All rights reserved. |
|
// Use of this source code is governed by a BSD-style |
|
// license that can be found in the LICENSE file. |
|
|
|
import ( |
|
"errors" |
|
"os" |
|
"reflect" |
|
"sync" |
|
"unsafe" |
|
|
|
"golang.org/x/sys/windows" |
|
) |
|
|
|
type memoryMap []byte |
|
|
|
// Windows |
|
var handleLock sync.Mutex |
|
var handleMap = map[uintptr]windows.Handle{} |
|
|
|
func mmap(fd int, length int) (data []byte, err error) { |
|
h, errno := windows.CreateFileMapping(windows.Handle(fd), nil, |
|
uint32(windows.PAGE_READONLY), 0, uint32(length), nil) |
|
if h == 0 { |
|
return nil, os.NewSyscallError("CreateFileMapping", errno) |
|
} |
|
|
|
addr, errno := windows.MapViewOfFile(h, uint32(windows.FILE_MAP_READ), 0, |
|
0, uintptr(length)) |
|
if addr == 0 { |
|
return nil, os.NewSyscallError("MapViewOfFile", errno) |
|
} |
|
handleLock.Lock() |
|
handleMap[addr] = h |
|
handleLock.Unlock() |
|
|
|
m := memoryMap{} |
|
dh := m.header() |
|
dh.Data = addr |
|
dh.Len = length |
|
dh.Cap = dh.Len |
|
|
|
return m, nil |
|
} |
|
|
|
func (m *memoryMap) header() *reflect.SliceHeader { |
|
return (*reflect.SliceHeader)(unsafe.Pointer(m)) |
|
} |
|
|
|
func flush(addr, len uintptr) error { |
|
errno := windows.FlushViewOfFile(addr, len) |
|
return os.NewSyscallError("FlushViewOfFile", errno) |
|
} |
|
|
|
func munmap(b []byte) (err error) { |
|
m := memoryMap(b) |
|
dh := m.header() |
|
|
|
addr := dh.Data |
|
length := uintptr(dh.Len) |
|
|
|
flush(addr, length) |
|
err = windows.UnmapViewOfFile(addr) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
handleLock.Lock() |
|
defer handleLock.Unlock() |
|
handle, ok := handleMap[addr] |
|
if !ok { |
|
// should be impossible; we would've errored above |
|
return errors.New("unknown base address") |
|
} |
|
delete(handleMap, addr) |
|
|
|
e := windows.CloseHandle(windows.Handle(handle)) |
|
return os.NewSyscallError("CloseHandle", e) |
|
}
|
|
|