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