vfs/
directory.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//! Module holding different kinds of pseudo directories and their building blocks.
6
7use crate::directory::entry_container::Directory;
8use crate::execution_scope::ExecutionScope;
9use crate::object_request::ToObjectRequest as _;
10use crate::path::Path;
11use fidl::endpoints::ServerEnd;
12use fidl_fuchsia_io as fio;
13use std::sync::Arc;
14
15#[cfg(test)]
16#[macro_use]
17pub(crate) mod test_utils;
18
19pub mod common;
20
21pub mod immutable;
22pub mod mutable;
23
24mod connection;
25pub mod dirents_sink;
26pub mod entry;
27pub mod entry_container;
28pub mod helper;
29pub mod read_dirents;
30pub mod simple;
31pub mod traversal_position;
32pub mod watchers;
33
34/// A directory can be open either as a directory or a node.
35#[derive(Clone)]
36pub struct DirectoryOptions {
37    pub(crate) rights: fio::Operations,
38}
39
40impl DirectoryOptions {
41    pub(crate) fn to_io1(&self) -> fio::OpenFlags {
42        // Note that rights in io1 correspond to several different rights in io2. The *_STAR_DIR
43        // constants defined in the protocol indicate which rights these flags map to. Note that
44        // this is more strict than the checks in FileOptions::to_io1, as OpenFlags map to several
45        // different io2 directory rights.
46        let mut flags = fio::OpenFlags::empty();
47        if self.rights.contains(fio::R_STAR_DIR) {
48            flags |= fio::OpenFlags::RIGHT_READABLE;
49        }
50        if self.rights.contains(fio::W_STAR_DIR) {
51            flags |= fio::OpenFlags::RIGHT_WRITABLE;
52        }
53        if self.rights.contains(fio::X_STAR_DIR) {
54            flags |= fio::OpenFlags::RIGHT_EXECUTABLE;
55        }
56        flags
57    }
58}
59
60impl From<&DirectoryOptions> for fio::Flags {
61    fn from(options: &DirectoryOptions) -> Self {
62        // There is 1:1 mapping between `fio::Operations` and `fio::Flags`.
63        fio::Flags::PROTOCOL_DIRECTORY | fio::Flags::from_bits_truncate(options.rights.bits())
64    }
65}
66
67impl Default for DirectoryOptions {
68    fn default() -> Self {
69        DirectoryOptions { rights: fio::R_STAR_DIR }
70    }
71}
72
73/// Helper function to serve a new connection to `directory` with `flags`. Errors will be
74/// communicated via epitaph on the returned proxy. A new [`crate::execution_scope::ExecutionScope`]
75/// will be created for the request.
76pub fn serve<D: Directory + ?Sized>(directory: Arc<D>, flags: fio::Flags) -> fio::DirectoryProxy {
77    crate::serve_directory(directory, Path::dot(), flags)
78}
79
80/// Helper function to serve a new connection to `directory` as read-only (i.e. with
81/// [`fio::PERM_READABLE`]). Errors will be communicated via epitaph on the returned proxy. A new
82/// [`crate::execution_scope::ExecutionScope`] will be created for the request.
83pub fn serve_read_only<D: Directory + ?Sized>(directory: Arc<D>) -> fio::DirectoryProxy {
84    crate::serve_directory(directory, Path::dot(), fio::PERM_READABLE)
85}
86
87/// Helper function to serve a connection to `directory` on `server_end` with specified `flags` and
88/// `scope`. Errors will be communicated via epitaph on `server_end`.
89pub fn serve_on<D: Directory + ?Sized>(
90    directory: Arc<D>,
91    flags: fio::Flags,
92    scope: ExecutionScope,
93    server_end: ServerEnd<fio::DirectoryMarker>,
94) {
95    let request = flags.to_object_request(server_end);
96    request.handle(|request| directory.open(scope, Path::dot(), flags, request));
97}