Storage capabilities

Storage capabilities allocate per-component isolated storage within a filesystem directory. This prevents component instances from accessing files belonging to other components, including their own children.

For information on directories that can be shared between components, see directory capabilities.

Backing directories

Each storage capability must be backed by a corresponding directory capability to host an isolated subdirectory for each component. When a component instance attempts to access the directory provided to it through a storage capability, the framework generates a unique subdirectory inside the backing directory for that component.

The framework allocates storage subdirectories based on either the component instance's moniker or a static instance ID . Each instance ID is a 256-bit globally unique identifier listed in a component storage index file.

The following is an example entry in a component storage index file containing a stable instance ID:

{
    instances: [
        {
            instance_id: "47c3bf08f3e560c4dee659c28fa8d863dbdc0b1dbb74065e6cb1f38441ac759c",
            moniker: "/core/my_component",
        },
    ],
}

Instance IDs allow a component's storage to persist across changes to the component's moniker, such as moving the component instance to a different realm. Storage IDs based on moniker are a good secondary option for tests or other use cases where storage does not need to be durable.

For more details on instance IDs, see Component storage index.

Providing storage capabilities

To provide a storage capability, a component must declare the capability and route it from self.

{
    capabilities: [
        {
            storage: "tmp",
            from: "self",
            backing_dir: "memfs",
            storage_id: "static_instance_id",
        },
    ],
}

You must specify backing_dir with a valid directory capability name.

The from field declares the component providing the backing directory. You may supply a component reference if the provider is another component.

Routing storage capabilities

Storage capabilities cannot be exposed to a parent component. Components should route the backing directory to an appropriate parent component where storage can be declared and offered to the necessary children.

For more details on how the framework routes component capabilities, see capability routing.

Offering

Offering a storage capability gives a child component access to that capability:

{
    offer: [
        {
            storage: "data",
            from: "self",
            to: [ "#storage-user" ],
        },
    ],
}

Consuming storage capabilities

To consume a storage capability, the component must request the capability and open the corresponding path in its namespace .

To request the capability, add a use declaration for it:

{
    use: [
        {
            storage: "data",
            path: "/example_dir",
        },
    ],
}

This populates the component's namespace with a directory at the provided path containing the isolated storage contents.

Storage example

Consider the following example where component A requests isolated storage tmp from its parent:

// A.cml
{
    use: [
        {
            storage: "tmp",
            path: "/example_dir",
        },
    ],
}

This provides an isolated storage directory at /example_dir in the namespace of component A. The parent component B offers this capability to A using a backing directory provided by the memfs component in the same realm:

// B.cml
{
    capabilities: [
        {
            storage: "tmp",
            from: "#memfs",
            backing_dir: "memfs",
        },
    ],
    offer: [
        {
            storage: "tmp",
            from: "self",
            to: [ "#A" ],
        },
    ],
    children: [
        { name: "A", url: "fuchsia-pkg://...", },
        { name: "memfs", url: "fuchsia-pkg://..." },
    ],
}

For more details on implementing directories, see directory capabilities.