Skip to main content

driver_manager_utils/
pkg_utils.rs

1// Copyright 2026 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 crate::errors::UtilsError;
6use fidl::endpoints::{ClientEnd, create_endpoints, create_proxy};
7use fidl_fuchsia_io as fio;
8
9pub async fn open_pkg_file(
10    pkg_dir: &fio::DirectoryProxy,
11    relative_binary_path: &str,
12) -> Result<zx::Vmo, UtilsError> {
13    let (file, server) = create_proxy::<fio::FileMarker>();
14    pkg_dir.open(
15        relative_binary_path,
16        fio::PERM_READABLE | fio::PERM_EXECUTABLE,
17        &fio::Options::default(),
18        server.into_channel(),
19    )?;
20
21    let vmo = file
22        .get_backing_memory(
23            fio::VmoFlags::READ | fio::VmoFlags::EXECUTE | fio::VmoFlags::PRIVATE_CLONE,
24        )
25        .await??;
26    Ok(vmo)
27}
28
29pub fn open_lib_dir(
30    pkg_dir: &fio::DirectoryProxy,
31) -> Result<ClientEnd<fio::DirectoryMarker>, UtilsError> {
32    let (lib_dir, server) = create_endpoints::<fio::DirectoryMarker>();
33    pkg_dir.open(
34        "lib",
35        fio::PERM_READABLE | fio::PERM_EXECUTABLE,
36        &fio::Options::default(),
37        server.into_channel(),
38    )?;
39    Ok(lib_dir)
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    use fidl::endpoints::{ServerEnd, create_proxy_and_stream};
46    use futures::StreamExt;
47    use vfs::directory::entry_container::Directory;
48    use vfs::execution_scope::ExecutionScope;
49    use vfs::object_request::ToObjectRequest;
50    use vfs::pseudo_directory;
51
52    #[fuchsia::test]
53    async fn test_open_pkg_file() {
54        let (pkg_client, mut pkg_stream) = create_proxy_and_stream::<fio::DirectoryMarker>();
55
56        fuchsia_async::Task::local(async move {
57            while let Some(Ok(request)) = pkg_stream.next().await {
58                if let fio::DirectoryRequest::Open { flags, path, object, .. } = request {
59                    assert_eq!(path, "bin/driver");
60                    assert!(flags.contains(fio::Flags::PERM_READ_BYTES | fio::Flags::PERM_EXECUTE));
61
62                    let server_end = ServerEnd::<fio::FileMarker>::new(object);
63                    let mut stream = server_end.into_stream();
64
65                    while let Some(Ok(request)) = stream.next().await {
66                        if let fio::FileRequest::GetBackingMemory { flags: _, responder } = request
67                        {
68                            let vmo = zx::Vmo::create(12).unwrap();
69                            vmo.write(b"test_content", 0).unwrap();
70                            responder.send(Ok(vmo)).unwrap();
71                        }
72                    }
73                }
74            }
75        })
76        .detach();
77
78        let vmo = open_pkg_file(&pkg_client, "bin/driver").await.expect("Failed to open pkg file");
79        let mut buffer = vec![0; 12];
80        vmo.read(&mut buffer, 0).expect("Failed to read vmo");
81        assert_eq!(&buffer, b"test_content");
82    }
83
84    #[fuchsia::test]
85    async fn test_open_lib_dir() {
86        let pkg_dir = pseudo_directory! {
87            "lib" => pseudo_directory! {},
88        };
89
90        let (pkg_client, pkg_server) = create_proxy::<fio::DirectoryMarker>();
91        let scope = ExecutionScope::new();
92        let flags = fio::PERM_READABLE | fio::PERM_EXECUTABLE;
93        let mut object_request = flags.to_object_request(pkg_server.into_channel());
94        pkg_dir
95            .open(scope, vfs::path::Path::dot(), flags, &mut object_request)
96            .expect("Failed to open");
97
98        let lib_dir = open_lib_dir(&pkg_client).expect("Failed to open lib dir");
99        let lib_proxy = lib_dir.into_proxy();
100
101        // Verify we can interact with the lib directory
102        let _attributes = lib_proxy
103            .get_attributes(fio::NodeAttributesQuery::empty())
104            .await
105            .expect("FIDL error")
106            .map_err(zx::Status::from_raw)
107            .expect("Failed to get attributes");
108    }
109}