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