blob: b7fa3a04db0885b68539fb6d4ae43daf33d73568 [file] [log] [blame]
Jayanth Othayoth224882b2017-05-04 05:46:45 -05001#include "dump_entry.hpp"
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -05002
Jayanth Othayotha320c7c2017-06-14 07:17:21 -05003#include "dump_manager.hpp"
4
Dhruvaraj Subhashchandran64f8da92021-12-08 03:48:23 -06005#include <fcntl.h>
6
Dhruvaraj Subhashchandran93f06412024-06-02 05:16:51 -05007#include <nlohmann/json.hpp>
Dhruvaraj Subhashchandran64f8da92021-12-08 03:48:23 -06008#include <phosphor-logging/elog-errors.hpp>
9#include <phosphor-logging/elog.hpp>
10#include <phosphor-logging/lg2.hpp>
11#include <sdeventplus/event.hpp>
12#include <sdeventplus/source/event.hpp>
13#include <xyz/openbmc_project/Common/File/error.hpp>
14#include <xyz/openbmc_project/Common/error.hpp>
15
16#include <cstring>
17
Jayanth Othayoth224882b2017-05-04 05:46:45 -050018namespace phosphor
19{
20namespace dump
21{
22
Dhruvaraj Subhashchandran64f8da92021-12-08 03:48:23 -060023using namespace phosphor::logging;
24
Jayanth Othayoth224882b2017-05-04 05:46:45 -050025void Entry::delete_()
26{
Jayanth Othayotha320c7c2017-06-14 07:17:21 -050027 // Remove Dump entry D-bus object
28 parent.erase(id);
Jayanth Othayoth224882b2017-05-04 05:46:45 -050029}
30
Dhruvaraj Subhashchandran64f8da92021-12-08 03:48:23 -060031sdbusplus::message::unix_fd Entry::getFileHandle()
32{
33 using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
34 using metadata = xyz::openbmc_project::Common::File::Open;
35 if (file.empty())
36 {
37 lg2::error("Failed to get file handle: File path is empty.");
38 elog<sdbusplus::xyz::openbmc_project::Common::Error::Unavailable>();
39 }
40
41 if (fdCloseEventSource)
42 {
43 // Return the existing file descriptor
44 return fdCloseEventSource->first;
45 }
46
47 int fd = open(file.c_str(), O_RDONLY | O_NONBLOCK);
48 if (fd == -1)
49 {
50 auto err = errno;
51 lg2::error("Failed to open dump file: id: {ID} error: {ERRNO}", "ID",
52 id, "ERRNO", std::strerror(errno));
53 elog<Open>(metadata::ERRNO(err), metadata::PATH(file.c_str()));
54 }
55
56 // Create a new Defer event source for closing this fd
57 sdeventplus::Event event = sdeventplus::Event::get_default();
58 auto eventSource = std::make_unique<sdeventplus::source::Defer>(
59 event, [this](auto& /*source*/) { closeFD(); });
60
61 // Store the file descriptor and event source in the optional pair
62 fdCloseEventSource = std::make_pair(fd, std::move(eventSource));
63
64 return fd;
65}
66
Dhruvaraj Subhashchandran93f06412024-06-02 05:16:51 -050067void Entry::serialize()
68{
69 // Folder for serialized entry
70 std::filesystem::path dir = file.parent_path() / PRESERVE;
71
72 // Serialized entry file
73 std::filesystem::path serializePath = dir / SERIAL_FILE;
74 try
75 {
76 if (!std::filesystem::exists(dir))
77 {
78 std::filesystem::create_directories(dir);
79 }
80
81 std::ofstream os(serializePath, std::ios::binary);
82 if (!os.is_open())
83 {
84 lg2::error("Failed to open file for serialization: {PATH} ", "PATH",
85 serializePath);
86 return;
87 }
88 nlohmann::json j;
89 j["version"] = CLASS_SERIALIZATION_VERSION;
90 j["dumpId"] = id;
91 j["originatorId"] = originatorId();
92 j["originatorType"] = originatorType();
93 j["startTime"] = startTime();
94
95 os << j.dump();
96 }
97 catch (const std::exception& e)
98 {
99 lg2::error("Serialization error: {PATH} {ERROR} ", "PATH",
100 serializePath, "ERROR", e);
101
102 // Remove the serialization folder if that got created
103 // Ignore the error since folder may not be created
104 std::error_code ec;
105 std::filesystem::remove_all(dir, ec);
106 }
107}
108
109void Entry::deserialize(const std::filesystem::path& dumpPath)
110{
111 try
112 {
113 // .preserve folder
114 std::filesystem::path dir = dumpPath / PRESERVE;
115 if (!std::filesystem::exists(dir))
116 {
117 lg2::info("Serialization directory: {SERIAL_DIR} doesnt exist, "
118 "skip deserialization",
119 "SERIAL_DIR", dir);
120 return;
121 }
122
123 // Serialized entry
124 std::filesystem::path serializePath = dir / SERIAL_FILE;
125 std::ifstream is(serializePath, std::ios::binary);
126 if (!is.is_open())
127 {
128 lg2::error("Failed to open file for deserialization: {PATH}",
129 "PATH", serializePath);
130 return;
131 }
132 nlohmann::json j;
133 is >> j;
134
135 uint32_t version;
136 j.at("version").get_to(version);
137 if (version == CLASS_SERIALIZATION_VERSION)
138 {
139 uint32_t storedId;
140 j.at("dumpId").get_to(storedId);
141 if (storedId == id)
142 {
143 originatorId(j["originatorId"].get<std::string>());
144 originatorType(j["originatorType"].get<originatorTypes>());
145 startTime(j["startTime"].get<uint64_t>());
146 }
147 else
148 {
149 lg2::error("The id ({ID_IN_FILE}) is not matching the dump id "
150 "({DUMPID}); skipping deserialization.",
151 "ID_IN_FILE", storedId, "DUMPID", id);
152
153 // Id is not matching, this could be due to file corruption
154 // deleting the .preserve folder.
155 // Attempt to delete the folder and ignore any error.
156 std::error_code ec;
157 std::filesystem::remove_all(dir, ec);
158 }
159 }
160 else
161 {
162 lg2::error("The serialized file version and current class version"
163 "doesnt match, skip deserialization {VERSION}",
164 "VERSION", version);
165 }
166 }
167 catch (const std::exception& e)
168 {
169 lg2::error("Deserialization error: {PATH}, {ERROR}", "PATH", dumpPath,
170 "ERROR", e);
171 }
172}
173
Jayanth Othayoth224882b2017-05-04 05:46:45 -0500174} // namespace dump
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500175} // namespace phosphor