starry-kernel 0.7.6

A Linux-compatible OS kernel built on ArceOS unikernel
Documentation
use alloc::{
    format,
    string::{String, ToString},
    vec::Vec,
};

use ax_fs_ng::vfs::FsContext;
use axfs_ng_vfs::DeviceId;

const MS_NOSUID: u32 = 2;
const MS_NODEV: u32 = 4;
const MS_NOEXEC: u32 = 8;
const MS_NOATIME: u32 = 1 << 10;
const MS_RELATIME: u32 = 1 << 21;
const MS_STRICTATIME: u32 = 1 << 24;

pub fn render_mountinfo(fs_context: &FsContext) -> String {
    let entries = fs_context.mount_namespace().walk_tree();
    let mut buf = String::new();
    for (mount_id, parent_id, mp) in entries {
        let root_loc = mp.root_location();

        let mount_point = root_loc
            .absolute_path()
            .map(|p| p.to_string())
            .unwrap_or_else(|_| "/".into());

        let fstype = root_loc.filesystem().name();
        let source = mp.source();
        let dev = DeviceId(mp.device());

        let options = render_options(mp.is_readonly(), mp.mount_flags());

        let optional_fields = if mp.is_shared() {
            let gid = mp.peer_group_id();
            if gid != 0 {
                Some(format!("shared:{gid}"))
            } else {
                None
            }
        } else if mp.is_slave() {
            mp.first_master_peer_group_id()
                .map(|gid| format!("master:{gid}"))
        } else if mp.is_unbindable() {
            Some("unbindable".into())
        } else {
            None
        };
        let optional_fields = optional_fields
            .as_deref()
            .map_or(String::new(), |fields| format!(" {fields}"));

        let _ = writeln!(
            &mut buf,
            "{mount_id} {parent_id} {}:{} / {mount_point} {options}{optional_fields} - {fstype} \
             {source} {options}",
            dev.major(),
            dev.minor(),
        );
    }
    buf
}

pub fn render_mounts(fs_context: &FsContext) -> String {
    let entries = fs_context.mount_namespace().walk_tree();
    let mut buf = String::new();
    for (_, _, mp) in entries {
        let root_loc = mp.root_location();

        let mount_point = root_loc
            .absolute_path()
            .map(|p| p.to_string())
            .unwrap_or_else(|_| "/".into());

        let fstype = root_loc.filesystem().name();
        let source = mp.source();
        let options = render_options(mp.is_readonly(), mp.mount_flags());

        let _ = writeln!(&mut buf, "{source} {mount_point} {fstype} {options} 0 0",);
    }
    buf
}

fn render_options(readonly: bool, flags: u32) -> String {
    let mut opts: Vec<&str> = Vec::new();
    opts.push(if readonly { "ro" } else { "rw" });
    if flags & MS_NOSUID != 0 {
        opts.push("nosuid");
    }
    if flags & MS_NODEV != 0 {
        opts.push("nodev");
    }
    if flags & MS_NOEXEC != 0 {
        opts.push("noexec");
    }
    if flags & MS_NOATIME != 0 {
        opts.push("noatime");
    }
    if flags & MS_RELATIME != 0 {
        opts.push("relatime");
    }
    if flags & MS_STRICTATIME != 0 {
        opts.push("strictatime");
    }
    opts.join(",")
}

use core::fmt::Write as _;