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