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