86 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +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)
 | 
						|
}
 |