blob: 648cd56fd80e76f3a1ed9ed8333d373b4034e1a2 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
fidl::endpoints::ServerEnd,
fidl_fuchsia_io::{DirectoryProxy, NodeMarker, DIRENT_TYPE_SERVICE, INO_UNKNOWN},
parking_lot::Mutex,
std::sync::Arc,
vfs as fvfs,
vfs::{
directory::entry::DirectoryEntry, directory::entry::EntryInfo,
execution_scope::ExecutionScope, path::Path,
},
};
pub type RoutingFn = Box<dyn FnMut(u32, u32, String, ServerEnd<NodeMarker>) + Send + Sync>;
// TODO(fxbug.dev/33398): move this into the pseudo dir fs crate.
/// DirectoryBroker exists to hold a slot in a fuchsia_vfs_pseudo_fs directory and proxy open
/// requests. A DirectoryBroker holds a closure provided at creation time, and whenever an open
/// request for this directory entry is received the given ServerEnd is passed into the closure,
/// which will presumably make an open request somewhere else and forward on the ServerEnd.
pub struct DirectoryBroker {
inner: Mutex<Inner>,
}
struct Inner {
/// The parameters are as follows:
/// flags: u32
/// mode: u32
/// relative_path: String
/// server_end: ServerEnd<NodeMarker>
route_open: RoutingFn,
entry_info: fvfs::directory::entry::EntryInfo,
}
impl DirectoryBroker {
/// new will create a new DirectoryBroker to forward directory open requests.
pub fn new(route_open: RoutingFn) -> Arc<DirectoryBroker> {
return Arc::new(DirectoryBroker {
inner: Mutex::new(Inner {
route_open,
entry_info: EntryInfo::new(INO_UNKNOWN, DIRENT_TYPE_SERVICE),
}),
});
}
pub fn from_directory_proxy(dir: DirectoryProxy) -> Arc<DirectoryBroker> {
Self::new(Box::new(
move |flags: u32,
mode: u32,
relative_path: String,
server_end: ServerEnd<NodeMarker>| {
// If we want to open the 'dir' directory directly, then call clone.
// Otherwise, pass long the remaining 'relative_path' to the component
// hosting the out directory to resolve.
if !relative_path.is_empty() {
// TODO(fsamuel): Currently DirectoryEntry::open does not return
// a Result so we cannot propagate this error up. We probably
// want to change that.
let _ = dir.open(flags, mode, &relative_path, server_end);
} else {
// TODO(fsamuel): For some reason, DirectoryProxy receives an
// empty string as a relative path. That is unsupported by open.
// Why does it receive an empty string? Shouldn't it be "."?
// Or should directories support empty strings as relative paths?
// For now, change the empty string to ".", but investigate further.
let _ = dir.open(flags, mode, ".", server_end);
}
},
))
}
}
impl DirectoryEntry for DirectoryBroker {
fn open(
self: Arc<Self>,
_scope: ExecutionScope,
flags: u32,
mode: u32,
path: Path,
server_end: ServerEnd<NodeMarker>,
) {
let mut this = self.inner.lock();
(&mut this.route_open)(flags, mode, path.into_string(), server_end);
}
fn entry_info(&self) -> fvfs::directory::entry::EntryInfo {
self.inner.lock().entry_info.clone()
}
fn can_hardlink(&self) -> bool {
false
}
}