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