devfs/
lib.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use anyhow::{bail, format_err, Context};
6use fidl::endpoints::ServerEnd;
7use fidl::HandleBased;
8use fuchsia_component::directory::AsRefDirectory;
9use fuchsia_component::server::ServiceFs;
10use futures::prelude::*;
11use log::info;
12use std::collections::HashSet;
13use vfs::remote;
14use {
15    fidl_fuchsia_io as fio, fidl_fuchsia_process as fprocess, fidl_fuchsia_process_lifecycle as fpl,
16};
17
18pub async fn main(
19    ns_entries: Vec<fprocess::NameInfo>,
20    directory_request: ServerEnd<fio::DirectoryMarker>,
21    lifecycle: ServerEnd<fpl::LifecycleMarker>,
22) -> Result<(), anyhow::Error> {
23    if lifecycle.is_invalid_handle() {
24        bail!("No valid handle found for lifecycle events");
25    }
26    if directory_request.is_invalid_handle() {
27        bail!("No valid handle found for outgoing directory");
28    }
29    let Some(svc) = ns_entries.iter().find(|e| e.path == "/svc") else {
30        bail!("No /svc in namespace");
31    };
32    svc.directory
33        .as_ref_directory()
34        .open("fuchsia.device.fs.lifecycle.Lifecycle", fio::Flags::empty(), lifecycle.into())
35        .context("Failed to connect to fuchsia.device.fs.Lifecycle")?;
36
37    let mut fs = ServiceFs::new();
38
39    let mut expose = HashSet::new();
40    expose.insert("dev");
41    for entry in ns_entries {
42        let path = entry
43            .path
44            .strip_prefix("/")
45            .ok_or_else(|| format_err!("Encountered illegal namespace path: {}", entry.path))?;
46        if !expose.remove(path) {
47            continue;
48        }
49        fs.add_entry_at(path, remote::remote_dir(entry.directory.into_proxy()));
50    }
51    if !expose.is_empty() {
52        let missing = expose.into_iter().collect::<Vec<_>>().join(",");
53        bail!("Failed to expose all entries: {missing}");
54    }
55
56    info!("[devfs] Initialized.");
57
58    fs.serve_connection(directory_request).context("failed to serve outgoing namespace")?;
59    fs.collect::<()>().await;
60    Err(format_err!("devfs ended unexpectedly"))
61}