1918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin/*
2918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * Copyright (C) 2015 The Android Open Source Project
3918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin *
4918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * Licensed under the Apache License, Version 2.0 (the "License");
5918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * you may not use this file except in compliance with the License.
6918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * You may obtain a copy of the License at
7918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin *
8918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin *      http://www.apache.org/licenses/LICENSE-2.0
9918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin *
10918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * Unless required by applicable law or agreed to in writing, software
11918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * distributed under the License is distributed on an "AS IS" BASIS,
12918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * See the License for the specific language governing permissions and
14918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin * limitations under the License.
15918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin */
16918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
17918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin#ifndef ANDROID_BASE_UNIQUE_FD_H
18918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin#define ANDROID_BASE_UNIQUE_FD_H
19918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
20918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin#include <unistd.h>
21918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
222a7b86337f7b149887588e4df532272abe3e931cChristopher Wiley// DO NOT INCLUDE OTHER LIBBASE HEADERS!
232a7b86337f7b149887588e4df532272abe3e931cChristopher Wiley// This file gets used in libbinder, and libbinder is used everywhere.
242a7b86337f7b149887588e4df532272abe3e931cChristopher Wiley// Including other headers from libbase frequently results in inclusion of
252a7b86337f7b149887588e4df532272abe3e931cChristopher Wiley// android-base/macros.h, which causes macro collisions.
26918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
27c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes// Container for a file descriptor that automatically closes the descriptor as
28c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes// it goes out of scope.
29c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes//
30c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes//      unique_fd ufd(open("/some/path", "r"));
31c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes//      if (ufd.get() == -1) return error;
32c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes//
33c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes//      // Do something useful, possibly including 'return'.
34c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes//
35c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes//      return 0; // Descriptor is closed for you.
36c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes//
37c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
38c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes// you find this class if you're searching for one of those names.
39918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlinnamespace android {
40918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlinnamespace base {
41918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
4213ea01db451b3993d175110a3336a58482be883dJosh Gaostruct DefaultCloser {
4313ea01db451b3993d175110a3336a58482be883dJosh Gao  static void Close(int fd) {
4413ea01db451b3993d175110a3336a58482be883dJosh Gao    // Even if close(2) fails with EINTR, the fd will have been closed.
4513ea01db451b3993d175110a3336a58482be883dJosh Gao    // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
4613ea01db451b3993d175110a3336a58482be883dJosh Gao    // else's fd.
4713ea01db451b3993d175110a3336a58482be883dJosh Gao    // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
4813ea01db451b3993d175110a3336a58482be883dJosh Gao    ::close(fd);
4913ea01db451b3993d175110a3336a58482be883dJosh Gao  }
5013ea01db451b3993d175110a3336a58482be883dJosh Gao};
5113ea01db451b3993d175110a3336a58482be883dJosh Gao
5213ea01db451b3993d175110a3336a58482be883dJosh Gaotemplate <typename Closer>
5313ea01db451b3993d175110a3336a58482be883dJosh Gaoclass unique_fd_impl final {
54918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin public:
5513ea01db451b3993d175110a3336a58482be883dJosh Gao  unique_fd_impl() : value_(-1) {}
56918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
5713ea01db451b3993d175110a3336a58482be883dJosh Gao  explicit unique_fd_impl(int value) : value_(value) {}
585d1b1a8b91a35f465e5af146bcfd5d7b4346854cJosh Gao  ~unique_fd_impl() { reset(); }
59918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
6013ea01db451b3993d175110a3336a58482be883dJosh Gao  unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {}
6113ea01db451b3993d175110a3336a58482be883dJosh Gao  unique_fd_impl& operator=(unique_fd_impl&& s) {
62918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    reset(s.release());
63918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    return *this;
64918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  }
65918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
665d1b1a8b91a35f465e5af146bcfd5d7b4346854cJosh Gao  void reset(int new_value = -1) {
67c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes    if (value_ != -1) {
6813ea01db451b3993d175110a3336a58482be883dJosh Gao      Closer::Close(value_);
69c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes    }
70918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    value_ = new_value;
71918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  }
72918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
73918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  int get() const { return value_; }
742c5d1d7cd914ec8ebf76c8a59d0889ebf5b538cdElliott Hughes  operator int() const { return get(); }
75918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
76c0e6e40cc916747a0a22c2538874348cda0ef607Elliott Hughes  int release() __attribute__((warn_unused_result)) {
77918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    int ret = value_;
78918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    value_ = -1;
79918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    return ret;
80918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  }
81918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
82918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin private:
83918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  int value_;
84918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
8513ea01db451b3993d175110a3336a58482be883dJosh Gao  unique_fd_impl(const unique_fd_impl&);
8613ea01db451b3993d175110a3336a58482be883dJosh Gao  void operator=(const unique_fd_impl&);
87918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin};
88918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
8913ea01db451b3993d175110a3336a58482be883dJosh Gaousing unique_fd = unique_fd_impl<DefaultCloser>;
9013ea01db451b3993d175110a3336a58482be883dJosh Gao
91918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin}  // namespace base
92918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin}  // namespace android
93918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
946496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gaotemplate <typename T>
956496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gaoint close(const android::base::unique_fd_impl<T>&)
966496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gao#if defined(__clang__)
976496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gao  __attribute__((__unavailable__(
986496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gao#else
996496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gao  __attribute__((__error__(
1006496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gao#endif
1016496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gao    "close called on unique_fd"
1026496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gao  )));
1036496c4bf6f31bd0714a341d51c1cff7f15938e84Josh Gao
10454c72aaccc45edf4832cfdc5053d9ae6acc9bcdfElliott Hughes#endif  // ANDROID_BASE_UNIQUE_FD_H
105