1 #include "ffdc_file.hpp"
2 
3 #include <errno.h>     // for errno
4 #include <fcntl.h>     // for open()
5 #include <string.h>    // for strerror()
6 #include <sys/stat.h>  // for open()
7 #include <sys/types.h> // for open()
8 
9 #include <phosphor-logging/lg2.hpp>
10 
11 #include <stdexcept>
12 #include <string>
13 
14 namespace watchdog
15 {
16 namespace dump
17 {
18 
19 FFDCFile::FFDCFile(const json& calloutDataObject) :
20     calloutData(calloutDataObject.dump())
21 {
22     prepareFFDCFile();
23 }
24 
25 FFDCFile::~FFDCFile()
26 {
27     // Close file descriptor.  Does nothing if descriptor was already closed.
28     if (descriptor.close() == -1)
29     {
30         lg2::error("Unable to close FFDC file: errormsg({ERRORMSG})",
31                    "ERRORMSG", strerror(errno));
32     }
33 
34     // Delete temporary file.  Does nothing if file was already deleted.
35     tempFile.remove();
36 }
37 
38 void FFDCFile::prepareFFDCFile()
39 {
40     // Open the temporary file for both reading and writing
41     int fd = open(tempFile.getPath().c_str(), O_RDWR);
42     if (fd == -1)
43     {
44         throw std::runtime_error{
45             std::string{"Unable to open FFDC file: "} + strerror(errno)};
46     }
47 
48     ssize_t rc = write(fd, calloutData.c_str(), calloutData.size());
49 
50     if (rc == -1)
51     {
52         lg2::error("Failed to write callout info in file({FILE}), "
53                    "errorno({ERRNO}), errormsg({ERRORMSG})",
54                    "FILE", tempFile.getPath(), "ERRNO", errno, "ERRORMSG",
55                    strerror(errno));
56 
57         throw std::runtime_error("Failed to write phalPELCallouts info");
58     }
59     else if (rc != static_cast<ssize_t>(calloutData.size()))
60     {
61         lg2::warning("Could not write all callout info in file({FILE}), "
62                      "written byte({WRITTEN}), total byte({TOTAL})",
63                      "FILE", tempFile.getPath(), "WRITTEN", rc, "TOTAL",
64                      calloutData.size());
65     }
66 
67     int retCode = lseek(fd, 0, SEEK_SET);
68 
69     if (retCode == -1)
70     {
71         lg2::error("Failed to seek file position to the beginning in "
72                    "file({FILE}), errorno({ERRNO}), errormsg({ERRORMSG})",
73                    "FILE", tempFile.getPath(), "ERRNO", errno, "ERRORMSG",
74                    strerror(errno));
75 
76         throw std::runtime_error(
77             "Failed to seek file position to the beginning of the file");
78     }
79 
80     // Store file descriptor in FileDescriptor object
81     descriptor.set(fd);
82 }
83 
84 } // namespace dump
85 } // namespace watchdog
86