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