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.