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