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