1 #include <iostream>
2 #include <string>
3 #include <sstream>
4 #include <fstream>
5 #include <stdexcept>
6 #include <phosphor-logging/log.hpp>
7 #include "version.hpp"
8 #include <phosphor-logging/elog-errors.hpp>
9 #include "xyz/openbmc_project/Common/error.hpp"
10 #include "item_updater.hpp"
11 #include <openssl/sha.h>
12 
13 namespace openpower
14 {
15 namespace software
16 {
17 namespace updater
18 {
19 
20 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
21 using namespace phosphor::logging;
22 using Argument = xyz::openbmc_project::Common::InvalidArgument;
23 
24 std::string Version::getId(const std::string& version)
25 {
26 
27     if (version.empty())
28     {
29         log<level::ERR>("Error version is empty");
30         elog<InvalidArgument>(Argument::ARGUMENT_NAME("Version"),
31                               Argument::ARGUMENT_VALUE(version.c_str()));
32     }
33 
34     unsigned char digest[SHA512_DIGEST_LENGTH];
35     SHA512_CTX ctx;
36     SHA512_Init(&ctx);
37     SHA512_Update(&ctx, version.c_str(), strlen(version.c_str()));
38     SHA512_Final(digest, &ctx);
39     char mdString[SHA512_DIGEST_LENGTH*2+1];
40     for (int i = 0; i < SHA512_DIGEST_LENGTH; i++)
41     {
42         snprintf(&mdString[i*2], 3, "%02x", (unsigned int)digest[i]);
43     }
44 
45     // Only need 8 hex digits.
46     std::string hexId = std::string(mdString);
47     return (hexId.substr(0, 8));
48 }
49 
50 std::map<std::string, std::string> Version::getValue(
51         const std::string& filePath, std::map<std::string, std::string> keys)
52 {
53     if (filePath.empty())
54     {
55         log<level::ERR>("Error filePath is empty");
56         elog<InvalidArgument>(Argument::ARGUMENT_NAME("FilePath"),
57                               Argument::ARGUMENT_VALUE(filePath.c_str()));
58     }
59 
60     std::ifstream efile;
61     std::string line;
62     efile.exceptions(std::ifstream::failbit |
63                      std::ifstream::badbit |
64                      std::ifstream::eofbit);
65 
66     try
67     {
68         efile.open(filePath);
69         while (getline(efile, line))
70         {
71             for(auto& key : keys)
72             {
73                 auto value = key.first + "=";
74                 auto keySize = value.length();
75                 if (line.compare(0, keySize, value) == 0)
76                 {
77                     key.second = line.substr(keySize);
78                     break;
79                 }
80             }
81         }
82         efile.close();
83     }
84     catch (const std::exception& e)
85     {
86         if (!efile.eof())
87         {
88             log<level::ERR>("Error in reading file");
89         }
90         efile.close();
91     }
92 
93     return keys;
94 }
95 
96 void Delete::delete_()
97 {
98     if (parent.eraseCallback)
99     {
100         parent.eraseCallback(parent.getId(parent.version()));
101     }
102 }
103 
104 void Version::updateDeleteInterface(sdbusplus::message::message& msg)
105 {
106     std::string interface, chassisState;
107     std::map<std::string, sdbusplus::message::variant<std::string>> properties;
108 
109     msg.read(interface, properties);
110 
111     for (const auto& p : properties)
112     {
113         if (p.first == "CurrentPowerState")
114         {
115             chassisState = p.second.get<std::string>();
116         }
117     }
118 
119     if ((parent.isVersionFunctional(this->versionId)) &&
120         (chassisState != CHASSIS_STATE_OFF))
121     {
122         if (deleteObject)
123         {
124             deleteObject.reset(nullptr);
125         }
126     }
127     else
128     {
129         if (!deleteObject)
130         {
131             deleteObject = std::make_unique<Delete>(bus, objPath, *this);
132         }
133     }
134 }
135 
136 } // namespace updater
137 } // namespace software
138 } // namespace openpower
139