blob: b176f8d8c9f52f2326017fd74065128b72c5c62f [file] [log] [blame]
// Copyright 2018 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 zx;
type OpenFlags = strict bits : uint32 {
/// Can read from target object.
RIGHT_READABLE = 0x00000001;
/// Can write to target object.
RIGHT_WRITABLE = 0x00000002;
/// Connection can map target object executable.
RIGHT_EXECUTABLE = 0x00000008;
/// Create the object if it doesn't exist.
CREATE = 0x00010000;
/// (with Create) Fail if the object already exists.
CREATE_IF_ABSENT = 0x00020000;
/// Truncate the object before usage.
TRUNCATE = 0x00040000;
/// Assert that the object to be opened is a directory.
/// Return an error if the target object is not a directory.
DIRECTORY = 0x00080000;
/// Seek to the end of the object before all writes.
APPEND = 0x00100000;
/// Open a reference to the object, not the object itself.
/// It is ONLY valid to pass the following flags together with `NODE_REFERENCE`:
/// - `DIRECTORY`
/// - `NOT_DIRECTORY`
/// - `DESCRIBE`
/// otherwise an error is returned.
/// If an object is opened or cloned using this method, the resulting connection does not carry
/// any permission flags.
/// The resulting node allows a limited set of operations: `GetAttr`, `Clone`, `Close`, `Describe`,
/// and, if the node is a file, these extra operations: `GetFlags`, `SetFlags`.
NODE_REFERENCE = 0x00400000;
/// Requests that an "OnOpen" event is sent to the interface request.
/// The event will contain a non-null NodeInfo if the open/clone is successful.
DESCRIBE = 0x00800000;
/// DO NOT USE. In process of being removed.
/// TODO(fxbug.dev/81185): Remove when all clients have updated to the latest SDK.
@deprecated("Temporary flag used by servers to maintain binary compatibility with clients.")
POSIX_DEPRECATED = 0x01000000;
/// Specify this flag to request POSIX-compatibility with respect to write permission handling.
/// Currently, it affects permission handling specifically during Open:
/// - If the target path is a directory, the rights on the new connection expand to include
/// `WRITABLE` if and only if the current connection and all intermediate mount points
/// are writable.
/// - Otherwise, this flag is ignored. It is an access denied error to request more rights
/// than those on the current connection, or any intermediate mount points.
///
/// If this flag is omitted, opening always uses the requested rights, failing the operation with
/// access denied error if requested rights exceeds the rights attached to the current connection.
///
/// If the requesting connection is read-only and the requested rights are read-only, the flag
/// may be ignored by the server, and is not forwarded downstream. This is an implementation detail,
/// necessary to enforce hierarchical permissions across mount points, and should have no effect
/// on the expected behavior for clients.
POSIX_WRITABLE = 0x08000000;
/// Specify this flag to request POSIX-compatibility with respect to execute permission handling.
/// Currently, it affects permission handling specifically during Open:
/// - If the target path is a directory, the rights on the new connection expand to include
/// `EXECUTABLE` if and only if the current connection and all intermediate mount
/// points are executable.
/// - Otherwise, this flag is ignored. It is an access denied error to request more rights
/// than those on the current connection, or any intermediate mount points.
///
/// If this flag is omitted, opening always uses the requested rights, failing the operation with
/// access denied error if requested rights exceeds the rights attached to the current connection.
///
/// If the requesting connection is read-only and the requested rights are read-only, the flag
/// may be ignored by the server, and is not forwarded downstream. This is an implementation detail,
/// necessary to enforce hierarchical permissions across mount points, and should have no effect
/// on the expected behavior for clients.
POSIX_EXECUTABLE = 0x10000000;
/// Assert that the object to be opened is not a directory.
/// Return an error if the target object is a directory.
NOT_DIRECTORY = 0x02000000;
/// When used during clone, the new connection inherits the rights on the source connection,
/// regardless if it is a file or directory. Otherwise, clone attempts to use the requested rights.
/// It is invalid to pass any of the `RIGHT_*` flags together with `OpenFlags.CLONE_SAME_RIGHTS`.
CLONE_SAME_RIGHTS = 0x04000000;
};
/// All known rights.
const OPEN_RIGHTS OpenFlags
= OpenFlags.RIGHT_READABLE | OpenFlags.RIGHT_WRITABLE | OpenFlags.RIGHT_EXECUTABLE;
/// Flags used when opening a node reference must fall within this mask.
const OPEN_FLAGS_ALLOWED_WITH_NODE_REFERENCE OpenFlags
= OpenFlags.DIRECTORY | OpenFlags.NOT_DIRECTORY | OpenFlags.DESCRIBE | OpenFlags.NODE_REFERENCE;
/// Bits reserved for posix protections. Native fuchsia filesystems
/// are not required to set bits contained within `MODE_PROTECTION_MASK`,
/// but filesystems that wish to do so may refer to sys/stat.h for their
/// definitions.
const MODE_PROTECTION_MASK uint32 = 0x00FFF;
/// Bits indicating node type. The canonical mechanism to check
/// for a node type is to take 'mode', bitwise AND it with the
/// `MODE_TYPE_MASK`, and check exact equality against a mode type.
const MODE_TYPE_MASK uint32 = 0xFF000;
const MODE_TYPE_DIRECTORY uint32 = 0x04000;
const MODE_TYPE_BLOCK_DEVICE uint32 = 0x06000;
const MODE_TYPE_FILE uint32 = 0x08000;
const MODE_TYPE_SOCKET uint32 = 0x0C000;
const MODE_TYPE_SERVICE uint32 = 0x10000;
/// The maximal buffer size which can be transmitted for buffered operations.
/// This capacity is currently set somewhat arbitrarily.
const MAX_BUF uint64 = 8192;
/// The maximum length, in bytes, of a filesystem string.
// TODO(smklein): Update to 4095. +1 is for null-terminator, which shouldn't be
// part of the FIDL length.
const MAX_PATH uint64 = 4096;
/// The maximum length, in bytes, of a single filesystem component.
const MAX_FILENAME uint64 = 255;
// Dirent type information associated with the results of ReadDirents.
// The following values are aligned with the values from libc's "dirent.h" "DT_...".
type DirentType = strict enum : uint8 {
/// A dirent with an unknown type.
UNKNOWN = 0;
/// A dirent representing a directory object.
DIRECTORY = 4;
/// A dirent representing a block device object.
BLOCK_DEVICE = 6;
/// A dirent representing a file object.
FILE = 8;
/// A dirent representing a socket object.
SOCKET = 12;
/// A dirent representing a service object.
SERVICE = 16;
};
/// Nodes which do not have ino values should return this value
/// from Readdir and GetAttr.
const INO_UNKNOWN uint64 = 0xFFFFFFFFFFFFFFFF;
/// DirectoryWatcher transmits messages from a filesystem server
/// about events happening in the filesystem. Clients can register
/// new watchers using the `Directory.Watch` method, where they can
/// filter which events they want to receive notifications for.
///
/// The DirectoryWatcher will send messages of the form:
/// ```
/// struct {
/// uint8 event;
/// uint8 len;
/// char name[];
/// };
/// ```
/// Where names are NOT null-terminated.
protocol DirectoryWatcher {};
type WatchEvent = strict enum : uint8 {
/// Indicates the directory being watched has been deleted.
DELETED = 0;
/// Indicates a node has been created (either new or moved) into a directory.
ADDED = 1;
/// Identifies a node has been removed (either deleted or moved) from the directory.
REMOVED = 2;
/// Identifies a node already existed in the directory when watching started.
EXISTING = 3;
/// Identifies that no more `EXISTING` events will be sent.
IDLE = 4;
};
type WatchMask = strict bits : uint32 {
/// Used by `Directory.Watch`. Requests transmission of `WatchEvent.DELETED`.
DELETED = 0x00000001;
/// Used by `Directory.Watch`. Requests transmission of `WatchEvent.ADDED`.
ADDED = 0x00000002;
/// Used by `Directory.Watch`. Requests transmission of `WatchEvent.REMOVED`.
REMOVED = 0x00000004;
/// Used by `Directory.Watch`. Requests transmission of `WatchEvent.EXISTING`.
EXISTING = 0x00000008;
/// Used by `Directory.Watch`. Requests transmission of `WatchEvent.IDLE`.
IDLE = 0x00000010;
};
protocol Directory {
compose Directory1;
compose Directory2;
};
/// Directory defines a node which is capable of containing other Objects.
protocol Directory1 {
compose Node1;
/// Opens a new object relative to this directory object.
///
/// `path` may contain multiple segments, separated by "/" characters, and should never be
/// empty; i.e. "" is an invalid path. A trailing slash implies OpenFlags.DIRECTORY. Components
/// must not be empty (i.e. "foo//bar" is invalid). ".." is disallowed anywhere in the path. "."
/// is only allowed if the path is exactly ".", but not otherwise. A leading '/' is allowed (and
/// is treated the same way as if not present, i.e. "/foo/bar' and "foo/bar" are the same).
///
/// If an unknown value is sent for flags the connection should be closed.
///
/// `OpenFlags.RIGHT_*` flags provided in `flags` will restrict access rights on
/// the `object` channel which will be connected to the opened entity.
///
/// Rights are never increased. When you open a nested entity within a directory, you may only
/// request the same rights as what the directory connection already has, or a subset of those.
/// Exceeding those rights causes an access denied error to be transmitted in the
/// `OnOpen` event if applicable, and the `object` connection closed.
///
/// `mode` is only used if an object is created and indicates the type of object to be
/// created. An unsupported mode will cause the connection to be closed.
/// The mode type, if set, must always be consistent with the OpenFlags.DIRECTORY and
/// OpenFlags.NOT_DIRECTORY flags, even if an object is not being created. If an object is not
/// being created, `mode` is otherwise ignored. If an object is being created and the mode
/// type is not set, a directory will be created if OpenFlags.DIRECTORY is set (explicitly or
/// implicitly), or otherwise a server chosen object type.
@selector("fuchsia.io1/Directory.Open")
Open(resource struct {
flags OpenFlags;
mode uint32;
path string:MAX_PATH;
object server_end:Node;
});
/// Reads a collection of variably sized dirents into a buffer.
/// The number of dirents in a directory may be very large: akin to
/// calling read multiple times on a file, directories have a seek
/// offset which is updated on subsequent calls to ReadDirents.
/// Each call to ReadDirents will only return whole dirent structures,
/// they will not get split across ReadDirent calls.
///
/// These dirents are of the form:
/// ```
/// struct dirent {
/// // Describes the inode of the entry.
/// uint64 ino;
/// // Describes the length of the dirent name in bytes.
/// uint8 size;
/// // Describes the type of the entry. Aligned with the
/// // POSIX d_type values. Use `DirentType` constants.
/// uint8 type;
/// // Unterminated name of entry.
/// char name[0];
/// }
/// ```
///
/// This method does not require any rights, since one could always probe for
/// directory contents by triggering name conflicts during file creation.
// TODO(smklein): Convert to a vector of variable-length objects, when
// llcpp arrives.
// TODO(smklein): Get rid of "max_bytes".
// TODO(smklein): Document the behavior when the seek pointer reaches the end of the directory.
@selector("fuchsia.io1/Directory.ReadDirents")
ReadDirents(struct {
max_bytes uint64;
}) -> (struct {
s zx.status;
dirents vector<uint8>:MAX_BUF;
});
/// Resets the directory seek offset.
///
/// This method does not require any rights, similar to ReadDirents.
@selector("fuchsia.io1/Directory.Rewind")
Rewind() -> (struct {
s zx.status;
});
/// Acquires a token to a Directory which can be used to identify
/// access to it at a later point in time.
///
/// This method requires following rights: `OpenFlags.RIGHT_WRITABLE`, otherwise returns
/// `ZX_ERR_BAD_HANDLE`.
@selector("fuchsia.io1/Directory.GetToken")
GetToken() -> (resource struct {
s zx.status;
token zx.handle:optional;
});
/// Creates a link to an object named src by the name dst, within a directory represented by
/// token.
///
/// `src` must be a resolved object name. Including "/" in the string will
/// return `ZX_ERR_INVALID_ARGS`.
///
/// `dst` must be a resolved object name. Including "/" in the string will
/// return `ZX_ERR_INVALID_ARGS`.
///
/// This method requires following rights: `OpenFlags.RIGHT_WRITABLE`, otherwise returns
/// `ZX_ERR_BAD_HANDLE`.
@selector("fuchsia.io1/Directory.Link")
Link(resource struct {
src string:MAX_FILENAME;
dst_parent_token zx.handle;
dst string:MAX_FILENAME;
}) -> (struct {
s zx.status;
});
/// Watches a directory, receiving events of added messages on the
/// watcher request channel.
///
/// Options must be zero; it is reserved.
///
/// This method does not require any rights, similar to ReadDirents.
@selector("fuchsia.io1/Directory.Watch")
Watch(resource struct {
mask WatchMask;
options uint32;
watcher server_end:DirectoryWatcher;
}) -> (struct {
s zx.status;
});
};