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