sandbox/fidl/
dir_connector.rs1use crate::dir_connector::DirConnectable;
6use crate::fidl::registry;
7use crate::fidl::registry::try_from_handle_in_registry;
8use crate::{
9 Capability, ConversionError, DirConnector, DirReceiver, RemoteError, WeakInstanceToken,
10};
11use cm_types::{Name, RelativePath};
12use fidl::endpoints::{ClientEnd, ServerEnd};
13use futures::channel::mpsc;
14use std::fmt;
15use std::sync::Arc;
16use vfs::directory::entry::{DirectoryEntry, EntryInfo, GetEntryInfo, OpenRequest};
17use vfs::execution_scope::ExecutionScope;
18use vfs::object_request::{ObjectRequest, ObjectRequestRef};
19use vfs::remote::RemoteLike;
20use {fidl_fuchsia_component_sandbox as fsandbox, fidl_fuchsia_io as fio, fuchsia_async as fasync};
21
22impl DirConnector {
23 pub(crate) fn new_with_fidl_receiver(
24 receiver_client: ClientEnd<fsandbox::DirReceiverMarker>,
25 scope: &fasync::Scope,
26 ) -> Self {
27 let (sender, receiver) = mpsc::unbounded();
28 let receiver = DirReceiver::new(receiver);
29 scope.spawn(receiver.handle_receiver(receiver_client.into_proxy()));
31 Self::new_sendable(sender)
32 }
33
34 pub fn from_directory_entry(
35 directory_entry: Arc<dyn DirectoryEntry>,
36 flags: fio::Flags,
37 ) -> Self {
38 assert_eq!(directory_entry.entry_info().type_(), fio::DirentType::Directory);
39 DirConnector::new_sendable(DirectoryEntryDirConnector {
40 directory_entry,
41 scope: ExecutionScope::new(),
42 flags,
43 })
44 }
45}
46
47struct DirectoryEntryDirConnector {
48 directory_entry: Arc<dyn DirectoryEntry>,
49 scope: ExecutionScope,
50 flags: fio::Flags,
51}
52
53impl fmt::Debug for DirectoryEntryDirConnector {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
56 #[allow(dead_code)]
57 #[derive(Debug)]
58 struct DirectoryEntryDirConnector<'a> {
59 scope: &'a ExecutionScope,
60 flags: &'a fio::Flags,
61 }
62 fmt::Debug::fmt(&DirectoryEntryDirConnector { scope: &self.scope, flags: &self.flags }, f)
63 }
64}
65
66impl DirConnectable for DirectoryEntryDirConnector {
67 fn maximum_flags(&self) -> fio::Flags {
68 self.flags
69 }
70
71 fn send(
72 &self,
73 channel: ServerEnd<fio::DirectoryMarker>,
74 subdir: RelativePath,
75 flags: Option<fio::Flags>,
76 ) -> Result<(), ()> {
77 let flags = flags.unwrap_or(self.flags);
78 let mut object_request =
79 ObjectRequest::new(flags, &fio::Options::default(), channel.into_channel());
80 let path = vfs::path::Path::validate_and_split(format!("{}", subdir))
81 .expect("relative path is invalid vfs path");
82 let open_request = OpenRequest::new(self.scope.clone(), flags, path, &mut object_request);
83 self.directory_entry.clone().open_entry(open_request).map_err(|_| ())
84 }
85}
86
87impl RemoteLike for DirConnector {
88 fn open(
89 self: Arc<Self>,
90 _scope: ExecutionScope,
91 mut path: vfs::path::Path,
92 flags: fio::Flags,
93 object_request: ObjectRequestRef<'_>,
94 ) -> Result<(), zx::Status> {
95 let mut relative_path = RelativePath::dot();
96 while let Some(segment) = path.next() {
97 let name = Name::new(segment).map_err(|_e|
98 zx::Status::INVALID_ARGS)?;
100 let success = relative_path.push(name);
101 if !success {
102 return Err(zx::Status::INVALID_ARGS);
104 }
105 }
106 self.send(object_request.take().into_server_end(), relative_path, Some(flags))
107 .map_err(|_| zx::Status::INTERNAL)
108 }
109}
110
111impl DirectoryEntry for DirConnector {
112 fn open_entry(self: Arc<Self>, request: OpenRequest<'_>) -> Result<(), zx::Status> {
113 request.open_remote(self)
114 }
115}
116
117impl GetEntryInfo for DirConnector {
118 fn entry_info(&self) -> EntryInfo {
119 EntryInfo::new(fio::INO_UNKNOWN, fio::DirentType::Directory)
120 }
121}
122
123impl crate::RemotableCapability for DirConnector {
124 fn try_into_directory_entry(
125 self,
126 _scope: ExecutionScope,
127 _token: WeakInstanceToken,
128 ) -> Result<Arc<dyn DirectoryEntry>, ConversionError> {
129 Ok(Arc::new(self))
130 }
131}
132
133impl TryFrom<fsandbox::DirConnector> for DirConnector {
134 type Error = RemoteError;
135
136 fn try_from(dir_connector: fsandbox::DirConnector) -> Result<Self, Self::Error> {
137 let any = try_from_handle_in_registry(dir_connector.token.as_handle_ref())?;
138 let Capability::DirConnector(dir_connector) = any else {
139 panic!("BUG: registry has a non-dir-connector capability under a dir-connector koid");
140 };
141 Ok(dir_connector)
142 }
143}
144
145impl From<DirConnector> for fsandbox::DirConnector {
146 fn from(value: DirConnector) -> Self {
147 fsandbox::DirConnector { token: registry::insert_token(value.into()) }
148 }
149}
150
151impl crate::fidl::IntoFsandboxCapability for DirConnector {
152 fn into_fsandbox_capability(self, _token: WeakInstanceToken) -> fsandbox::Capability {
153 fsandbox::Capability::DirConnector(self.into())
154 }
155}