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