1 /* 2 * Copyright (C) 2023 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 #pragma once 18 19 #include <binder/Common.h> 20 21 #ifndef BINDER_NO_LIBBASE 22 23 #include <android-base/unique_fd.h> 24 25 namespace android::binder { 26 using android::base::borrowed_fd; 27 using android::base::unique_fd; 28 } // namespace android::binder 29 30 #else // BINDER_NO_LIBBASE 31 32 #include <errno.h> 33 #include <fcntl.h> // not needed for unique_fd, but a lot of users depend on open(3) 34 #include <unistd.h> 35 36 namespace android::binder { 37 38 // Container for a file descriptor that automatically closes the descriptor as 39 // it goes out of scope. 40 // 41 // unique_fd ufd(open("/some/path", "r")); 42 // if (!ufd.ok()) return error; 43 // 44 // // Do something useful with ufd.get(), possibly including early 'return'. 45 // 46 // return 0; // Descriptor is closed for you. 47 // 48 class LIBBINDER_EXPORTED unique_fd final { 49 public: unique_fd()50 unique_fd() {} 51 unique_fd(int fd)52 explicit unique_fd(int fd) { reset(fd); } ~unique_fd()53 ~unique_fd() { reset(); } 54 55 unique_fd(const unique_fd&) = delete; 56 void operator=(const unique_fd&) = delete; unique_fd(unique_fd && other)57 unique_fd(unique_fd&& other) noexcept { reset(other.release()); } 58 unique_fd& operator=(unique_fd&& s) noexcept { 59 int fd = s.fd_; 60 s.fd_ = -1; 61 reset(fd); 62 return *this; 63 } 64 65 [[clang::reinitializes]] void reset(int new_value = -1) { 66 int previous_errno = errno; 67 68 if (fd_ != -1) { 69 ::close(fd_); 70 } 71 72 fd_ = new_value; 73 errno = previous_errno; 74 } 75 get()76 int get() const { return fd_; } 77 ok()78 bool ok() const { return get() >= 0; } 79 release()80 [[nodiscard]] int release() { 81 int ret = fd_; 82 fd_ = -1; 83 return ret; 84 } 85 86 private: 87 int fd_ = -1; 88 }; 89 90 // A wrapper type that can be implicitly constructed from either int or 91 // unique_fd. This supports cases where you don't actually own the file 92 // descriptor, and can't take ownership, but are temporarily acting as if 93 // you're the owner. 94 // 95 // One example would be a function that needs to also allow 96 // STDERR_FILENO, not just a newly-opened fd. Another example would be JNI code 97 // that's using a file descriptor that's actually owned by a 98 // ParcelFileDescriptor or whatever on the Java side, but where the JNI code 99 // would like to enforce this weaker sense of "temporary ownership". 100 // 101 // If you think of unique_fd as being like std::string in that represents 102 // ownership, borrowed_fd is like std::string_view (and int is like const 103 // char*). 104 struct LIBBINDER_EXPORTED borrowed_fd { borrowed_fdborrowed_fd105 /* implicit */ borrowed_fd(int fd) : fd_(fd) {} // NOLINT borrowed_fdborrowed_fd106 /* implicit */ borrowed_fd(const unique_fd& ufd) : fd_(ufd.get()) {} // NOLINT 107 getborrowed_fd108 int get() const { return fd_; } 109 110 private: 111 int fd_ = -1; 112 }; 113 114 } // namespace android::binder 115 116 #endif // BINDER_NO_LIBBASE 117