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}