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