mirror of
https://github.com/Dushistov/sdcv.git
synced 2026-01-11 20:59:47 +00:00
Allows simplifying the mmap sanity checks in mapfile, and actually ensuring they won't break when -D_FILE_OFFSET_BITS=64
94 lines
2.1 KiB
C++
94 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_MMAP
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#endif
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
#include <glib.h>
|
|
|
|
class MapFile
|
|
{
|
|
public:
|
|
MapFile() {}
|
|
~MapFile();
|
|
MapFile(const MapFile &) = delete;
|
|
MapFile &operator=(const MapFile &) = delete;
|
|
bool open(const char *file_name, off_t file_size);
|
|
gchar *begin() { return data; }
|
|
|
|
private:
|
|
char *data = nullptr;
|
|
#ifdef HAVE_MMAP
|
|
size_t size = 0u;
|
|
int mmap_fd = -1;
|
|
#elif defined(_WIN32)
|
|
HANDLE hFile = 0;
|
|
HANDLE hFileMap = 0;
|
|
#endif
|
|
};
|
|
|
|
inline bool MapFile::open(const char *file_name, off_t file_size)
|
|
{
|
|
#ifdef HAVE_MMAP
|
|
if ((mmap_fd = ::open(file_name, O_RDONLY)) < 0) {
|
|
// g_print("Open file %s failed!\n",fullfilename);
|
|
return false;
|
|
}
|
|
struct stat st;
|
|
if (fstat(mmap_fd, &st) == -1 || st.st_size < 0 || (st.st_size == 0 && S_ISREG(st.st_mode))
|
|
|| st.st_size != file_size) {
|
|
close(mmap_fd);
|
|
return false;
|
|
}
|
|
|
|
size = static_cast<size_t>(st.st_size);
|
|
data = (gchar *)mmap(nullptr, size, PROT_READ, MAP_SHARED, mmap_fd, 0);
|
|
if ((void *)data == (void *)(-1)) {
|
|
// g_print("mmap file %s failed!\n",idxfilename);
|
|
size = 0u;
|
|
data = nullptr;
|
|
return false;
|
|
}
|
|
#elif defined(_WIN32)
|
|
hFile = CreateFile(file_name, GENERIC_READ, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
|
hFileMap = CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0, file_size, nullptr);
|
|
data = (gchar *)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, file_size);
|
|
#else
|
|
gsize read_len;
|
|
if (!g_file_get_contents(file_name, &data, &read_len, nullptr))
|
|
return false;
|
|
|
|
if (read_len != file_size)
|
|
return false;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
inline MapFile::~MapFile()
|
|
{
|
|
if (!data)
|
|
return;
|
|
#ifdef HAVE_MMAP
|
|
munmap(data, size);
|
|
close(mmap_fd);
|
|
#else
|
|
#ifdef _WIN32
|
|
UnmapViewOfFile(data);
|
|
CloseHandle(hFileMap);
|
|
CloseHandle(hFile);
|
|
#else
|
|
g_free(data);
|
|
#endif
|
|
#endif
|
|
}
|