CHANGELOG + FS helpers
This commit is contained in:
@ -233,6 +233,67 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
||||
case (LIST_DIRECTORY_INTO_FILE): {
|
||||
return actionListDirectoryIntoFile(actionId, commandedBy, data, size);
|
||||
}
|
||||
case (LIST_DIRECTORY_DUMP_DIRECTLY): {
|
||||
return actionListDirectoryDumpDirectly(actionId, commandedBy, data, size);
|
||||
}
|
||||
case (CP_HELPER): {
|
||||
CpHelperParser parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::ostringstream oss("cp ", std::ostringstream::ate);
|
||||
if (parser.isRecursiveOptSet()) {
|
||||
oss << "-r ";
|
||||
}
|
||||
auto &sourceTgt = parser.destTgtPair();
|
||||
oss << sourceTgt.sourceName << " " << sourceTgt.targetName;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (MV_HELPER): {
|
||||
MvHelperParser parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::ostringstream oss("mv ", std::ostringstream::ate);
|
||||
auto &sourceTgt = parser.destTgtPair();
|
||||
oss << sourceTgt.sourceName << " " << sourceTgt.targetName;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (RM_HELPER): {
|
||||
RmHelperParser parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::ostringstream oss("rm ", std::ostringstream::ate);
|
||||
if (parser.isRecursiveOptSet() or parser.isForceOptSet()) {
|
||||
oss << "-";
|
||||
}
|
||||
if (parser.isRecursiveOptSet()) {
|
||||
oss << "r";
|
||||
}
|
||||
if (parser.isForceOptSet()) {
|
||||
oss << "f";
|
||||
}
|
||||
size_t removeTargetSize = 0;
|
||||
const char *removeTgt = parser.getRemoveTarget(removeTargetSize);
|
||||
oss << " " << removeTgt;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (SWITCH_REBOOT_FILE_HANDLING): {
|
||||
if (size < 1) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
@ -911,57 +972,115 @@ ReturnValue_t CoreController::initVersionFile() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
// TODO: Packet definition for clean deserialization
|
||||
// 2 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with
|
||||
// null termination, at least 7 bytes for minimum target file name /tmp/a with
|
||||
// null termination.
|
||||
if (size < 14) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
ReturnValue_t CoreController::actionListDirectoryDumpDirectly(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
core::ListDirectoryCmdBase parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// We could also make -l optional, but I can't think of a reason why to not use -l..
|
||||
|
||||
// This flag specifies to run ls with -a
|
||||
bool aFlag = data[0];
|
||||
data += 1;
|
||||
// This flag specifies to run ls with -R
|
||||
bool RFlag = data[1];
|
||||
data += 1;
|
||||
|
||||
size_t remainingSize = size - 2;
|
||||
// One larger for null termination, which prevents undefined behaviour if the sent
|
||||
// strings are not 0 terminated properly
|
||||
std::vector<uint8_t> repoAndTargetFileBuffer(remainingSize + 1, 0);
|
||||
std::memcpy(repoAndTargetFileBuffer.data(), data, remainingSize);
|
||||
const char *currentCharPtr = reinterpret_cast<const char *>(repoAndTargetFileBuffer.data());
|
||||
// Full target file name
|
||||
std::string repoName(currentCharPtr);
|
||||
size_t repoLength = repoName.length();
|
||||
// The other string needs to be at least one letter plus NULL termination to be valid at all
|
||||
// The first string also needs to be NULL terminated, but the termination is not included
|
||||
// in the string length, so this is subtracted from the remaining size as well
|
||||
if (repoLength > remainingSize - 3) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
// The file length will not include the NULL termination, so we skip it
|
||||
currentCharPtr += repoLength + 1;
|
||||
std::string targetFileName(currentCharPtr);
|
||||
std::ostringstream oss;
|
||||
std::ostringstream oss("ls -l", std::ostringstream::ate);
|
||||
oss << "ls -l";
|
||||
if (aFlag) {
|
||||
if (parser.aFlagSet()) {
|
||||
oss << "a";
|
||||
}
|
||||
if (RFlag) {
|
||||
if (parser.rFlagSet()) {
|
||||
oss << "R";
|
||||
}
|
||||
|
||||
size_t repoNameLen = 0;
|
||||
const char *repoName = parser.getRepoName(repoNameLen);
|
||||
|
||||
oss << " " << repoName << " > " << LIST_DIR_DUMP_WORK_FILE;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryDumpDirectly");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (parser.compressionOptionSet()) {
|
||||
std::string compressedName = LIST_DIR_DUMP_WORK_FILE + std::string(".tar.xz");
|
||||
oss.str("");
|
||||
oss << "tar -cJvf /tmp/dir_listing_compressed.tmp " << LIST_DIR_DUMP_WORK_FILE;
|
||||
ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryDumpDirectly");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
oss.str("");
|
||||
// Overwrite the old work file with the compressed archive.
|
||||
oss << "mv /tmp/dir_listing_compressed.tmp " << LIST_DIR_DUMP_WORK_FILE;
|
||||
ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryDumpDirectly");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
std::array<uint8_t, 1024> dirListingBuf{};
|
||||
std::ifstream ifile("/tmp/dir_listing.tmp", std::ios::binary);
|
||||
std::error_code e;
|
||||
size_t totalFileSize = std::filesystem::file_size(LIST_DIR_DUMP_WORK_FILE, e);
|
||||
size_t dumpedBytes = 0;
|
||||
size_t nextDumpLen = 0;
|
||||
while (dumpedBytes < totalFileSize) {
|
||||
nextDumpLen = 1024;
|
||||
if (totalFileSize - dumpedBytes < 1024) {
|
||||
nextDumpLen = totalFileSize - dumpedBytes;
|
||||
}
|
||||
ifile.read(reinterpret_cast<char *>(dirListingBuf.data()), nextDumpLen);
|
||||
result = actionHelper.reportData(commandedBy, actionId, dirListingBuf.data(), nextDumpLen);
|
||||
if (result != returnvalue::OK) {
|
||||
// Remove work file when we are done
|
||||
std::filesystem::remove(LIST_DIR_DUMP_WORK_FILE, e);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// Remove work file when we are done
|
||||
std::filesystem::remove(LIST_DIR_DUMP_WORK_FILE, e);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
core::ListDirectoryIntoFile parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostringstream oss("ls -l", std::ostringstream::ate);
|
||||
oss << "ls -l";
|
||||
if (parser.aFlagSet()) {
|
||||
oss << "a";
|
||||
}
|
||||
if (parser.rFlagSet()) {
|
||||
oss << "R";
|
||||
}
|
||||
|
||||
size_t repoNameLen = 0;
|
||||
const char *repoName = parser.getRepoName(repoNameLen);
|
||||
size_t targetFileNameLen = 0;
|
||||
const char *targetFileName = parser.getTargetName(targetFileNameLen);
|
||||
oss << " " << repoName << " > " << targetFileName;
|
||||
int result = std::system(oss.str().c_str());
|
||||
if (result != 0) {
|
||||
sif::info << "Executing list directory request, command: " << oss.str() << std::endl;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryIntoFile");
|
||||
actionHelper.finish(false, commandedBy, actionId);
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
if (parser.compressionOptionSet()) {
|
||||
std::string compressedName = targetFileName + std::string(".tar.xz");
|
||||
oss.str("");
|
||||
oss << "tar -cJvf " << compressedName << " " << targetFileName;
|
||||
sif::info << "Compressing directory listing: " << oss.str() << std::endl;
|
||||
ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryIntoFile");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
Reference in New Issue
Block a user