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     /**
37      * @brief Move constructor.
38      *
39      * @details description ownership of a file descriptor.
40      *
41      * @param other - FileDescriptor object being moved
42      */
43     FileDescriptor(FileDescriptor&& other) : fd(other.fd)
44     {
45         other.fd = -1;
46     }
47 
48     /**
49      * @brief Move assignment operator.
50      *
51      * @details description the file descriptor owned by this object, if any.
52      * Then transfers ownership of the file descriptor owned by the other
53      * object.
54      *
55      * @param other - FileDescriptor object being moved
56      */
57     FileDescriptor& operator=(FileDescriptor&& other)
58     {
59         // Verify not assigning object to itself (a = std::move(a))
60         if (this != &other)
61         {
62             set(other.fd);
63             other.fd = -1;
64         }
65         return *this;
66     }
67 
68     /**
69      * @brief brief description.
70      *
71      * @details Closes the file descriptor if necessary.
72      */
73     ~FileDescriptor()
74     {
75         close();
76     }
77 
78     /**
79      * @brief Returns the file descriptor.
80      *
81      * @return File descriptor.  Returns -1 if this object does not contain an
82      *         open file descriptor.
83      */
84     int operator()() const
85     {
86         return fd;
87     }
88 
89     /**
90      * @brief Check whether this object contains an open file descriptor.
91      *
92      * @return true if object contains an open file descriptor, false otherwise.
93      */
94     operator bool() const
95     {
96         return fd != -1;
97     }
98 
99     /**
100      * @brief Closes the file descriptor.
101      *
102      * @details Does nothing if the file descriptor was not set or was already
103      * closed.
104      *
105      * @return 0 if descriptor was successfully closed.  Returns -1 if an error
106      *         occurred; errno will be set appropriately.
107      */
108     int close()
109     {
110         int rc = 0;
111         if (fd >= 0)
112         {
113             rc = ::close(fd);
114             fd = -1;
115         }
116         return rc;
117     }
118 
119     /**
120      * @brief Sets the file descriptor.
121      *
122      * @details Closes the previous file descriptor if necessary.
123      *
124      * @param[in] descriptor - File descriptor
125      */
126     void set(int descriptor)
127     {
128         (void)close();
129         fd = descriptor;
130     }
131 
132   private:
133     /**
134      * @brief File descriptor.
135      */
136     int fd = -1;
137 };
138 
139 } // namespace dump
140 } // namespace watchdog
141