16e36587aSZane Shelley #pragma once
26e36587aSZane Shelley 
36e36587aSZane Shelley #include <unistd.h> // for close()
46e36587aSZane Shelley 
56e36587aSZane Shelley namespace util
66e36587aSZane Shelley {
76e36587aSZane Shelley 
86e36587aSZane Shelley /**
96e36587aSZane Shelley  * @class FileDescriptor
106e36587aSZane Shelley  *
116e36587aSZane Shelley  * This class manages an open file descriptor.
126e36587aSZane Shelley  *
136e36587aSZane Shelley  * The file descriptor can be closed by calling close().  Otherwise it will be
146e36587aSZane Shelley  * closed by the destructor.
156e36587aSZane Shelley  *
166e36587aSZane Shelley  * FileDescriptor objects cannot be copied, but they can be moved.  This enables
176e36587aSZane Shelley  * them to be stored in containers like std::vector.
186e36587aSZane Shelley  */
196e36587aSZane Shelley class FileDescriptor
206e36587aSZane Shelley {
216e36587aSZane Shelley   public:
226e36587aSZane Shelley     FileDescriptor() = default;
236e36587aSZane Shelley     FileDescriptor(const FileDescriptor&) = delete;
246e36587aSZane Shelley     FileDescriptor& operator=(const FileDescriptor&) = delete;
256e36587aSZane Shelley 
266e36587aSZane Shelley     /**
276e36587aSZane Shelley      * Constructor.
286e36587aSZane Shelley      *
296e36587aSZane Shelley      * @param[in] fd - File descriptor
306e36587aSZane Shelley      */
FileDescriptor(int fd)316e36587aSZane Shelley     explicit FileDescriptor(int fd) : fd(fd) {}
326e36587aSZane Shelley 
336e36587aSZane Shelley     /**
346e36587aSZane Shelley      * Move constructor.
356e36587aSZane Shelley      *
366e36587aSZane Shelley      * Transfers ownership of a file descriptor.
376e36587aSZane Shelley      *
386e36587aSZane Shelley      * @param other - FileDescriptor object being moved
396e36587aSZane Shelley      */
FileDescriptor(FileDescriptor && other)406e36587aSZane Shelley     FileDescriptor(FileDescriptor&& other) : fd(other.fd)
416e36587aSZane Shelley     {
426e36587aSZane Shelley         other.fd = -1;
436e36587aSZane Shelley     }
446e36587aSZane Shelley 
456e36587aSZane Shelley     /**
466e36587aSZane Shelley      * Move assignment operator.
476e36587aSZane Shelley      *
486e36587aSZane Shelley      * Closes the file descriptor owned by this object, if any.  Then transfers
496e36587aSZane Shelley      * ownership of the file descriptor owned by the other object.
506e36587aSZane Shelley      *
516e36587aSZane Shelley      * @param other - FileDescriptor object being moved
526e36587aSZane Shelley      */
operator =(FileDescriptor && other)536e36587aSZane Shelley     FileDescriptor& operator=(FileDescriptor&& other)
546e36587aSZane Shelley     {
556e36587aSZane Shelley         // Verify not assigning object to itself (a = std::move(a))
566e36587aSZane Shelley         if (this != &other)
576e36587aSZane Shelley         {
586e36587aSZane Shelley             set(other.fd);
596e36587aSZane Shelley             other.fd = -1;
606e36587aSZane Shelley         }
616e36587aSZane Shelley         return *this;
626e36587aSZane Shelley     }
636e36587aSZane Shelley 
646e36587aSZane Shelley     /**
656e36587aSZane Shelley      * Destructor.
666e36587aSZane Shelley      *
676e36587aSZane Shelley      * Closes the file descriptor if necessary.
686e36587aSZane Shelley      */
~FileDescriptor()696e36587aSZane Shelley     ~FileDescriptor()
706e36587aSZane Shelley     {
716e36587aSZane Shelley         close();
726e36587aSZane Shelley     }
736e36587aSZane Shelley 
746e36587aSZane Shelley     /**
756e36587aSZane Shelley      * Returns the file descriptor.
766e36587aSZane Shelley      *
776e36587aSZane Shelley      * @return File descriptor.  Returns -1 if this object does not contain an
786e36587aSZane Shelley      *         open file descriptor.
796e36587aSZane Shelley      */
operator ()() const80*584f179eSZane Shelley     int operator()() const
816e36587aSZane Shelley     {
826e36587aSZane Shelley         return fd;
836e36587aSZane Shelley     }
846e36587aSZane Shelley 
856e36587aSZane Shelley     /**
866e36587aSZane Shelley      * Returns whether this object contains an open file descriptor.
876e36587aSZane Shelley      *
886e36587aSZane Shelley      * @return true if object contains an open file descriptor, false otherwise.
896e36587aSZane Shelley      */
operator bool() const906e36587aSZane Shelley     operator bool() const
916e36587aSZane Shelley     {
926e36587aSZane Shelley         return fd != -1;
936e36587aSZane Shelley     }
946e36587aSZane Shelley 
956e36587aSZane Shelley     /**
966e36587aSZane Shelley      * Closes the file descriptor.
976e36587aSZane Shelley      *
986e36587aSZane Shelley      * Does nothing if the file descriptor was not set or was already closed.
996e36587aSZane Shelley      *
1006e36587aSZane Shelley      * @return 0 if descriptor was successfully closed.  Returns -1 if an error
1016e36587aSZane Shelley      *         occurred; errno will be set appropriately.
1026e36587aSZane Shelley      */
close()1036e36587aSZane Shelley     int close()
1046e36587aSZane Shelley     {
1056e36587aSZane Shelley         int rc = 0;
1066e36587aSZane Shelley         if (fd >= 0)
1076e36587aSZane Shelley         {
1086e36587aSZane Shelley             rc = ::close(fd);
1096e36587aSZane Shelley             fd = -1;
1106e36587aSZane Shelley         }
1116e36587aSZane Shelley         return rc;
1126e36587aSZane Shelley     }
1136e36587aSZane Shelley 
1146e36587aSZane Shelley     /**
1156e36587aSZane Shelley      * Sets the file descriptor.
1166e36587aSZane Shelley      *
1176e36587aSZane Shelley      * Closes the previous file descriptor if necessary.
1186e36587aSZane Shelley      *
1196e36587aSZane Shelley      * @param[in] descriptor - File descriptor
1206e36587aSZane Shelley      */
set(int descriptor)1216e36587aSZane Shelley     void set(int descriptor)
1226e36587aSZane Shelley     {
1236e36587aSZane Shelley         close();
1246e36587aSZane Shelley         fd = descriptor;
1256e36587aSZane Shelley     }
1266e36587aSZane Shelley 
1276e36587aSZane Shelley   private:
1286e36587aSZane Shelley     /**
1296e36587aSZane Shelley      * File descriptor.
1306e36587aSZane Shelley      */
1316e36587aSZane Shelley     int fd = -1;
1326e36587aSZane Shelley };
1336e36587aSZane Shelley 
1346e36587aSZane Shelley } // namespace util
135