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 <fcntl.h> 21 22#if !defined(_WIN32) 23#include <sys/socket.h> 24#endif 25 26#include <sys/types.h> 27#include <unistd.h> 28 29// DO NOT INCLUDE OTHER LIBBASE HEADERS! 30// This file gets used in libbinder, and libbinder is used everywhere. 31// Including other headers from libbase frequently results in inclusion of 32// android-base/macros.h, which causes macro collisions. 33 34// Container for a file descriptor that automatically closes the descriptor as 35// it goes out of scope. 36// 37// unique_fd ufd(open("/some/path", "r")); 38// if (ufd.get() == -1) return error; 39// 40// // Do something useful, possibly including 'return'. 41// 42// return 0; // Descriptor is closed for you. 43// 44// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help 45// you find this class if you're searching for one of those names. 46namespace android { 47namespace base { 48 49struct DefaultCloser { 50 static void Close(int fd) { 51 // Even if close(2) fails with EINTR, the fd will have been closed. 52 // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone 53 // else's fd. 54 // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html 55 ::close(fd); 56 } 57}; 58 59template <typename Closer> 60class unique_fd_impl final { 61 public: 62 unique_fd_impl() : value_(-1) {} 63 64 explicit unique_fd_impl(int value) : value_(value) {} 65 ~unique_fd_impl() { reset(); } 66 67 unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {} 68 unique_fd_impl& operator=(unique_fd_impl&& s) { 69 reset(s.release()); 70 return *this; 71 } 72 73 void reset(int new_value = -1) { 74 if (value_ != -1) { 75 Closer::Close(value_); 76 } 77 value_ = new_value; 78 } 79 80 int get() const { return value_; } 81 operator int() const { return get(); } 82 83 int release() __attribute__((warn_unused_result)) { 84 int ret = value_; 85 value_ = -1; 86 return ret; 87 } 88 89 private: 90 int value_; 91 92 unique_fd_impl(const unique_fd_impl&); 93 void operator=(const unique_fd_impl&); 94}; 95 96using unique_fd = unique_fd_impl<DefaultCloser>; 97 98#if !defined(_WIN32) 99 100// Inline functions, so that they can be used header-only. 101inline bool Pipe(unique_fd* read, unique_fd* write) { 102 int pipefd[2]; 103 104#if defined(__linux__) 105 if (pipe2(pipefd, O_CLOEXEC) != 0) { 106 return false; 107 } 108#else // defined(__APPLE__) 109 if (pipe(pipefd) != 0) { 110 return false; 111 } 112 113 if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) { 114 close(pipefd[0]); 115 close(pipefd[1]); 116 return false; 117 } 118#endif 119 120 read->reset(pipefd[0]); 121 write->reset(pipefd[1]); 122 return true; 123} 124 125inline bool Socketpair(int domain, int type, int protocol, unique_fd* left, unique_fd* right) { 126 int sockfd[2]; 127 if (socketpair(domain, type, protocol, sockfd) != 0) { 128 return false; 129 } 130 left->reset(sockfd[0]); 131 right->reset(sockfd[1]); 132 return true; 133} 134 135inline bool Socketpair(int type, unique_fd* left, unique_fd* right) { 136 return Socketpair(AF_UNIX, type, 0, left, right); 137} 138 139#endif // !defined(_WIN32) 140 141} // namespace base 142} // namespace android 143 144template <typename T> 145int close(const android::base::unique_fd_impl<T>&) 146#if defined(__clang__) 147 __attribute__((__unavailable__( 148#else 149 __attribute__((__error__( 150#endif 151 "close called on unique_fd" 152 ))); 153 154#endif // ANDROID_BASE_UNIQUE_FD_H 155