|  | #include "ffdc_file.hpp" | 
|  |  | 
|  | #include <errno.h>     // for errno | 
|  | #include <fcntl.h>     // for open() | 
|  | #include <string.h>    // for strerror() | 
|  | #include <sys/stat.h>  // for open() | 
|  | #include <sys/types.h> // for open() | 
|  |  | 
|  | #include <phosphor-logging/lg2.hpp> | 
|  |  | 
|  | #include <stdexcept> | 
|  | #include <string> | 
|  |  | 
|  | namespace watchdog | 
|  | { | 
|  | namespace dump | 
|  | { | 
|  |  | 
|  | FFDCFile::FFDCFile(const json& calloutDataObject) : | 
|  | calloutData(calloutDataObject.dump()) | 
|  | { | 
|  | prepareFFDCFile(); | 
|  | } | 
|  |  | 
|  | FFDCFile::~FFDCFile() | 
|  | { | 
|  | // Close file descriptor.  Does nothing if descriptor was already closed. | 
|  | if (descriptor.close() == -1) | 
|  | { | 
|  | lg2::error("Unable to close FFDC file: errormsg({ERRORMSG})", | 
|  | "ERRORMSG", strerror(errno)); | 
|  | } | 
|  |  | 
|  | // Delete temporary file.  Does nothing if file was already deleted. | 
|  | tempFile.remove(); | 
|  | } | 
|  |  | 
|  | void FFDCFile::prepareFFDCFile() | 
|  | { | 
|  | // Open the temporary file for both reading and writing | 
|  | int fd = open(tempFile.getPath().c_str(), O_RDWR); | 
|  | if (fd == -1) | 
|  | { | 
|  | throw std::runtime_error{ | 
|  | std::string{"Unable to open FFDC file: "} + strerror(errno)}; | 
|  | } | 
|  |  | 
|  | ssize_t rc = write(fd, calloutData.c_str(), calloutData.size()); | 
|  |  | 
|  | if (rc == -1) | 
|  | { | 
|  | lg2::error("Failed to write callout info in file({FILE}), " | 
|  | "errorno({ERRNO}), errormsg({ERRORMSG})", | 
|  | "FILE", tempFile.getPath(), "ERRNO", errno, "ERRORMSG", | 
|  | strerror(errno)); | 
|  |  | 
|  | throw std::runtime_error("Failed to write phalPELCallouts info"); | 
|  | } | 
|  | else if (rc != static_cast<ssize_t>(calloutData.size())) | 
|  | { | 
|  | lg2::warning("Could not write all callout info in file({FILE}), " | 
|  | "written byte({WRITTEN}), total byte({TOTAL})", | 
|  | "FILE", tempFile.getPath(), "WRITTEN", rc, "TOTAL", | 
|  | calloutData.size()); | 
|  | } | 
|  |  | 
|  | int retCode = lseek(fd, 0, SEEK_SET); | 
|  |  | 
|  | if (retCode == -1) | 
|  | { | 
|  | lg2::error("Failed to seek file position to the beginning in " | 
|  | "file({FILE}), errorno({ERRNO}), errormsg({ERRORMSG})", | 
|  | "FILE", tempFile.getPath(), "ERRNO", errno, "ERRORMSG", | 
|  | strerror(errno)); | 
|  |  | 
|  | throw std::runtime_error( | 
|  | "Failed to seek file position to the beginning of the file"); | 
|  | } | 
|  |  | 
|  | // Store file descriptor in FileDescriptor object | 
|  | descriptor.set(fd); | 
|  | } | 
|  |  | 
|  | } // namespace dump | 
|  | } // namespace watchdog |