#include "dump_entry.hpp" #include "dump_manager.hpp" #include #include #include #include #include #include #include #include #include #include namespace phosphor { namespace dump { using namespace phosphor::logging; void Entry::delete_() { // Remove Dump entry D-bus object parent.erase(id); } sdbusplus::message::unix_fd Entry::getFileHandle() { using namespace sdbusplus::xyz::openbmc_project::Common::File::Error; using metadata = xyz::openbmc_project::Common::File::Open; if (file.empty()) { lg2::error("Failed to get file handle: File path is empty."); elog(); } if (fdCloseEventSource) { // Return the existing file descriptor return fdCloseEventSource->first; } int fd = open(file.c_str(), O_RDONLY | O_NONBLOCK); if (fd == -1) { auto err = errno; lg2::error("Failed to open dump file: id: {ID} error: {ERRNO}", "ID", id, "ERRNO", std::strerror(errno)); elog(metadata::ERRNO(err), metadata::PATH(file.c_str())); } // Create a new Defer event source for closing this fd sdeventplus::Event event = sdeventplus::Event::get_default(); auto eventSource = std::make_unique( event, [this](auto& /*source*/) { closeFD(); }); // Store the file descriptor and event source in the optional pair fdCloseEventSource = std::make_pair(fd, std::move(eventSource)); return fd; } void Entry::serialize() { // Folder for serialized entry std::filesystem::path dir = file.parent_path() / PRESERVE; // Serialized entry file std::filesystem::path serializePath = dir / SERIAL_FILE; try { if (!std::filesystem::exists(dir)) { std::filesystem::create_directories(dir); } std::ofstream os(serializePath, std::ios::binary); if (!os.is_open()) { lg2::error("Failed to open file for serialization: {PATH} ", "PATH", serializePath); return; } nlohmann::json j; j["version"] = CLASS_SERIALIZATION_VERSION; j["dumpId"] = id; j["originatorId"] = originatorId(); j["originatorType"] = originatorType(); j["startTime"] = startTime(); os << j.dump(); } catch (const std::exception& e) { lg2::error("Serialization error: {PATH} {ERROR} ", "PATH", serializePath, "ERROR", e); // Remove the serialization folder if that got created // Ignore the error since folder may not be created std::error_code ec; std::filesystem::remove_all(dir, ec); } } void Entry::deserialize(const std::filesystem::path& dumpPath) { try { // .preserve folder std::filesystem::path dir = dumpPath / PRESERVE; if (!std::filesystem::exists(dir)) { lg2::info("Serialization directory: {SERIAL_DIR} doesnt exist, " "skip deserialization", "SERIAL_DIR", dir); return; } // Serialized entry std::filesystem::path serializePath = dir / SERIAL_FILE; std::ifstream is(serializePath, std::ios::binary); if (!is.is_open()) { lg2::error("Failed to open file for deserialization: {PATH}", "PATH", serializePath); return; } nlohmann::json j; is >> j; uint32_t version; j.at("version").get_to(version); if (version == CLASS_SERIALIZATION_VERSION) { uint32_t storedId; j.at("dumpId").get_to(storedId); if (storedId == id) { originatorId(j["originatorId"].get()); originatorType(j["originatorType"].get()); startTime(j["startTime"].get()); } else { lg2::error("The id ({ID_IN_FILE}) is not matching the dump id " "({DUMPID}); skipping deserialization.", "ID_IN_FILE", storedId, "DUMPID", id); // Id is not matching, this could be due to file corruption // deleting the .preserve folder. // Attempt to delete the folder and ignore any error. std::error_code ec; std::filesystem::remove_all(dir, ec); } } else { lg2::error("The serialized file version and current class version" "doesnt match, skip deserialization {VERSION}", "VERSION", version); } } catch (const std::exception& e) { lg2::error("Deserialization error: {PATH}, {ERROR}", "PATH", dumpPath, "ERROR", e); } } } // namespace dump } // namespace phosphor