1 // Based on https://github.com/witwall/mman-win32
2
3 #include "mman.h"
4 #include "log/iwlog.h"
5 #include <errno.h>
6 #include <io.h>
7
8 #ifndef FILE_MAP_EXECUTE
9 #define FILE_MAP_EXECUTE 0x0020
10 #endif /* FILE_MAP_EXECUTE */
11
__map_mman_error(const DWORD err,const int deferr)12 static int __map_mman_error(const DWORD err, const int deferr) {
13 if (!err) {
14 return 0;
15 }
16 iwrc rc = IW_ERROR_FAIL;
17 rc = iwrc_set_werror(rc, err);
18 iwlog_ecode_error3(rc);
19 return deferr;
20 }
21
__map_mmap_prot_page(const int prot,const int flags)22 static DWORD __map_mmap_prot_page(const int prot, const int flags) {
23 DWORD protect = 0;
24 if (prot == PROT_NONE) {
25 return protect;
26 }
27 if ((prot & PROT_EXEC)) {
28 protect = ((prot & PROT_WRITE)) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
29 } else {
30 protect = ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE)) ? PAGE_READWRITE : PAGE_READONLY;
31 }
32 return protect;
33 }
34
__map_mmap_prot_file(const int prot,const int flags)35 static DWORD __map_mmap_prot_file(const int prot, const int flags) {
36 DWORD desiredAccess = 0;
37 if (prot == PROT_NONE) {
38 return desiredAccess;
39 }
40 if ((prot & PROT_WRITE)) {
41 if (flags & MAP_PRIVATE) {
42 desiredAccess |= FILE_MAP_COPY;
43 } else {
44 desiredAccess |= FILE_MAP_WRITE;
45 }
46 } else if ((prot & PROT_READ)) {
47 desiredAccess |= FILE_MAP_READ;
48 }
49 if ((prot & PROT_EXEC)) {
50 desiredAccess |= FILE_MAP_EXECUTE;
51 }
52 return desiredAccess;
53 }
54
mmap(void * addr,size_t len,int prot,int flags,HANDLE fh,OffsetType off)55 void *mmap(void *addr, size_t len, int prot, int flags, HANDLE fh, OffsetType off) {
56 HANDLE fm;
57 void *map = MAP_FAILED;
58
59 #ifdef _MSC_VER
60 #pragma warning(push)
61 #pragma warning(disable: 4293)
62 #endif
63
64 const DWORD dwFileOffsetLow = (sizeof(OffsetType) <= sizeof(DWORD)) ?
65 (DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
66 const DWORD dwFileOffsetHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ?
67 (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
68 const DWORD protect = __map_mmap_prot_page(prot, flags);
69 const DWORD desiredAccess = __map_mmap_prot_file(prot, flags);
70 const OffsetType maxSize = off + (OffsetType)len;
71 const DWORD dwMaxSizeLow = (sizeof(OffsetType) <= sizeof(DWORD)) ?
72 (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL);
73 const DWORD dwMaxSizeHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ?
74 (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL);
75
76 #ifdef _MSC_VER
77 #pragma warning(pop)
78 #endif
79
80 errno = 0;
81 if ((flags & MAP_FIXED) != 0 || prot == PROT_EXEC) {
82 errno = EINVAL;
83 return MAP_FAILED;
84 }
85 if (!(flags & MAP_ANONYMOUS) && fh == INVALID_HANDLE_VALUE) {
86 errno = EBADF;
87 return MAP_FAILED;
88 }
89 fm = CreateFileMapping(fh, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL);
90 if (fm == NULL) {
91 errno = __map_mman_error(GetLastError(), EPERM);
92 return MAP_FAILED;
93 }
94 map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len);
95 CloseHandle(fm);
96 if (map == NULL) {
97 errno = __map_mman_error(GetLastError(), EPERM);
98 return MAP_FAILED;
99 }
100 return map;
101 }
102
munmap(void * addr,size_t len)103 int munmap(void *addr, size_t len) {
104 if (UnmapViewOfFile(addr)) {
105 return 0;
106 }
107 errno = __map_mman_error(GetLastError(), EPERM);
108 return -1;
109 }
110
msync(void * addr,size_t len,int flags)111 int msync(void *addr, size_t len, int flags) {
112 if (FlushViewOfFile(addr, len)) {
113 return 0;
114 }
115 errno = __map_mman_error(GetLastError(), EPERM);
116 return -1;
117 }
118
mlock(const void * addr,size_t len)119 int mlock(const void *addr, size_t len) {
120 if (VirtualLock((LPVOID)addr, len)) {
121 return 0;
122 }
123 errno = __map_mman_error(GetLastError(), EPERM);
124 return -1;
125 }
126
munlock(const void * addr,size_t len)127 int munlock(const void *addr, size_t len) {
128 if (VirtualUnlock((LPVOID)addr, len)) {
129 return 0;
130 }
131 errno = __map_mman_error(GetLastError(), EPERM);
132 return -1;
133 }
134