Skip to content

Commit 7e214c7

Browse files
authored
Merge pull request #164 from database64128/mmap-windows
Modernize Windows mmap code (again)
2 parents 4ce5c4d + 2a6b0bf commit 7e214c7

File tree

3 files changed

+21
-105
lines changed

3 files changed

+21
-105
lines changed

LICENSE

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,3 @@ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1313
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1414
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1515
PERFORMANCE OF THIS SOFTWARE.
16-
17-
--------------------------------------------------------------------
18-
19-
The file mmap_windows.go is governed by the following license:
20-
21-
Copyright (c) 2011, Evan Shaw <[email protected]>
22-
All rights reserved.
23-
24-
Redistribution and use in source and binary forms, with or without
25-
modification, are permitted provided that the following conditions are met:
26-
* Redistributions of source code must retain the above copyright
27-
notice, this list of conditions and the following disclaimer.
28-
* Redistributions in binary form must reproduce the above copyright
29-
notice, this list of conditions and the following disclaimer in the
30-
documentation and/or other materials provided with the distribution.
31-
* Neither the name of the copyright holder nor the
32-
names of its contributors may be used to endorse or promote products
33-
derived from this software without specific prior written permission.
34-
35-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
36-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
37-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38-
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
39-
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
41-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
42-
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,4 @@ with your changes.
3333

3434
## License ##
3535

36-
This is free software, primarily licensed under the ISC License. The file
37-
`mmap_windows.go` is licensed under a BSD-style license by Evan Shaw.
36+
This is free software, primarily licensed under the ISC License.

mmap_windows.go

Lines changed: 20 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,14 @@
33

44
package maxminddb
55

6-
// Windows support largely borrowed from mmap-go.
7-
//
8-
// Copyright (c) 2011, Evan Shaw <[email protected]>
9-
// All rights reserved.
10-
11-
// Redistribution and use in source and binary forms, with or without
12-
// modification, are permitted provided that the following conditions are met:
13-
// * Redistributions of source code must retain the above copyright
14-
// notice, this list of conditions and the following disclaimer.
15-
// * Redistributions in binary form must reproduce the above copyright
16-
// notice, this list of conditions and the following disclaimer in the
17-
// documentation and/or other materials provided with the distribution.
18-
// * Neither the name of the copyright holder nor the
19-
// names of its contributors may be used to endorse or promote products
20-
// derived from this software without specific prior written permission.
21-
22-
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23-
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24-
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25-
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
26-
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27-
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28-
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29-
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30-
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31-
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32-
336
import (
347
"errors"
358
"os"
36-
"sync"
379
"unsafe"
3810

3911
"golang.org/x/sys/windows"
4012
)
4113

42-
// Windows
43-
var (
44-
handleLock sync.Mutex
45-
handleMap = map[uintptr]windows.Handle{}
46-
)
47-
4814
// mmap maps a file into memory and returns a byte slice.
4915
func mmap(fd int, length int) ([]byte, error) {
5016
// Create a file mapping
@@ -53,74 +19,54 @@ func mmap(fd int, length int) ([]byte, error) {
5319
nil,
5420
windows.PAGE_READONLY,
5521
0,
56-
uint32(length),
22+
0,
5723
nil,
5824
)
5925
if err != nil {
6026
return nil, os.NewSyscallError("CreateFileMapping", err)
6127
}
28+
defer windows.CloseHandle(handle)
6229

6330
// Map the file into memory
64-
addr, err := windows.MapViewOfFile(
31+
addrUintptr, err := windows.MapViewOfFile(
6532
handle,
6633
windows.FILE_MAP_READ,
6734
0,
6835
0,
69-
uintptr(length),
36+
0,
7037
)
7138
if err != nil {
72-
windows.CloseHandle(handle)
7339
return nil, os.NewSyscallError("MapViewOfFile", err)
7440
}
7541

76-
// Store the handle in the map
77-
handleLock.Lock()
78-
handleMap[addr] = handle
79-
handleLock.Unlock()
80-
81-
data := unsafe.Slice((*byte)(unsafe.Pointer(addr)), length)
82-
return data, nil
83-
}
84-
85-
// flush ensures changes to a memory-mapped region are written to disk.
86-
func flush(addr, length uintptr) error {
87-
err := windows.FlushViewOfFile(addr, length)
88-
if err != nil {
89-
return os.NewSyscallError("FlushViewOfFile", err)
42+
// When there's not enough address space for the whole file (e.g. large
43+
// files on 32-bit systems), MapViewOfFile may return a partial mapping.
44+
// Query the region size and fail on partial mappings.
45+
var info windows.MemoryBasicInformation
46+
if err := windows.VirtualQuery(addrUintptr, &info, unsafe.Sizeof(info)); err != nil {
47+
_ = windows.UnmapViewOfFile(addrUintptr)
48+
return nil, os.NewSyscallError("VirtualQuery", err)
9049
}
91-
return nil
50+
if info.RegionSize < uintptr(length) {
51+
_ = windows.UnmapViewOfFile(addrUintptr)
52+
return nil, errors.New("file too large")
53+
}
54+
55+
// Workaround for unsafeptr check in go vet, see
56+
// https://github.com/golang/go/issues/58625
57+
addr := *(*unsafe.Pointer)(unsafe.Pointer(&addrUintptr))
58+
return unsafe.Slice((*byte)(addr), length), nil
9259
}
9360

9461
// munmap unmaps a memory-mapped file and releases associated resources.
9562
func munmap(b []byte) error {
9663
// Convert slice to base address and length
9764
data := unsafe.SliceData(b)
9865
addr := uintptr(unsafe.Pointer(data))
99-
length := uintptr(len(b))
100-
101-
// Flush the memory region
102-
if err := flush(addr, length); err != nil {
103-
return err
104-
}
10566

10667
// Unmap the memory
10768
if err := windows.UnmapViewOfFile(addr); err != nil {
10869
return os.NewSyscallError("UnmapViewOfFile", err)
10970
}
110-
111-
// Remove the handle from the map and close it
112-
handleLock.Lock()
113-
defer handleLock.Unlock()
114-
115-
handle, ok := handleMap[addr]
116-
if !ok {
117-
// should be impossible; we would've errored above
118-
return errors.New("unknown base address")
119-
}
120-
delete(handleMap, addr)
121-
122-
if err := windows.CloseHandle(handle); err != nil {
123-
return os.NewSyscallError("CloseHandle", err)
124-
}
12571
return nil
12672
}

0 commit comments

Comments
 (0)