1 #include "version.hpp" 2 3 #include "item_updater.hpp" 4 #include "xyz/openbmc_project/Common/error.hpp" 5 6 #include <openssl/sha.h> 7 8 #include <fstream> 9 #include <iostream> 10 #include <phosphor-logging/elog-errors.hpp> 11 #include <phosphor-logging/log.hpp> 12 #include <sstream> 13 #include <stdexcept> 14 #include <string> 15 16 namespace openpower 17 { 18 namespace software 19 { 20 namespace updater 21 { 22 23 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 24 using namespace phosphor::logging; 25 using Argument = xyz::openbmc_project::Common::InvalidArgument; 26 27 std::string Version::getId(const std::string& version) 28 { 29 30 if (version.empty()) 31 { 32 log<level::ERR>("Error version is empty"); 33 return {}; 34 } 35 36 unsigned char digest[SHA512_DIGEST_LENGTH]; 37 SHA512_CTX ctx; 38 SHA512_Init(&ctx); 39 SHA512_Update(&ctx, version.c_str(), strlen(version.c_str())); 40 SHA512_Final(digest, &ctx); 41 char mdString[SHA512_DIGEST_LENGTH * 2 + 1]; 42 for (int i = 0; i < SHA512_DIGEST_LENGTH; i++) 43 { 44 snprintf(&mdString[i * 2], 3, "%02x", (unsigned int)digest[i]); 45 } 46 47 // Only need 8 hex digits. 48 std::string hexId = std::string(mdString); 49 return (hexId.substr(0, 8)); 50 } 51 52 std::map<std::string, std::string> 53 Version::getValue(const std::string& filePath, 54 std::map<std::string, std::string> keys) 55 { 56 if (filePath.empty()) 57 { 58 log<level::ERR>("Error filePath is empty"); 59 elog<InvalidArgument>(Argument::ARGUMENT_NAME("FilePath"), 60 Argument::ARGUMENT_VALUE(filePath.c_str())); 61 } 62 63 std::ifstream efile; 64 std::string line; 65 efile.exceptions(std::ifstream::failbit | std::ifstream::badbit | 66 std::ifstream::eofbit); 67 68 try 69 { 70 efile.open(filePath); 71 while (getline(efile, line)) 72 { 73 for (auto& key : keys) 74 { 75 auto value = key.first + "="; 76 auto keySize = value.length(); 77 if (line.compare(0, keySize, value) == 0) 78 { 79 key.second = line.substr(keySize); 80 break; 81 } 82 } 83 } 84 efile.close(); 85 } 86 catch (const std::exception& e) 87 { 88 if (!efile.eof()) 89 { 90 log<level::ERR>("Error in reading file"); 91 } 92 efile.close(); 93 } 94 95 return keys; 96 } 97 98 std::pair<std::string, std::string> 99 Version::getVersions(const std::string& versionPart) 100 { 101 // versionPart contains strings like below: 102 // open-power-romulus-v2.2-rc1-48-g268344f-dirty 103 // buildroot-2018.11.1-7-g5d7cc8c 104 // skiboot-v6.2 105 std::istringstream iss(versionPart); 106 std::string line; 107 std::string version; 108 std::stringstream ss; 109 std::string extendedVersion; 110 111 if (!std::getline(iss, line)) 112 { 113 log<level::ERR>("Unable to read from version", 114 entry("VERSION=%s", versionPart.c_str())); 115 return {}; 116 } 117 version = line; 118 119 while (std::getline(iss, line)) 120 { 121 // Each line starts with a tab, let's trim it 122 line.erase(line.begin(), 123 std::find_if(line.begin(), line.end(), 124 [](int c) { return !std::isspace(c); })); 125 ss << line << ','; 126 } 127 extendedVersion = ss.str(); 128 129 // Erase the last ',', if there is one 130 if (!extendedVersion.empty()) 131 { 132 extendedVersion.pop_back(); 133 } 134 return {version, extendedVersion}; 135 } 136 137 void Delete::delete_() 138 { 139 if (parent.eraseCallback) 140 { 141 parent.eraseCallback(parent.getId(parent.version())); 142 } 143 } 144 145 void Version::updateDeleteInterface(sdbusplus::message::message& msg) 146 { 147 std::string interface, chassisState; 148 std::map<std::string, std::variant<std::string>> properties; 149 150 msg.read(interface, properties); 151 152 for (const auto& p : properties) 153 { 154 if (p.first == "CurrentPowerState") 155 { 156 chassisState = std::get<std::string>(p.second); 157 } 158 } 159 if (chassisState.empty()) 160 { 161 // The chassis power state property did not change, return. 162 return; 163 } 164 165 if ((parent.isVersionFunctional(this->versionId)) && 166 (chassisState != CHASSIS_STATE_OFF)) 167 { 168 if (deleteObject) 169 { 170 deleteObject.reset(nullptr); 171 } 172 } 173 else 174 { 175 if (!deleteObject) 176 { 177 deleteObject = std::make_unique<Delete>(bus, objPath, *this); 178 } 179 } 180 } 181 182 } // namespace updater 183 } // namespace software 184 } // namespace openpower 185