eive-obsw/bsp_q7s/memory/FileSystemHandler.cpp

239 lines
8.5 KiB
C++
Raw Normal View History

2021-07-08 12:22:41 +02:00
#include "FileSystemHandler.h"
2021-07-19 19:21:34 +02:00
#include <cstring>
#include <filesystem>
2022-01-17 15:58:27 +01:00
#include <fstream>
2022-01-17 15:58:27 +01:00
#include "bsp_q7s/core/CoreController.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/memory/GenericFileSystemMessage.h"
#include "fsfw/tasks/TaskFactory.h"
2021-07-08 12:32:24 +02:00
2022-01-17 15:58:27 +01:00
FileSystemHandler::FileSystemHandler(object_id_t fileSystemHandler)
: SystemObject(fileSystemHandler) {
2022-02-22 20:27:13 +01:00
auto mqArgs = MqArgs(this->getObjectId());
mq = QueueFactory::instance()->createMessageQueue(FS_MAX_QUEUE_SIZE,
MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
2021-07-08 12:22:41 +02:00
}
2022-01-17 15:58:27 +01:00
FileSystemHandler::~FileSystemHandler() { QueueFactory::instance()->deleteMessageQueue(mq); }
2021-07-08 12:22:41 +02:00
ReturnValue_t FileSystemHandler::performOperation(uint8_t unsignedChar) {
2022-01-17 15:58:27 +01:00
while (true) {
try {
fileSystemHandlerLoop();
} catch (std::bad_alloc& e) {
// Restart OBSW, hints at a memory leak
sif::error << "Allocation error in FileSystemHandler::performOperation" << e.what()
<< std::endl;
// Set up an error file or a special flag in the scratch buffer for these cases
triggerEvent(CoreController::ALLOC_FAILURE, 0, 0);
CoreController::incrementAllocationFailureCount();
}
}
2021-07-12 17:23:32 +02:00
}
void FileSystemHandler::fileSystemHandlerLoop() {
2022-01-17 15:58:27 +01:00
CommandMessage filemsg;
2022-08-24 17:27:47 +02:00
ReturnValue_t result = returnvalue::OK;
2022-01-17 15:58:27 +01:00
while (true) {
if (opCounter % 5 == 0) {
if (coreCtrl->sdInitFinished()) {
fileSystemCheckup();
}
}
result = mq->receiveMessage(&filemsg);
if (result == MessageQueueIF::EMPTY) {
break;
2022-08-24 17:27:47 +02:00
} else if (result != returnvalue::FAILED) {
2022-01-17 15:58:27 +01:00
sif::warning << "FileSystemHandler::performOperation: Message reception failed!" << std::endl;
break;
}
Command_t command = filemsg.getCommand();
switch (command) {
case (GenericFileSystemMessage::CMD_CREATE_DIRECTORY): {
break;
}
case (GenericFileSystemMessage::CMD_CREATE_FILE): {
break;
}
2021-07-12 17:23:32 +02:00
}
opCounter++;
2022-01-17 15:58:27 +01:00
}
// This task will have a low priority and will run permanently in the background
// so we will just run in a permanent loop here and check file system
// messages permanently
opCounter++;
TaskFactory::instance()->delayTask(1000);
2021-07-12 17:23:32 +02:00
}
2021-07-08 12:32:24 +02:00
2021-07-12 17:23:32 +02:00
void FileSystemHandler::fileSystemCheckup() {
2022-01-17 15:58:27 +01:00
SdCardManager::SdStatePair statusPair;
2022-05-24 00:20:23 +02:00
sdcMan->getSdCardsStatus(statusPair);
sd::SdCard preferredSdCard = sdcMan->getPreferredSdCard();
2022-01-17 15:58:27 +01:00
if ((preferredSdCard == sd::SdCard::SLOT_0) and (statusPair.first == sd::SdState::MOUNTED)) {
currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
} else if ((preferredSdCard == sd::SdCard::SLOT_1) and
(statusPair.second == sd::SdState::MOUNTED)) {
currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT;
} else {
std::string sdString;
if (preferredSdCard == sd::SdCard::SLOT_0) {
sdString = "0";
} else {
sdString = "1";
}
sif::warning << "FileSystemHandler::performOperation: "
"Inconsistent state detected"
<< std::endl;
sif::warning << "Preferred SD card is " << sdString
<< " but does not appear to be mounted. Attempting fix.." << std::endl;
// This function will appear to fix the inconsistent state
ReturnValue_t result = sdcMan->sanitizeState(&statusPair, preferredSdCard);
2022-08-24 17:27:47 +02:00
if (result != returnvalue::OK) {
2022-01-17 15:58:27 +01:00
// Oh no.
triggerEvent(SdCardManager::SANITIZATION_FAILED, 0, 0);
sif::error << "FileSystemHandler::fileSystemCheckup: Sanitization failed" << std::endl;
}
}
2021-07-08 12:22:41 +02:00
}
2021-07-08 12:32:24 +02:00
2022-01-17 15:58:27 +01:00
MessageQueueId_t FileSystemHandler::getCommandQueue() const { return mq->getId(); }
2021-07-08 12:32:24 +02:00
2021-07-12 17:23:32 +02:00
ReturnValue_t FileSystemHandler::initialize() {
2022-01-17 15:58:27 +01:00
coreCtrl = ObjectManager::instance()->get<CoreController>(objects::CORE_CONTROLLER);
if (coreCtrl == nullptr) {
sif::error << "FileSystemHandler::initialize: Could not retrieve core controller handle"
<< std::endl;
}
sdcMan = SdCardManager::instance();
2022-05-24 00:20:23 +02:00
sd::SdCard preferredSdCard = sdcMan->getPreferredSdCard();
2022-01-17 15:58:27 +01:00
if (preferredSdCard == sd::SdCard::SLOT_0) {
currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT;
} else if (preferredSdCard == sd::SdCard::SLOT_1) {
currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-07-12 17:23:32 +02:00
}
2022-01-17 15:58:27 +01:00
ReturnValue_t FileSystemHandler::appendToFile(const char* repositoryPath, const char* filename,
const uint8_t* data, size_t size,
uint16_t packetNumber, FileSystemArgsIF* args) {
auto path = getInitPath(args) / repositoryPath / filename;
if (not std::filesystem::exists(path)) {
return FILE_DOES_NOT_EXIST;
}
std::ofstream file(path, std::ios_base::app | std::ios_base::out);
file.write(reinterpret_cast<const char*>(data), size);
if (not file.good()) {
return GENERIC_FILE_ERROR;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-07-08 12:32:24 +02:00
}
2022-01-17 15:58:27 +01:00
ReturnValue_t FileSystemHandler::createFile(const char* repositoryPath, const char* filename,
const uint8_t* data, size_t size,
FileSystemArgsIF* args) {
auto path = getInitPath(args) / filename;
if (std::filesystem::exists(path)) {
return FILE_ALREADY_EXISTS;
}
std::ofstream file(path);
file.write(reinterpret_cast<const char*>(data), size);
if (not file.good()) {
return GENERIC_FILE_ERROR;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-07-08 12:32:24 +02:00
}
2022-01-17 15:58:27 +01:00
ReturnValue_t FileSystemHandler::removeFile(const char* repositoryPath, const char* filename,
FileSystemArgsIF* args) {
auto path = getInitPath(args) / repositoryPath / filename;
if (not std::filesystem::exists(path)) {
return FILE_DOES_NOT_EXIST;
}
int result = std::remove(path.c_str());
if (result != 0) {
sif::warning << "FileSystemHandler::deleteFile: Failed with code " << result << std::endl;
return GENERIC_FILE_ERROR;
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-07-08 12:32:24 +02:00
}
2021-07-12 17:23:32 +02:00
2022-01-17 15:58:27 +01:00
ReturnValue_t FileSystemHandler::createDirectory(const char* repositoryPath, const char* dirname,
bool createParentDirs, FileSystemArgsIF* args) {
auto path = getInitPath(args) / repositoryPath / dirname;
if (std::filesystem::exists(path)) {
return DIRECTORY_ALREADY_EXISTS;
}
if (std::filesystem::create_directory(path)) {
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-01-17 15:58:27 +01:00
}
sif::warning << "Creating directory " << path << " failed" << std::endl;
return GENERIC_FILE_ERROR;
2021-07-12 17:23:32 +02:00
}
2021-11-19 13:22:20 +01:00
ReturnValue_t FileSystemHandler::removeDirectory(const char* repositoryPath, const char* dirname,
2022-01-17 15:58:27 +01:00
bool deleteRecurively, FileSystemArgsIF* args) {
auto path = getInitPath(args) / repositoryPath / dirname;
if (not std::filesystem::exists(path)) {
return DIRECTORY_DOES_NOT_EXIST;
}
std::error_code err;
if (not deleteRecurively) {
if (std::filesystem::remove(path, err)) {
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-01-17 15:58:27 +01:00
} else {
// Check error code. Most probably denied permissions because folder is not empty
sif::warning << "FileSystemHandler::removeDirectory: Deleting directory failed with "
"code "
<< err.value() << ": " << strerror(err.value()) << std::endl;
if (err.value() == ENOTEMPTY) {
return DIRECTORY_NOT_EMPTY;
} else {
return GENERIC_FILE_ERROR;
}
}
} else {
if (std::filesystem::remove_all(path, err)) {
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2022-01-17 15:58:27 +01:00
} else {
sif::warning << "FileSystemHandler::removeDirectory: Deleting directory failed with "
"code "
<< err.value() << ": " << strerror(err.value()) << std::endl;
// Check error code
if (err.value() == ENOTEMPTY) {
return DIRECTORY_NOT_EMPTY;
} else {
return GENERIC_FILE_ERROR;
}
}
2022-01-17 15:58:27 +01:00
}
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-07-12 17:23:32 +02:00
}
2021-07-19 14:34:03 +02:00
2022-01-17 15:58:27 +01:00
ReturnValue_t FileSystemHandler::renameFile(const char* repositoryPath, const char* oldFilename,
const char* newFilename, FileSystemArgsIF* args) {
auto basepath = getInitPath(args) / repositoryPath;
std::filesystem::rename(basepath / oldFilename, basepath / newFilename);
2022-08-24 17:27:47 +02:00
return returnvalue::OK;
2021-11-25 21:38:13 +01:00
}
2022-01-17 15:58:27 +01:00
void FileSystemHandler::parseCfg(FsCommandCfg* cfg, bool& useMountPrefix) {
if (cfg != nullptr) {
useMountPrefix = cfg->useMountPrefix;
}
2021-07-19 14:34:03 +02:00
}
2021-11-19 13:22:20 +01:00
2021-11-25 21:38:13 +01:00
std::filesystem::path FileSystemHandler::getInitPath(FileSystemArgsIF* args) {
2022-01-17 15:58:27 +01:00
bool useMountPrefix = true;
parseCfg(reinterpret_cast<FsCommandCfg*>(args), useMountPrefix);
std::string path;
if (useMountPrefix) {
path = currentMountPrefix;
}
return std::filesystem::path(path);
2021-11-19 13:22:20 +01:00
}