#include "Core.h" #ifdef PLATFORM_POSIX #include #endif namespace Upp { int FileMapping::MappingGranularity() { static int mg = 0; #ifdef PLATFORM_WIN32 ONCELOCK { SYSTEM_INFO info; GetSystemInfo(&info); mg = info.dwAllocationGranularity; } #else ONCELOCK { mg = getpagesize(); } #endif return mg; } FileMapping::FileMapping(const char *file_) { #ifdef PLATFORM_WIN32 hfile = INVALID_HANDLE_VALUE; hmap = NULL; #endif #ifdef PLATFORM_POSIX hfile = -1; #endif base = rawbase = NULL; size = rawsize = 0; offset = rawoffset = 0; filesize = -1; write = false; if(file_) Open(file_); } #ifdef PLATFORM_WIN32 bool FileMapping::Open(const char *filename, dword mode, int64 wsize) #else bool FileMapping::Open(const char *filename, dword mode, int64 wsize, mode_t acm) #endif { Close(); write = (mode & FileStream::MODEMASK) != FileStream::READ; #ifdef PLATFORM_WIN32 if(!FileStream::OpenHandle(filename, mode, hfile, filesize)) return false; if((mode & FileStream::MODEMASK) == FileStream::CREATE) filesize = wsize; else wsize = 0; hmap = CreateFileMapping(hfile, NULL, write ? PAGE_READWRITE : PAGE_READONLY, HIDWORD(wsize), LODWORD(wsize), NULL); if(!hmap) { Close(); return false; } #else if(!FileStream::OpenHandle(filename, mode, hfile, filesize, acm)) return false; if((mode & FileStream::MODEMASK) == FileStream::CREATE) { (void)ftruncate(hfile, wsize); filesize = wsize; } #endif return true; } bool FileMapping::Create(const char *file, int64 filesize, bool delete_share) { return Open(file, FileStream::CREATE | (delete_share ? FileStream::DELETESHARE : 0), filesize); } byte *FileMapping::Map(int64 mapoffset, size_t maplen) { ASSERT(IsOpen()); Unmap(); mapoffset = minmax(mapoffset, 0, filesize); int gran = MappingGranularity(); int64 rawoff = mapoffset & -gran; maplen = (size_t)min(maplen, filesize - mapoffset); size_t rawsz = (size_t)min((maplen + (size_t)(mapoffset - rawoff) + gran - 1) & -gran, filesize - rawoff); rawoffset = rawoff; rawsize = rawsz; #ifdef PLATFORM_WIN32 rawbase = (byte *)MapViewOfFile(hmap, write ? FILE_MAP_WRITE : FILE_MAP_READ, HIDWORD(rawoffset), LODWORD(rawoffset), rawsize); #else rawbase = (byte *)mmap(0, rawsize, PROT_READ | (write ? PROT_WRITE : 0), #ifdef PLATFORM_FREEBSD MAP_NOSYNC, #else MAP_SHARED, #endif hfile, rawoffset); #endif #ifdef PLATFORM_POSIX if(rawbase == (byte *)-1) #else if(!rawbase) #endif return NULL; offset = mapoffset; size = maplen; base = rawbase + (int)(offset - rawoffset); return base; } bool FileMapping::Unmap() { bool ok = true; if(rawbase) { #ifdef PLATFORM_WIN32 ok = !!UnmapViewOfFile(rawbase); #endif #ifdef PLATFORM_POSIX ok = (munmap((void *)rawbase, rawsize) == 0); #endif } base = rawbase = NULL; size = 0; return ok; } bool FileMapping::Close() { bool ok = Unmap(); #ifdef PLATFORM_WIN32 if(hmap) { if(!CloseHandle(hmap)) ok = false; hmap = NULL; } if(IsOpen()) { if(!CloseHandle(hfile)) ok = false; hfile = INVALID_HANDLE_VALUE; } #endif #ifdef PLATFORM_POSIX if(IsOpen()) { if(close(hfile) != 0) ok = false; hfile = -1; } #endif filesize = -1; offset = 0; size = 0; write = false; return ok; } Time FileMapping::GetTime() const { ASSERT(IsOpen()); #ifdef PLATFORM_WIN32 FileTime ft; GetFileTime(hfile, NULL, NULL, &ft); return ft; #endif #ifdef PLATFORM_POSIX struct stat st; fstat(hfile, &st); return Time(st.st_mtime); #endif } }