vfs/lib.rs
1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! A library to create "pseudo" file systems. These file systems are backed by in process
6//! callbacks. Examples are: component configuration, debug information or statistics.
7
8#![recursion_limit = "1024"]
9
10pub mod test_utils;
11
12#[macro_use]
13pub mod common;
14
15pub mod execution_scope;
16pub use ::name;
17pub mod path;
18
19pub mod directory;
20pub mod file;
21pub mod node;
22pub mod object_request;
23mod protocols;
24pub mod remote;
25mod request_handler;
26pub mod service;
27pub mod symlink;
28pub mod temp_clone;
29pub mod token_registry;
30pub mod tree_builder;
31
32// --- pseudo_directory ---
33
34// pseudo_directory! uses helper functions that live in this module. It needs to be accessible
35// from the outside of this crate.
36#[doc(hidden)]
37pub mod pseudo_directory;
38
39/// Builds a pseudo directory using a simple DSL, potentially containing files and nested pseudo
40/// directories.
41///
42/// A directory is described using a sequence of rules of the following form:
43///
44/// <name> `=>` <something that implements DirectoryEntry>
45///
46/// separated by commas, with an optional trailing comma.
47///
48/// It generates a nested pseudo directory, using [`directory::immutable::Simple::new()`] then
49/// adding all the specified entries in it, by calling
50/// [`crate::directory::helper::DirectlyMutable::add_entry`].
51///
52/// Note: Names specified as literals (both `str` and `[u8]`) are compared during compilation time,
53/// so you should get a nice error message, if you specify the same entry name twice. As entry
54/// names can be specified as expressions, you can easily work around this check - you will still
55/// get an error, but it would be a `panic!` in this case. In any case the error message will
56/// contain details of the location of the generating macro and the duplicate entry name.
57///
58/// # Examples
59///
60/// This will construct a small tree of read-only files:
61/// ```
62/// let root = pseudo_directory! {
63/// "etc" => pseudo_directory! {
64/// "fstab" => read_only(b"/dev/fs /"),
65/// "passwd" => read_only(b"[redacted]"),
66/// "shells" => read_only(b"/bin/bash"),
67/// "ssh" => pseudo_directory! {
68/// "sshd_config" => read_only(b"# Empty"),
69/// },
70/// },
71/// "uname" => read_only(b"Fuchsia"),
72/// };
73/// ```
74pub use vfs_macros::pseudo_directory;
75
76pub use common::CreationMode;
77pub use execution_scope::{ExecutionScope, WeakExecutionScope};
78pub use object_request::{ObjectRequest, ObjectRequestRef, ToObjectRequest};
79pub use path::Path;
80pub use protocols::ProtocolsExt;
81
82// This allows the pseudo_directory! macro to use absolute paths within this crate to refer to the
83// helper functions. External crates that use pseudo_directory! will rely on the pseudo_directory
84// export above.
85#[cfg(test)]
86extern crate self as vfs;
87
88#[cfg(test)]
89use flex_test_placeholders as _;
90#[cfg(all(test, feature = "fdomain"))]
91use fuchsia_fs_fdomain as _;
92
93use directory::entry_container::Directory;
94use flex_fuchsia_io as fio;
95use std::sync::Arc;
96
97/// Helper function to serve a new connection to the directory at `path` under `root` with `flags`.
98/// Errors will be communicated via epitaph on the returned proxy. A new [`ExecutionScope`] will be
99/// created for the request.
100///
101/// To serve `root` itself, use [`crate::directory::serve`] or set `path` to [`Path::dot`].
102pub fn serve_directory<D: Directory + ?Sized>(
103 root: Arc<D>,
104 path: Path,
105 scope: ExecutionScope,
106 flags: fio::Flags,
107) -> fio::DirectoryProxy {
108 let (proxy, server) = scope.domain().create_proxy::<fio::DirectoryMarker>();
109 let request = flags.to_object_request(server);
110 request.handle(|request| root.open(scope, path, flags, request));
111 proxy
112}
113
114/// Helper function to serve a new connection to the file at `path` under `root` with `flags`.
115/// Errors will be communicated via epitaph on the returned proxy. A new [`ExecutionScope`] will be
116/// created for the request.
117///
118/// To serve an object that implements [`crate::file::File`], use [`crate::file::serve`].
119pub fn serve_file<D: Directory + ?Sized>(
120 root: Arc<D>,
121 path: Path,
122 scope: ExecutionScope,
123 flags: fio::Flags,
124) -> fio::FileProxy {
125 let (proxy, server) = scope.domain().create_proxy::<fio::FileMarker>();
126 let request = flags.to_object_request(server);
127 request.handle(|request| root.open(scope, path, flags, request));
128 proxy
129}