sandbox/fidl/
dir_entry.rs1use crate::connector::Connectable;
6use crate::fidl::registry;
7use crate::{Connector, ConversionError, DirEntry, RemotableCapability, WeakInstanceToken};
8use fidl::handle::Status;
9use std::sync::Arc;
10use vfs::ToObjectRequest;
11use vfs::directory::entry::{DirectoryEntry, EntryInfo, GetEntryInfo, OpenRequest};
12use vfs::execution_scope::ExecutionScope;
13use {fidl_fuchsia_component_sandbox as fsandbox, fidl_fuchsia_io as fio};
14
15impl RemotableCapability for DirEntry {
16 fn try_into_directory_entry(
17 self,
18 _scope: ExecutionScope,
19 _token: WeakInstanceToken,
20 ) -> Result<Arc<dyn DirectoryEntry>, ConversionError> {
21 Ok(self.to_directory_entry())
22 }
23}
24
25impl From<DirEntry> for fsandbox::DirEntry {
26 fn from(value: DirEntry) -> Self {
27 fsandbox::DirEntry { token: registry::insert_token(value.into()) }
28 }
29}
30
31impl crate::fidl::IntoFsandboxCapability for DirEntry {
32 fn into_fsandbox_capability(self, _token: WeakInstanceToken) -> fsandbox::Capability {
33 fsandbox::Capability::DirEntry(self.into())
34 }
35}
36
37impl Connectable for DirEntry {
38 fn send(&self, message: crate::Message) -> Result<(), ()> {
39 const FLAGS: fio::Flags = fio::Flags::PROTOCOL_SERVICE;
40 FLAGS.to_object_request(message.channel).handle(|request| {
41 self.open_entry(OpenRequest::new(
42 ExecutionScope::new(),
43 FLAGS,
44 vfs::Path::dot(),
45 request,
46 ))
47 });
48 Ok(())
49 }
50}
51
52impl GetEntryInfo for DirEntry {
53 fn entry_info(&self) -> EntryInfo {
54 self.entry.entry_info()
55 }
56}
57
58impl DirectoryEntry for DirEntry {
59 fn open_entry(self: Arc<Self>, request: OpenRequest<'_>) -> Result<(), Status> {
60 self.entry.clone().open_entry(request)
61 }
62}
63
64impl DirEntry {
65 pub fn new(entry: Arc<dyn DirectoryEntry>) -> Self {
67 Self { entry }
68 }
69
70 pub fn to_directory_entry(self) -> Arc<dyn DirectoryEntry> {
71 self.entry
72 }
73
74 pub fn open_entry(&self, open_request: OpenRequest<'_>) -> Result<(), Status> {
76 self.entry.clone().open_entry(open_request)
77 }
78
79 pub fn dirent_type(&self) -> fio::DirentType {
80 self.entry.entry_info().type_()
81 }
82}
83
84impl From<Connector> for DirEntry {
85 fn from(connector: Connector) -> Self {
86 Self::new(vfs::service::endpoint(move |_scope, server_end| {
87 let _ = connector.send_channel(server_end.into_zx_channel().into());
88 }))
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use crate::Capability;
96 use crate::fidl::IntoFsandboxCapability;
97 use fidl::endpoints;
98 use fidl_fuchsia_io as fio;
99 use test_util::Counter;
100 use vfs::directory::entry::{EntryInfo, GetEntryInfo, OpenRequest};
101 use vfs::execution_scope::ExecutionScope;
102 use vfs::path::Path;
103 use vfs::remote::RemoteLike;
104 use vfs::{ObjectRequestRef, ToObjectRequest};
105
106 struct MockDir(Counter);
107 impl DirectoryEntry for MockDir {
108 fn open_entry(self: Arc<Self>, request: OpenRequest<'_>) -> Result<(), zx::Status> {
109 request.open_remote(self)
110 }
111 }
112 impl GetEntryInfo for MockDir {
113 fn entry_info(&self) -> EntryInfo {
114 EntryInfo::new(fio::INO_UNKNOWN, fio::DirentType::Directory)
115 }
116 }
117 impl RemoteLike for MockDir {
118 fn open(
119 self: Arc<Self>,
120 _scope: ExecutionScope,
121 _relative_path: Path,
122 _flags: fio::Flags,
123 _object_request: ObjectRequestRef<'_>,
124 ) -> Result<(), Status> {
125 self.0.inc();
126 Ok(())
127 }
128 }
129
130 #[fuchsia::test]
131 async fn into_fidl() {
132 let mock_dir = Arc::new(MockDir(Counter::new(0)));
133 let dir_entry = Capability::DirEntry(DirEntry::new(mock_dir.clone()));
134
135 let cap = dir_entry.into_fsandbox_capability(WeakInstanceToken::new_invalid());
138 let cap = Capability::try_from(cap).unwrap();
139 let Capability::DirEntry(dir_entry) = cap else {
140 panic!();
141 };
142
143 assert_eq!(mock_dir.0.get(), 0);
144 let scope = ExecutionScope::new();
145 const FLAGS: fio::Flags = fio::PERM_READABLE;
146 let (_client, server) = endpoints::create_endpoints::<fio::DirectoryMarker>();
147 let mut object_request = FLAGS.to_object_request(server);
148 let dir_entry = dir_entry
149 .clone()
150 .try_into_directory_entry(scope.clone(), WeakInstanceToken::new_invalid())
151 .unwrap();
152 dir_entry
153 .open_entry(OpenRequest::new(scope.clone(), FLAGS, Path::dot(), &mut object_request))
154 .unwrap();
155 assert_eq!(mock_dir.0.get(), 1);
156 }
157}