]> git.proxmox.com Git - libgit2.git/blob - src/util/win32/map.c
New upstream version 1.5.0+ds
[libgit2.git] / src / util / win32 / map.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "git2_util.h"
9
10 #include "map.h"
11 #include <errno.h>
12
13 #ifndef NO_MMAP
14
15 static DWORD get_page_size(void)
16 {
17 static DWORD page_size;
18 SYSTEM_INFO sys;
19
20 if (!page_size) {
21 GetSystemInfo(&sys);
22 page_size = sys.dwPageSize;
23 }
24
25 return page_size;
26 }
27
28 static DWORD get_allocation_granularity(void)
29 {
30 static DWORD granularity;
31 SYSTEM_INFO sys;
32
33 if (!granularity) {
34 GetSystemInfo(&sys);
35 granularity = sys.dwAllocationGranularity;
36 }
37
38 return granularity;
39 }
40
41 int git__page_size(size_t *page_size)
42 {
43 *page_size = get_page_size();
44 return 0;
45 }
46
47 int git__mmap_alignment(size_t *page_size)
48 {
49 *page_size = get_allocation_granularity();
50 return 0;
51 }
52
53 int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset)
54 {
55 HANDLE fh = (HANDLE)_get_osfhandle(fd);
56 DWORD alignment = get_allocation_granularity();
57 DWORD fmap_prot = 0;
58 DWORD view_prot = 0;
59 DWORD off_low = 0;
60 DWORD off_hi = 0;
61 off64_t page_start;
62 off64_t page_offset;
63
64 GIT_MMAP_VALIDATE(out, len, prot, flags);
65
66 out->data = NULL;
67 out->len = 0;
68 out->fmh = NULL;
69
70 if (fh == INVALID_HANDLE_VALUE) {
71 errno = EBADF;
72 git_error_set(GIT_ERROR_OS, "failed to mmap. Invalid handle value");
73 return -1;
74 }
75
76 if (prot & GIT_PROT_WRITE)
77 fmap_prot |= PAGE_READWRITE;
78 else if (prot & GIT_PROT_READ)
79 fmap_prot |= PAGE_READONLY;
80
81 if (prot & GIT_PROT_WRITE)
82 view_prot |= FILE_MAP_WRITE;
83 if (prot & GIT_PROT_READ)
84 view_prot |= FILE_MAP_READ;
85
86 page_start = (offset / alignment) * alignment;
87 page_offset = offset - page_start;
88
89 if (page_offset != 0) { /* offset must be multiple of the allocation granularity */
90 errno = EINVAL;
91 git_error_set(GIT_ERROR_OS, "failed to mmap. Offset must be multiple of allocation granularity");
92 return -1;
93 }
94
95 out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL);
96 if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) {
97 git_error_set(GIT_ERROR_OS, "failed to mmap. Invalid handle value");
98 out->fmh = NULL;
99 return -1;
100 }
101
102 off_low = (DWORD)(page_start);
103 off_hi = (DWORD)(page_start >> 32);
104 out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len);
105 if (!out->data) {
106 git_error_set(GIT_ERROR_OS, "failed to mmap. No data written");
107 CloseHandle(out->fmh);
108 out->fmh = NULL;
109 return -1;
110 }
111 out->len = len;
112
113 return 0;
114 }
115
116 int p_munmap(git_map *map)
117 {
118 int error = 0;
119
120 GIT_ASSERT_ARG(map);
121
122 if (map->data) {
123 if (!UnmapViewOfFile(map->data)) {
124 git_error_set(GIT_ERROR_OS, "failed to munmap. Could not unmap view of file");
125 error = -1;
126 }
127 map->data = NULL;
128 }
129
130 if (map->fmh) {
131 if (!CloseHandle(map->fmh)) {
132 git_error_set(GIT_ERROR_OS, "failed to munmap. Could not close handle");
133 error = -1;
134 }
135 map->fmh = NULL;
136 }
137
138 return error;
139 }
140
141 #endif