xref: /openbmc/phosphor-logging/extensions/openpower-pels/repository.cpp (revision 89fa082a68c975128db6fa96eab33200c6bc7bb6)
1*89fa082aSMatt Spinler #include "repository.hpp"
2*89fa082aSMatt Spinler 
3*89fa082aSMatt Spinler #include <fstream>
4*89fa082aSMatt Spinler #include <phosphor-logging/log.hpp>
5*89fa082aSMatt Spinler #include <xyz/openbmc_project/Common/File/error.hpp>
6*89fa082aSMatt Spinler 
7*89fa082aSMatt Spinler namespace openpower
8*89fa082aSMatt Spinler {
9*89fa082aSMatt Spinler namespace pels
10*89fa082aSMatt Spinler {
11*89fa082aSMatt Spinler 
12*89fa082aSMatt Spinler namespace fs = std::filesystem;
13*89fa082aSMatt Spinler using namespace phosphor::logging;
14*89fa082aSMatt Spinler namespace file_error = sdbusplus::xyz::openbmc_project::Common::File::Error;
15*89fa082aSMatt Spinler 
16*89fa082aSMatt Spinler Repository::Repository(const std::filesystem::path& basePath) :
17*89fa082aSMatt Spinler     _logPath(basePath / "logs")
18*89fa082aSMatt Spinler {
19*89fa082aSMatt Spinler     if (!fs::exists(_logPath))
20*89fa082aSMatt Spinler     {
21*89fa082aSMatt Spinler         fs::create_directories(_logPath);
22*89fa082aSMatt Spinler     }
23*89fa082aSMatt Spinler }
24*89fa082aSMatt Spinler 
25*89fa082aSMatt Spinler std::string Repository::getPELFilename(uint32_t pelID, const BCDTime& time)
26*89fa082aSMatt Spinler {
27*89fa082aSMatt Spinler     char name[50];
28*89fa082aSMatt Spinler     sprintf(name, "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X", time.yearMSB,
29*89fa082aSMatt Spinler             time.yearLSB, time.month, time.day, time.hour, time.minutes,
30*89fa082aSMatt Spinler             time.seconds, time.hundredths, pelID);
31*89fa082aSMatt Spinler     return std::string{name};
32*89fa082aSMatt Spinler }
33*89fa082aSMatt Spinler 
34*89fa082aSMatt Spinler void Repository::add(std::unique_ptr<PEL>& pel)
35*89fa082aSMatt Spinler {
36*89fa082aSMatt Spinler     auto path = _logPath / getPELFilename(pel->id(), pel->commitTime());
37*89fa082aSMatt Spinler     std::ofstream file{path, std::ios::binary};
38*89fa082aSMatt Spinler 
39*89fa082aSMatt Spinler     if (!file.good())
40*89fa082aSMatt Spinler     {
41*89fa082aSMatt Spinler         // If this fails, the filesystem is probably full so it isn't like
42*89fa082aSMatt Spinler         // we could successfully create yet another error log here.
43*89fa082aSMatt Spinler         auto e = errno;
44*89fa082aSMatt Spinler         log<level::ERR>("Failed creating PEL file",
45*89fa082aSMatt Spinler                         entry("FILE=%s", path.c_str()));
46*89fa082aSMatt Spinler         fs::remove(path);
47*89fa082aSMatt Spinler         log<level::ERR>("Unable to open PEL file for writing",
48*89fa082aSMatt Spinler                         entry("ERRNO=%d", e), entry("PATH=%s", path.c_str()));
49*89fa082aSMatt Spinler         throw file_error::Open();
50*89fa082aSMatt Spinler     }
51*89fa082aSMatt Spinler 
52*89fa082aSMatt Spinler     auto data = pel->data();
53*89fa082aSMatt Spinler     file.write(reinterpret_cast<const char*>(data.data()), data.size());
54*89fa082aSMatt Spinler 
55*89fa082aSMatt Spinler     if (file.fail())
56*89fa082aSMatt Spinler     {
57*89fa082aSMatt Spinler         // Same note as above about not being able to create an error log
58*89fa082aSMatt Spinler         // for this case even if we wanted.
59*89fa082aSMatt Spinler         auto e = errno;
60*89fa082aSMatt Spinler         log<level::ERR>("Failed writing PEL file",
61*89fa082aSMatt Spinler                         entry("FILE=%s", path.c_str()));
62*89fa082aSMatt Spinler         file.close();
63*89fa082aSMatt Spinler         fs::remove(path);
64*89fa082aSMatt Spinler         log<level::ERR>("Unable to write PEL file", entry("ERRNO=%d", e),
65*89fa082aSMatt Spinler                         entry("PATH=%s", path.c_str()));
66*89fa082aSMatt Spinler         throw file_error::Write();
67*89fa082aSMatt Spinler     }
68*89fa082aSMatt Spinler }
69*89fa082aSMatt Spinler 
70*89fa082aSMatt Spinler } // namespace pels
71*89fa082aSMatt Spinler } // namespace openpower
72