// 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; // Interfaces which may be returned by NodeInfo, an object // returned when calling Open or Describe: // The default protocol, interface information must be acquired some // other way. struct Service { uint8 reserved; }; // The object may be cast to interface 'File'. struct FileObject { handle<event>? event; }; // The object may be cast to interface 'Directory'. struct DirectoryObject { uint8 reserved; }; // The object is accompanied by a pipe. struct Pipe { handle<socket> socket; }; // The object is accompanied by a VMO. struct Vmofile { handle<vmo> vmo; uint64 offset; uint64 length; }; // The object may be cast to interface 'Device'. struct Device { handle<event>? event; }; // Describes how the connection to the Object should be handled, as well as // how to interpret the optional handle. union NodeInfo { Service service; FileObject file; DirectoryObject directory; Pipe pipe; Vmofile vmofile; Device device; }; // Can read from target object. const uint32 OPEN_RIGHT_READABLE = 0x00000001; // Can write to target object. const uint32 OPEN_RIGHT_WRITABLE = 0x00000002; // Connection can mount/umount filesystem. const uint32 OPEN_RIGHT_ADMIN = 0x00000004; // Create the object if it doesn't exist. const uint32 OPEN_FLAG_CREATE = 0x00010000; // (with Create) Fail if the object already exists. const uint32 OPEN_FLAG_CREATE_IF_ABSENT = 0x00020000; // Truncate the object before usage. const uint32 OPEN_FLAG_TRUNCATE = 0x00040000; // Return an error if the target object is not a directory. const uint32 OPEN_FLAG_DIRECTORY = 0x00080000; // Seek to the end of the object before all writes. const uint32 OPEN_FLAG_APPEND = 0x00100000; // If the object is a mount point, open the local directory. const uint32 OPEN_FLAG_NO_REMOTE = 0x00200000; // Open a reference to the object, not the object itself. const uint32 OPEN_FLAG_NODE_REFERENCE = 0x00400000; // Requests that an "OnOpen" event is sent, with // a non-null NodeInfo (if the open is successful). // Implies "OPEN_FLAG_STATUS". const uint32 OPEN_FLAG_DESCRIBE = 0x00800000; // Requests that an "OnOpen" event is sent. const uint32 OPEN_FLAG_STATUS = 0x01000000; // Node defines the minimal interface for entities which can be accessed in a filesystem. [Layout="Simple", FragileBase] interface Node { // Create another connection to the same remote object. Clone(uint32 flags, request<Node> object); // Terminates connection with object. Close() -> (zx.status s); // Returns extra information about the type of the object. // If the |Describe| operation fails, the connection is closed. Describe() -> (NodeInfo info); // An event produced eagerly by a fidl server if requested // by open flags. // Indicates the success or failure of the open operation, // and optionally describes the object. // If the status is |ZX_OK| and |OPEN_FLAG_DESCRIBE| was passed // to open, |info| contains descriptive information about // the object (the same as would be returned by |Describe|), // otherwise it is null. -> OnOpen(zx.status s, NodeInfo? info); // Synchronizes updates to the node to the underlying media, if it exists. Sync() -> (zx.status s); // Acquire information about the node. GetAttr() -> (zx.status s, NodeAttributes attributes); // Update information about the node. SetAttr(uint32 flags, NodeAttributes attributes) -> (zx.status s); // Deprecated. Only for use with compatibility with devhost. Ioctl(uint32 opcode, uint64 max_out, vector<handle>:MAX_IOCTL_HANDLES handles, vector<uint8>:MAX_BUF in) -> (zx.status s, vector<handle>:MAX_IOCTL_HANDLES handles, vector<uint8>:MAX_BUF out); }; // 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 uint32 MODE_PROTECTION_MASK = 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 uint32 MODE_TYPE_MASK = 0xFF000; const uint32 MODE_TYPE_DIRECTORY = 0x04000; const uint32 MODE_TYPE_BLOCK_DEVICE = 0x06000; const uint32 MODE_TYPE_FILE = 0x08000; const uint32 MODE_TYPE_SOCKET = 0x0C000; const uint32 MODE_TYPE_SERVICE = 0x10000; // NodeAttributes defines generic information about a filesystem node. struct NodeAttributes { // Protection bits and node type information describe in 'mode'. uint32 mode; // A filesystem-unique ID. uint64 id; // Node size, in bytes. uint64 content_size; // Space needed to store node (possibly larger than size), in bytes. uint64 storage_size; // Hard link count. uint64 link_count; // Time of creation (may be updated manually after creation) in ns since Unix epoch, UTC. uint64 creation_time; // Time of last modification in ns since Unix epoch, UTC. uint64 modification_time; }; const uint64 MAX_IOCTL_HANDLES = 2; const uint64 MAX_BUF = 8192; const uint64 MAX_PATH = 4096; const uint64 MAX_FILENAME = 255; // The fields of 'attributes' which are used to update the Node are indicated // by the 'flags' argument. const uint32 NODE_ATTRIBUTE_FLAG_CREATION_TIME = 0x00000001; const uint32 NODE_ATTRIBUTE_FLAG_MODIFICATION_TIME = 0x00000002; // Update the Seek offset. enum SeekOrigin : uint32 { // Seek from the start of the file. START = 0; // Seek from the current position in the file. CURRENT = 1; // Seek from the end of the file. END = 2; }; // VMO access rights. const uint32 VMO_FLAG_READ = 0x00000001; const uint32 VMO_FLAG_WRITE = 0x00000002; const uint32 VMO_FLAG_EXEC = 0x00000004; // Require a copy-on-write clone of the underlying VMO. // The request should fail if the VMO is not cloned. // May not be supplied with fuchsia_io_VMO_FLAG_EXACT. const uint32 VMO_FLAG_PRIVATE = 0x00010000; // Require an exact (non-cloned) handle to the underlying VMO. // The request should fail if a handle to the exact VMO // is not returned. // May not be supplied with VMO_FLAG_PRIVATE. const uint32 VMO_FLAG_EXACT = 0x00020000; // File defines the interface of a node which contains a flat layout of data. [Layout = "Simple"] interface File : Node { // Read 'count' bytes at the seek offset. // The seek offset is moved forward by the number of bytes read. Read(uint64 count) -> (zx.status s, vector<uint8>:MAX_BUF data); // Read 'count' bytes at the provided offset. // Does not affect the seek offset. ReadAt(uint64 count, uint64 offset) -> (zx.status s, vector<uint8>:MAX_BUF data); // Write data at the seek offset. // The seek offset is moved forward by the number of bytes written. Write(vector<uint8>:MAX_BUF data) -> (zx.status s, uint64 actual); // Write data to the provided offset. // Does not affect the seek offset. WriteAt(vector<uint8>:MAX_BUF data, uint64 offset) -> (zx.status s, uint64 actual); Seek(int64 offset, SeekOrigin start) -> (zx.status s, uint64 offset); // Shrink the file size to 'length' bytes. Truncate(uint64 length) -> (zx.status s); // Acquire the Directory::Open rights and flags used to access this file. GetFlags() -> (zx.status s, uint32 flags); // Change the Directory::Open flags used to access the file. // Supported flags which can be turned on / off: // - OPEN_FLAG_APPEND SetFlags(uint32 flags) -> (zx.status s); // Acquire a VMO representing this file, if there is one, with the // requested access rights. GetVmo(uint32 flags) -> (zx.status s, handle<vmo>? vmo); }; // Dirent type information associated with the results of ReadDirents. const uint8 DIRENT_TYPE_UNKNOWN = 0; const uint8 DIRENT_TYPE_DIRECTORY = 4; const uint8 DIRENT_TYPE_BLOCK_DEVICE = 6; const uint8 DIRENT_TYPE_FILE = 8; const uint8 DIRENT_TYPE_SOCKET = 12; const uint8 DIRENT_TYPE_SERVICE = 16; // Nodes which do not have ino values should return this value // from Readdir and GetAttr. const uint64 INO_UNKNOWN = 0xFFFFFFFFFFFFFFFF; // Indicates the directory being watched has been deleted. const uint8 WATCH_EVENT_DELETED = 0; // Indicates a node has been created (either new or moved) into a directory. const uint8 WATCH_EVENT_ADDED = 1; // Identifies a node has been removed (either deleted or moved) from the directory. const uint8 WATCH_EVENT_REMOVED = 2; // Identifies a node already existed in the directory when watching started. const uint8 WATCH_EVENT_EXISTING = 3; // Identifies that no more WATCH_EVENT_EXISTING events will be sent. const uint8 WATCH_EVENT_IDLE = 4; // The following are bitmasks corresponding to the "watch events". // They may be used as arguments to the Directory Watch method, to // specify which events should receive notifications. const uint32 WATCH_MASK_DELETED = 0x00000001; const uint32 WATCH_MASK_ADDED = 0x00000002; const uint32 WATCH_MASK_REMOVED = 0x00000004; const uint32 WATCH_MASK_EXISTING = 0x00000008; const uint32 WATCH_MASK_IDLE = 0x00000010; const uint32 WATCH_MASK_ALL = 0x0000001F; // WARNING(ZX-2645): Unused. // // WatchedEvent describes events returned from a DirectoryWatcher. struct WatchedEvent { uint8 event; uint8 len; vector<uint8>:MAX_FILENAME name; }; // WARNING(ZX-2645): Unused. // // 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. [Layout = "Simple"] interface DirectoryWatcher { // TODO(smklein): Convert this to a vector of WatchedEvents, when possible. OnEvent(vector<uint8>:MAX_BUF events); }; // Directory defines a node which is capable of containing other Objects. [Layout = "Simple", FragileBase] interface Directory : Node { // Open a new object relative to this directory object. Open(uint32 flags, uint32 mode, string:MAX_PATH path, request<Node> object); // Remove an object relative to this directory object. Unlink(string:MAX_PATH path) -> (zx.status s); // 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. // // These dirents are of the form: // struct dirent { // // Describes the inode of the entry. // uint64 ino; // // Describes the length of the dirent name. // uint8 size; // // Describes the type of the entry. Aligned with the // // POSIX d_type values. Use DIRENT_TYPE_* constants. // uint8 type; // // Unterminated name of entry. // char name[0]; // } ReadDirents(uint64 max_bytes) -> (zx.status s, vector<uint8>:MAX_BUF dirents); // Reset the directory seek offset. Rewind() -> (zx.status s); // Acquire a token to a Directory which can be used to identify // access to it at a later point in time. GetToken() -> (zx.status s, handle? token); // Within the directory, rename an object named src to the name dst, in // a directory represented by token. Rename(string:MAX_PATH src, handle dst_parent_token, string:MAX_PATH dst) -> (zx.status s); // Within the directory, create a link to an object named src by the name // dst, within a directory represented by token. Link(string:MAX_PATH src, handle dst_parent_token, string:MAX_PATH dst) -> (zx.status s); // Watches a directory, receiving events of added messages on the // watcher request channel. // // The "watcher" handle will send messages of the form: // struct { // uint8 event; // uint8 len; // char name[]; // }; // Where names are NOT null-terminated. // // This API is unstable; in the future, watcher will be a "DirectoryWatcher" client. // // Mask specifies a bitmask of events to observe. // Options must be zero; it is reserved. Watch(uint32 mask, uint32 options, handle<channel> watcher) -> (zx.status s); }; const uint32 MOUNT_CREATE_FLAG_REPLACE = 0x00000001; const uint64 MAX_FS_NAME_BUFFER = 32; struct FilesystemInfo { // The number of data bytes which may be stored in a filesystem. uint64 total_bytes; // The number of data bytes which are in use by the filesystem. uint64 used_bytes; // The number of nodes which may be stored in the filesystem. uint64 total_nodes; // The number of nodes used by the filesystem. uint64 used_nodes; // The amount of space which may be allocated from the underlying // volume manager. If unsupported, this will be zero. uint64 free_shared_pool_bytes; // A unique identifier for this filesystem instance. Will not be preserved // across reboots. uint64 fs_id; // The size of a single filesystem block. uint32 block_size; // The maximum length of a filesystem name. uint32 max_filename_size; // A unique identifier for the type of the underlying filesystem. uint32 fs_type; uint32 padding; // TODO(smklein): Replace this field with a string when supported // by the "Simple" interface. At the moment, name is a fixed-size, // null-terminated buffer. array<int8>:MAX_FS_NAME_BUFFER name; }; // DirectoryAdmin defines a directory which is capable of handling // administrator tasks within the filesystem. [Layout = "Simple"] interface DirectoryAdmin : Directory { // Mount a channel representing a remote filesystem onto this directory. // All future requests to this node will be forwarded to the remote filesytem. // To re-open a node without forwarding to the remote target, the node // should be opened with OPEN_FLAG_NO_RMOTE. Mount(Directory remote) -> (zx.status s); // Atomically create a directory with a provided path, and mount the // remote handle to the newly created directory. MountAndCreate(Directory remote, string:MAX_FILENAME name, uint32 flags) -> (zx.status s); // Unmount this filesystem. After this function returns successfully, // all connections to the filesystem will be terminated. Unmount() -> (zx.status s); // Detach a node which was previously attached to this directory // with Mount. UnmountNode() -> (zx.status s, Directory? remote); // Query the filesystem for filesystem-specific information. QueryFilesystem() -> (zx.status s, FilesystemInfo? info); // Acquire the path to the device backing this filesystem, if there is one. GetDevicePath() -> (zx.status s, string:MAX_PATH? path); };