2022-08-10 17:03:23 +02:00
|
|
|
#include "HostFilesystem.h"
|
|
|
|
|
|
|
|
#include <filesystem>
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
#include "fsfw/serialize.h"
|
|
|
|
|
|
|
|
using namespace std::filesystem;
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
HostFilesystem::HostFilesystem() = default;
|
|
|
|
|
|
|
|
ReturnValue_t HostFilesystem::writeToFile(FileOpParams params, const uint8_t *data) {
|
2022-08-11 10:19:25 +02:00
|
|
|
if (params.path() == nullptr) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
2022-08-11 10:19:25 +02:00
|
|
|
path path(params.path());
|
2023-03-08 14:47:03 +01:00
|
|
|
std::error_code e;
|
|
|
|
if (not exists(path, e)) {
|
2022-08-10 17:03:23 +02:00
|
|
|
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
|
|
|
}
|
2022-09-15 16:02:46 +02:00
|
|
|
// This is equivalent to "r+" mode, which is what we need here. Only using ::out would truncate
|
|
|
|
// the file
|
|
|
|
ofstream file(path, ios::binary | ios::out | ios::in);
|
2022-08-10 17:03:23 +02:00
|
|
|
if (file.fail()) {
|
|
|
|
return HasFileSystemIF::GENERIC_FILE_ERROR;
|
|
|
|
}
|
|
|
|
file.seekp(static_cast<unsigned int>(params.offset));
|
|
|
|
file.write(reinterpret_cast<const char *>(data), static_cast<unsigned int>(params.size));
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t HostFilesystem::readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize,
|
|
|
|
size_t maxSize) {
|
2022-08-11 10:19:25 +02:00
|
|
|
if (params.path() == nullptr) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
2022-08-11 10:19:25 +02:00
|
|
|
path path(params.path());
|
2023-03-08 14:47:03 +01:00
|
|
|
std::error_code e;
|
|
|
|
if (not exists(path, e)) {
|
2022-08-10 17:03:23 +02:00
|
|
|
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
|
|
|
}
|
|
|
|
ifstream file(path);
|
|
|
|
if (file.fail()) {
|
|
|
|
return HasFileSystemIF::GENERIC_FILE_ERROR;
|
|
|
|
}
|
2022-08-17 11:39:15 +02:00
|
|
|
auto sizeToRead = static_cast<unsigned int>(params.size);
|
|
|
|
file.seekg(static_cast<unsigned int>(params.offset));
|
|
|
|
if (readSize + sizeToRead > maxSize) {
|
2022-08-10 17:03:23 +02:00
|
|
|
return SerializeIF::BUFFER_TOO_SHORT;
|
|
|
|
}
|
2022-08-17 11:39:15 +02:00
|
|
|
file.read(reinterpret_cast<char *>(*buffer), sizeToRead);
|
|
|
|
readSize += sizeToRead;
|
|
|
|
*buffer += sizeToRead;
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t HostFilesystem::createFile(FilesystemParams params, const uint8_t *data,
|
|
|
|
size_t size) {
|
|
|
|
if (params.path == nullptr) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
|
|
|
path path(params.path);
|
2023-03-08 14:47:03 +01:00
|
|
|
std::error_code e;
|
|
|
|
if (exists(path, e)) {
|
2022-08-10 17:03:23 +02:00
|
|
|
return HasFileSystemIF::FILE_ALREADY_EXISTS;
|
|
|
|
}
|
|
|
|
ofstream file(path);
|
|
|
|
if (file.fail()) {
|
|
|
|
return HasFileSystemIF::GENERIC_FILE_ERROR;
|
|
|
|
}
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t HostFilesystem::removeFile(const char *path_, FileSystemArgsIF *args) {
|
|
|
|
if (path_ == nullptr) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
|
|
|
path path(path_);
|
2023-03-08 14:47:03 +01:00
|
|
|
std::error_code e;
|
|
|
|
if (not exists(path, e)) {
|
2022-08-10 17:03:23 +02:00
|
|
|
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
|
|
|
}
|
|
|
|
if (remove(path, errorCode)) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
|
|
|
return HasFileSystemIF::GENERIC_FILE_ERROR;
|
|
|
|
}
|
2022-08-11 09:32:18 +02:00
|
|
|
|
2022-08-10 17:03:23 +02:00
|
|
|
ReturnValue_t HostFilesystem::createDirectory(FilesystemParams params, bool createParentDirs) {
|
|
|
|
if (params.path == nullptr) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
|
|
|
path dirPath(params.path);
|
2022-08-11 09:32:18 +02:00
|
|
|
|
2023-03-08 14:47:03 +01:00
|
|
|
std::error_code e;
|
|
|
|
if (exists(dirPath, e)) {
|
2022-08-11 09:32:18 +02:00
|
|
|
return HasFileSystemIF::DIRECTORY_ALREADY_EXISTS;
|
|
|
|
}
|
2022-08-17 16:10:52 +02:00
|
|
|
|
2022-08-10 17:03:23 +02:00
|
|
|
if (createParentDirs) {
|
2022-08-11 09:32:18 +02:00
|
|
|
if (create_directories(dirPath, errorCode)) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-11 09:32:18 +02:00
|
|
|
}
|
|
|
|
return HasFileSystemIF::GENERIC_DIR_ERROR;
|
|
|
|
}
|
|
|
|
if (create_directory(dirPath, errorCode)) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
2022-08-11 09:32:18 +02:00
|
|
|
return HasFileSystemIF::GENERIC_DIR_ERROR;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
2022-08-11 09:32:18 +02:00
|
|
|
|
2022-08-10 17:03:23 +02:00
|
|
|
ReturnValue_t HostFilesystem::removeDirectory(FilesystemParams params, bool deleteRecurively) {
|
2022-08-11 09:32:18 +02:00
|
|
|
if (params.path == nullptr) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-08-11 09:32:18 +02:00
|
|
|
}
|
|
|
|
path dirPath(params.path);
|
2023-03-08 14:47:03 +01:00
|
|
|
std::error_code e;
|
|
|
|
if (not exists(dirPath, e)) {
|
2022-08-11 09:32:18 +02:00
|
|
|
return HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST;
|
|
|
|
}
|
|
|
|
if (is_regular_file(dirPath)) {
|
|
|
|
return HasFileSystemIF::NOT_A_DIRECTORY;
|
|
|
|
}
|
|
|
|
if (deleteRecurively) {
|
|
|
|
if (remove_all(dirPath, errorCode)) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-11 09:32:18 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (remove(dirPath, errorCode)) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-11 09:32:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Error handling
|
|
|
|
if (errorCode == std::errc::directory_not_empty) {
|
|
|
|
return HasFileSystemIF::DIRECTORY_NOT_EMPTY;
|
|
|
|
}
|
|
|
|
return HasFileSystemIF::GENERIC_DIR_ERROR;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
2022-08-11 09:32:18 +02:00
|
|
|
|
2022-08-11 10:10:05 +02:00
|
|
|
ReturnValue_t HostFilesystem::rename(const char *oldPath_, const char *newPath_,
|
|
|
|
FileSystemArgsIF *args) {
|
2022-08-11 09:32:18 +02:00
|
|
|
if (oldPath_ == nullptr or newPath_ == nullptr) {
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-08-11 09:32:18 +02:00
|
|
|
}
|
|
|
|
path oldPath(oldPath_);
|
|
|
|
path newPath(newPath_);
|
|
|
|
errorCode.clear();
|
|
|
|
std::filesystem::rename(oldPath, newPath, errorCode);
|
|
|
|
if (errorCode) {
|
|
|
|
return HasFileSystemIF::GENERIC_RENAME_ERROR;
|
|
|
|
}
|
2022-08-22 16:35:53 +02:00
|
|
|
return returnvalue::OK;
|
2022-08-10 17:03:23 +02:00
|
|
|
}
|
2022-09-05 17:42:56 +02:00
|
|
|
|
|
|
|
bool HostFilesystem::fileExists(FilesystemParams params) {
|
|
|
|
path path(params.path);
|
2023-03-08 14:47:03 +01:00
|
|
|
std::error_code e;
|
|
|
|
return filesystem::exists(path, e);
|
2022-09-05 17:42:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) {
|
|
|
|
path path(params.path);
|
2023-03-08 14:47:03 +01:00
|
|
|
std::error_code e;
|
|
|
|
if (not filesystem::exists(path, e)) {
|
2022-09-05 17:42:56 +02:00
|
|
|
return FILE_DOES_NOT_EXIST;
|
|
|
|
}
|
2023-06-18 19:04:36 +02:00
|
|
|
// Specify truncaion flug explicitely.
|
|
|
|
ofstream of(path, std::ios::out | std::ios::trunc);
|
2022-09-05 17:42:56 +02:00
|
|
|
return returnvalue::OK;
|
|
|
|
}
|
2023-02-24 16:49:23 +01:00
|
|
|
|
|
|
|
bool HostFilesystem::isDirectory(const char *path) { return filesystem::is_directory(path); }
|
|
|
|
|
|
|
|
ReturnValue_t HostFilesystem::getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
|
|
|
|
size_t &baseNameLen) {
|
|
|
|
std::string path(params.path);
|
|
|
|
std::string baseName = path.substr(path.find_last_of("/\\") + 1);
|
|
|
|
if (baseName.size() + 1 > maxLen) {
|
|
|
|
return returnvalue::FAILED;
|
|
|
|
}
|
|
|
|
std::memcpy(nameBuf, baseName.c_str(), baseName.size());
|
|
|
|
nameBuf[baseName.size()] = '\0';
|
|
|
|
baseNameLen = baseName.size();
|
|
|
|
return returnvalue::OK;
|
|
|
|
}
|