1 #include "utils.hpp"
2 
3 #include <unistd.h>
4 
5 #include <phosphor-logging/lg2.hpp>
6 
7 namespace utils
8 {
9 
10 PHOSPHOR_LOG2_USING;
11 
getService(sdbusplus::bus_t & bus,const std::string & path,const std::string & interface)12 std::string getService(sdbusplus::bus_t& bus, const std::string& path,
13                        const std::string& interface)
14 {
15     auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
16                                       MAPPER_BUSNAME, "GetObject");
17 
18     method.append(path);
19     method.append(std::vector<std::string>({interface}));
20 
21     std::vector<std::pair<std::string, std::vector<std::string>>> response;
22 
23     try
24     {
25         auto reply = bus.call(method);
26         reply.read(response);
27         if (response.empty())
28         {
29             error(
30                 "Empty response from mapper for getting service name: {PATH} {INTERFACE}",
31                 "PATH", path, "INTERFACE", interface);
32             return std::string{};
33         }
34     }
35     catch (const sdbusplus::exception_t& e)
36     {
37         error("Error in mapper method call for ({PATH}, {INTERFACE}: {ERROR}",
38               "ERROR", e, "PATH", path, "INTERFACE", interface);
39         return std::string{};
40     }
41     return response[0].first;
42 }
43 
setProperty(sdbusplus::bus_t & bus,const std::string & objectPath,const std::string & interface,const std::string & propertyName,const PropertyValue & value)44 void setProperty(sdbusplus::bus_t& bus, const std::string& objectPath,
45                  const std::string& interface, const std::string& propertyName,
46                  const PropertyValue& value)
47 {
48     auto service = getService(bus, objectPath, interface);
49     if (service.empty())
50     {
51         return;
52     }
53 
54     auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
55                                       "org.freedesktop.DBus.Properties", "Set");
56     method.append(interface.c_str(), propertyName.c_str(), value);
57 
58     bus.call_noreply(method);
59 }
60 
mergeFiles(const std::vector<std::string> & srcFiles,const std::string & dstFile)61 void mergeFiles(const std::vector<std::string>& srcFiles,
62                 const std::string& dstFile)
63 {
64     std::ofstream outFile(dstFile, std::ios::out);
65     for (const auto& file : srcFiles)
66     {
67         std::ifstream inFile;
68         inFile.open(file, std::ios_base::in);
69         if (!inFile)
70         {
71             continue;
72         }
73 
74         inFile.peek();
75         if (inFile.eof())
76         {
77             inFile.close();
78             continue;
79         }
80 
81         outFile << inFile.rdbuf();
82         inFile.close();
83     }
84     outFile.close();
85 }
86 
87 namespace internal
88 {
89 
90 /* @brief Helper function to build a string from command arguments */
buildCommandStr(char ** args)91 static std::string buildCommandStr(char** args)
92 {
93     std::string command = "";
94     for (int i = 0; args[i]; i++)
95     {
96         command += args[i];
97         command += " ";
98     }
99     return command;
100 }
101 
executeCmd(char ** args)102 std::pair<int, std::string> executeCmd(char** args)
103 {
104     std::array<char, 512> buffer;
105     std::string cmd = buildCommandStr(args);
106     std::stringstream result;
107     int rc;
108     FILE* pipe = popen(cmd.c_str(), "r");
109     if (!pipe)
110     {
111         error("Failed to execute command: {COMMAND}", "COMMAND", cmd);
112         return {-1, std::string{}};
113     }
114     while (fgets(buffer.data(), buffer.size(), pipe) != nullptr)
115     {
116         result << buffer.data();
117     }
118     rc = pclose(pipe);
119     return {rc, result.str()};
120 }
121 
122 } // namespace internal
123 
124 } // namespace utils
125