starnix_kernel_runner/
mounts.rs1use anyhow::{Error, anyhow, bail};
6use fidl_fuchsia_io as fio;
7use starnix_core::fs::fuchsia::{RemoteBundle, new_remotefs_in_root};
8use starnix_core::fs::tmpfs::TmpFs;
9use starnix_core::task::{CurrentTask, Kernel};
10use starnix_core::vfs::fs_args::MountParams;
11use starnix_core::vfs::{FileSystemHandle, FileSystemOptions, FsString};
12
13use starnix_uapi::mount_flags::{MountFlags, MountpointFlags};
14
15pub struct MountAction {
16 pub path: FsString,
17 pub fs: FileSystemHandle,
18 pub flags: MountpointFlags,
19}
20
21impl MountAction {
22 pub fn new_for_root(
23 kernel: &Kernel,
24 pkg: &fio::DirectorySynchronousProxy,
25 spec: &str,
26 ) -> Result<MountAction, Error> {
27 let (spec, options) = MountSpec::parse(spec)?;
28 assert_eq!(spec.mount_point.as_slice(), b"/");
29 let rights = fio::PERM_READABLE | fio::PERM_EXECUTABLE;
30
31 let fs = match spec.fs_type.as_slice() {
35 b"remote_bundle" => RemoteBundle::new_fs_in_base(kernel, pkg, options, rights)?,
36 b"remote_pkg_subdir" => new_remotefs_in_root(kernel, pkg, options, rights)?,
37 b"tmpfs" => TmpFs::new_fs_with_options(kernel, options)?,
38 _ => bail!("unsupported root file system: {}", spec.fs_type),
39 };
40
41 Ok(spec.into_action(fs))
42 }
43
44 pub fn from_spec(
45 current_task: &CurrentTask,
46 pkg: &fio::DirectorySynchronousProxy,
47 spec: &str,
48 ) -> Result<MountAction, Error> {
49 let (spec, options) = MountSpec::parse(spec)?;
50 let rights = fio::PERM_READABLE | fio::PERM_EXECUTABLE;
51
52 let fs = match spec.fs_type.as_slice() {
53 b"remote_bundle" => {
55 RemoteBundle::new_fs_in_base(current_task.kernel(), pkg, options, rights)?
56 }
57
58 b"remote_pkg_subdir" => {
60 new_remotefs_in_root(current_task.kernel(), pkg, options, rights)?
61 }
62
63 _ => current_task.create_filesystem(spec.fs_type.as_ref(), options)?,
64 };
65
66 Ok(spec.into_action(fs))
67 }
68}
69
70struct MountSpec {
71 mount_point: FsString,
72 fs_type: FsString,
73 flags: MountFlags,
74}
75
76impl MountSpec {
77 fn parse(spec: &str) -> Result<(MountSpec, FileSystemOptions), Error> {
78 let mut iter = spec.splitn(4, ':');
79 let mount_point =
80 iter.next().ok_or_else(|| anyhow!("mount point is missing from {:?}", spec))?;
81 let fs_type = iter.next().ok_or_else(|| anyhow!("fs type is missing from {:?}", spec))?;
82 let fs_src = match iter.next() {
83 Some(src) if !src.is_empty() => src,
84 _ => ".",
85 };
86
87 let mut params = MountParams::parse(iter.next().unwrap_or_default().into())?;
88 let flags = params.remove_mount_flags();
89
90 Ok((
91 MountSpec { fs_type: fs_type.into(), mount_point: mount_point.into(), flags },
92 FileSystemOptions {
93 source: fs_src.into(),
94 flags: flags.file_system_flags().into(),
95 params,
96 },
97 ))
98 }
99
100 fn into_action(self, fs: FileSystemHandle) -> MountAction {
101 MountAction { path: self.mount_point, fs, flags: self.flags.mountpoint_flags() }
102 }
103}