1 #ifndef ANDROID_PDX_FILE_HANDLE_H_ 2 #define ANDROID_PDX_FILE_HANDLE_H_ 3 4 #include <fcntl.h> 5 #include <unistd.h> 6 7 #include <string> 8 9 namespace android { 10 namespace pdx { 11 12 enum class FileHandleMode { 13 Local, 14 Remote, 15 Borrowed, 16 }; 17 18 // Manages ownership, sharing, and lifetime of file descriptors. 19 template <FileHandleMode Mode> 20 class FileHandle { 21 public: 22 static constexpr int kEmptyFileHandle = -1; 23 24 // Constructs an empty FileHandle object. FileHandle()25 FileHandle() : fd_(kEmptyFileHandle) {} 26 27 // Constructs a FileHandle from an integer file descriptor and takes 28 // ownership. FileHandle(int fd)29 explicit FileHandle(int fd) : fd_(fd) {} 30 31 // Constructs a FileHandle by opening |path|. The arguments follow the 32 // semantics of open(). 33 FileHandle(const std::string& path, int flags, mode_t mode = 0) { 34 fd_ = open(path.c_str(), flags, mode); 35 } 36 37 // Constructs a FileHandle by opening |path| relative to |dir_fd|, following 38 // the semantics of openat(). 39 FileHandle(const int directory_fd, const std::string& path, int flags, 40 mode_t mode = 0) { 41 fd_ = openat(directory_fd, path.c_str(), flags, mode); 42 } 43 44 // Move constructor that assumes ownership of the file descriptor, leaving the 45 // other FileHandle object empty. FileHandle(FileHandle && other)46 FileHandle(FileHandle&& other) noexcept { 47 fd_ = other.fd_; 48 other.fd_ = kEmptyFileHandle; 49 } 50 51 // Returns a FileHandle as a duplicate handle of |fd|. Borrowed handles and 52 // handles in remote handle space are not duplicated. AsDuplicate(const int fd)53 static FileHandle AsDuplicate(const int fd) { 54 if (Mode == FileHandleMode::Local) 55 return FileHandle(dup(fd)); 56 else 57 return FileHandle(fd); 58 } 59 60 // Destructor closes the file descriptor when non-empty. ~FileHandle()61 ~FileHandle() { Close(); } 62 63 // Move assignment operator that assumes ownership of the underlying file 64 // descriptor, leaving the other FileHandle object empty. 65 FileHandle& operator=(FileHandle&& other) noexcept { 66 if (this != &other) { 67 Reset(other.fd_); 68 other.fd_ = kEmptyFileHandle; 69 } 70 return *this; 71 } 72 73 // Resets the underlying file handle to |fd|. Reset(int fd)74 void Reset(int fd) { 75 Close(); 76 fd_ = fd; 77 } 78 79 // Closes the underlying file descriptor when non-empty. Close()80 void Close() { 81 if (IsValid() && Mode == FileHandleMode::Local) 82 close(fd_); 83 fd_ = kEmptyFileHandle; 84 } 85 86 // Return the internal fd, passing ownership to the caller. Release()87 int Release() { 88 int release_fd = fd_; 89 fd_ = kEmptyFileHandle; 90 return release_fd; 91 } 92 93 // Duplicates the underlying file descriptor and returns a FileHandle that 94 // owns the new file descriptor. File descriptors are not duplicated when Mode 95 // is Remote or Borrowed. Duplicate()96 FileHandle Duplicate() const { 97 return FileHandle(Mode == FileHandleMode::Local ? dup(fd_) : fd_); 98 } 99 Borrow()100 FileHandle<FileHandleMode::Borrowed> Borrow() const { 101 return FileHandle<FileHandleMode::Borrowed>(Get()); 102 } 103 104 // Gets the underlying file descriptor value. Get()105 int Get() const { return fd_; } IsValid()106 bool IsValid() const { return fd_ >= 0; } 107 explicit operator bool() const { return IsValid(); } 108 109 private: 110 int fd_; 111 112 FileHandle(const FileHandle&) = delete; 113 void operator=(const FileHandle&) = delete; 114 }; 115 116 // Alias for a file handle in the local process' handle space. 117 using LocalHandle = FileHandle<FileHandleMode::Local>; 118 119 // Alias for a file handle in another process' handle space. Handles returned 120 // from pushing a file object or channel must be stored in this type of handle 121 // class, which doesn't close the underlying file descriptor. The underlying 122 // file descriptor in this wrapper should not be passed to close() because doing 123 // so would close an unrelated file descriptor in the local handle space. 124 using RemoteHandle = FileHandle<FileHandleMode::Remote>; 125 126 // Alias for borrowed handles in the local process' handle space. A borrowed 127 // file handle is not close() because this wrapper does not own the underlying 128 // file descriptor. Care must be take to ensure that a borrowed file handle 129 // remains valid during use. 130 using BorrowedHandle = FileHandle<FileHandleMode::Borrowed>; 131 132 // FileReference is a 16 bit integer used in IPC serialization to be 133 // transferred across processes. You can convert this value to a local file 134 // handle by calling Transaction.GetFileHandle() on client side and 135 // Message.GetFileHandle() on service side. 136 using FileReference = int16_t; 137 138 } // namespace pdx 139 } // namespace android 140 141 #endif // ANDROID_PDX_FILE_HANDLE_H_ 142