IsoSpec  1.95
mman.c
1 /*
2  * This file has been included as a part of IsoSpec project, under a MIT licence. It
3  * comes from the repository:
4  *
5  * https://github.com/witwall/mman-win32
6  *
7  * which itself is a mirror of:
8  *
9  * https://code.google.com/archive/p/mman-win32/
10  */
11 
12 #include "platform.h"
13 #if ISOSPEC_GOT_MMAN && !ISOSPEC_GOT_SYSTEM_MMAN
14 
15 #include <windows.h>
16 #include <errno.h>
17 #include <io.h>
18 
19 #include "mman.h"
20 
21 #ifndef FILE_MAP_EXECUTE
22 #define FILE_MAP_EXECUTE 0x0020
23 #endif /* FILE_MAP_EXECUTE */
24 
25 static int __map_mman_error(const DWORD err, const int deferr)
26 {
27  if (err == 0)
28  return 0;
29  //TODO: implement
30  return err;
31 }
32 
33 static DWORD __map_mmap_prot_page(const int prot)
34 {
35  DWORD protect = 0;
36 
37  if (prot == PROT_NONE)
38  return protect;
39 
40  if ((prot & PROT_EXEC) != 0)
41  {
42  protect = ((prot & PROT_WRITE) != 0) ?
43  PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
44  }
45  else
46  {
47  protect = ((prot & PROT_WRITE) != 0) ?
48  PAGE_READWRITE : PAGE_READONLY;
49  }
50 
51  return protect;
52 }
53 
54 static DWORD __map_mmap_prot_file(const int prot)
55 {
56  DWORD desiredAccess = 0;
57 
58  if (prot == PROT_NONE)
59  return desiredAccess;
60 
61  if ((prot & PROT_READ) != 0)
62  desiredAccess |= FILE_MAP_READ;
63  if ((prot & PROT_WRITE) != 0)
64  desiredAccess |= FILE_MAP_WRITE;
65  if ((prot & PROT_EXEC) != 0)
66  desiredAccess |= FILE_MAP_EXECUTE;
67 
68  return desiredAccess;
69 }
70 
71 void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType off)
72 {
73  HANDLE fm, h;
74 
75  void * map = MAP_FAILED;
76 
77 #ifdef _MSC_VER
78 #pragma warning(push)
79 #pragma warning(disable: 4293)
80 #endif
81 
82  const DWORD dwFileOffsetLow = (sizeof(OffsetType) <= sizeof(DWORD)) ?
83  (DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
84  const DWORD dwFileOffsetHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ?
85  (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
86  const DWORD protect = __map_mmap_prot_page(prot);
87  const DWORD desiredAccess = __map_mmap_prot_file(prot);
88 
89  const OffsetType maxSize = off + (OffsetType)len;
90 
91  const DWORD dwMaxSizeLow = (sizeof(OffsetType) <= sizeof(DWORD)) ?
92  (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL);
93  const DWORD dwMaxSizeHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ?
94  (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL);
95 
96 #ifdef _MSC_VER
97 #pragma warning(pop)
98 #endif
99 
100  errno = 0;
101 
102  if (len == 0
103  /* Unsupported flag combinations */
104  || (flags & MAP_FIXED) != 0
105  /* Usupported protection combinations */
106  || prot == PROT_EXEC)
107  {
108  errno = EINVAL;
109  return MAP_FAILED;
110  }
111 
112  h = ((flags & MAP_ANONYMOUS) == 0) ?
113  (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE;
114 
115  if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE)
116  {
117  errno = EBADF;
118  return MAP_FAILED;
119  }
120 
121  fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL);
122 
123  if (fm == NULL)
124  {
125  errno = __map_mman_error(GetLastError(), EPERM);
126  return MAP_FAILED;
127  }
128 
129  map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len);
130 
131  CloseHandle(fm);
132 
133  if (map == NULL)
134  {
135  errno = __map_mman_error(GetLastError(), EPERM);
136  return MAP_FAILED;
137  }
138 
139  return map;
140 }
141 
142 int munmap(void *addr, size_t len)
143 {
144  if (UnmapViewOfFile(addr))
145  return 0;
146 
147  errno = __map_mman_error(GetLastError(), EPERM);
148 
149  return -1;
150 }
151 
152 int _mprotect(void *addr, size_t len, int prot)
153 {
154  DWORD newProtect = __map_mmap_prot_page(prot);
155  DWORD oldProtect = 0;
156 
157  if (VirtualProtect(addr, len, newProtect, &oldProtect))
158  return 0;
159 
160  errno = __map_mman_error(GetLastError(), EPERM);
161 
162  return -1;
163 }
164 
165 int msync(void *addr, size_t len, int flags)
166 {
167  if (FlushViewOfFile(addr, len))
168  return 0;
169 
170  errno = __map_mman_error(GetLastError(), EPERM);
171 
172  return -1;
173 }
174 
175 int mlock(const void *addr, size_t len)
176 {
177  if (VirtualLock((LPVOID)addr, len))
178  return 0;
179 
180  errno = __map_mman_error(GetLastError(), EPERM);
181 
182  return -1;
183 }
184 
185 int munlock(const void *addr, size_t len)
186 {
187  if (VirtualUnlock((LPVOID)addr, len))
188  return 0;
189 
190  errno = __map_mman_error(GetLastError(), EPERM);
191 
192  return -1;
193 }
194 
195 #endif