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
2269d2f9819785775c86137f5ff3298cd46b14a516Josh Gao// DO NOT INCLUDE OTHER LIBBASE HEADERS!
2369d2f9819785775c86137f5ff3298cd46b14a516Josh Gao// This file gets used in libbinder, and libbinder is used everywhere.
2469d2f9819785775c86137f5ff3298cd46b14a516Josh Gao// Including other headers from libbase frequently results in inclusion of
2569d2f9819785775c86137f5ff3298cd46b14a516Josh Gao// android-base/macros.h, which causes macro collisions.
26918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
2769d2f9819785775c86137f5ff3298cd46b14a516Josh Gao// Container for a file descriptor that automatically closes the descriptor as
2869d2f9819785775c86137f5ff3298cd46b14a516Josh Gao// it goes out of scope.
2969d2f9819785775c86137f5ff3298cd46b14a516Josh Gao//
3069d2f9819785775c86137f5ff3298cd46b14a516Josh Gao//      unique_fd ufd(open("/some/path", "r"));
3169d2f9819785775c86137f5ff3298cd46b14a516Josh Gao//      if (ufd.get() == -1) return error;
3269d2f9819785775c86137f5ff3298cd46b14a516Josh Gao//
3369d2f9819785775c86137f5ff3298cd46b14a516Josh Gao//      // Do something useful, possibly including 'return'.
3469d2f9819785775c86137f5ff3298cd46b14a516Josh Gao//
3569d2f9819785775c86137f5ff3298cd46b14a516Josh Gao//      return 0; // Descriptor is closed for you.
3669d2f9819785775c86137f5ff3298cd46b14a516Josh Gao//
3769d2f9819785775c86137f5ff3298cd46b14a516Josh Gao// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
3869d2f9819785775c86137f5ff3298cd46b14a516Josh Gao// you find this class if you're searching for one of those names.
39918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlinnamespace android {
40918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlinnamespace base {
41918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
4269d2f9819785775c86137f5ff3298cd46b14a516Josh Gaostruct DefaultCloser {
4369d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  static void Close(int fd) {
4469d2f9819785775c86137f5ff3298cd46b14a516Josh Gao    // Even if close(2) fails with EINTR, the fd will have been closed.
4569d2f9819785775c86137f5ff3298cd46b14a516Josh Gao    // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
4669d2f9819785775c86137f5ff3298cd46b14a516Josh Gao    // else's fd.
4769d2f9819785775c86137f5ff3298cd46b14a516Josh Gao    // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
4869d2f9819785775c86137f5ff3298cd46b14a516Josh Gao    ::close(fd);
4969d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  }
5069d2f9819785775c86137f5ff3298cd46b14a516Josh Gao};
5169d2f9819785775c86137f5ff3298cd46b14a516Josh Gao
5269d2f9819785775c86137f5ff3298cd46b14a516Josh Gaotemplate <typename Closer>
5369d2f9819785775c86137f5ff3298cd46b14a516Josh Gaoclass unique_fd_impl final {
54918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin public:
5569d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  unique_fd_impl() : value_(-1) {}
56918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
5769d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  explicit unique_fd_impl(int value) : value_(value) {}
5869d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  ~unique_fd_impl() { clear(); }
59918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
6069d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {}
6169d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  unique_fd_impl& operator=(unique_fd_impl&& s) {
62918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    reset(s.release());
63918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    return *this;
64918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  }
65918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
66918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  void reset(int new_value) {
6769d2f9819785775c86137f5ff3298cd46b14a516Josh Gao    if (value_ != -1) {
6869d2f9819785775c86137f5ff3298cd46b14a516Josh Gao      Closer::Close(value_);
6969d2f9819785775c86137f5ff3298cd46b14a516Josh Gao    }
70918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    value_ = new_value;
71918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  }
72918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
73918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  void clear() {
74918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    reset(-1);
75918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  }
76918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
77918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  int get() const { return value_; }
7869d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  operator int() const { return get(); }
79918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
8069d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  int release() __attribute__((warn_unused_result)) {
81918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    int ret = value_;
82918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    value_ = -1;
83918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin    return ret;
84918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  }
85918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
86918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin private:
87918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin  int value_;
88918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
8969d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  unique_fd_impl(const unique_fd_impl&);
9069d2f9819785775c86137f5ff3298cd46b14a516Josh Gao  void operator=(const unique_fd_impl&);
91918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin};
92918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
9369d2f9819785775c86137f5ff3298cd46b14a516Josh Gaousing unique_fd = unique_fd_impl<DefaultCloser>;
9469d2f9819785775c86137f5ff3298cd46b14a516Josh Gao
95918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin}  // namespace base
96918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin}  // namespace android
97918b9e8dc6dfd7fcbb17a9ac6c4c96fd1bbf78f1Casey Dahlin
9869d2f9819785775c86137f5ff3298cd46b14a516Josh Gao#endif  // ANDROID_BASE_UNIQUE_FD_H
99