| // 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/connection.h> |
| #include <lib/vfs/cpp/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. |
| // |
| // Instances of this class are thread-safe. |
| class PseudoFile : public File { |
| public: |
| // Handler called to read from the pseudo-file. |
| using ReadHandler = fit::function<zx_status_t(std::vector<uint8_t>* output)>; |
| |
| // Handler called to write into the pseudo-file. |
| using WriteHandler = fit::function<void(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 |buffer_capacity| |
| // determines the maximum number of bytes which can be written to the |
| // pseudo-file's input buffer when it it opened for writing. |
| PseudoFile(ReadHandler read_handler = ReadHandler(), |
| WriteHandler write_handler = WriteHandler(), |
| size_t buffer_capacity = 1024); |
| |
| ~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<Connection>* connection) override; |
| |
| uint32_t GetAdditionalAllowedFlags() const override; |
| |
| uint32_t GetProhibitiveFlags() const override; |
| |
| private: |
| class Content final : public 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; |
| |
| 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: |
| uint32_t GetAdditionalAllowedFlags() const override; |
| |
| uint32_t GetProhibitiveFlags() const override; |
| |
| void SendOnOpenEvent(zx_status_t status) override; |
| |
| private: |
| 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 buffer_capacity_; |
| }; |
| |
| } // namespace vfs |
| |
| #endif // LIB_VFS_CPP_PSEUDO_FILE_H_ |