// // Created on 2024-05-17. // #include "os_utils.h" #include "utf_convert.h" #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) #include #include #include #include #include bool ReadFile(std::string_view path, std::vector& 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 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 std::string GetErrorMsg(int errorCode) { return strerror(std::abs(errorCode)); } #elif defined(_WIN32) #include bool ReadFile(std::string_view path, std::vector& 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 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