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