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