diff options
| author | Markus Mittendrein <git@maxmitti.tk> | 2019-03-08 00:22:20 +0100 |
|---|---|---|
| committer | Markus Mittendrein <git@maxmitti.tk> | 2019-03-08 00:25:57 +0100 |
| commit | 31693290ed717d700480774f4f6b49dbe9b9b704 (patch) | |
| tree | 4cbbeb7ea82a950ea3c9ebadea6276d750482c4b /src | |
| parent | 841ee0e92516827e6dd6f2101903b5ec1cc85fb4 (diff) | |
| download | cc4group-31693290ed717d700480774f4f6b49dbe9b9b704.tar.gz cc4group-31693290ed717d700480774f4f6b49dbe9b9b704.zip | |
Windows support (hopefully!)
Diffstat (limited to 'src')
| -rw-r--r-- | src/cc4group.c | 37 | ||||
| -rw-r--r-- | src/platform/platform.h | 32 | ||||
| -rw-r--r-- | src/platform/unix.c | 13 | ||||
| -rw-r--r-- | src/platform/windows.c | 108 |
4 files changed, 174 insertions, 16 deletions
diff --git a/src/cc4group.c b/src/cc4group.c index 1a8c344..fb2036e 100644 --- a/src/cc4group.c +++ b/src/cc4group.c @@ -10,14 +10,16 @@ #include "c4groupentrycore.h" #include "GenericList.h" +#include "platform/platform.h" + #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <string.h> #include <errno.h> -#include <sys/mman.h> #include <sys/time.h> #include <time.h> +#include <utime.h> #include <assert.h> #include <stdio.h> @@ -208,7 +210,7 @@ static void deleteChildren(GroupEntryList* const entries) GroupEntryListDestroy(entries); } -static void* cc4group_mapSizedWriteFd(CC4Group* const this, int fd, size_t size) +static void* cc4group_mapSizedWriteFd(CC4Group* const this, int fd, size_t size, void** extra) { // allocate file size // https://gist.github.com/marcetcheverry/991042 @@ -224,17 +226,18 @@ static void* cc4group_mapSizedWriteFd(CC4Group* const this, int fd, size_t size) return MAP_FAILED; } - return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + return cc4group_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0, extra); } typedef struct { void* addr; size_t size; + void* extra; } MunmapData; static void cc4group_unmapTmpMemoryFile(MunmapData* data) { - if(munmap(data->addr, data->size) == -1) + if(cc4group_munmap(data->addr, data->size, data->extra) == -1) { fprintf(stderr, "WARNING: munmap: Unmapping tempory file failed: %s\n", strerror(errno)); } @@ -246,7 +249,7 @@ static void* cc4group_createTmpMemoryFile(CC4Group* const this, const size_t siz { void* ret; #define TMP_FILE "cc4group.tmp" - int tmpFile = open(TMP_FILE, O_CREAT | O_RDWR | O_TRUNC | O_EXCL, 0600); + int tmpFile = open(TMP_FILE, O_CREAT | O_BINARY | O_RDWR | O_TRUNC | O_EXCL, 0600); if(tmpFile == -1) { SET_ERRNO_ERROR("open: Opening tmp file \"" TMP_FILE "\""); @@ -259,7 +262,8 @@ static void* cc4group_createTmpMemoryFile(CC4Group* const this, const size_t siz } #undef TMP_FILE - ret = cc4group_mapSizedWriteFd(this, tmpFile, size); + void* mmapExtra; + ret = cc4group_mapSizedWriteFd(this, tmpFile, size, &mmapExtra); if(ret == MAP_FAILED) { // error message is set in the method @@ -274,7 +278,7 @@ static void* cc4group_createTmpMemoryFile(CC4Group* const this, const size_t siz fprintf(stderr, "ERROR: allocating memory for cleanup data: %s\n", strerror(errno)); } - *unmapData = (MunmapData){ret, size}; + *unmapData = (MunmapData){ret, size, mmapExtra}; *cleanupJob = (CC4Group_CleanupJob){(CC4Group_CleanupFunc)cc4group_unmapTmpMemoryFile, unmapData}; } @@ -330,6 +334,7 @@ static void cc4group_uncompressGroup(CC4Group* const this) uint8_t* retData = NULL; C4GroupHeader* header = NULL; uint8_t* mappedFile = MAP_FAILED; + void* mapExtra; uint8_t* mappedTmpFile = NULL; bool inflateStarted = false; size_t currentSize = 0; @@ -344,7 +349,7 @@ static void cc4group_uncompressGroup(CC4Group* const this) int file = -1; for(;;) { - file = open(this->path, O_RDONLY); + file = open(this->path, O_RDONLY | O_BINARY); if(file != -1) { break; @@ -386,7 +391,7 @@ static void cc4group_uncompressGroup(CC4Group* const this) } off_t size = st.st_size; - mappedFile = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0); + mappedFile = cc4group_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, file, 0, &mapExtra); if(close(file) == -1) { @@ -537,7 +542,7 @@ ret: if(mappedFile != MAP_FAILED) { - if(munmap(mappedFile, size) == -1) + if(cc4group_munmap(mappedFile, size, mapExtra) == -1) { fprintf(stderr, "WARNING: munmap: Unmapping the group file failed: %s\n", strerror(errno)); } @@ -814,7 +819,7 @@ static bool cc4group_extractEntry(CC4Group* const this, const C4GroupEntryData* assert(root); assert(!root->core.Directory); - int file = open(targetPath, O_WRONLY | O_CREAT | O_EXCL, root->core.Executable ? 0755 : 0644); + int file = open(targetPath, O_WRONLY | O_BINARY | O_CREAT | O_EXCL, root->core.Executable ? 0755 : 0644); if(file == -1) { SET_ERRNO_ERROR("open: Creating target file"); @@ -827,10 +832,10 @@ static bool cc4group_extractEntry(CC4Group* const this, const C4GroupEntryData* fprintf(stderr, "WARNING: close: Closing the extracted file \"%s\" failed: %s\n", targetPath, strerror(errno)); } - struct timeval tv[2] = {{.tv_usec = 0, .tv_sec = root->core.Modified}, {.tv_usec = 0, .tv_sec = root->core.Modified}}; - if(utimes(targetPath, tv) == -1) + struct utimbuf times = {.actime = root->core.Modified, .modtime = root->core.Modified}; + if(utime(targetPath, ×) == -1) { - fprintf(stderr, "WARNING: utimes: Setting modification time for \"%s\" failed: %s\n", targetPath, strerror(errno)); + fprintf(stderr, "WARNING: utime: Setting modification time for \"%s\" failed: %s\n", targetPath, strerror(errno)); } return true; @@ -861,7 +866,7 @@ static bool cc4group_extractChildren(CC4Group* const this, const C4GroupEntryDat if(root->core.Directory) { assert(root->children); - if(mkdir(tmpPath, 0755) == -1 /*&& errno != EEXIST*/) + if(cc4group_mkdir(tmpPath, 0755) == -1 /*&& errno != EEXIST*/) { SET_ERRNO_ERROR("mkdir: Creating target directory"); success = false; @@ -1184,7 +1189,7 @@ static bool cc4group_saveIt(CC4Group* const this, const char* const path, bool c assert(this); bool success = false; - int file = open(path, O_WRONLY | O_CREAT | (overwrite ? O_TRUNC : O_EXCL), 0644); + int file = open(path, O_WRONLY | O_BINARY | O_CREAT | (overwrite ? O_TRUNC : O_EXCL), 0644); if(file == -1) { diff --git a/src/platform/platform.h b/src/platform/platform.h new file mode 100644 index 0000000..aaa6138 --- /dev/null +++ b/src/platform/platform.h @@ -0,0 +1,32 @@ +#pragma once + +#include <stddef.h> +#include <sys/types.h> + +#ifdef CC4GROUP_PLATFORM_WINDOWS + #define PROT_READ 0x1 + #define PROT_WRITE 0x2 + /* This flag is only available in WinXP+ */ + #ifdef FILE_MAP_EXECUTE + #define PROT_EXEC 0x4 + #else + #define PROT_EXEC 0x0 + #define FILE_MAP_EXECUTE 0 + #endif + + #define MAP_SHARED 0x01 + #define MAP_PRIVATE 0x02 + #define MAP_ANONYMOUS 0x20 + #define MAP_ANON MAP_ANONYMOUS + #define MAP_FAILED ((void *) -1) + + #define cc4group_mkdir(path, mode) mkdir((path)) +#else + #include <sys/mman.h> + + #define cc4group_mkdir(path, mode) mkdir((path), (mode)) + #define O_BINARY 0 +#endif + +void *cc4group_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset, void** extra); +int cc4group_munmap(void *addr, size_t length, void* extra);
\ No newline at end of file diff --git a/src/platform/unix.c b/src/platform/unix.c new file mode 100644 index 0000000..ecf5166 --- /dev/null +++ b/src/platform/unix.c @@ -0,0 +1,13 @@ +#include "platform.h" + +void *cc4group_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset, void** extra) +{ + (void)extra; + return mmap(start, length, prot, flags, fd, offset); +} + +int cc4group_munmap(void *addr, size_t length, void* extra) +{ + (void)extra; + return munmap(addr, length); +} diff --git a/src/platform/windows.c b/src/platform/windows.c new file mode 100644 index 0000000..fb37837 --- /dev/null +++ b/src/platform/windows.c @@ -0,0 +1,108 @@ +/* mmap() replacement for Windows + * + * Author: Mike Frysinger <vapier@gentoo.org> + * Modified to not leak the CreateFileMapping-Handle, as well as fixed MAP_PRIVATE to actually work by Markus Mittendrein + * Placed into the public domain + */ + +/* References: + * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx + * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx + * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx + * https://source.winehq.org/source/dlls/kernel32/virtual.c#0356 + * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx + */ + +#include <io.h> +#include <windows.h> +#include <sys/types.h> + +#include <stdio.h> + +#include "platform.h" + +#ifdef __USE_FILE_OFFSET64 +# define DWORD_HI(x) (x >> 32) +# define DWORD_LO(x) ((x) & 0xffffffff) +#else +# define DWORD_HI(x) (0) +# define DWORD_LO(x) (x) +#endif + +void *cc4group_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset, void** extra) +{ + (void)start; + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return MAP_FAILED; + if (fd == -1) { + if (!(flags & MAP_ANON) || offset) + return MAP_FAILED; + } else if (flags & MAP_ANON) + return MAP_FAILED; + + DWORD flProtect; + if (prot & PROT_WRITE) { + if (prot & PROT_EXEC) { + if(prot & MAP_PRIVATE) + flProtect = PAGE_EXECUTE_WRITECOPY; + else + flProtect = PAGE_EXECUTE_READWRITE; + } + else { + if(prot & MAP_PRIVATE) + flProtect = PAGE_WRITECOPY; + else + flProtect = PAGE_READWRITE; + } + } else if (prot & PROT_EXEC) { + if (prot & PROT_READ) + flProtect = PAGE_EXECUTE_READ; + else if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE; + } else + flProtect = PAGE_READONLY; + + off_t end = length + offset; + HANDLE mmap_fd, h; + if (fd == -1) + mmap_fd = INVALID_HANDLE_VALUE; + else + mmap_fd = (HANDLE)_get_osfhandle(fd); + h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); + if (h == NULL) + return MAP_FAILED; + + DWORD dwDesiredAccess; + if (flags & MAP_PRIVATE) + dwDesiredAccess = FILE_MAP_COPY; + else if (prot & PROT_WRITE) + dwDesiredAccess = FILE_MAP_WRITE; + else + dwDesiredAccess = FILE_MAP_READ; + if (prot & PROT_EXEC) + dwDesiredAccess |= FILE_MAP_EXECUTE; + if (flags & MAP_PRIVATE) + dwDesiredAccess |= FILE_MAP_COPY; + + void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); + if (ret == NULL) { + CloseHandle(h); + ret = MAP_FAILED; + } + + *extra = h; + + return ret; +} + +int cc4group_munmap(void *addr, size_t length, void* extra) +{ + (void)length; + UnmapViewOfFile(addr); + CloseHandle(extra); + /* ruh-ro, we leaked handle from CreateFileMapping() ... */ + return 0; +} + +#undef DWORD_HI +#undef DWORD_LO |
