|  | // Copyright 2019 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef LIB_VFS_CPP_PSEUDO_FILE_H_ | 
|  | #define LIB_VFS_CPP_PSEUDO_FILE_H_ | 
|  |  | 
|  | #include <lib/vfs/cpp/internal/connection.h> | 
|  | #include <lib/vfs/cpp/internal/file.h> | 
|  |  | 
|  | namespace vfs { | 
|  |  | 
|  | // Buffered pseudo-file. | 
|  | // | 
|  | // This variant is optimized for incrementally reading and writing properties | 
|  | // which are larger than can typically be read or written by the client in | 
|  | // a single I/O transaction. | 
|  | // | 
|  | // In read mode, the pseudo-file invokes its read handler when the file is | 
|  | // opened and retains the content in a buffer which the client incrementally | 
|  | // reads from and can seek within. | 
|  | // | 
|  | // In write mode, the client incrementally writes into and seeks within the | 
|  | // buffer which the pseudo-file delivers as a whole to the write handler when | 
|  | // the file is closed(if there were any writes).  Truncation is also supported. | 
|  | // | 
|  | // This class is thread-hostile. | 
|  | // | 
|  | //  # Simple usage | 
|  | // | 
|  | // Instances of this class should be owned and managed on the same thread | 
|  | // that services their connections. | 
|  | // | 
|  | // # Advanced usage | 
|  | // | 
|  | // You can use a background thread to service connections provided: | 
|  | // async_dispatcher_t for the background thread is stopped or suspended | 
|  | // prior to destroying the file. | 
|  | class PseudoFile final : public vfs::internal::File { | 
|  | public: | 
|  | // Handler called to read from the pseudo-file. | 
|  | using ReadHandler = fit::function<zx_status_t(std::vector<uint8_t>* output, size_t max_bytes)>; | 
|  |  | 
|  | // Handler called to write into the pseudo-file. | 
|  | using WriteHandler = fit::function<zx_status_t(std::vector<uint8_t> input)>; | 
|  |  | 
|  | // Creates a buffered pseudo-file. | 
|  | // | 
|  | // |read_handler| cannot be null. If the |write_handler| is null, then the | 
|  | // pseudo-file is considered not writable. The |max_file_size| | 
|  | // determines the maximum number of bytes which can be written to and read from | 
|  | // the pseudo-file's input buffer when it it opened for writing/reading. | 
|  | PseudoFile(size_t max_file_size, ReadHandler read_handler = ReadHandler(), | 
|  | WriteHandler write_handler = WriteHandler()); | 
|  |  | 
|  | ~PseudoFile() override; | 
|  |  | 
|  | // |Node| implementations: | 
|  | zx_status_t GetAttr(fuchsia::io::NodeAttributes* out_attributes) const override; | 
|  |  | 
|  | protected: | 
|  | zx_status_t CreateConnection(uint32_t flags, | 
|  | std::unique_ptr<vfs::internal::Connection>* connection) override; | 
|  |  | 
|  | NodeKind::Type GetKind() const override; | 
|  |  | 
|  | private: | 
|  | class Content final : public vfs::internal::Connection, public File { | 
|  | public: | 
|  | Content(PseudoFile* file, uint32_t flags, std::vector<uint8_t> content); | 
|  | ~Content() override; | 
|  |  | 
|  | // |File| implementations: | 
|  | zx_status_t ReadAt(uint64_t count, uint64_t offset, std::vector<uint8_t>* out_data) override; | 
|  | zx_status_t WriteAt(std::vector<uint8_t> data, uint64_t offset, uint64_t* out_actual) override; | 
|  | zx_status_t Truncate(uint64_t length) override; | 
|  |  | 
|  | uint64_t GetLength() override; | 
|  |  | 
|  | size_t GetCapacity() override; | 
|  |  | 
|  | // Connection implementation: | 
|  | zx_status_t BindInternal(zx::channel request, async_dispatcher_t* dispatcher) override; | 
|  |  | 
|  | // |Node| implementations: | 
|  | std::unique_ptr<Connection> Close(Connection* connection) override; | 
|  |  | 
|  | zx_status_t PreClose(Connection* connection) override; | 
|  |  | 
|  | void Clone(uint32_t flags, uint32_t parent_flags, zx::channel request, | 
|  | async_dispatcher_t* dispatcher) override; | 
|  |  | 
|  | zx_status_t GetAttr(fuchsia::io::NodeAttributes* out_attributes) const override; | 
|  |  | 
|  | protected: | 
|  | void SendOnOpenEvent(zx_status_t status) override; | 
|  |  | 
|  | NodeKind::Type GetKind() const override; | 
|  |  | 
|  | private: | 
|  | zx_status_t TryFlushIfRequired(); | 
|  |  | 
|  | void SetInputLength(size_t length); | 
|  |  | 
|  | PseudoFile* const file_; | 
|  |  | 
|  | std::vector<uint8_t> buffer_; | 
|  | uint32_t flags_; | 
|  |  | 
|  | // true if the file was written into | 
|  | bool dirty_ = false; | 
|  | }; | 
|  |  | 
|  | // |File| implementations: | 
|  | uint64_t GetLength() override; | 
|  |  | 
|  | size_t GetCapacity() override; | 
|  |  | 
|  | ReadHandler const read_handler_; | 
|  | WriteHandler const write_handler_; | 
|  | const size_t max_file_size_; | 
|  | }; | 
|  |  | 
|  | }  // namespace vfs | 
|  |  | 
|  | #endif  // LIB_VFS_CPP_PSEUDO_FILE_H_ |