16e36587aSZane Shelley #include "util/temporary_file.hpp"
26e36587aSZane Shelley 
36e36587aSZane Shelley #include <errno.h>  // for errno
46e36587aSZane Shelley #include <stdlib.h> // for mkstemp()
56e36587aSZane Shelley #include <string.h> // for strerror()
66e36587aSZane Shelley #include <unistd.h> // for close()
76e36587aSZane Shelley 
86e36587aSZane Shelley #include <stdexcept>
96e36587aSZane Shelley #include <string>
106e36587aSZane Shelley 
116e36587aSZane Shelley namespace util
126e36587aSZane Shelley {
136e36587aSZane Shelley 
TemporaryFile()146e36587aSZane Shelley TemporaryFile::TemporaryFile()
156e36587aSZane Shelley {
166e36587aSZane Shelley     // Build template path required by mkstemp()
17*27dd6368SPatrick Williams     std::string templatePath = fs::temp_directory_path() /
18*27dd6368SPatrick Williams                                "openpower-hw-diags-XXXXXX";
196e36587aSZane Shelley 
206e36587aSZane Shelley     // Generate unique file name, create file, and open it.  The XXXXXX
216e36587aSZane Shelley     // characters are replaced by mkstemp() to make the file name unique.
226e36587aSZane Shelley     int fd = mkstemp(templatePath.data());
236e36587aSZane Shelley     if (fd == -1)
246e36587aSZane Shelley     {
256e36587aSZane Shelley         throw std::runtime_error{
266e36587aSZane Shelley             std::string{"Unable to create temporary file: "} + strerror(errno)};
276e36587aSZane Shelley     }
286e36587aSZane Shelley 
296e36587aSZane Shelley     // Store path to temporary file
306e36587aSZane Shelley     path = templatePath;
316e36587aSZane Shelley 
326e36587aSZane Shelley     // Close file descriptor
336e36587aSZane Shelley     if (close(fd) == -1)
346e36587aSZane Shelley     {
356e36587aSZane Shelley         // Save errno value; will likely change when we delete temporary file
366e36587aSZane Shelley         int savedErrno = errno;
376e36587aSZane Shelley 
386e36587aSZane Shelley         // Delete temporary file.  The destructor won't be called because the
396e36587aSZane Shelley         // exception below causes this constructor to exit without completing.
406e36587aSZane Shelley         remove();
416e36587aSZane Shelley 
426e36587aSZane Shelley         throw std::runtime_error{
436e36587aSZane Shelley             std::string{"Unable to close temporary file: "} +
446e36587aSZane Shelley             strerror(savedErrno)};
456e36587aSZane Shelley     }
466e36587aSZane Shelley }
476e36587aSZane Shelley 
operator =(TemporaryFile && file)486e36587aSZane Shelley TemporaryFile& TemporaryFile::operator=(TemporaryFile&& file)
496e36587aSZane Shelley {
506e36587aSZane Shelley     // Verify not assigning object to itself (a = std::move(a))
516e36587aSZane Shelley     if (this != &file)
526e36587aSZane Shelley     {
536e36587aSZane Shelley         // Delete temporary file owned by this object
546e36587aSZane Shelley         remove();
556e36587aSZane Shelley 
566e36587aSZane Shelley         // Move temporary file path from other object, transferring ownership
576e36587aSZane Shelley         path = std::move(file.path);
586e36587aSZane Shelley 
596e36587aSZane Shelley         // Clear path in other object; after move path is in unspecified state
606e36587aSZane Shelley         file.path.clear();
616e36587aSZane Shelley     }
626e36587aSZane Shelley     return *this;
636e36587aSZane Shelley }
646e36587aSZane Shelley 
remove()656e36587aSZane Shelley void TemporaryFile::remove()
666e36587aSZane Shelley {
676e36587aSZane Shelley     if (!path.empty())
686e36587aSZane Shelley     {
696e36587aSZane Shelley         // Delete temporary file from file system
706e36587aSZane Shelley         fs::remove(path);
716e36587aSZane Shelley 
726e36587aSZane Shelley         // Clear path to indicate file has been deleted
736e36587aSZane Shelley         path.clear();
746e36587aSZane Shelley     }
756e36587aSZane Shelley }
766e36587aSZane Shelley 
776e36587aSZane Shelley } // namespace util
78