]>
Commit | Line | Data |
---|---|---|
79ca2edc RJ |
1 | |
2 | #include "map.h" | |
3 | #include <errno.h> | |
4 | ||
5 | ||
6 | static DWORD get_page_size(void) | |
7 | { | |
8 | static DWORD page_size; | |
9 | SYSTEM_INFO sys; | |
10 | ||
11 | if (!page_size) { | |
12 | GetSystemInfo(&sys); | |
13 | page_size = sys.dwAllocationGranularity; | |
14 | } | |
15 | ||
16 | return page_size; | |
17 | } | |
18 | ||
19 | int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, off_t offset) | |
20 | { | |
21 | HANDLE fh = (HANDLE)_get_osfhandle(fd); | |
22 | DWORD page_size = get_page_size(); | |
23 | DWORD fmap_prot = 0; | |
24 | DWORD view_prot = 0; | |
25 | DWORD off_low = 0; | |
26 | DWORD off_hi = 0; | |
27 | off_t page_start; | |
28 | off_t page_offset; | |
29 | ||
30 | assert((out != NULL) && (len > 0)); | |
31 | ||
32 | if ((out == NULL) || (len == 0)) { | |
33 | errno = EINVAL; | |
34 | return GIT_ERROR; | |
35 | } | |
36 | ||
37 | out->data = NULL; | |
38 | out->len = 0; | |
39 | out->fmh = NULL; | |
40 | ||
41 | if (fh == INVALID_HANDLE_VALUE) { | |
42 | errno = EBADF; | |
43 | return GIT_ERROR; | |
44 | } | |
45 | ||
46 | if (prot & GIT_PROT_WRITE) | |
47 | fmap_prot |= PAGE_READWRITE; | |
48 | else if (prot & GIT_PROT_READ) | |
49 | fmap_prot |= PAGE_READONLY; | |
50 | else { | |
51 | errno = EINVAL; | |
52 | return GIT_ERROR; | |
53 | } | |
54 | ||
55 | if (prot & GIT_PROT_WRITE) | |
56 | view_prot |= FILE_MAP_WRITE; | |
57 | if (prot & GIT_PROT_READ) | |
58 | view_prot |= FILE_MAP_READ; | |
59 | ||
60 | if (flags & GIT_MAP_FIXED) { | |
61 | errno = EINVAL; | |
62 | return GIT_ERROR; | |
63 | } | |
64 | ||
65 | page_start = (offset / page_size) * page_size; | |
66 | page_offset = offset - page_start; | |
67 | ||
68 | if (page_offset != 0) { /* offset must be multiple of page size */ | |
69 | errno = EINVAL; | |
70 | return GIT_ERROR; | |
71 | } | |
72 | ||
73 | out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL); | |
74 | if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) { | |
75 | /* errno = ? */ | |
76 | out->fmh = NULL; | |
77 | return GIT_ERROR; | |
78 | } | |
79 | ||
80 | off_low = (DWORD)(page_start); | |
81 | if (sizeof(off_t) > 4) | |
82 | off_hi = (DWORD)(page_start >> 32); | |
83 | out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len); | |
84 | if (!out->data) { | |
85 | /* errno = ? */ | |
86 | CloseHandle(out->fmh); | |
87 | out->fmh = NULL; | |
88 | return GIT_ERROR; | |
89 | } | |
90 | out->len = len; | |
91 | ||
92 | return GIT_SUCCESS; | |
93 | } | |
94 | ||
95 | int git__munmap(git_map *map) | |
96 | { | |
97 | assert(map != NULL); | |
98 | ||
99 | if (!map) | |
100 | return GIT_ERROR; | |
101 | ||
102 | if (map->data) { | |
103 | if (!UnmapViewOfFile(map->data)) { | |
104 | /* errno = ? */ | |
105 | CloseHandle(map->fmh); | |
106 | map->data = NULL; | |
107 | map->fmh = NULL; | |
108 | return GIT_ERROR; | |
109 | } | |
110 | map->data = NULL; | |
111 | } | |
112 | ||
113 | if (map->fmh) { | |
114 | if (!CloseHandle(map->fmh)) { | |
115 | /* errno = ? */ | |
116 | map->fmh = NULL; | |
117 | return GIT_ERROR; | |
118 | } | |
119 | map->fmh = NULL; | |
120 | } | |
121 | ||
122 | return GIT_SUCCESS; | |
123 | } | |
124 | ||
125 |