#include "config.h" #include "download_manager.hpp" #include "xyz/openbmc_project/Common/error.hpp" #include #include #include #include #include #include #include #include #include #include namespace phosphor { namespace software { namespace manager { using namespace sdbusplus::error::xyz::openbmc_project::common; PHOSPHOR_LOG2_USING; using namespace phosphor::logging; namespace fs = std::filesystem; void Download::downloadViaTFTP(std::string fileName, std::string serverAddress) { using Argument = xyz::openbmc_project::common::InvalidArgument; // Sanitize the fileName string if (!fileName.empty()) { fileName.erase(std::remove(fileName.begin(), fileName.end(), '/'), fileName.end()); fileName = fileName.substr(fileName.find_first_not_of('.')); } if (fileName.empty()) { error("Filename is empty"); elog(Argument::ARGUMENT_NAME("FileName"), Argument::ARGUMENT_VALUE(fileName.c_str())); return; } if (serverAddress.empty()) { error("ServerAddress is empty"); elog(Argument::ARGUMENT_NAME("ServerAddress"), Argument::ARGUMENT_VALUE(serverAddress.c_str())); return; } info("Downloading {PATH} via TFTP: {SERVERADDRESS}", "PATH", fileName, "SERVERADDRESS", serverAddress); // Check if IMAGE DIR exists fs::path imgDirPath(IMG_UPLOAD_DIR); std::error_code ec; if (!fs::is_directory(imgDirPath, ec)) { error("Image Dir {PATH} does not exist: {ERROR_MSG}", "PATH", imgDirPath, "ERROR_MSG", ec.message()); elog(); return; } pid_t pid = fork(); if (pid == 0) { pid_t nextPid = fork(); if (nextPid == 0) { // child process execl("/usr/bin/tftp", "tftp", "-g", "-r", fileName.c_str(), serverAddress.c_str(), "-l", (std::string{IMG_UPLOAD_DIR} + '/' + fileName).c_str(), (char*)0); // execl only returns on fail error("Error ({ERRNO}) occurred during the TFTP call", "ERRNO", errno); elog(); } else if (nextPid < 0) { error("Error ({ERRNO}) occurred during fork", "ERRNO", errno); elog(); } // do nothing as parent if all is going well // when parent exits, child will be reparented under init // and then be reaped properly exit(0); } else if (pid < 0) { error("Error ({ERRNO}) occurred during fork", "ERRNO", errno); elog(); } else { int status; if (waitpid(pid, &status, 0) < 0) { error("Error ({ERRNO}) occurred during waitpid", "ERRNO", errno); } else if (WEXITSTATUS(status) != 0) { error("Failed ({STATUS}) to launch tftp", "STATUS", status); } } return; } } // namespace manager } // namespace software } // namespace phosphor