vfs/directory/
entry_container.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//! `EntryContainer` is a trait implemented by directories that allow manipulation of their
6//! content.
7
8use crate::directory::dirents_sink;
9use crate::directory::traversal_position::TraversalPosition;
10use crate::execution_scope::ExecutionScope;
11use crate::node::Node;
12use crate::object_request::ObjectRequestRef;
13use crate::path::Path;
14use fidl::endpoints::ServerEnd;
15use fidl_fuchsia_io as fio;
16use futures::future::BoxFuture;
17use std::any::Any;
18use std::future::{ready, Future};
19use std::sync::Arc;
20use zx_status::Status;
21
22mod private {
23    use fidl_fuchsia_io as fio;
24
25    /// A type-preserving wrapper around [`fuchsia_async::Channel`].
26    #[derive(Debug)]
27    pub struct DirectoryWatcher {
28        channel: fuchsia_async::Channel,
29    }
30
31    impl DirectoryWatcher {
32        /// Provides access to the underlying channel.
33        pub fn channel(&self) -> &fuchsia_async::Channel {
34            let Self { channel } = self;
35            channel
36        }
37    }
38
39    impl TryFrom<fidl::endpoints::ServerEnd<fio::DirectoryWatcherMarker>> for DirectoryWatcher {
40        type Error = zx_status::Status;
41
42        fn try_from(
43            server_end: fidl::endpoints::ServerEnd<fio::DirectoryWatcherMarker>,
44        ) -> Result<Self, Self::Error> {
45            let channel = fuchsia_async::Channel::from_channel(server_end.into_channel());
46            Ok(Self { channel })
47        }
48    }
49}
50
51pub use private::DirectoryWatcher;
52
53/// All directories implement this trait.  If a directory can be modified it should
54/// also implement the `MutableDirectory` trait.
55pub trait Directory: Node {
56    /// Opens a connection to this item if the `path` is "." or a connection to an item inside this
57    /// one otherwise.  `path` will not contain any "." or ".." components.
58    ///
59    /// `flags` holds one or more of the `OPEN_RIGHT_*`, `OPEN_FLAG_*` constants.  Processing of the
60    /// `flags` value is specific to the item - in particular, the `OPEN_RIGHT_*` flags need to
61    /// match the item capabilities.
62    ///
63    /// It is the responsibility of the implementation to strip POSIX flags if the path crosses
64    /// a boundary that does not have the required permissions.
65    ///
66    /// It is the responsibility of the implementation to send an `OnOpen` event on the channel
67    /// contained by `server_end` in case [`fio::OpenFlags::DESCRIBE`]` was set.
68    ///
69    /// This method is called via either `Open` or `Clone` fuchsia.io methods. Any errors that occur
70    /// during this process should be sent as a channel closure epitaph via `server_end`. No errors
71    /// should ever affect the connection where `Open` or `Clone` were received.
72    fn open(
73        self: Arc<Self>,
74        scope: ExecutionScope,
75        flags: fio::OpenFlags,
76        path: Path,
77        server_end: ServerEnd<fio::NodeMarker>,
78    );
79
80    /// Opens a connection to this item if the `path` is "." or a connection to an item inside
81    /// this one otherwise.  `path` will not contain any "." or ".." components.
82    ///
83    /// `flags` corresponds to the fuchsia.io [`fio::Flags`] type. See fuchsia.io's Open3 method for
84    /// more information regarding how flags are handled and what flag combinations are valid.
85    ///
86    /// If this method was initiated by a FIDL Open3 call, hierarchical rights are enforced at the
87    /// connection layer.
88    ///
89    /// If the implementation takes `object_request`, it is then responsible for sending an
90    /// `OnRepresentation` event when `flags` includes [`fio::Flags::FLAG_SEND_REPRESENTATION`].
91    ///
92    /// This method is called via either `Open3` or `Reopen` fuchsia.io methods. Any errors returned
93    /// during this process will be sent via an epitaph on the `object_request` channel before
94    /// closing the channel.
95    fn open3(
96        self: Arc<Self>,
97        scope: ExecutionScope,
98        path: Path,
99        flags: fio::Flags,
100        object_request: ObjectRequestRef<'_>,
101    ) -> Result<(), Status>;
102
103    /// Same as `open3` but the implementation is async. This may be more efficient if the directory
104    /// needs to do async work to open the connection.
105    fn open3_async(
106        self: Arc<Self>,
107        scope: ExecutionScope,
108        path: Path,
109        flags: fio::Flags,
110        object_request: ObjectRequestRef<'_>,
111    ) -> impl Future<Output = Result<(), Status>> + Send
112    where
113        Self: Sized,
114    {
115        ready(self.open3(scope, path, flags, object_request))
116    }
117
118    /// Reads directory entries starting from `pos` by adding them to `sink`.
119    /// Once finished, should return a sealed sink.
120    // The lifetimes here are because of https://github.com/rust-lang/rust/issues/63033.
121    fn read_dirents<'a>(
122        &'a self,
123        pos: &'a TraversalPosition,
124        sink: Box<dyn dirents_sink::Sink>,
125    ) -> impl Future<Output = Result<(TraversalPosition, Box<dyn dirents_sink::Sealed>), Status>> + Send
126    where
127        Self: Sized;
128
129    /// Register a watcher for this directory.
130    /// Implementations will probably want to use a `Watcher` to manage watchers.
131    fn register_watcher(
132        self: Arc<Self>,
133        scope: ExecutionScope,
134        mask: fio::WatchMask,
135        watcher: DirectoryWatcher,
136    ) -> Result<(), Status>;
137
138    /// Unregister a watcher from this directory. The watcher should no longer
139    /// receive events.
140    fn unregister_watcher(self: Arc<Self>, key: usize);
141}
142
143/// This trait indicates a directory that can be mutated by adding and removing entries.
144/// This trait must be implemented to use a `MutableConnection`, however, a directory could also
145/// implement the `DirectlyMutable` type, which provides a blanket implementation of this trait.
146pub trait MutableDirectory: Directory + Send + Sync {
147    /// Adds a child entry to this directory.  If the target exists, it should fail with
148    /// ZX_ERR_ALREADY_EXISTS.
149    fn link<'a>(
150        self: Arc<Self>,
151        _name: String,
152        _source_dir: Arc<dyn Any + Send + Sync>,
153        _source_name: &'a str,
154    ) -> BoxFuture<'a, Result<(), Status>> {
155        Box::pin(ready(Err(Status::NOT_SUPPORTED)))
156    }
157
158    /// Set the mutable attributes of this directory based on the values in `attributes`. If the
159    /// directory does not support updating *all* of the specified attributes, implementations
160    /// should fail with `ZX_ERR_NOT_SUPPORTED`.
161    fn update_attributes(
162        &self,
163        attributes: fio::MutableNodeAttributes,
164    ) -> impl Future<Output = Result<(), Status>> + Send
165    where
166        Self: Sized;
167
168    /// Removes an entry from this directory.
169    fn unlink(
170        self: Arc<Self>,
171        name: &str,
172        must_be_directory: bool,
173    ) -> impl Future<Output = Result<(), Status>> + Send
174    where
175        Self: Sized;
176
177    /// Syncs the directory.
178    fn sync(&self) -> impl Future<Output = Result<(), Status>> + Send
179    where
180        Self: Sized;
181
182    /// Renames into this directory.
183    fn rename(
184        self: Arc<Self>,
185        _src_dir: Arc<dyn MutableDirectory>,
186        _src_name: Path,
187        _dst_name: Path,
188    ) -> BoxFuture<'static, Result<(), Status>> {
189        Box::pin(ready(Err(Status::NOT_SUPPORTED)))
190    }
191
192    /// Creates a symbolic link.
193    fn create_symlink(
194        &self,
195        _name: String,
196        _target: Vec<u8>,
197        _connection: Option<ServerEnd<fio::SymlinkMarker>>,
198    ) -> impl Future<Output = Result<(), Status>> + Send
199    where
200        Self: Sized,
201    {
202        ready(Err(Status::NOT_SUPPORTED))
203    }
204
205    /// List extended attributes.
206    fn list_extended_attributes(&self) -> impl Future<Output = Result<Vec<Vec<u8>>, Status>> + Send
207    where
208        Self: Sized,
209    {
210        ready(Err(Status::NOT_SUPPORTED))
211    }
212
213    /// Get the value for an extended attribute.
214    fn get_extended_attribute(
215        &self,
216        _name: Vec<u8>,
217    ) -> impl Future<Output = Result<Vec<u8>, Status>> + Send
218    where
219        Self: Sized,
220    {
221        ready(Err(Status::NOT_SUPPORTED))
222    }
223
224    /// Set the value for an extended attribute.
225    fn set_extended_attribute(
226        &self,
227        _name: Vec<u8>,
228        _value: Vec<u8>,
229        _mode: fio::SetExtendedAttributeMode,
230    ) -> impl Future<Output = Result<(), Status>> + Send
231    where
232        Self: Sized,
233    {
234        ready(Err(Status::NOT_SUPPORTED))
235    }
236
237    /// Remove the value for an extended attribute.
238    fn remove_extended_attribute(
239        &self,
240        _name: Vec<u8>,
241    ) -> impl Future<Output = Result<(), Status>> + Send
242    where
243        Self: Sized,
244    {
245        ready(Err(Status::NOT_SUPPORTED))
246    }
247}