Files
NandPartitionTableConvert/os_utils.cc
2024-05-17 21:40:15 +08:00

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