Home | History | Annotate | Download | only in pdx
      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.
     25   FileHandle() : fd_(kEmptyFileHandle) {}
     26 
     27   // Constructs a FileHandle from an integer file descriptor and takes
     28   // ownership.
     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.
     46   FileHandle(FileHandle&& other) {
     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.
     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.
     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) {
     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|.
     74   void Reset(int fd) {
     75     Close();
     76     fd_ = fd;
     77   }
     78 
     79   // Closes the underlying file descriptor when non-empty.
     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.
     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.
     96   FileHandle Duplicate() const {
     97     return FileHandle(Mode == FileHandleMode::Local ? dup(fd_) : fd_);
     98   }
     99 
    100   FileHandle<FileHandleMode::Borrowed> Borrow() const {
    101     return FileHandle<FileHandleMode::Borrowed>(Get());
    102   }
    103 
    104   // Gets the underlying file descriptor value.
    105   int Get() const { return fd_; }
    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