19462e066SShawn McCarney #pragma once
29462e066SShawn McCarney 
39462e066SShawn McCarney #include <unistd.h> // for close()
49462e066SShawn McCarney 
59462e066SShawn McCarney namespace phosphor::power::util
69462e066SShawn McCarney {
79462e066SShawn McCarney 
89462e066SShawn McCarney /**
99462e066SShawn McCarney  * @class FileDescriptor
109462e066SShawn McCarney  *
119462e066SShawn McCarney  * This class manages an open file descriptor.
129462e066SShawn McCarney  *
139462e066SShawn McCarney  * The file descriptor can be closed by calling close().  Otherwise it will be
149462e066SShawn McCarney  * closed by the destructor.
159462e066SShawn McCarney  *
169462e066SShawn McCarney  * FileDescriptor objects cannot be copied, but they can be moved.  This enables
179462e066SShawn McCarney  * them to be stored in containers like std::vector.
189462e066SShawn McCarney  */
199462e066SShawn McCarney class FileDescriptor
209462e066SShawn McCarney {
219462e066SShawn McCarney   public:
229462e066SShawn McCarney     FileDescriptor() = default;
239462e066SShawn McCarney     FileDescriptor(const FileDescriptor&) = delete;
249462e066SShawn McCarney     FileDescriptor& operator=(const FileDescriptor&) = delete;
259462e066SShawn McCarney 
269462e066SShawn McCarney     /**
279462e066SShawn McCarney      * Constructor.
289462e066SShawn McCarney      *
299462e066SShawn McCarney      * @param[in] fd - File descriptor
309462e066SShawn McCarney      */
FileDescriptor(int fd)31*48781aefSPatrick Williams     FileDescriptor(int fd) : fd(fd) {}
329462e066SShawn McCarney 
339462e066SShawn McCarney     /**
349462e066SShawn McCarney      * Move constructor.
359462e066SShawn McCarney      *
369462e066SShawn McCarney      * Transfers ownership of a file descriptor.
379462e066SShawn McCarney      *
389462e066SShawn McCarney      * @param other - FileDescriptor object being moved
399462e066SShawn McCarney      */
FileDescriptor(FileDescriptor && other)409462e066SShawn McCarney     FileDescriptor(FileDescriptor&& other) : fd(other.fd)
419462e066SShawn McCarney     {
429462e066SShawn McCarney         other.fd = -1;
439462e066SShawn McCarney     }
449462e066SShawn McCarney 
459462e066SShawn McCarney     /**
469462e066SShawn McCarney      * Move assignment operator.
479462e066SShawn McCarney      *
489462e066SShawn McCarney      * Closes the file descriptor owned by this object, if any.  Then transfers
499462e066SShawn McCarney      * ownership of the file descriptor owned by the other object.
509462e066SShawn McCarney      *
519462e066SShawn McCarney      * @param other - FileDescriptor object being moved
529462e066SShawn McCarney      */
operator =(FileDescriptor && other)539462e066SShawn McCarney     FileDescriptor& operator=(FileDescriptor&& other)
549462e066SShawn McCarney     {
559462e066SShawn McCarney         // Verify not assigning object to itself (a = std::move(a))
569462e066SShawn McCarney         if (this != &other)
579462e066SShawn McCarney         {
589462e066SShawn McCarney             set(other.fd);
599462e066SShawn McCarney             other.fd = -1;
609462e066SShawn McCarney         }
619462e066SShawn McCarney         return *this;
629462e066SShawn McCarney     }
639462e066SShawn McCarney 
649462e066SShawn McCarney     /**
659462e066SShawn McCarney      * Destructor.
669462e066SShawn McCarney      *
679462e066SShawn McCarney      * Closes the file descriptor if necessary.
689462e066SShawn McCarney      */
~FileDescriptor()699462e066SShawn McCarney     ~FileDescriptor()
709462e066SShawn McCarney     {
719462e066SShawn McCarney         close();
729462e066SShawn McCarney     }
739462e066SShawn McCarney 
749462e066SShawn McCarney     /**
759462e066SShawn McCarney      * Returns the file descriptor.
769462e066SShawn McCarney      *
779462e066SShawn McCarney      * @return File descriptor.  Returns -1 if this object does not contain an
789462e066SShawn McCarney      *         open file descriptor.
799462e066SShawn McCarney      */
operator ()()809462e066SShawn McCarney     int operator()()
819462e066SShawn McCarney     {
829462e066SShawn McCarney         return fd;
839462e066SShawn McCarney     }
849462e066SShawn McCarney 
859462e066SShawn McCarney     /**
869462e066SShawn McCarney      * Returns whether this object contains an open file descriptor.
879462e066SShawn McCarney      *
889462e066SShawn McCarney      * @return true if object contains an open file descriptor, false otherwise.
899462e066SShawn McCarney      */
operator bool() const909462e066SShawn McCarney     operator bool() const
919462e066SShawn McCarney     {
929462e066SShawn McCarney         return fd != -1;
939462e066SShawn McCarney     }
949462e066SShawn McCarney 
959462e066SShawn McCarney     /**
969462e066SShawn McCarney      * Closes the file descriptor.
979462e066SShawn McCarney      *
989462e066SShawn McCarney      * Does nothing if the file descriptor was not set or was already closed.
999462e066SShawn McCarney      *
1009462e066SShawn McCarney      * @return 0 if descriptor was successfully closed.  Returns -1 if an error
1019462e066SShawn McCarney      *         occurred; errno will be set appropriately.
1029462e066SShawn McCarney      */
close()1039462e066SShawn McCarney     int close()
1049462e066SShawn McCarney     {
1059462e066SShawn McCarney         int rc = 0;
1069462e066SShawn McCarney         if (fd >= 0)
1079462e066SShawn McCarney         {
1089462e066SShawn McCarney             rc = ::close(fd);
1099462e066SShawn McCarney             fd = -1;
1109462e066SShawn McCarney         }
1119462e066SShawn McCarney         return rc;
1129462e066SShawn McCarney     }
1139462e066SShawn McCarney 
1149462e066SShawn McCarney     /**
1159462e066SShawn McCarney      * Sets the file descriptor.
1169462e066SShawn McCarney      *
1179462e066SShawn McCarney      * Closes the previous file descriptor if necessary.
1189462e066SShawn McCarney      *
1199462e066SShawn McCarney      * @param[in] descriptor - File descriptor
1209462e066SShawn McCarney      */
set(int descriptor)1219462e066SShawn McCarney     void set(int descriptor)
1229462e066SShawn McCarney     {
1239462e066SShawn McCarney         close();
1249462e066SShawn McCarney         fd = descriptor;
1259462e066SShawn McCarney     }
1269462e066SShawn McCarney 
1279462e066SShawn McCarney   private:
1289462e066SShawn McCarney     /**
1299462e066SShawn McCarney      * File descriptor.
1309462e066SShawn McCarney      */
1319462e066SShawn McCarney     int fd = -1;
1329462e066SShawn McCarney };
1339462e066SShawn McCarney 
1349462e066SShawn McCarney } // namespace phosphor::power::util
135