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