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