allow dest handler to handle folder destinations

This commit is contained in:
Robin Müller 2023-02-24 16:49:23 +01:00
parent f0415a97b1
commit 893b434728
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
7 changed files with 81 additions and 20 deletions

View File

@ -281,12 +281,10 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
} }
ReturnValue_t result = OK; ReturnValue_t result = OK;
size_t sourceNameSize = 0; size_t sourceNameSize = 0;
const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize); const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
if (sourceNameSize + 1 > tp.sourceName.size()) { if (sourceNameSize + 1 > tp.sourceName.size()) {
fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR, 0, 0); fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: source filename too large" << std::endl;
#endif
return FAILED; return FAILED;
} }
std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize); std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize);
@ -294,10 +292,7 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
size_t destNameSize = 0; size_t destNameSize = 0;
const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize); const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
if (destNameSize + 1 > tp.destName.size()) { if (destNameSize + 1 > tp.destName.size()) {
fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR, 0, 0); fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: dest filename too large" << std::endl;
#endif
return FAILED; return FAILED;
} }
std::memcpy(tp.destName.data(), destNamePtr, destNameSize); std::memcpy(tp.destName.data(), destNamePtr, destNameSize);
@ -307,27 +302,25 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
// so there is no need to create a file or truncate an existing file // so there is no need to create a file or truncate an existing file
if (destNameSize > 0 and sourceNameSize > 0) { if (destNameSize > 0 and sourceNameSize > 0) {
FilesystemParams fparams(tp.destName.data()); FilesystemParams fparams(tp.destName.data());
// handling to allow only specifying target directory. Example:
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
if (dp.user.vfs.isDirectory(tp.destName.data())) {
result = tryBuildingAbsoluteDestName(destNameSize);
if (result != OK) {
return result;
}
}
if (dp.user.vfs.fileExists(fparams)) { if (dp.user.vfs.fileExists(fparams)) {
result = dp.user.vfs.truncateFile(fparams); result = dp.user.vfs.truncateFile(fparams);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
// TODO: Provide execution step as parameter fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast<uint8_t>(fsmRes.step),
result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: file truncation error with code " << result
<< std::endl;
#endif
return FAILED; return FAILED;
// TODO: Relevant for filestore rejection error? // TODO: Relevant for filestore rejection error?
} }
} else { } else {
result = dp.user.vfs.createFile(fparams); result = dp.user.vfs.createFile(fparams);
if (result != OK) { if (result != OK) {
fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast<uint8_t>(fsmRes.step), fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: file creation error with code " << result << std::endl;
#endif
return FAILED; return FAILED;
// TODO: Relevant for filestore rejection error? // TODO: Relevant for filestore rejection error?
} }
@ -394,6 +387,37 @@ ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
return OK; return OK;
} }
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
char baseNameBuf[tp.destName.size()]{};
FilesystemParams fparamsSrc(tp.sourceName.data());
size_t baseNameLen = 0;
ReturnValue_t result =
dp.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf, sizeof(baseNameBuf), baseNameLen);
if (result != returnvalue::OK or baseNameLen == 0) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
return FAILED;
}
// Destination name + slash + base name + null termination
if (destNameSize + 1 + baseNameLen + 1 > tp.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
"dest filename too large after adding source base name");
return FAILED;
}
tp.destName[destNameSize++] = '/';
std::memcpy(tp.destName.data() + destNameSize, baseNameBuf, baseNameLen);
destNameSize += baseNameLen;
tp.destName[destNameSize++] = '\0';
return OK;
}
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) {
fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR,
static_cast<uint8_t>(fsmRes.step), result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: " << info << std::endl;
#endif
}
void cfdp::DestHandler::finish() { void cfdp::DestHandler::finish() {
tp.reset(); tp.reset();
dp.packetListRef.clear(); dp.packetListRef.clear();

View File

@ -191,9 +191,11 @@ class DestHandler {
ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData, ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData,
size_t maxSize); size_t maxSize);
ReturnValue_t handleTransferCompletion(); ReturnValue_t handleTransferCompletion();
ReturnValue_t tryBuildingAbsoluteDestName(size_t destNameSize);
ReturnValue_t sendFinishedPdu(); ReturnValue_t sendFinishedPdu();
ReturnValue_t noticeOfCompletion(); ReturnValue_t noticeOfCompletion();
ReturnValue_t checksumVerification(); ReturnValue_t checksumVerification();
void fileErrorHandler(Event event, ReturnValue_t result, const char* info);
const FsmResult& updateFsmRes(uint8_t errors); const FsmResult& updateFsmRes(uint8_t errors);
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx); void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
void finish(); void finish();

View File

@ -74,6 +74,12 @@ class HasFileSystemIF {
return MessageQueueIF::NO_QUEUE; return MessageQueueIF::NO_QUEUE;
} }
// Get the base filename without the full directory path
virtual ReturnValue_t getBaseFilename(FilesystemParams params, char* nameBuf, size_t maxLen,
size_t& baseNameLen) = 0;
virtual bool isDirectory(const char* path) = 0;
virtual bool fileExists(FilesystemParams params) = 0; virtual bool fileExists(FilesystemParams params) = 0;
/** /**

View File

@ -160,3 +160,18 @@ ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) {
ofstream of(path); ofstream of(path);
return returnvalue::OK; return returnvalue::OK;
} }
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;
}

View File

@ -9,6 +9,9 @@ class HostFilesystem : public HasFileSystemIF {
public: public:
HostFilesystem(); HostFilesystem();
ReturnValue_t getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
size_t &baseNameLen) override;
bool isDirectory(const char *path) override;
bool fileExists(FilesystemParams params) override; bool fileExists(FilesystemParams params) override;
ReturnValue_t truncateFile(FilesystemParams params) override; ReturnValue_t truncateFile(FilesystemParams params) override;
ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override; ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override;

View File

@ -138,3 +138,10 @@ ReturnValue_t FilesystemMock::truncateFile(FilesystemParams params) {
truncateCalledOnFile = params.path; truncateCalledOnFile = params.path;
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t FilesystemMock::getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
size_t &baseNameLen) {
return returnvalue::OK;
}
bool FilesystemMock::isDirectory(const char *path) { return false; }

View File

@ -56,6 +56,10 @@ class FilesystemMock : public HasFileSystemIF {
std::string truncateCalledOnFile; std::string truncateCalledOnFile;
ReturnValue_t feedFile(const std::string &filename, std::ifstream &file); ReturnValue_t feedFile(const std::string &filename, std::ifstream &file);
ReturnValue_t getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
size_t &baseNameLen) override;
bool isDirectory(const char *path) override;
bool fileExists(FilesystemParams params) override; bool fileExists(FilesystemParams params) override;
ReturnValue_t truncateFile(FilesystemParams params) override; ReturnValue_t truncateFile(FilesystemParams params) override;