/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "MemMappedFile.hpp" #include "Base/Logger.hpp" #ifdef _MSC_VER #include #else #include #include #include #include #include #endif namespace OpenVulkano { class MemMappedFile::Internal final { public: void* address = nullptr; size_t size = 0; #ifdef _MSC_VER HANDLE fileHandle; HANDLE fileMappingHandle; Internal(const char* file, FileMode fileMode) { //TODO handle other file modes than read fileHandle = CreateFile( TEXT(file), // file to open GENERIC_READ, // open for reading 0, // do not share NULL, // default security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attribute template if (fileHandle == INVALID_HANDLE_VALUE) { Logger::FILESYS->critical("Failed to open file: {}", file); return; } LARGE_INTEGER fileSize; if (!GetFileSizeEx(fileHandle, &fileSize)) { Logger::FILESYS->critical("Failed to get size of file: {}", file); CloseHandle(fileHandle); return; } size = fileSize.QuadPart; fileMappingHandle = CreateFileMapping( fileHandle, NULL, // default security PAGE_READONLY, // read-only access 0, // maximum object size (high-order) 0, // maximum object size (low-order) NULL); // name of the mapping object if (fileMappingHandle == 0) { Logger::FILESYS->critical("Failed to create file mapping handle: {}", file); CloseHandle(fileHandle); size = 0; return; } address = MapViewOfFile( fileMappingHandle, // handle to the map object FILE_MAP_READ, // read access 0, // max. object size 0, // size of the hFile 0); // map the entire file if (address == nullptr) { Logger::FILESYS->critical("Failed to create file mapping: {}", file); CloseHandle(fileMappingHandle); CloseHandle(fileHandle); size = 0; } } ~Internal() { UnmapViewOfFile(address); CloseHandle(fileMappingHandle); CloseHandle(fileHandle); } #else int fileHandle; struct stat fileStat; Internal(const char* file, FileMode fileMode) { fileHandle = open(file, fileMode); if (fstat(fileHandle, &fileStat) == -1) { Logger::FILESYS->critical("Failed to query stats for file: {}", file); return; } address = mmap(nullptr, fileStat.st_size, fileMode + 1, MAP_PRIVATE, fileHandle, 0); if (address == MAP_FAILED) { Logger::FILESYS->critical("Failed to memory map file: {}", file); address = nullptr; } size = fileStat.st_size; } ~Internal() { munmap(address, fileStat.st_size); close(fileHandle); } #endif }; MemMappedFile::MemMappedFile(const std::filesystem::path& path, FileMode fileMode) { m_internal = std::make_shared(path.string().c_str(), fileMode); m_data = m_internal->address; m_size = (m_data) ? m_internal->size : 0; } }