1/*
2 * Copyright (C) 2015 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 ANDROID_BASE_UNIQUE_FD_H
18#define ANDROID_BASE_UNIQUE_FD_H
19
20#include <unistd.h>
21
22// DO NOT INCLUDE OTHER LIBBASE HEADERS!
23// This file gets used in libbinder, and libbinder is used everywhere.
24// Including other headers from libbase frequently results in inclusion of
25// android-base/macros.h, which causes macro collisions.
26
27// Container for a file descriptor that automatically closes the descriptor as
28// it goes out of scope.
29//
30//      unique_fd ufd(open("/some/path", "r"));
31//      if (ufd.get() == -1) return error;
32//
33//      // Do something useful, possibly including 'return'.
34//
35//      return 0; // Descriptor is closed for you.
36//
37// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
38// you find this class if you're searching for one of those names.
39namespace android {
40namespace base {
41
42struct DefaultCloser {
43  static void Close(int fd) {
44    // Even if close(2) fails with EINTR, the fd will have been closed.
45    // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
46    // else's fd.
47    // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
48    ::close(fd);
49  }
50};
51
52template <typename Closer>
53class unique_fd_impl final {
54 public:
55  unique_fd_impl() : value_(-1) {}
56
57  explicit unique_fd_impl(int value) : value_(value) {}
58  ~unique_fd_impl() { reset(); }
59
60  unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {}
61  unique_fd_impl& operator=(unique_fd_impl&& s) {
62    reset(s.release());
63    return *this;
64  }
65
66  void reset(int new_value = -1) {
67    if (value_ != -1) {
68      Closer::Close(value_);
69    }
70    value_ = new_value;
71  }
72
73  int get() const { return value_; }
74  operator int() const { return get(); }
75
76  int release() __attribute__((warn_unused_result)) {
77    int ret = value_;
78    value_ = -1;
79    return ret;
80  }
81
82 private:
83  int value_;
84
85  unique_fd_impl(const unique_fd_impl&);
86  void operator=(const unique_fd_impl&);
87};
88
89using unique_fd = unique_fd_impl<DefaultCloser>;
90
91}  // namespace base
92}  // namespace android
93
94template <typename T>
95int close(const android::base::unique_fd_impl<T>&)
96#if defined(__clang__)
97  __attribute__((__unavailable__(
98#else
99  __attribute__((__error__(
100#endif
101    "close called on unique_fd"
102  )));
103
104#endif  // ANDROID_BASE_UNIQUE_FD_H
105