Home | History | Annotate | Download | only in streams
      1 // Copyright 2015 The Chromium OS Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef LIBBRILLO_BRILLO_STREAMS_FILE_STREAM_H_
      6 #define LIBBRILLO_BRILLO_STREAMS_FILE_STREAM_H_
      7 
      8 #include <base/files/file_path.h>
      9 #include <base/macros.h>
     10 #include <brillo/brillo_export.h>
     11 #include <brillo/streams/stream.h>
     12 
     13 namespace brillo {
     14 
     15 // FileStream class provides the implementation of brillo::Stream for files
     16 // and file-descriptor-based streams, such as pipes and sockets.
     17 // The FileStream class cannot be instantiated by clients directly. However
     18 // they should use the static factory methods such as:
     19 //  - FileStream::Open(): to open a file by name.
     20 //  - FileStream::CreateTemporary(): to create a temporary file stream.
     21 //  - FileStream::FromFileDescriptor(): to create a stream using an existing
     22 //    file descriptor.
     23 class BRILLO_EXPORT FileStream : public Stream {
     24  public:
     25   // See comments for FileStream::Open() for detailed description of this enum.
     26   enum class Disposition {
     27     OPEN_EXISTING,  // Open existing file only. Fail if doesn't exist.
     28     CREATE_ALWAYS,  // Create empty file, possibly overwriting existing file.
     29     CREATE_NEW_ONLY,  // Create new file if doesn't exist already.
     30     TRUNCATE_EXISTING,  // Open/truncate existing file. Fail if doesn't exist.
     31   };
     32 
     33   // Simple interface to wrap native library calls so that they can be mocked
     34   // out for testing.
     35   struct FileDescriptorInterface {
     36     using DataCallback = base::Callback<void(Stream::AccessMode)>;
     37 
     38     virtual ~FileDescriptorInterface() = default;
     39 
     40     virtual bool IsOpen() const = 0;
     41     virtual ssize_t Read(void* buf, size_t nbyte) = 0;
     42     virtual ssize_t Write(const void* buf, size_t nbyte) = 0;
     43     virtual off64_t Seek(off64_t offset, int whence) = 0;
     44     virtual mode_t GetFileMode() const = 0;
     45     virtual uint64_t GetSize() const = 0;
     46     virtual int Truncate(off64_t length) const = 0;
     47     virtual int Close() = 0;
     48     virtual bool WaitForData(AccessMode mode,
     49                              const DataCallback& data_callback,
     50                              ErrorPtr* error) = 0;
     51     virtual int WaitForDataBlocking(AccessMode in_mode,
     52                                     base::TimeDelta timeout,
     53                                     AccessMode* out_mode) = 0;
     54     virtual void CancelPendingAsyncOperations() = 0;
     55   };
     56 
     57   // == Construction ==========================================================
     58 
     59   // Opens a file at specified |path| for reading, writing or both as indicated
     60   // by |mode|. The |disposition| specifies how the file must be opened/created:
     61   //  - OPEN_EXISTING   - opens the existing file and keeps its content intact.
     62   //                      The seek pointer is at the beginning of the file.
     63   //  - CREATE_ALWAYS   - creates the file always. If it exists, the file is
     64   //                      truncated.
     65   //  - CREATE_NEW_ONLY - creates a new file only if it doesn't exist. Fails
     66   //                      otherwise. This can be useful for creating lock files.
     67   //  - TRUNCATE_EXISTING - opens existing file and truncates it to zero length.
     68   //                       Fails if the file doesn't already exist.
     69   // If successful, the open file stream is returned. Otherwise returns the
     70   // stream pointer containing nullptr and fills in the details of the error
     71   // in |error| object, if provided.
     72   static StreamPtr Open(const base::FilePath& path,
     73                         AccessMode mode,
     74                         Disposition disposition,
     75                         ErrorPtr* error);
     76 
     77   // Creates a temporary unnamed file and returns a stream to it. The file will
     78   // be deleted when the stream is destroyed.
     79   static StreamPtr CreateTemporary(ErrorPtr* error);
     80 
     81   // Creates a file stream based on existing file descriptor. The file
     82   // descriptor will be set into non-blocking mode and will be owned by the
     83   // resulting stream (and closed when the stream is destroyed).
     84   // If the function fails, returns a null stream pointer and sets the error
     85   // details to |error| object. Also note that it is the caller's responsibility
     86   // to close the file descriptor if this function fails, since the stream
     87   // hasn't been created yet and didn't take ownership of the file descriptor.
     88   // |own_descriptor| indicates whether the stream must close the underlying
     89   // file descriptor when its CloseBlocking() method is called. This should be
     90   // set to false for file descriptors that shouldn't be closed (e.g. stdin).
     91   static StreamPtr FromFileDescriptor(int file_descriptor,
     92                                       bool own_descriptor,
     93                                       ErrorPtr* error);
     94 
     95   // == Stream capabilities ===================================================
     96   bool IsOpen() const override;
     97   bool CanRead() const override;
     98   bool CanWrite() const override;
     99   bool CanSeek() const override;
    100   bool CanGetSize() const override;
    101 
    102   // == Stream size operations ================================================
    103   uint64_t GetSize() const override;
    104   bool SetSizeBlocking(uint64_t size, ErrorPtr* error) override;
    105   uint64_t GetRemainingSize() const override;
    106 
    107   // == Seek operations =======================================================
    108   uint64_t GetPosition() const override;
    109   bool Seek(int64_t offset,
    110             Whence whence,
    111             uint64_t* new_position,
    112             ErrorPtr* error) override;
    113 
    114   // == Read operations =======================================================
    115   bool ReadNonBlocking(void* buffer,
    116                        size_t size_to_read,
    117                        size_t* size_read,
    118                        bool* end_of_stream,
    119                        ErrorPtr* error) override;
    120 
    121   // == Write operations ======================================================
    122   bool WriteNonBlocking(const void* buffer,
    123                         size_t size_to_write,
    124                         size_t* size_written,
    125                         ErrorPtr* error) override;
    126 
    127   // == Finalizing/closing streams  ===========================================
    128   bool FlushBlocking(ErrorPtr* error) override;
    129   bool CloseBlocking(ErrorPtr* error) override;
    130 
    131   // == Data availability monitoring ==========================================
    132 
    133   // Override for Stream::WaitForData to start watching the associated file
    134   // descriptor for non-blocking read/write operations.
    135   bool WaitForData(AccessMode mode,
    136                    const base::Callback<void(AccessMode)>& callback,
    137                    ErrorPtr* error) override;
    138 
    139   // Runs select() on the file descriptor to wait until we can do non-blocking
    140   // I/O on it.
    141   bool WaitForDataBlocking(AccessMode in_mode,
    142                            base::TimeDelta timeout,
    143                            AccessMode* out_mode,
    144                            ErrorPtr* error) override;
    145 
    146   // Cancels pending asynchronous read/write operations.
    147   void CancelPendingAsyncOperations() override;
    148 
    149  private:
    150   friend class FileStreamTest;
    151 
    152   // Internal constructor used by the factory methods Open(), CreateTemporary(),
    153   // and FromFileDescriptor().
    154   FileStream(std::unique_ptr<FileDescriptorInterface> fd_interface,
    155              AccessMode mode);
    156 
    157   // Wrapper for the file descriptor. Used in testing to mock out the real
    158   // file system APIs.
    159   std::unique_ptr<FileDescriptorInterface> fd_interface_;
    160 
    161   // The access mode this stream is open with.
    162   AccessMode access_mode_{AccessMode::READ_WRITE};
    163 
    164   // Set to false for streams that are guaranteed non-seekable.
    165   bool seekable_{true};
    166 
    167   // Set to false for streams that have unknown size.
    168   bool can_get_size_{false};
    169 
    170   DISALLOW_COPY_AND_ASSIGN(FileStream);
    171 };
    172 
    173 }  // namespace brillo
    174 
    175 #endif  // LIBBRILLO_BRILLO_STREAMS_FILE_STREAM_H_
    176