blob: 2cbd648afcb0a96fe3eedb65f15537855db804f1 [file] [log] [blame]
// Copyright 2018 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::RequestStream,
fidl_fuchsia_io::{
DirectoryObject, DirectoryProxy, DirectoryRequest, DirectoryRequestStream,
OPEN_FLAG_DESCRIBE,
},
fuchsia_async as fasync,
fuchsia_zircon::Status,
futures::future::BoxFuture,
futures::future::FutureExt,
futures::stream::StreamExt,
parking_lot::Mutex,
std::{collections::HashMap, sync::Arc},
};
type OpenCounter = Arc<Mutex<HashMap<String, u64>>>;
fn handle_directory_request_stream(
mut stream: DirectoryRequestStream,
open_counts: OpenCounter,
) -> BoxFuture<'static, ()> {
async move {
while let Some(req) = stream.next().await {
handle_directory_request(req.unwrap(), Arc::clone(&open_counts)).await;
}
}
.boxed()
}
async fn handle_directory_request(req: DirectoryRequest, open_counts: OpenCounter) {
match req {
DirectoryRequest::Clone { flags, object, control_handle: _control_handle } => {
let stream = DirectoryRequestStream::from_channel(
fasync::Channel::from_channel(object.into_channel()).unwrap(),
);
describe_dir(flags, &stream);
fasync::Task::spawn(handle_directory_request_stream(stream, Arc::clone(&open_counts)))
.detach();
}
DirectoryRequest::Open {
flags: _flags,
mode: _mode,
path,
object: _object,
control_handle: _control_handle,
} => {
*open_counts.lock().entry(path).or_insert(0) += 1;
}
other => panic!("unhandled request type: {:?}", other),
}
}
pub fn describe_dir(flags: u32, stream: &DirectoryRequestStream) {
let ch = stream.control_handle();
if flags & OPEN_FLAG_DESCRIBE != 0 {
let mut ni = fidl_fuchsia_io::NodeInfo::Directory(DirectoryObject);
ch.send_on_open_(Status::OK.into_raw(), Some(&mut ni)).expect("send_on_open");
}
}
pub fn spawn_directory_handler() -> (DirectoryProxy, OpenCounter) {
let (proxy, stream) =
fidl::endpoints::create_proxy_and_stream::<fidl_fuchsia_io::DirectoryMarker>().unwrap();
let open_counts = Arc::new(Mutex::new(HashMap::<String, u64>::new()));
fasync::Task::spawn(handle_directory_request_stream(stream, Arc::clone(&open_counts))).detach();
(proxy, open_counts)
}