1 #pragma once
2 
3 #include <unistd.h> // for close()
4 
5 namespace phosphor::power::util
6 {
7 
8 /**
9  * @class FileDescriptor
10  *
11  * This class manages an open file descriptor.
12  *
13  * The file descriptor can be closed by calling close().  Otherwise it will be
14  * closed by the destructor.
15  *
16  * FileDescriptor objects cannot be copied, but they can be moved.  This enables
17  * them to be stored in containers like std::vector.
18  */
19 class FileDescriptor
20 {
21   public:
22     FileDescriptor() = default;
23     FileDescriptor(const FileDescriptor&) = delete;
24     FileDescriptor& operator=(const FileDescriptor&) = delete;
25 
26     /**
27      * Constructor.
28      *
29      * @param[in] fd - File descriptor
30      */
31     FileDescriptor(int fd) : fd(fd)
32     {
33     }
34 
35     /**
36      * Move constructor.
37      *
38      * Transfers ownership of a file descriptor.
39      *
40      * @param other - FileDescriptor object being moved
41      */
42     FileDescriptor(FileDescriptor&& other) : fd(other.fd)
43     {
44         other.fd = -1;
45     }
46 
47     /**
48      * Move assignment operator.
49      *
50      * Closes the file descriptor owned by this object, if any.  Then transfers
51      * ownership of the file descriptor owned by the other object.
52      *
53      * @param other - FileDescriptor object being moved
54      */
55     FileDescriptor& operator=(FileDescriptor&& other)
56     {
57         // Verify not assigning object to itself (a = std::move(a))
58         if (this != &other)
59         {
60             set(other.fd);
61             other.fd = -1;
62         }
63         return *this;
64     }
65 
66     /**
67      * Destructor.
68      *
69      * Closes the file descriptor if necessary.
70      */
71     ~FileDescriptor()
72     {
73         close();
74     }
75 
76     /**
77      * Returns the file descriptor.
78      *
79      * @return File descriptor.  Returns -1 if this object does not contain an
80      *         open file descriptor.
81      */
82     int operator()()
83     {
84         return fd;
85     }
86 
87     /**
88      * Returns whether this object contains an open file descriptor.
89      *
90      * @return true if object contains an open file descriptor, false otherwise.
91      */
92     operator bool() const
93     {
94         return fd != -1;
95     }
96 
97     /**
98      * Closes the file descriptor.
99      *
100      * Does nothing if the file descriptor was not set or was already closed.
101      *
102      * @return 0 if descriptor was successfully closed.  Returns -1 if an error
103      *         occurred; errno will be set appropriately.
104      */
105     int close()
106     {
107         int rc = 0;
108         if (fd >= 0)
109         {
110             rc = ::close(fd);
111             fd = -1;
112         }
113         return rc;
114     }
115 
116     /**
117      * Sets the file descriptor.
118      *
119      * Closes the previous file descriptor if necessary.
120      *
121      * @param[in] descriptor - File descriptor
122      */
123     void set(int descriptor)
124     {
125         close();
126         fd = descriptor;
127     }
128 
129   private:
130     /**
131      * File descriptor.
132      */
133     int fd = -1;
134 };
135 
136 } // namespace phosphor::power::util
137