Skip to main content

vfs/directory/
helper.rs

1// Copyright 2020 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
5use crate::directory::entry::DirectoryEntry;
6use crate::directory::entry_container::Directory;
7use crate::name::Name;
8use name::ParseNameError;
9use std::sync::Arc;
10use thiserror::Error;
11use zx_status::Status;
12
13/// An entry with the same name already exists in the directory.
14#[derive(Error, Debug)]
15#[error("An entry with the same name already exists in the directory")]
16pub struct AlreadyExists;
17
18impl Into<Status> for AlreadyExists {
19    fn into(self) -> Status {
20        Status::ALREADY_EXISTS
21    }
22}
23
24/// The entry identified by `name` is not a directory.
25#[derive(Error, Debug)]
26#[error("The specified entry is not a directory")]
27pub struct NotDirectory;
28
29impl Into<Status> for NotDirectory {
30    fn into(self) -> Status {
31        Status::NOT_DIR
32    }
33}
34
35/// `DirectlyMutable` is a superset of `MutableDirectory` which also allows server-side management
36/// of directory entries (via `add_entry` and `remove_entry`).
37pub trait DirectlyMutable: Directory + Send + Sync {
38    /// Adds a child entry to this directory.
39    ///
40    /// Possible errors are:
41    ///   * `ZX_ERR_INVALID_ARGS` or `ZX_ERR_BAD_PATH` if `name` is not a valid [`Name`].
42    ///   * `ZX_ERR_ALREADY_EXISTS` if an entry with the same name is already present in the
43    ///     directory.
44    fn add_entry(
45        &self,
46        name: impl TryInto<Name, Error: Into<ParseNameError>>,
47        entry: Arc<dyn DirectoryEntry>,
48    ) -> Result<(), Status> {
49        self.add_entry_may_overwrite(name, entry, false)
50    }
51
52    /// Adds a child entry to this directory. If `overwrite` is true, this function may overwrite
53    /// an existing entry.
54    ///
55    /// Possible errors are:
56    ///   * `ZX_ERR_INVALID_ARGS` or `ZX_ERR_BAD_PATH` if `name` is not a valid [`Name`].
57    ///   * `ZX_ERR_ALREADY_EXISTS` if an entry with the same name is already present in the
58    ///     directory and `overwrite` is false.
59    fn add_entry_may_overwrite(
60        &self,
61        name: impl TryInto<Name, Error: Into<ParseNameError>>,
62        entry: Arc<dyn DirectoryEntry>,
63        overwrite: bool,
64    ) -> Result<(), Status> {
65        let name: Name = name.try_into().map_err(Into::into)?;
66        self.add_entry_impl(name, entry, overwrite)
67            .map_err(|_: AlreadyExists| Status::ALREADY_EXISTS)
68    }
69
70    /// Adds a child entry to this directory.
71    fn add_entry_impl(
72        &self,
73        name: Name,
74        entry: Arc<dyn DirectoryEntry>,
75        overwrite: bool,
76    ) -> Result<(), AlreadyExists>;
77
78    /// Removes a child entry from this directory.  In case an entry with the matching name was
79    /// found, the entry will be returned to the caller.  If `must_be_directory` is true, an error
80    /// is returned if the entry is not a directory.
81    ///
82    /// Possible errors are:
83    ///   * `ZX_ERR_INVALID_ARGS` or `ZX_ERR_BAD_PATH` if `name` is not a valid [`Name`].
84    ///   * `ZX_ERR_NOT_DIR` if the entry identified by `name` is not a directory and
85    ///     `must_be_directory` is true.
86    fn remove_entry<NameT>(
87        &self,
88        name: NameT,
89        must_be_directory: bool,
90    ) -> Result<Option<Arc<dyn DirectoryEntry>>, Status>
91    where
92        NameT: Into<String>,
93        Self: Sized,
94    {
95        let name: String = name.into();
96        let name: Name = name.try_into()?;
97        let entry = self
98            .remove_entry_impl(name, must_be_directory)
99            .map_err(|_: NotDirectory| Status::NOT_DIR)?;
100        Ok(entry)
101    }
102
103    /// Removes a child entry from this directory.  In case an entry with the matching name was
104    /// found, the entry will be returned to the caller.
105    fn remove_entry_impl(
106        &self,
107        name: Name,
108        must_be_directory: bool,
109    ) -> Result<Option<Arc<dyn DirectoryEntry>>, NotDirectory>;
110}