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