| // 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. |
| |
| library fuchsia.io2; |
| |
| using fuchsia.mem; |
| using zx; |
| |
| // TODO: We should run some experiments to see what's the optimum value, or |
| // what's the point of diminishing marginal returns. |
| /// The maximum I/O size that is allowed for read/write operations using |
| /// byte vectors. |
| const uint64 MAX_TRANSFER_SIZE = 8192; |
| |
| /// The byte vector type used for read/write operations. |
| using Transfer = bytes:MAX_TRANSFER_SIZE; |
| |
| /// A [`fuchsia.io2/Node`] which contains a sequence of bytes of definite |
| /// length. |
| protocol File { |
| compose Node; |
| |
| /// Moves the offset at which the next invocation of [`Read`] or [`Write`] |
| /// will occur. The seek offset is specific to each file connection. |
| /// |
| /// + request `origin` the reference point where `offset` will be based on. |
| /// + request `offset` the number of bytes to seek. |
| /// - response `offset_from_start` the adjusted seek offset, from the start |
| /// of the file. |
| /// |
| /// This method does not require any rights. |
| Seek(SeekOrigin origin, int64 offset) |
| -> (uint64 offset_from_start) error zx.status; |
| |
| /// Reads up to 'count' bytes at the seek offset. |
| /// The seek offset is moved forward by the number of bytes read. |
| /// |
| /// ## Invariants |
| /// |
| /// * The returned `data.length` will never be greater than `count`. |
| /// * If `data.length` is less than `count`, it means that the seek offset |
| /// has reached the end of file as part of this operation. |
| /// * If `data.length` is zero while `count` is not, it means that the |
| /// seek offset is already at or beyond the end of file, and no data could |
| /// be read. |
| /// * If `count` is zero, the server should perform all the checks ensuring |
| /// read access without actually read anything, and return an empty |
| /// `data` vector. |
| /// |
| /// This method requires the [`Rights.READ_BYTES`] right. |
| Read(uint64 count) -> (Transfer data) error zx.status; |
| |
| /// Writes data at the seek offset. |
| /// The seek offset is moved forward by the number of bytes written. |
| /// If the file is in append mode, the seek offset is first set to the end |
| /// of the file, followed by the write, in one atomic step. |
| /// |
| /// The file size may grow if the seek offset plus `data.length` is beyond |
| /// the current end of file. |
| /// |
| /// + request `data` the byte buffer to write to the file. |
| /// - response `actual_count` the number of bytes written. |
| /// |
| /// ## Invariants |
| /// |
| /// * The returned `actual_count` will never be greater than `data.length`. |
| /// * If the server is unable to write all the data due to e.g. not enough |
| /// space, `actual_count` may be less than `data.length`. |
| /// * If `data.length` is zero, the server should perform all the checks |
| /// ensuring write access without mutating the file. The seek offset |
| /// is still updated if in append mode. |
| /// |
| /// This method requires the [`Rights.WRITE_BYTES`] right. |
| Write(Transfer data) -> (uint64 actual_count) error zx.status; |
| |
| /// Reads up to 'count' bytes at the provided offset. |
| /// Does not affect the seek offset. |
| /// |
| /// ## Invariants |
| /// |
| /// * The returned `data.length` will never be greater than `count`. |
| /// * If `data.length` is less than `count`, it means that `ReadAt` has hit |
| /// the end of file as part of this operation. |
| /// * If `data.length` is zero while `count` is not, it means that `offset` |
| /// is at or past the end of file, and no data can be read. |
| /// * If `count` is zero, the server should perform all the checks ensuring |
| /// read access without actually reading anything, and return an empty |
| /// `data` vector. |
| /// |
| /// This method requires the [`Rights.READ_BYTES`] right. |
| ReadAt(uint64 count, uint64 offset) -> (Transfer data) error zx.status; |
| |
| /// Writes data at the provided offset. |
| /// Does not affect the seek offset. |
| /// |
| /// The file size may grow if `offset` plus `data.length` is past the |
| /// current end of file. |
| /// |
| /// + request `data` the byte buffer to write to the file. |
| /// + request `offset` the offset from start of the file to begin writing. |
| /// - response `actual_count` the number of bytes written. |
| /// |
| /// ## Invariants |
| /// |
| /// * The returned `actual_count` will never be greater than `data.length`. |
| /// * If the server is unable to write all the data due to e.g. not enough |
| /// space, `actual_count` may be less than `data.length`. |
| /// * If `data.length` is zero, the server should perform all the checks |
| /// ensuring write access without mutating the file. |
| /// |
| /// This method requires the [`Rights.WRITE_BYTES`] right. |
| WriteAt(Transfer data, uint64 offset) |
| -> (uint64 actual_count) error zx.status; |
| |
| /// Shrinks or grows the file size to 'length' bytes. |
| /// |
| /// If file size is reduced by this operation, the extra trailing data' |
| /// is discarded. |
| /// If file size is increased by this operation, the extended area appears |
| /// as if it was zeroed. |
| /// |
| /// This method requires the [`Rights.WRITE_BYTES`] right. |
| Resize(uint64 length) -> () error zx.status; |
| |
| /// Acquires a [`fuchsia.mem/Range`] representing this file, if |
| /// there is one, with the requested access rights. |
| /// |
| /// + request `flags` a [`VmoFlags`] indicating the desired mode of access. |
| /// - response `buffer` the requested [`fuchsia.mem/Range`]. |
| /// * error a [`zx.status`] value indicating the failure. |
| /// |
| /// This method requires the following rights: |
| /// |
| /// * [`Rights.READ_BYTES`] if `flags` includes [`VmoFlags.READ`]. |
| /// * [`Rights.WRITE_BYTES`] if `flags` includes [`VmoFlags.WRITE`]. |
| /// * [`Rights.EXECUTE`] if `flags` includes [`VmoFlags.EXECUTE`]. |
| GetMemRange(VmoFlags flags) -> (fuchsia.mem.Range buffer) error zx.status; |
| }; |
| |
| /// The reference point for updating the seek offset. See [`File.Seek`]. |
| enum SeekOrigin : uint32 { |
| /// Seek from the start of the file. |
| /// The seek offset will be set to `offset` bytes. |
| /// The seek offset cannot be negative in this case. |
| START = 1; |
| |
| /// Seek from the current position in the file. |
| /// The seek offset will be the current seek offset plus `offset` bytes. |
| CURRENT = 2; |
| |
| /// Seek from the end of the file. |
| /// The seek offset will be the file size plus `offset` bytes. |
| END = 3; |
| }; |
| |
| bits VmoFlags : uint64 { |
| /// Requests that the VMO be readable. |
| READ = 0x00000001; |
| |
| /// Requests that the VMO be writable. |
| WRITE = 0x00000002; |
| |
| //// Request that the VMO be executable. |
| EXECUTE = 0x00000004; |
| |
| /// Require a copy-on-write clone of the underlying VMO. |
| /// The request should fail if the VMO cannot be cloned. |
| /// May not be supplied with `SHARED_BUFFER`. |
| PRIVATE_CLONE = 0x00010000; |
| |
| /// Require an exact (non-cloned) handle to the underlying VMO. |
| /// All clients using this flag would get a VMO with the same koid. |
| /// The request should fail if a handle to the exact VMO cannot be returned. |
| /// May not be supplied with `PRIVATE_CLONE`. |
| SHARED_BUFFER = 0x00020000; |
| }; |
| |
| /// Auxiliary data for the file representation of a node. |
| /// The selection of this variant in [`Representation`] implies that the |
| /// connection speaks the [`fuchsia.io2/File`] protocol. |
| table FileInfo { |
| /// An optional event which transmits information about an object's |
| /// readability or writability. This event relays information about the |
| /// underlying object, not the capability granted to client: this event |
| /// may be signalled "readable" on a connection that does not have |
| /// the capability to read. |
| /// |
| /// This event will be present if the following conditions are met: |
| /// |
| /// - The `available_operations` on the file connection is not empty. |
| /// - The filesystem supports signalling readability/writability events. |
| /// |
| /// The [`FileSignal`] values may be observed on this event. |
| 1: handle<event> observer; |
| |
| /// Returns if the file is opened in append mode. |
| /// In append mode, the seek offset is moved to the end before every |
| /// write, the two steps performed in an atomic manner. |
| 2: bool is_append; |
| }; |
| |
| bits FileSignal : uint32 { |
| /// Indicates the file is ready for reading. |
| READABLE = 0x01000000; // ZX_USER_SIGNAL_0 |
| |
| /// Indicates the file is ready for writing. |
| WRITABLE = 0x02000000; // ZX_USER_SIGNAL_1 |
| }; |