blob: b5b6f65eb56ed521791aff47648eaa7e8eebc75b [file] [log] [blame]
// 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.io;
using fuchsia.unknown;
using zx;
/// The maximum size for an extended attribute name.
@available(added=18)
const MAX_ATTRIBUTE_NAME uint64 = 255;
/// The name of an extended attribute. It can not contain any null bytes. Other
/// than that and the maximum size, no particular structure is imposed on the
/// name.
@available(added=18)
alias ExtendedAttributeName = vector<uint8>:MAX_ATTRIBUTE_NAME;
/// The maximum size for an extended attribute value to be included inline.
/// Values larger than this size are passed in a vmo.
@available(added=18)
const MAX_INLINE_ATTRIBUTE_VALUE uint64 = 32768;
/// The maximum size of a chunk in the ListExtendedAttributes iterator.
@available(added=18)
const MAX_LIST_ATTRIBUTES_CHUNK uint64 = 128;
/// The value type for an extended attribute. If the value is less than 32768
/// bytes, then it is included inline. Values larger than this size are written
/// into a vmo buffer.
@available(added=18)
type ExtendedAttributeValue = strict resource union {
1: bytes vector<uint8>:MAX_INLINE_ATTRIBUTE_VALUE;
2: buffer zx.Handle:VMO;
};
type NodeAttributesQuery = strict bits : uint64 {
/// Requests [`NodeAttributes.protocols`].
PROTOCOLS = 0x1;
/// Requests [`NodeAttributes.abilities`].
ABILITIES = 0x2;
/// Requests [`NodeAttributes.content_size`].
CONTENT_SIZE = 0x4;
/// Requests [`NodeAttributes.storage_size`].
STORAGE_SIZE = 0x8;
/// Requests [`NodeAttributes.link_count`].
LINK_COUNT = 0x10;
/// Requests [`NodeAttributes.id`].
ID = 0x20;
/// Requests [`NodeAttributes.creation_time`].
CREATION_TIME = 0x40;
/// Requests [`NodeAttributes.modification_time`].
MODIFICATION_TIME = 0x80;
/// Posix attributes.
@available(added=18)
MODE = 0x100;
@available(added=18)
UID = 0x200;
@available(added=18)
GID = 0x400;
@available(added=18)
RDEV = 0x800;
@available(added=18)
ACCESS_TIME = 0x1000;
@available(added=18)
CHANGE_TIME = 0x2000;
/// Verity attributes.
@available(added=HEAD)
OPTIONS = 0x4000;
@available(added=HEAD)
ROOT_HASH = 0x8000;
@available(added=HEAD)
VERITY_ENABLED = 0x10000;
};
type MutableNodeAttributes = table {
/// Time of creation in nanoseconds since the Unix epoch, UTC.
1: creation_time uint64;
/// Time of last modification in nanoseconds since the Unix epoch, UTC.
2: modification_time uint64;
/// POSIX compatibility attributes. Most filesystems will not support
/// these. Those that do must simply store and retrieve them (e.g. as
/// extended attributes) and not attempt to interpret them (e.g. by doing
/// permission checks or handling device opens specially).
@available(added=18)
3: mode uint32; // mode_t
@available(added=18)
4: uid uint32; // uid_t
@available(added=18)
5: gid uint32; // gid_t
@available(added=18)
6: rdev uint64; // dev_t
/// Time of last access in nanoseconds since the Unix epoch, UTC. Note that servers might not
/// always update this if this is the only attribute being updated.
@available(added=18)
7: access_time uint64;
};
// TODO(https://fxbug.dev/42057114): Inline this into its only reference when fidlgen_go is fixed.
type ConnectionInfo = resource table {
/// The rights possessed by the current connection. Note: `rights` limits
/// the set of operations allowed on the connection, but does not guarantee
/// their availability. For example, one may have the [`Rights.EXECUTE`]
/// right on a file connection, but the file itself does not have the
/// `EXECUTE` ability, and hence cannot be executed. See
/// [`ConnectionOptions.rights`].
1: rights Rights;
};
type NodeAttributes2 = struct {
// TODO(https://fxbug.dev/42124231): fostr does not escape C++ keywords.
// Drop the `_attributes` suffixes when fostr is fixed or retired.
mutable_attributes MutableNodeAttributes;
immutable_attributes @generated_name("ImmutableNodeAttributes") table {
/// Describes the kinds of representations supported by the node.
/// Note: This is not the result of the connection-time negotiation,
/// which is conveyed via `representation`.
1: protocols NodeProtocolKinds;
/// Describes the kinds of operations supported by the node.
/// Note: This is distinct from the rights used at connection time.
2: abilities Abilities;
/// Node size, in bytes.
3: content_size uint64;
/// Space needed to store the node (possibly larger than size), in bytes.
4: storage_size uint64;
/// Number of hard links to the node. It must be at least one.
5: link_count uint64;
/// An ID for the node. See [`Id`].
/// This `id` should be unique among all entries of a directory.
6: id Id;
/// Time of last change to the metadata in nanoseconds since the Unix epoch, UTC.
@available(added=HEAD)
7: change_time uint64;
/// Contains the verification options for verity-enabled files.
@available(added=HEAD)
8: options VerificationOptions;
/// The root hash for the file. Not all filesystems support this across all files.
@available(added=HEAD)
9: root_hash vector<uint8>:64;
/// True if this file is verity-enabled.
@available(added=HEAD)
10: verity_enabled bool;
};
};
// TODO(https://fxbug.dev/42056856): Use a generated constant.
const NODE_PROTOCOL_NAME string = "fuchsia.io/Node";
/// Node defines the minimal protocol for entities which can be accessed
/// in a filesystem.
closed protocol Node2 {
@available(added=9)
compose fuchsia.unknown.Closeable;
@available(added=9)
compose fuchsia.unknown.Queryable;
/// Creates another connection to the same node.
@selector("fuchsia.io/Node.Reopen")
strict Reopen(resource struct {
// [`Rights`] can't be optional or boxed, hence a table.
rights_request @generated_name("RightsRequest") table {
/// Requested rights on the new connection.
///
/// If [`rights`] exceed the rights of the requesting connection
/// then [`object_request`] will be closed with a
/// `ZX_ERR_ACCESS_DENIED` epitaph.
///
/// If absent, inherits the rights from the requesting connection.
1: rights Rights;
};
object_request server_end:Node;
});
/// Terminates the connection to the node.
///
/// After calling `Close`, the client must not send any other requests.
/// Servers, after sending the status response, should close the connection
/// regardless of status and without sending an epitaph.
///
/// Closing the client end of the channel should be semantically equivalent
/// to calling `Close` without knowing when the close has completed or its
/// status.
///
/// This method does not require any rights.
@available(replaced=9)
@selector("fuchsia.io/Node.Close")
strict Close() -> () error zx.Status;
/// An event produced eagerly by the server if requested by
/// [`NodeFlags.GET_REPRESENTATION`]. This event will be the first message
/// from the server, and is sent exactly once.
///
/// The active variant corresponds to one of the supported protocols of
/// the node, and represents the result of the connection-time
/// negotiation. Provides auxiliary handles if applicable.
///
/// If the client specified more than one protocol in `protocols` during
/// [`Directory.Open`], the [`Representation`] carries additionally the
/// result of the connection-time negotiation via its tag.
///
/// The elements have one-to-one correspondence with the members of
/// [`NodeProtocolKinds`].
///
/// This is a special case of [`fuchsia.unknown/Queryable.Query`] +
/// inherent `Describe` methods on the specific protocols. It exists as
/// an optimization to avoid an additional round trip.
@selector("fuchsia.io/Node.OnRepresentation")
strict -> OnRepresentation(@generated_name("Representation") flexible resource union {
/// Auxiliary data for the connector representation of a node, used
/// for protocol discovery and connection.
///
/// It supports connecting to arbitrary protocols exported by the
/// filesystem server at a path, including ones that do not compose
/// [`Node2`].
///
/// See [`NodeProtocolKinds.CONNECTOR`].
1: connector @generated_name("ConnectorInfo") table {
/// Requested attributes for the object. This is only populated if requested.
@available(added=18)
1: attributes NodeAttributes2;
};
/// Auxiliary data for the directory representation of a node. The
/// selection of this variant in [`Representation`] implies that the
/// connection speaks the [`Directory`] protocol.
///
/// See [`NodeProtocolKinds.DIRECTORY`].
2: directory DirectoryInfo;
/// Auxiliary data for the file representation of a node. The
/// selection of this variant in [`Representation`] implies that the
/// connection speaks the [`File`] protocol.
///
/// See [`NodeProtocolKinds.FILE`].
3: file FileInfo;
/// Auxilliary data for the symlink representation of a node. The
/// selection of this variant in [`Representation`] implies that the
/// connection speaks the [`Symlink`] protocol.
///
/// See [`NodeProtocolKinds.SYMLINK`].
@available(added=18)
4: symlink SymlinkInfo;
});
// TODO(https://fxbug.dev/42157659): uncomment and implement.
// /// Acquires a token which can be used to identify this connection at a later point in
// /// time. The token will remain valid for as long as the connection requesting the token
// /// remains open.
// ///
// /// This method does not require any rights. Note that the token identifies
// /// the connection, hence carries the rights information on this connection.
// @selector("fuchsia.io/Node.GetToken")
// GetToken2() -> (resource struct {
// token Token;
// }) error zx.Status;
/// Acquires information about the connection.
///
/// This method does not require any rights.
@selector("fuchsia.io/Node.GetConnectionInfo")
strict GetConnectionInfo() -> (ConnectionInfo);
/// Acquires information about the node.
///
/// The attributes of a node should be stable, independent of the
/// specific protocol used to access it.
///
/// If a particular attribute is not applicable or not supported,
/// filesystems should leave the corresponding field absent.
///
/// + `query` a bit-mask specifying which attributes to fetch. The server
/// should not return more than necessary.
/// - `attributes` the returned attributes.
///
/// This method requires the [`Rights.GET_ATTRIBUTES`] right.
@selector("fuchsia.io/Node.GetAttributes")
strict GetAttributes(struct {
/// Set the corresponding bit to one to query that particular attribute.
///
/// The elements here correspond one-to-one with [`NodeAttributes`].
query NodeAttributesQuery;
}) -> (NodeAttributes2) error zx.Status;
/// Updates information about the node.
///
/// + `attributes` the presence of a table field in `attributes` indicates
/// the intent to update the corresponding attribute.
///
/// This method requires the [`Rights.UPDATE_ATTRIBUTES`] right.
@selector("fuchsia.io/Node.UpdateAttributes")
strict UpdateAttributes(MutableNodeAttributes) -> () error zx.Status;
/// Synchronizes updates to the node to the underlying media, if it exists.
///
/// This method will return when the filesystem server has flushed the
/// relevant updates to the underlying media, but does not guarantee the
/// underlying media has persisted the information, nor that any information
/// is committed to hardware. Clients may use `Sync` to ensure ordering
/// between operations.
///
/// This method does not require any rights.
@selector("fuchsia.io/Node.Sync")
strict Sync() -> () error zx.Status;
/// Creates an iterator over all the extended attribute names associated
/// with this node. If an error occurs it is returned as an epitaph on the
/// iterator request channel, and then the channel is closed.
///
/// GetExtendedAttributes can be used with any of these names to retrieve
/// the associated value.
///
/// This method requires the [`Rights.GET_ATTRIBUTES`] right.
@available(added=18)
@selector("fuchsia.io/Node.ListExtendedAttributes")
strict ListExtendedAttributes(resource struct {
iterator server_end:ExtendedAttributeIterator;
});
/// Get the value associated with the given attribute `name` for this node.
///
/// Attribute names have a maximum length of MAX_ATTRIBUTE_NAME. No
/// particular structure is imposed on them.
///
/// This method requires the [`Rights.GET_ATTRIBUTES`] right.
@available(added=18)
@selector("fuchsia.io/Node.GetExtendedAttribute")
strict GetExtendedAttribute(struct {
name ExtendedAttributeName;
}) -> (ExtendedAttributeValue) error zx.Status;
/// Set the value for the given attribute `name` to `value` for this node.
///
/// The attribute name may exist, in which case the attribute is updated.
/// If the attribute doesn't exist, it is created. The name should have no
/// null bytes in it. If it does, ZX_ERR_INVALID_ARGS is returned.
///
/// This method requires the [`Rights.UPDATE_ATTRIBUTES`] right.
@available(added=18)
@selector("fuchsia.io/Node.SetExtendedAttribute")
strict SetExtendedAttribute(resource struct {
name ExtendedAttributeName;
value ExtendedAttributeValue;
/// Specifies the behavior based on the current state of the attribute.
mode @generated_name("SetExtendedAttributeMode") strict enum {
/// Set the value of the extended attribute regardless of whether it
/// already exists.
SET = 1;
/// Create a new extended attribute. Fail if it already exists.
CREATE = 2;
/// Replace the value of an existing extended attribute. Fail if it
/// doesn't already exist.
REPLACE = 3;
};
}) -> () error zx.Status;
/// Remove the specified extended attribute.
///
/// If the attribute doesn't exist, ZX_ERR_NOT_FOUND is returned.
///
/// This method requires the [`Rights.UPDATE_ATTRIBUTES`] right.
@available(added=18)
@selector("fuchsia.io/Node.RemoveExtendedAttribute")
strict RemoveExtendedAttribute(struct {
name ExtendedAttributeName;
}) -> () error zx.Status;
};
@available(added=18)
closed protocol ExtendedAttributeIterator {
/// Get the next chunk of extended attribute names. If this is the last
/// chunk, last will be true, and the channel will be closed after the
/// call.
@selector("fuchsia.io/ExtendedAttributeIterator.GetNext")
strict GetNext() -> (struct {
attributes vector<ExtendedAttributeName>:MAX_LIST_ATTRIBUTES_CHUNK;
last bool;
}) error zx.Status;
};
// Not all nodes support Linkable (e.g. Directories don't).
@available(added=18)
closed protocol Linkable {
/// Creates a link to this this object with name `dst` in the directory represented by
/// `dst_parent_token`.
///
/// `dst` must be a resolved object name. Including "/" in the string will return
/// `ZX_ERR_INVALID_ARGS`.
///
/// This method requires the maximal set of rights supported by the filesystem for this object.
/// For files this would typically be [`Rights.READ_BYTES`], [`Rights.WRITE_BYTES`],
/// [`Rights.GET_ATTRIBUTES`] and [`Rights.UPDATE_ATTRIBUTES`]. Some filesystems might also
/// support the [`Rights.EXECUTE`] right. Insufficient rights will result in
/// `ZX_ERR_ACCESS_DENIED`.
///
/// If this object has no links, it will fail with `ZX_ERR_NOT_FOUND`.
///
/// This method does not have the same atomicity properties has the `Directory::Link` method,
/// which means that calling `Open` then `LinkInto` is not equivalent to `Directory::Link`
/// because `LinkInto` will not prevent the source from being renamed or unlinked.
@selector("fuchsia.io/Linkable.LinkInto")
strict LinkInto(resource struct {
dst_parent_token Token;
dst Name;
}) -> () error zx.Status;
};