#include "config.h" #include "version.hpp" #include "xyz/openbmc_project/Common/error.hpp" #include #include #include #include #include #include #include #include namespace phosphor { namespace software { namespace manager { using namespace phosphor::logging; using Argument = xyz::openbmc_project::Common::InvalidArgument; using namespace sdbusplus::xyz::openbmc_project::Common::Error; std::string Version::getValue(const std::string& manifestFilePath, std::string key) { key = key + "="; auto keySize = key.length(); if (manifestFilePath.empty()) { log("Error MANIFESTFilePath is empty"); elog( Argument::ARGUMENT_NAME("manifestFilePath"), Argument::ARGUMENT_VALUE(manifestFilePath.c_str())); } std::string value{}; std::ifstream efile; std::string line; efile.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); // Too many GCC bugs (53984, 66145) to do this the right way... try { efile.open(manifestFilePath); while (getline(efile, line)) { if (line.compare(0, keySize, key) == 0) { value = line.substr(keySize); break; } } efile.close(); } catch (const std::exception& e) { log("Error in reading MANIFEST file"); } return value; } std::string Version::getId(const std::string& version) { if (version.empty()) { log("Error version is empty"); elog(Argument::ARGUMENT_NAME("Version"), Argument::ARGUMENT_VALUE(version.c_str())); } unsigned char digest[SHA512_DIGEST_LENGTH]; SHA512_CTX ctx; SHA512_Init(&ctx); SHA512_Update(&ctx, version.c_str(), strlen(version.c_str())); SHA512_Final(digest, &ctx); char mdString[SHA512_DIGEST_LENGTH * 2 + 1]; for (int i = 0; i < SHA512_DIGEST_LENGTH; i++) { snprintf(&mdString[i * 2], 3, "%02x", (unsigned int)digest[i]); } // Only need 8 hex digits. std::string hexId = std::string(mdString); return (hexId.substr(0, 8)); } std::string Version::getBMCVersion(const std::string& releaseFilePath) { std::string versionKey = "VERSION_ID="; std::string version{}; std::ifstream efile; std::string line; efile.open(releaseFilePath); while (getline(efile, line)) { if (line.substr(0, versionKey.size()).find(versionKey) != std::string::npos) { std::size_t pos = line.find_first_of('"') + 1; version = line.substr(pos, line.find_last_of('"') - pos); break; } } efile.close(); if (version.empty()) { log("Error BMC current version is empty"); elog(); } return version; } bool Version::isFunctional() { return versionStr == getBMCVersion(OS_RELEASE_FILE); } void Delete::delete_() { if (parent.eraseCallback) { parent.eraseCallback(parent.getId(parent.version())); } } } // namespace manager } // namespace software } // namespace phosphor