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 * Move constructor. 36 * 37 * Transfers ownership of a file descriptor. 38 * 39 * @param other - FileDescriptor object being moved 40 */ 41 FileDescriptor(FileDescriptor&& other) : fd(other.fd) 42 { 43 other.fd = -1; 44 } 45 46 /** 47 * Move assignment operator. 48 * 49 * Closes the file descriptor owned by this object, if any. Then transfers 50 * ownership of the file descriptor owned by the other object. 51 * 52 * @param other - FileDescriptor object being moved 53 */ 54 FileDescriptor& operator=(FileDescriptor&& other) 55 { 56 // Verify not assigning object to itself (a = std::move(a)) 57 if (this != &other) 58 { 59 set(other.fd); 60 other.fd = -1; 61 } 62 return *this; 63 } 64 65 /** 66 * Destructor. 67 * 68 * Closes the file descriptor if necessary. 69 */ 70 ~FileDescriptor() 71 { 72 close(); 73 } 74 75 /** 76 * Returns the file descriptor. 77 * 78 * @return File descriptor. Returns -1 if this object does not contain an 79 * open file descriptor. 80 */ 81 int operator()() 82 { 83 return fd; 84 } 85 86 /** 87 * Returns whether this object contains an open file descriptor. 88 * 89 * @return true if object contains an open file descriptor, false otherwise. 90 */ 91 operator bool() const 92 { 93 return fd != -1; 94 } 95 96 /** 97 * Closes the file descriptor. 98 * 99 * Does nothing if the file descriptor was not set or was already closed. 100 * 101 * @return 0 if descriptor was successfully closed. Returns -1 if an error 102 * occurred; errno will be set appropriately. 103 */ 104 int close() 105 { 106 int rc = 0; 107 if (fd >= 0) 108 { 109 rc = ::close(fd); 110 fd = -1; 111 } 112 return rc; 113 } 114 115 /** 116 * Sets the file descriptor. 117 * 118 * Closes the previous file descriptor if necessary. 119 * 120 * @param[in] descriptor - File descriptor 121 */ 122 void set(int descriptor) 123 { 124 close(); 125 fd = descriptor; 126 } 127 128 private: 129 /** 130 * File descriptor. 131 */ 132 int fd = -1; 133 }; 134 135 } // namespace phosphor::power::util 136