#include "FileSystemHandler.h" #include "fsfw/tasks/TaskFactory.h" #include "fsfw/memory/GenericFileSystemMessage.h" #include "fsfw/ipc/QueueFactory.h" #include FileSystemHandler::FileSystemHandler(object_id_t fileSystemHandler): SystemObject(fileSystemHandler) { mq = QueueFactory::instance()->createMessageQueue(FS_MAX_QUEUE_SIZE); } FileSystemHandler::~FileSystemHandler() { QueueFactory::instance()->deleteMessageQueue(mq); } ReturnValue_t FileSystemHandler::performOperation(uint8_t unsignedChar) { 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; // TODO: If we trigger an event, it might not get sent because were restarting // Set up an error file or a special flag in the scratch buffer. // TODO: CoreController: Implement function to restart OBC } } } void FileSystemHandler::fileSystemHandlerLoop() { CommandMessage filemsg; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; while(true) { if(opCounter % 5 == 0) { fileSystemCheckup(); } result = mq->receiveMessage(&filemsg); if(result == MessageQueueIF::EMPTY) { break; } else if(result != HasReturnvaluesIF::RETURN_FAILED) { 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; } } opCounter++; } // 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 TaskFactory::instance()->delayTask(1000); } void FileSystemHandler::fileSystemCheckup() { SdCardManager::SdStatusPair statusPair; sdcMan->getSdCardActiveStatus(statusPair); sd::SdCard preferredSdCard; sdcMan->getPreferredSdCard(preferredSdCard); if((preferredSdCard == sd::SdCard::SLOT_0) and (statusPair.first == sd::SdStatus::MOUNTED)) { currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; } if((preferredSdCard == sd::SdCard::SLOT_1) and (statusPair.second == sd::SdStatus::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. 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); if(result != HasReturnvaluesIF::RETURN_OK) { // Oh no. // TODO: Trigger medium severity event sif::error << "Fix failed" << std::endl; } } } MessageQueueId_t FileSystemHandler::getCommandQueue() const { return mq->getId(); } ReturnValue_t FileSystemHandler::initialize() { sdcMan = SdCardManager::instance(); sd::SdCard preferredSdCard; ReturnValue_t result = sdcMan->getPreferredSdCard(preferredSdCard); if(result != HasReturnvaluesIF::RETURN_OK) { return result; } 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; } return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t FileSystemHandler::appendToFile(const char *repositoryPath, const char *filename, const uint8_t *data, size_t size, uint16_t packetNumber, void *args) { // A double slash between repo and filename should not be an issue, so add it in any case std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + std::string(filename); return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t FileSystemHandler::createFile(const char *repositoryPath, const char *filename, const uint8_t *data, size_t size, void *args) { // A double slash between repo and filename should not be an issue, so add it in any case std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + std::string(filename); return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t FileSystemHandler::deleteFile(const char *repositoryPath, const char *filename, void *args) { // A double slash between repo and filename should not be an issue, so add it in any case std::string fullPath = currentMountPrefix + std::string(repositoryPath) + "/" + std::string(filename); return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t FileSystemHandler::createDirectory(const char *repositoryPath, void *args) { std::string fullPath = currentMountPrefix + std::string(repositoryPath); if(std::filesystem::exists(fullPath)) { return DIRECTORY_ALREADY_EXISTS; } if(std::filesystem::create_directory(fullPath)) { return HasReturnvaluesIF::RETURN_OK; } sif::warning << "Creating directory " << fullPath << " failed" << std::endl; return GENERIC_FILE_ERROR; } ReturnValue_t FileSystemHandler::removeDirectory(const char *repositoryPath, bool deleteRecurively, void *args) { std::string fullPath = currentMountPrefix + std::string(repositoryPath); if(not std::filesystem::exists(fullPath)) { return DIRECTORY_DOES_NOT_EXIST; } std::error_code err; if(not deleteRecurively) { if(std::filesystem::remove(fullPath, err)) { return HasReturnvaluesIF::RETURN_OK; } else { // Check error code. Most probably denied permissions because folder is not empty } } else { if(std::filesystem::remove_all(fullPath, err)) { return HasReturnvaluesIF::RETURN_OK; } else { // Check error code } } return HasReturnvaluesIF::RETURN_OK; }