1 #include "util/temporary_file.hpp"
2 
3 #include <errno.h>  // for errno
4 #include <stdlib.h> // for mkstemp()
5 #include <string.h> // for strerror()
6 #include <unistd.h> // for close()
7 
8 #include <stdexcept>
9 #include <string>
10 
11 namespace util
12 {
13 
TemporaryFile()14 TemporaryFile::TemporaryFile()
15 {
16     // Build template path required by mkstemp()
17     std::string templatePath =
18         fs::temp_directory_path() / "openpower-hw-diags-XXXXXX";
19 
20     // Generate unique file name, create file, and open it.  The XXXXXX
21     // characters are replaced by mkstemp() to make the file name unique.
22     int fd = mkstemp(templatePath.data());
23     if (fd == -1)
24     {
25         throw std::runtime_error{
26             std::string{"Unable to create temporary file: "} + strerror(errno)};
27     }
28 
29     // Store path to temporary file
30     path = templatePath;
31 
32     // Close file descriptor
33     if (close(fd) == -1)
34     {
35         // Save errno value; will likely change when we delete temporary file
36         int savedErrno = errno;
37 
38         // Delete temporary file.  The destructor won't be called because the
39         // exception below causes this constructor to exit without completing.
40         remove();
41 
42         throw std::runtime_error{
43             std::string{"Unable to close temporary file: "} +
44             strerror(savedErrno)};
45     }
46 }
47 
operator =(TemporaryFile && file)48 TemporaryFile& TemporaryFile::operator=(TemporaryFile&& file)
49 {
50     // Verify not assigning object to itself (a = std::move(a))
51     if (this != &file)
52     {
53         // Delete temporary file owned by this object
54         remove();
55 
56         // Move temporary file path from other object, transferring ownership
57         path = std::move(file.path);
58 
59         // Clear path in other object; after move path is in unspecified state
60         file.path.clear();
61     }
62     return *this;
63 }
64 
remove()65 void TemporaryFile::remove()
66 {
67     if (!path.empty())
68     {
69         // Delete temporary file from file system
70         fs::remove(path);
71 
72         // Clear path to indicate file has been deleted
73         path.clear();
74     }
75 }
76 
77 } // namespace util
78