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