diff options
author | Chris Robinson <[email protected]> | 2016-08-31 08:14:50 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2016-08-31 08:14:50 -0700 |
commit | e01c33792108e3f0026c29a63ce38096d232aa51 (patch) | |
tree | 61fea53c14aa03f9038e320e817119147a23f1c6 | |
parent | ccf90df07215b4317e2842641a8915d757868e8b (diff) |
Add some helper wrappers to mmap files
-rw-r--r-- | Alc/compat.h | 13 | ||||
-rw-r--r-- | Alc/helpers.c | 107 |
2 files changed, 120 insertions, 0 deletions
diff --git a/Alc/compat.h b/Alc/compat.h index 0443692a..114fc655 100644 --- a/Alc/compat.h +++ b/Alc/compat.h @@ -25,6 +25,19 @@ FILE *al_fopen(const char *fname, const char *mode); #endif +struct FileMapping { +#ifdef _WIN32 + HANDLE file; + HANDLE fmap; +#else + int fd; +#endif + void *ptr; + size_t len; +}; +struct FileMapping MapFileToMem(const char *fname); +void UnmapFileMem(const struct FileMapping *mapping); + al_string GetProcPath(void); #ifdef HAVE_DYNLOAD diff --git a/Alc/helpers.c b/Alc/helpers.c index 2a059c68..9d7d564f 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -89,6 +89,10 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x #endif #ifndef _WIN32 +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> #include <unistd.h> #elif defined(_WIN32_IE) #include <shlobj.h> @@ -598,6 +602,68 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) return results; } + +struct FileMapping MapFileToMem(const char *fname) +{ + struct FileMapping ret = { NULL, NULL, NULL, 0 }; + MEMORY_BASIC_INFORMATION meminfo; + HANDLE file, fmap; + WCHAR *wname; + void *ptr; + + wname = FromUTF8(fname); + + file = CreateFileW(wname, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(file == INVALID_HANDLE_VALUE) + { + ERR("Failed to open %s: %lu\n", fname, GetLastError()); + free(wname); + return ret; + } + free(wname); + wname = NULL; + + fmap = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL); + if(!fmap) + { + ERR("Failed to create map for %s: %lu\n", fname, GetLastError()); + CloseHandle(file); + return ret; + } + + ptr = MapViewOfFile(fmap, FILE_MAP_READ, 0, 0, 0); + if(!ptr) + { + ERR("Failed to map %s: %lu\n", fname, GetLastError()); + CloseHandle(fmap); + CloseHandle(file); + return ret; + } + + if(VirtualQuery(ptr, &meminfo, sizeof(meminfo)) != sizeof(meminfo)) + { + ERR("Failed to get map size for %s: %lu\n", fname, GetLastError()); + UnmapViewOfFile(ptr); + CloseHandle(fmap); + CloseHandle(file); + return ret; + } + + ret.file = file; + ret.fmap = fmap; + ret.ptr = ptr; + ret.len = meminfo.RegionSize; + return ret; +} + +void UnmapFileMem(const struct FileMapping *mapping) +{ + UnmapViewOfFile(mapping->ptr); + CloseHandle(mapping->fmap); + CloseHandle(mapping->file); +} + #else al_string GetProcPath(void) @@ -810,6 +876,47 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir) return results; } + +struct FileMapping MapFileToMem(const char *fname) +{ + struct FileMapping ret = { -1, NULL, 0 }; + struct stat sbuf; + void *ptr; + int fd; + + fd = open(fname, O_RDONLY, 0); + if(fd == -1) + { + ERR("Failed to open %s: (%d) %s\n", fname, errno, strerror(errno)); + return ret; + } + if(fstat(fd, &sbuf) == -1) + { + ERR("Failed to stat %s: (%d) %s\n", fname, errno, strerror(errno)); + close(fd); + return ret; + } + + ptr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if(ptr == MAP_FAILED) + { + ERR("Failed to map %s: (%d) %s\n", fname, errno, strerror(errno)); + close(fd); + return ret; + } + + ret.fd = fd; + ret.ptr = ptr; + ret.len = sbuf.st_size; + return ret; +} + +void UnmapFileMem(const struct FileMapping *mapping) +{ + munmap(mapping->ptr, mapping->len); + close(mapping->fd); +} + #endif |