• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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