150 lines
4.0 KiB
C++
150 lines
4.0 KiB
C++
//
|
|
// Created on 2024-05-17.
|
|
//
|
|
|
|
#include "os_utils.h"
|
|
|
|
#include "utf_convert.h"
|
|
|
|
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
|
|
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <cerrno>
|
|
#include <cstring>
|
|
|
|
bool ReadFile(std::string_view path, std::vector<uint8_t>& out, size_t maxSize, int& errorCode) {
|
|
if (maxSize == 0) {
|
|
errorCode = -EINVAL;
|
|
return false;
|
|
}
|
|
int fd = open(std::string(path).c_str(), O_RDONLY);
|
|
if (fd < 0) {
|
|
errorCode = -errno;
|
|
return false;
|
|
}
|
|
struct stat64 st{};
|
|
if (fstat64(fd, &st) < 0) {
|
|
close(fd);
|
|
errorCode = -errno;
|
|
return false;
|
|
}
|
|
if (st.st_size > maxSize) {
|
|
close(fd);
|
|
errorCode = -EOVERFLOW;
|
|
return false;
|
|
}
|
|
out.resize(st.st_size);
|
|
ssize_t remaining = st.st_size;
|
|
ssize_t read = 0;
|
|
uint8_t* ptr = out.data();
|
|
while (remaining > 0) {
|
|
read = ::read(fd, ptr, remaining);
|
|
if (read < 0) {
|
|
close(fd);
|
|
errorCode = -errno;
|
|
return false;
|
|
}
|
|
remaining -= read;
|
|
ptr += read;
|
|
}
|
|
close(fd);
|
|
return true;
|
|
|
|
}
|
|
|
|
bool WriteFile(std::string_view path, std::span<const uint8_t> data, int& errorCode) {
|
|
int fd = open(std::string(path).c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
if (fd < 0) {
|
|
errorCode = -errno;
|
|
return false;
|
|
}
|
|
ssize_t remaining = data.size_bytes();
|
|
ssize_t written = 0;
|
|
const uint8_t* ptr = data.data();
|
|
while (remaining > 0) {
|
|
written = ::write(fd, ptr, remaining);
|
|
if (written < 0) {
|
|
close(fd);
|
|
errorCode = -errno;
|
|
return false;
|
|
}
|
|
remaining -= written;
|
|
ptr += written;
|
|
}
|
|
close(fd);
|
|
return true;
|
|
}
|
|
|
|
#include <cwchar>
|
|
|
|
|
|
std::string GetErrorMsg(int errorCode) {
|
|
return strerror(std::abs(errorCode));
|
|
}
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
#include <windows.h>
|
|
|
|
bool ReadFile(std::string_view path, std::vector<uint8_t>& out, size_t maxSize, int& errorCode) {
|
|
std::wstring wpath = utfcvt::UTF8ToWide(path);
|
|
HANDLE hFile = CreateFileW(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
errorCode = -(int) GetLastError();
|
|
return false;
|
|
}
|
|
LARGE_INTEGER fileSize;
|
|
if (!GetFileSizeEx(hFile, &fileSize)) {
|
|
CloseHandle(hFile);
|
|
errorCode = -(int) GetLastError();
|
|
return false;
|
|
}
|
|
if (fileSize.QuadPart > maxSize) {
|
|
CloseHandle(hFile);
|
|
errorCode = -ERROR_FILE_TOO_LARGE;
|
|
return false;
|
|
}
|
|
out.resize(fileSize.QuadPart);
|
|
DWORD bytesRead = 0;
|
|
if (!ReadFile(hFile, out.data(), fileSize.LowPart, &bytesRead, nullptr)) {
|
|
CloseHandle(hFile);
|
|
errorCode = -(int) GetLastError();
|
|
return false;
|
|
}
|
|
CloseHandle(hFile);
|
|
return true;
|
|
}
|
|
|
|
bool WriteFile(std::string_view path, std::span<const uint8_t> data, int& errorCode) {
|
|
std::wstring wpath = utfcvt::UTF8ToWide(path);
|
|
HANDLE hFile = CreateFileW(wpath.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
errorCode = -(int) GetLastError();
|
|
return false;
|
|
}
|
|
DWORD bytesWritten = 0;
|
|
if (!WriteFile(hFile, data.data(), (DWORD) data.size_bytes(), &bytesWritten, nullptr)) {
|
|
CloseHandle(hFile);
|
|
errorCode = -(int) GetLastError();
|
|
return false;
|
|
}
|
|
CloseHandle(hFile);
|
|
return true;
|
|
}
|
|
|
|
std::string GetErrorMsg(int errorCode) {
|
|
LPWSTR msgBuf = nullptr;
|
|
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &msgBuf, 0, nullptr);
|
|
std::wstring msg(msgBuf);
|
|
LocalFree(msgBuf);
|
|
return utfcvt::WideToUTF8(msg);
|
|
}
|
|
|
|
#else
|
|
#error "Unsupported platform"
|
|
#endif
|