1 /* 2 * Copyright (C) 2015, 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef UNIQUEFD_H_ 18 #define UNIQUEFD_H_ 19 20 #include <fcntl.h> 21 #include <unistd.h> 22 23 #include <memory> 24 25 namespace android { 26 27 /* 28 * Using UniqueFd: 29 * 1. Create UniqueFd object: 30 * auto fd_obj = UniqueFd(open("SomeFile", xxx)); 31 * 32 * 2. Check whether the fd_obj is empty: 33 * if (!fd_obj) { return -errno; } 34 * 35 * 3. Accessing the file descriptor: 36 * int ret = read(fd_obj.Get(), buf, buf_size); 37 * 38 * 4. Closing the file: 39 * FD will be closed once execution leaves fd_obj scope (on any return, 40 * exception, destruction of class/struct where object is member, etc.). 41 * User can also force closing the fd_obj by calling: 42 * fd_obj = UniqueFd(); 43 * // fd is closed and fd_obj is empty now. 44 * 45 * 5. File descriptor may be transferred to the code, which will close it after 46 * using. This can be done in 2 ways: 47 * a. Duplicate the fd, in this case both fds should be closed separately: 48 * int out_fd = dup(fd_obj.Get(); 49 * ... 50 * close(out_fd); 51 * b. Transfer ownership, use this method if you do not need the fd anymore. 52 * int out_fd = fd_obj.Release(); 53 * // fd_obj is empty now. 54 * ... 55 * close(out_fd); 56 * 57 * 6. Transferring fd into another UniqueFD object: 58 * UniqueFd fd_obj_2 = std::move(fd_obj); 59 * // fd_obj empty now 60 */ 61 62 constexpr int kEmptyFd = -1; 63 64 class UniqueFd { 65 public: 66 UniqueFd() = default; UniqueFd(int fd)67 explicit UniqueFd(int fd) : fd_(fd){}; 68 69 auto Release [[nodiscard]] () -> int { 70 return std::exchange(fd_, kEmptyFd); 71 } 72 73 auto Get [[nodiscard]] () const -> int { 74 return fd_; 75 } 76 Dup(int fd)77 static auto Dup(int fd) { 78 // NOLINTNEXTLINE(android-cloexec-dup): fcntl has issue (see issue #63) 79 return UniqueFd(dup(fd)); 80 } 81 82 explicit operator bool() const { 83 return fd_ != kEmptyFd; 84 } 85 ~UniqueFd()86 ~UniqueFd() { 87 Set(kEmptyFd); 88 } 89 90 /* Allow move semantics */ UniqueFd(UniqueFd && rhs)91 UniqueFd(UniqueFd &&rhs) noexcept { 92 Set(rhs.Release()); 93 } 94 95 auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & { 96 Set(rhs.Release()); 97 return *this; 98 } 99 100 /* Disable copy semantics */ 101 UniqueFd(const UniqueFd &) = delete; 102 auto operator=(const UniqueFd &) = delete; 103 104 private: Set(int new_fd)105 void Set(int new_fd) { 106 if (fd_ != kEmptyFd) { 107 close(fd_); 108 } 109 fd_ = new_fd; 110 } 111 112 int fd_ = kEmptyFd; 113 }; 114 115 } // namespace android 116 117 #endif 118