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 <unistd.h> 21 22 #include <memory> 23 24 namespace android { 25 26 /* 27 * Using UniqueFd: 28 * 1. Create UniqueFd object: 29 * auto fd_obj = UniqueFd(open("SomeFile", xxx)); 30 * 31 * 2. Check whether the fd_obj is empty: 32 * if (!fd_obj) { return -errno; } 33 * 34 * 3. Accessing the file descriptor: 35 * int ret = read(fd_obj.Get(), buf, buf_size); 36 * 37 * 4. Closing the file: 38 * FD will be closed once execution leaves fd_obj scope (on any return, 39 * exception, destruction of class/struct where object is member, etc.). 40 * User can also force closing the fd_obj by calling: 41 * fd_obj = UniqueFd(); 42 * // fd is closed and fd_obj is empty now. 43 * 44 * 5. File descriptor may be transferred to the code, which will close it after 45 * using. This can be done in 2 ways: 46 * a. Duplicate the fd, in this case both fds should be closed separately: 47 * int out_fd = dup(fd_obj.Get(); 48 * ... 49 * close(out_fd); 50 * b. Transfer ownership, use this method if you do not need the fd anymore. 51 * int out_fd = fd_obj.Release(); 52 * // fd_obj is empty now. 53 * ... 54 * close(out_fd); 55 * 56 * 6. Transferring fd into another UniqueFD object: 57 * UniqueFd fd_obj_2 = std::move(fd_obj); 58 * // fd_obj empty now 59 */ 60 61 constexpr int kEmptyFd = -1; 62 63 class UniqueFd { 64 public: 65 UniqueFd() = default; UniqueFd(int fd)66 explicit UniqueFd(int fd) : fd_(fd){}; 67 68 auto Release [[nodiscard]] () -> int { 69 return std::exchange(fd_, kEmptyFd); 70 } 71 72 auto Get [[nodiscard]] () const -> int { 73 return fd_; 74 } 75 76 explicit operator bool() const { 77 return fd_ != kEmptyFd; 78 } 79 ~UniqueFd()80 ~UniqueFd() { 81 Set(kEmptyFd); 82 } 83 84 /* Allow move semantics */ UniqueFd(UniqueFd && rhs)85 UniqueFd(UniqueFd &&rhs) noexcept { 86 Set(rhs.Release()); 87 } 88 89 auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & { 90 Set(rhs.Release()); 91 return *this; 92 } 93 94 /* Disable copy semantics */ 95 UniqueFd(const UniqueFd &) = delete; 96 auto operator=(const UniqueFd &) = delete; 97 98 private: Set(int new_fd)99 void Set(int new_fd) { 100 if (fd_ != kEmptyFd) { 101 close(fd_); 102 } 103 fd_ = new_fd; 104 } 105 106 int fd_ = kEmptyFd; 107 }; 108 109 } // namespace android 110 111 #endif 112