| #include "config.h" | 
 |  | 
 | #include "serialize.hpp" | 
 |  | 
 | #include <cereal/archives/json.hpp> | 
 | #include <phosphor-logging/log.hpp> | 
 | #include <sdbusplus/server.hpp> | 
 |  | 
 | #include <filesystem> | 
 | #include <fstream> | 
 |  | 
 | namespace phosphor | 
 | { | 
 | namespace software | 
 | { | 
 | namespace updater | 
 | { | 
 |  | 
 | using namespace phosphor::logging; | 
 | namespace fs = std::filesystem; | 
 |  | 
 | const std::string priorityName = "priority"; | 
 | const std::string purposeName = "purpose"; | 
 |  | 
 | void storePriority(const std::string& versionId, uint8_t priority) | 
 | { | 
 |     auto path = fs::path(PERSIST_DIR) / versionId; | 
 |     if (!fs::is_directory(path)) | 
 |     { | 
 |         if (fs::exists(path)) | 
 |         { | 
 |             // Delete if it's a non-directory file | 
 |             log<level::WARNING>("Removing non-directory file", | 
 |                                 entry("PATH=%s", path.c_str())); | 
 |             fs::remove_all(path); | 
 |         } | 
 |         fs::create_directories(path); | 
 |     } | 
 |     path = path / priorityName; | 
 |  | 
 |     std::ofstream os(path.c_str()); | 
 |     cereal::JSONOutputArchive oarchive(os); | 
 |     oarchive(cereal::make_nvp(priorityName, priority)); | 
 | } | 
 |  | 
 | void storePurpose(const std::string& versionId, VersionPurpose purpose) | 
 | { | 
 |     auto path = fs::path(PERSIST_DIR) / versionId; | 
 |     if (!fs::is_directory(path)) | 
 |     { | 
 |         if (fs::exists(path)) | 
 |         { | 
 |             // Delete if it's a non-directory file | 
 |             log<level::WARNING>("Removing non-directory file", | 
 |                                 entry("PATH=%s", path.c_str())); | 
 |             fs::remove_all(path); | 
 |         } | 
 |         fs::create_directories(path); | 
 |     } | 
 |     path = path / purposeName; | 
 |  | 
 |     std::ofstream os(path.c_str()); | 
 |     cereal::JSONOutputArchive oarchive(os); | 
 |     oarchive(cereal::make_nvp(purposeName, purpose)); | 
 | } | 
 |  | 
 | bool restorePriority(const std::string& versionId, uint8_t& priority) | 
 | { | 
 |     auto path = fs::path(PERSIST_DIR) / versionId / priorityName; | 
 |     if (fs::exists(path)) | 
 |     { | 
 |         std::ifstream is(path.c_str(), std::ios::in); | 
 |         try | 
 |         { | 
 |             cereal::JSONInputArchive iarchive(is); | 
 |             iarchive(cereal::make_nvp(priorityName, priority)); | 
 |             return true; | 
 |         } | 
 |         catch (cereal::Exception& e) | 
 |         { | 
 |             fs::remove_all(path); | 
 |         } | 
 |     } | 
 |  | 
 |     // Find the mtd device "u-boot-env" to retrieve the environment variables | 
 |     std::ifstream mtdDevices("/proc/mtd"); | 
 |     std::string device, devicePath; | 
 |  | 
 |     try | 
 |     { | 
 |         while (std::getline(mtdDevices, device)) | 
 |         { | 
 |             if (device.find("u-boot-env") != std::string::npos) | 
 |             { | 
 |                 devicePath = "/dev/" + device.substr(0, device.find(':')); | 
 |                 break; | 
 |             } | 
 |         } | 
 |  | 
 |         if (!devicePath.empty()) | 
 |         { | 
 |             std::ifstream input(devicePath.c_str()); | 
 |             std::string envVars; | 
 |             std::getline(input, envVars); | 
 |  | 
 |             std::string versionVar = versionId + "="; | 
 |             auto varPosition = envVars.find(versionVar); | 
 |  | 
 |             if (varPosition != std::string::npos) | 
 |             { | 
 |                 // Grab the environment variable for this versionId. These | 
 |                 // variables follow the format "versionId=priority\0" | 
 |                 auto var = envVars.substr(varPosition); | 
 |                 priority = std::stoi(var.substr(versionVar.length())); | 
 |                 return true; | 
 |             } | 
 |         } | 
 |     } | 
 |     catch (const std::exception& e) | 
 |     {} | 
 |  | 
 |     return false; | 
 | } | 
 |  | 
 | bool restorePurpose(const std::string& versionId, VersionPurpose& purpose) | 
 | { | 
 |     auto path = fs::path(PERSIST_DIR) / versionId / purposeName; | 
 |     if (fs::exists(path)) | 
 |     { | 
 |         std::ifstream is(path.c_str(), std::ios::in); | 
 |         try | 
 |         { | 
 |             cereal::JSONInputArchive iarchive(is); | 
 |             iarchive(cereal::make_nvp(purposeName, purpose)); | 
 |             return true; | 
 |         } | 
 |         catch (cereal::Exception& e) | 
 |         { | 
 |             fs::remove_all(path); | 
 |         } | 
 |     } | 
 |  | 
 |     return false; | 
 | } | 
 |  | 
 | void removePersistDataDirectory(const std::string& versionId) | 
 | { | 
 |     auto path = fs::path(PERSIST_DIR) / versionId; | 
 |     if (fs::exists(path)) | 
 |     { | 
 |         fs::remove_all(path); | 
 |     } | 
 | } | 
 |  | 
 | } // namespace updater | 
 | } // namespace software | 
 | } // namespace phosphor |