| // Copyright 2021 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.fxfs; |
| |
| using fuchsia.io; |
| using zx; |
| |
| /// Designates the purpose of a key. |
| type KeyPurpose = flexible enum { |
| /// The key will be used to encrypt metadata. |
| METADATA = 1; |
| /// The key will be used to encrypt data. |
| DATA = 2; |
| }; |
| |
| @discoverable |
| closed protocol Crypt { |
| /// Creates a new key wrapped with the key identified by `wrapping_key_id`. `owner` identifies |
| /// the owner of the key and must be supplied to `UnwrapKeys`. The crypt service chooses a |
| /// `wrapping_key_id` which must be supplied to UnwrapKeys. The `wrapping_key_id` has no |
| /// meaning to Fxfs. |
| strict CreateKey(struct { |
| owner uint64; |
| purpose KeyPurpose; |
| }) -> (struct { |
| wrapping_key_id uint64; |
| wrapped_key vector<uint8>:48; |
| unwrapped_key vector<uint8>:32; |
| }) error zx.Status; |
| |
| /// Unwraps a key that is wrapped by the key identified by `wrapping_key_id`. `owner` must be |
| /// the same as that passed to `CreateKey`. This can fail due to permission reasons, but an |
| /// incorrect key or owner will not fail; it will just return an unwrapped key that won't |
| /// actually decrpyt the data. |
| strict UnwrapKey(struct { |
| wrapping_key_id uint64; |
| owner uint64; |
| key vector<uint8>:48; |
| }) -> (struct { |
| unwrapped_key vector<uint8>:32; |
| }) error zx.Status; |
| }; |
| |
| type CryptSettings = table { |
| 1: active_data_wrapping_key_id uint64; |
| 2: active_metadata_wrapping_key_id uint64; |
| }; |
| |
| @discoverable |
| closed protocol CryptManagement { |
| /// Adds a new wrapping key to the Crypt service. The new key will immediately be available |
| /// for unwrapping keys (Crypt::UnwrapKeys) but won't be used for wrapping keys until |
| /// CryptManagement::SetActiveKeys is called. |
| strict AddWrappingKey(struct { |
| wrapping_key_id uint64; |
| key vector<uint8>:32; |
| }) -> () error zx.Status; |
| |
| /// Updates the key which will be used for wrapping keys (Crypt::CreateKey). `purpose` |
| /// describes which active key to modify. |
| strict SetActiveKey(struct { |
| purpose KeyPurpose; |
| wrapping_key_id uint64; |
| }) -> () error zx.Status; |
| |
| /// Forgets a wrapping key, preventing its use for future key-unwrapping. All future calls to |
| /// Crypt::UnwrapKeys with that wrapping key ID will fail. |
| /// If either the data or metadata part of the key is active, an error is returned. |
| strict ForgetWrappingKey(struct { |
| wrapping_key_id uint64; |
| }) -> () error zx.Status; |
| }; |
| |
| type MountOptions = resource struct { |
| /// An optional connection to a crypt client (for encrypted volumes). |
| crypt client_end:<Crypt, optional>; |
| |
| /// If true, mount as a blob filesystem. |
| as_blob bool; |
| }; |
| |
| type CheckOptions = resource struct { |
| /// An optional connection to a crypt client (for encrypted volumes). |
| crypt client_end:<Crypt, optional>; |
| }; |
| |
| closed protocol Volume { |
| /// Mounts the volume. If the volume is encrypted, `options.crypt` should provide all key |
| /// access for the given volume. `outgoing_directory` will contain the root and other services |
| /// exposed by the volume. To lock the volume, call fuchsia.fs.Admin.Shutdown on the returned |
| /// handle. |
| // TODO(https://fxbug.dev/42181598): Try to share options with fuchsia.fs_startup StartOptions. |
| strict Mount(resource struct { |
| outgoing_directory server_end:fuchsia.io.Directory; |
| options MountOptions; |
| }) -> () error zx.Status; |
| |
| /// Check the volume for consistency. If the volume is encrypted, `options.crypt` should |
| /// provide all key access for the given volume. |
| strict Check(resource struct { |
| options CheckOptions; |
| }) -> () error zx.Status; |
| |
| /// Set the limit in bytes on the volume. Setting it lower than current usage is accepted but |
| /// will prevent further increases. |
| strict SetLimit(struct { |
| bytes uint64; |
| }) -> () error zx.Status; |
| |
| /// Get the allocation limit for the volume. A return value of 0 indicates that there |
| /// is no limit and the volume can be extended as long as there is available space on the |
| /// device. |
| /// |
| /// The volume may be larger than this limit if a smaller limit was applied after the |
| /// volume had already grown to the current size. |
| /// |
| /// The volume limit persists across reboots. |
| strict GetLimit() -> (struct { |
| bytes uint64; |
| }) error zx.Status; |
| }; |
| |
| /// A token used for paging through tracked projects. One may be returned by the `ProjectId.List` |
| /// call so it can be passed into the succeeding call to continue the listing from where it left |
| /// off. |
| type ProjectIterToken = struct { |
| value uint64; |
| }; |
| |
| /// Storage for a pair of related byte and node values. |
| type BytesAndNodes = struct { |
| bytes uint64; |
| nodes uint64; |
| }; |
| |
| @discoverable |
| closed protocol ProjectId { |
| /// Set the limit in bytes and node count for an XFS project id. Setting limits lower than |
| /// current usage is accepted but may in the future prevent further increases. Returns |
| /// ZX_ERR_OUT_OF_RANGE if `project_id` is set to zero. |
| strict SetLimit(struct { |
| project_id uint64; |
| bytes uint64; |
| nodes uint64; |
| }) -> () error zx.Status; |
| |
| /// Stop tracking a project id. This will return ZX_ERR_NOT_FOUND if the project isn't |
| /// currently tracked. It will succeed even if the project is still in use more by one or more |
| /// nodes. |
| strict Clear(struct { |
| project_id uint64; |
| }) -> () error zx.Status; |
| |
| /// Apply project id to a node_id from a GetAttrs call. This will return ZX_ERR_NOT_FOUND if |
| /// node doesn't exist, ZX_ERR_ALREADY_EXISTS if there is already a `project_id` applied to |
| /// the node, and ZX_ERR_OUT_OF_RANGE if `project_id` is set to zero. |
| strict SetForNode(struct { |
| node_id uint64; |
| project_id uint64; |
| }) -> () error zx.Status; |
| |
| /// Get the project id based on a given node_id from a GetAttrs call.This will return |
| /// ZX_ERR_NOT_FOUND if the node doesn't exist, and a `project_id` of zero if one is not |
| /// currently applied. |
| strict GetForNode(struct { |
| node_id uint64; |
| }) -> (struct { |
| project_id uint64; |
| }) error zx.Status; |
| |
| /// Remove any project id marker for a given node_id from a GetAttrs call. This will return |
| /// ZX_ERR_NOT_FOUND if the node doesn't exist, or success if the node is found to currently |
| /// have no project id applied to it. |
| strict ClearForNode(struct { |
| node_id uint64; |
| }) -> () error zx.Status; |
| |
| /// Fetches project id numbers currently tracked with a limit or with non-zero usage from lowest |
| /// to highest. If `token` is null, start at the beginning, if `token` is populated with a |
| /// previously provided `next_token` the iteration continues where it left off. If there are |
| /// more projects to be listed then `next_token` will be populated, otherwise it will be null. |
| strict List(struct { |
| token box<ProjectIterToken>; |
| }) -> (struct { |
| entries vector<uint64>:MAX; |
| next_token box<ProjectIterToken>; |
| }) error zx.Status; |
| |
| /// Looks up the limit and usage for a tracked `project_id`. If the `project_id` does not have |
| /// a limit set, or non-zero usage it will return ZX_ERR_NOT_FOUND. |
| strict Info(struct { |
| project_id uint64; |
| }) -> (struct { |
| limit BytesAndNodes; |
| usage BytesAndNodes; |
| }) error zx.Status; |
| }; |
| |
| /// fuchsia.fxfs.Volumes is only used for creating volumes. Other operations (e.g. enumeration and |
| /// deletion) are serviced by the `volumes` directory offered by Fxfs in its export root. Volumes |
| /// appear as files within this directory, and these files should also speak the |
| /// `fuchsia.fxfs.Volume` protocol. |
| /// |
| /// `mount_options` affects how the resulting volume is mounted. For encrypted volumes, the crypt |
| /// setting in the `mount_options` is also used when creating the volume. `outgoing_directory` will |
| /// be connected to the root directory of the volume. |
| @discoverable |
| closed protocol Volumes { |
| /// Creates and mounts a new volume identified by `name`. `mount_options` affects how the |
| /// resulting volume is mounted. For encrypted volumes, `mount_options.crypt` is also used when |
| /// creating the volume. `outgoing_directory` will be connected to the root directory of the |
| /// volume. |
| strict Create(resource struct { |
| name string:fuchsia.io.MAX_FILENAME; |
| outgoing_directory server_end:fuchsia.io.Directory; |
| mount_options MountOptions; |
| }) -> () error zx.Status; |
| |
| /// Permanently deletes a volume identified by `name`. If the volume is mounted, this call will |
| /// fail. |
| strict Remove(struct { |
| name string:fuchsia.io.MAX_FILENAME; |
| }) -> () error zx.Status; |
| }; |
| |
| /// Error type for [`BlobCreator.Create`]. |
| type CreateBlobError = strict enum { |
| /// This blob is currently readable in fxblob. |
| ALREADY_EXISTS = 1; |
| |
| /// An unspecified error occurred while creating the blob. |
| INTERNAL = 2; |
| }; |
| |
| @discoverable |
| closed protocol BlobCreator { |
| /// Creates a blob with the merkle root `hash`. If `allow_existing` is true, the server will |
| /// overwrite the existing blob if there is one. The client will truncate the blob with |
| /// [BlobWriter.GetVmo] and get a handle to a vmo in return. The client will then write blob |
| /// contents into the vmo and call [BlobWriter.BytesReady] on the 'writer` to signal to the |
| /// server that some number of bytes has been written to the vmo. |
| strict Create(struct { |
| hash array<uint8, 32>; |
| allow_existing bool; |
| }) -> (resource struct { |
| writer client_end:BlobWriter; |
| }) error CreateBlobError; |
| }; |
| |
| closed protocol BlobWriter { |
| /// Truncates the blob associated with this BlobWriter proxy to length `size`. Returns a handle |
| /// to a `vmo` shared between the server and the client, which is implemented as a ring buffer. |
| /// As the client writes blob contents into the `vmo`, it will call BytesReady to signal to the |
| /// server that some number of bytes have been written. |
| /// |
| /// Ring Buffer Semantics |
| /// The server sets the size of the vmo passed back to the client. The chunks that the client |
| /// writes are arbitrarily sized and do not have any alignment guarantees. Any particular write |
| /// can wrap around the ring buffer. The client can have several outstanding BytesReady |
| /// requests but the client is responsible for not overwriting a given range in the ring buffer |
| /// until the BytesReady request corresponding to that range has completed. |
| strict GetVmo(struct { |
| size uint64; |
| }) -> (resource struct { |
| vmo zx.Handle:VMO; |
| }) error zx.Status; |
| |
| /// Indicates to the server that an additional `bytes_written` number of bytes have been |
| /// written to the shared vmo and are ready to be read off the vmo and written to disk. The |
| /// blob will be readable when the final BytesReady response is received by the client. |
| strict BytesReady(struct { |
| bytes_written uint64; |
| }) -> () error zx.Status; |
| }; |
| |
| @discoverable |
| closed protocol BlobReader { |
| /// Given the hash of a blob, returns a VMO with its contents. |
| strict GetVmo(struct { |
| blob_hash array<uint8, 32>; |
| }) -> (resource struct { |
| vmo zx.Handle:VMO; |
| }) error zx.Status; |
| }; |
| |
| /// This is an internal protocol for on-device debugging and testing only. |
| /// See `ffx fxfs help` for more details. |
| @discoverable |
| closed protocol Debug { |
| /// Forces a compaction. |
| strict Compact() -> () error zx.Status; |
| |
| /// Deletes a recorded profile from a volume. |
| strict DeleteProfile(struct { |
| volume string:fuchsia.io.MAX_FILENAME; |
| profile string:fuchsia.io.MAX_FILENAME; |
| }) -> () error zx.Status; |
| }; |