1 #include "config.h" 2 3 #include "serialize.hpp" 4 5 #include <cereal/archives/json.hpp> 6 #include <experimental/filesystem> 7 #include <fstream> 8 #include <phosphor-logging/log.hpp> 9 #include <sdbusplus/server.hpp> 10 11 namespace phosphor 12 { 13 namespace software 14 { 15 namespace updater 16 { 17 18 using namespace phosphor::logging; 19 namespace fs = std::experimental::filesystem; 20 21 const std::string priorityName = "priority"; 22 const std::string purposeName = "purpose"; 23 24 void storePriority(const std::string& versionId, uint8_t priority) 25 { 26 auto path = fs::path(PERSIST_DIR) / versionId; 27 if (!fs::is_directory(path)) 28 { 29 if (fs::exists(path)) 30 { 31 // Delete if it's a non-directory file 32 log<level::WARNING>("Removing non-directory file", 33 entry("PATH=%s", path.c_str())); 34 fs::remove_all(path); 35 } 36 fs::create_directories(path); 37 } 38 path = path / priorityName; 39 40 std::ofstream os(path.c_str()); 41 cereal::JSONOutputArchive oarchive(os); 42 oarchive(cereal::make_nvp(priorityName, priority)); 43 } 44 45 void storePurpose(const std::string& versionId, VersionPurpose purpose) 46 { 47 auto path = fs::path(PERSIST_DIR) / versionId; 48 if (!fs::is_directory(path)) 49 { 50 if (fs::exists(path)) 51 { 52 // Delete if it's a non-directory file 53 log<level::WARNING>("Removing non-directory file", 54 entry("PATH=%s", path.c_str())); 55 fs::remove_all(path); 56 } 57 fs::create_directories(path); 58 } 59 path = path / purposeName; 60 61 std::ofstream os(path.c_str()); 62 cereal::JSONOutputArchive oarchive(os); 63 oarchive(cereal::make_nvp(purposeName, purpose)); 64 } 65 66 bool restorePriority(const std::string& versionId, uint8_t& priority) 67 { 68 auto path = fs::path(PERSIST_DIR) / versionId / priorityName; 69 if (fs::exists(path)) 70 { 71 std::ifstream is(path.c_str(), std::ios::in); 72 try 73 { 74 cereal::JSONInputArchive iarchive(is); 75 iarchive(cereal::make_nvp(priorityName, priority)); 76 return true; 77 } 78 catch (cereal::Exception& e) 79 { 80 fs::remove_all(path); 81 } 82 } 83 84 // Find the mtd device "u-boot-env" to retrieve the environment variables 85 std::ifstream mtdDevices("/proc/mtd"); 86 std::string device, devicePath; 87 88 try 89 { 90 while (std::getline(mtdDevices, device)) 91 { 92 if (device.find("u-boot-env") != std::string::npos) 93 { 94 devicePath = "/dev/" + device.substr(0, device.find(':')); 95 break; 96 } 97 } 98 99 if (!devicePath.empty()) 100 { 101 std::ifstream input(devicePath.c_str()); 102 std::string envVars; 103 std::getline(input, envVars); 104 105 std::string versionVar = versionId + "="; 106 auto varPosition = envVars.find(versionVar); 107 108 if (varPosition != std::string::npos) 109 { 110 // Grab the environment variable for this versionId. These 111 // variables follow the format "versionId=priority\0" 112 auto var = envVars.substr(varPosition); 113 priority = std::stoi(var.substr(versionVar.length())); 114 return true; 115 } 116 } 117 } 118 catch (const std::exception& e) 119 { 120 } 121 122 return false; 123 } 124 125 bool restorePurpose(const std::string& versionId, VersionPurpose& purpose) 126 { 127 auto path = fs::path(PERSIST_DIR) / versionId / purposeName; 128 if (fs::exists(path)) 129 { 130 std::ifstream is(path.c_str(), std::ios::in); 131 try 132 { 133 cereal::JSONInputArchive iarchive(is); 134 iarchive(cereal::make_nvp(purposeName, purpose)); 135 return true; 136 } 137 catch (cereal::Exception& e) 138 { 139 fs::remove_all(path); 140 } 141 } 142 143 return false; 144 } 145 146 void removePersistDataDirectory(const std::string& versionId) 147 { 148 auto path = fs::path(PERSIST_DIR) / versionId; 149 if (fs::exists(path)) 150 { 151 fs::remove_all(path); 152 } 153 } 154 155 } // namespace updater 156 } // namespace software 157 } // namespace phosphor 158