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