lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame^] | 1 | /* mmap() replacement for Windows |
| 2 | * |
| 3 | * Author: Mike Frysinger <vapier@gentoo.org> |
| 4 | * Placed into the public domain |
| 5 | */ |
| 6 | |
| 7 | /* References: |
| 8 | * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx |
| 9 | * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx |
| 10 | * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx |
| 11 | * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx |
| 12 | */ |
| 13 | |
| 14 | #include <io.h> |
| 15 | #include <windows.h> |
| 16 | #include <sys/types.h> |
| 17 | |
| 18 | #define PROT_READ 0x1 |
| 19 | #define PROT_WRITE 0x2 |
| 20 | /* This flag is only available in WinXP+ */ |
| 21 | #ifdef FILE_MAP_EXECUTE |
| 22 | #define PROT_EXEC 0x4 |
| 23 | #else |
| 24 | #define PROT_EXEC 0x0 |
| 25 | #define FILE_MAP_EXECUTE 0 |
| 26 | #endif |
| 27 | |
| 28 | #define MAP_SHARED 0x01 |
| 29 | #define MAP_PRIVATE 0x02 |
| 30 | #define MAP_ANONYMOUS 0x20 |
| 31 | #define MAP_ANON MAP_ANONYMOUS |
| 32 | #define MAP_FAILED ((void *) -1) |
| 33 | |
| 34 | #ifdef __USE_FILE_OFFSET64 |
| 35 | # define DWORD_HI(x) (x >> 32) |
| 36 | # define DWORD_LO(x) ((x) & 0xffffffff) |
| 37 | #else |
| 38 | # define DWORD_HI(x) (0) |
| 39 | # define DWORD_LO(x) (x) |
| 40 | #endif |
| 41 | |
| 42 | static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) |
| 43 | { |
| 44 | if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) |
| 45 | return MAP_FAILED; |
| 46 | if (fd == -1) { |
| 47 | if (!(flags & MAP_ANON) || offset) |
| 48 | return MAP_FAILED; |
| 49 | } else if (flags & MAP_ANON) |
| 50 | return MAP_FAILED; |
| 51 | |
| 52 | DWORD flProtect; |
| 53 | if (prot & PROT_WRITE) { |
| 54 | if (prot & PROT_EXEC) |
| 55 | flProtect = PAGE_EXECUTE_READWRITE; |
| 56 | else |
| 57 | flProtect = PAGE_READWRITE; |
| 58 | } else if (prot & PROT_EXEC) { |
| 59 | if (prot & PROT_READ) |
| 60 | flProtect = PAGE_EXECUTE_READ; |
| 61 | else if (prot & PROT_EXEC) |
| 62 | flProtect = PAGE_EXECUTE; |
| 63 | } else |
| 64 | flProtect = PAGE_READONLY; |
| 65 | |
| 66 | off_t end = length + offset; |
| 67 | HANDLE mmap_fd, h; |
| 68 | if (fd == -1) |
| 69 | mmap_fd = INVALID_HANDLE_VALUE; |
| 70 | else |
| 71 | mmap_fd = (HANDLE)_get_osfhandle(fd); |
| 72 | h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); |
| 73 | if (h == NULL) |
| 74 | return MAP_FAILED; |
| 75 | |
| 76 | DWORD dwDesiredAccess; |
| 77 | if (prot & PROT_WRITE) |
| 78 | dwDesiredAccess = FILE_MAP_WRITE; |
| 79 | else |
| 80 | dwDesiredAccess = FILE_MAP_READ; |
| 81 | if (prot & PROT_EXEC) |
| 82 | dwDesiredAccess |= FILE_MAP_EXECUTE; |
| 83 | if (flags & MAP_PRIVATE) |
| 84 | dwDesiredAccess |= FILE_MAP_COPY; |
| 85 | void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); |
| 86 | if (ret == NULL) { |
| 87 | CloseHandle(h); |
| 88 | ret = MAP_FAILED; |
| 89 | } |
| 90 | return ret; |
| 91 | } |
| 92 | |
| 93 | static void munmap(void *addr, size_t length) |
| 94 | { |
| 95 | UnmapViewOfFile(addr); |
| 96 | /* ruh-ro, we leaked handle from CreateFileMapping() ... */ |
| 97 | } |
| 98 | |
| 99 | #undef DWORD_HI |
| 100 | #undef DWORD_LO |