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