blob: 7ef43ad00c74ba67fca7aba1b9953cad3f113697 [file] [log] [blame]
// 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;
};