syncthing/vendor/github.com/oschwald/maxminddb-golang/mmap_windows.go
2016-07-04 13:34:34 +02:00

84 lines
1.7 KiB
Go

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)
}