1 #pragma once
2
3 #include "util/file_descriptor.hpp"
4 #include "util/temporary_file.hpp"
5 #include "xyz/openbmc_project/Logging/Create/server.hpp"
6
7 #include <cstdint>
8 #include <filesystem>
9
10 namespace util
11 {
12
13 namespace fs = std::filesystem;
14 using FFDCFormat =
15 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat;
16
17 /**
18 * @class FFDCFile
19 *
20 * File that contains FFDC (first failure data capture) data.
21 *
22 * This class is used to store FFDC data in an error log. The FFDC data is
23 * passed to the error logging system using a file descriptor.
24 *
25 * The constructor creates the file and opens it for both reading and writing.
26 *
27 * Use getFileDescriptor() to obtain the file descriptor needed to read or write
28 * data to the file.
29 *
30 * Use remove() to delete the file. Otherwise the file will be deleted by the
31 * destructor.
32 *
33 * FFDCFile objects cannot be copied, but they can be moved. This enables them
34 * to be stored in containers like std::vector.
35 */
36 class FFDCFile
37 {
38 public:
39 // Specify which compiler-generated methods we want
40 FFDCFile() = delete;
41 FFDCFile(const FFDCFile&) = delete;
42 FFDCFile(FFDCFile&&) = default;
43 FFDCFile& operator=(const FFDCFile&) = delete;
44 FFDCFile& operator=(FFDCFile&&) = default;
45 ~FFDCFile() = default;
46
47 /**
48 * Constructor.
49 *
50 * Creates the file and opens it for both reading and writing.
51 *
52 * Throws an exception if an error occurs.
53 *
54 * @param format format type of the contained data
55 * @param subType format subtype; used for the 'Custom' type
56 * @param version version of the data format; used for the 'Custom' type
57 */
58 explicit FFDCFile(FFDCFormat format, uint8_t subType = 0,
59 uint8_t version = 0);
60
61 /**
62 * Returns the file descriptor for the file.
63 *
64 * The file is open for both reading and writing.
65 *
66 * @return file descriptor
67 */
getFileDescriptor() const68 int getFileDescriptor() const
69 {
70 // Return the integer file descriptor within the FileDescriptor object
71 return descriptor();
72 }
73
74 /**
75 * Returns the format type of the contained data.
76 *
77 * @return format type
78 */
getFormat() const79 FFDCFormat getFormat() const
80 {
81 return format;
82 }
83
84 /**
85 * Returns the absolute path to the file.
86 *
87 * @return absolute path
88 */
getPath() const89 const fs::path& getPath() const
90 {
91 return tempFile.getPath();
92 }
93
94 /**
95 * Returns the format subtype.
96 *
97 * @return subtype
98 */
getSubType() const99 uint8_t getSubType() const
100 {
101 return subType;
102 }
103
104 /**
105 * Returns the version of the data format.
106 *
107 * @return version
108 */
getVersion() const109 uint8_t getVersion() const
110 {
111 return version;
112 }
113
114 /**
115 * Closes and deletes the file.
116 *
117 * Does nothing if the file has already been removed.
118 *
119 * Throws an exception if an error occurs.
120 */
121 void remove();
122
123 private:
124 /**
125 * Format type of the contained data.
126 */
127 FFDCFormat format{FFDCFormat::Text};
128
129 /**
130 * Format subtype; used for the 'Custom' type.
131 */
132 uint8_t subType{0};
133
134 /**
135 * Version of the data format; used for the 'Custom' type.
136 */
137 uint8_t version{0};
138
139 /**
140 * Temporary file where FFDC data is stored.
141 *
142 * The TemporaryFile destructor will automatically delete the file if it was
143 * not explicitly deleted using remove().
144 */
145 TemporaryFile tempFile{};
146
147 /**
148 * File descriptor for reading from/writing to the file.
149 *
150 * The FileDescriptor destructor will automatically close the file if it was
151 * not explicitly closed using remove().
152 */
153 FileDescriptor descriptor{};
154 };
155
156 using FFDCTuple =
157 std::tuple<FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>;
158
159 /** Transforms a list of FFDC files to a list of FFDC tuples. */
transformFFDC(const std::vector<FFDCFile> & i_files,std::vector<FFDCTuple> & o_tuples)160 inline void transformFFDC(const std::vector<FFDCFile>& i_files,
161 std::vector<FFDCTuple>& o_tuples)
162 {
163 o_tuples.clear();
164
165 std::transform(i_files.begin(), i_files.end(), std::back_inserter(o_tuples),
166 [](const auto& e) {
167 return FFDCTuple(
168 e.getFormat(), e.getSubType(), e.getVersion(),
169 sdbusplus::message::unix_fd(e.getFileDescriptor()));
170 });
171 }
172
173 } // namespace util
174