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