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