#![no_std] #![no_main] use lancer_user::fs::{self, MOUNT_INFO_ENTRY_SIZE, MountInfoEntry}; use lancer_user::net; use lancer_user::println; use lancer_user::syscall; fn fs_type_name(t: u8) -> &'static str { match t { 0 => "lancerfs", 1 => "ramfs", 2 => "generic", _ => "unknown", } } fn fmt_u64(val: u64, buf: &mut [u8; 20]) -> &str { match val { 0 => "0", _ => { let mut tmp = [0u8; 20]; fn fill(v: u64, tmp: &mut [u8; 20], pos: usize) -> usize { match v { 0 => pos, _ => { tmp[pos] = b'0' + (v % 10) as u8; fill(v / 10, tmp, pos + 1) } } } let digits = fill(val, &mut tmp, 0); (0..digits).for_each(|j| { buf[j] = tmp[digits - 1 - j]; }); match core::str::from_utf8(&buf[..digits]) { Ok(s) => s, Err(_) => "?", } } } } #[unsafe(no_mangle)] pub extern "C" fn lancer_main() -> ! { let _ = net::init(); let mut client = unsafe { fs::init() }; println!("Mount Type Total Used Free Use%"); let mut buf = [0u8; MOUNT_INFO_ENTRY_SIZE * 16]; let count = match client.mount_info(&mut buf) { Ok(c) => c, Err(e) => { println!("df: {}", e.name()); syscall::exit(); } }; (0..count).for_each(|i| { let off = i * MOUNT_INFO_ENTRY_SIZE; if let Some(entry) = MountInfoEntry::from_bytes(&buf[off..]) { let prefix = entry.prefix_slice(); let mount_str = match prefix.is_empty() { true => "/", false => core::str::from_utf8(prefix).unwrap_or("?"), }; let needs_slash = !prefix.is_empty() && prefix[0] != b'/'; let total = entry.total_blocks; let free = entry.free_blocks; let used = total.saturating_sub(free); let pct = match total { 0 => 0u64, t => (used * 100) / t, }; let mut tb = [0u8; 20]; let mut ub = [0u8; 20]; let mut fb = [0u8; 20]; let mut pb = [0u8; 20]; let ts = fmt_u64(total, &mut tb); let us = fmt_u64(used, &mut ub); let fs = fmt_u64(free, &mut fb); let ps = fmt_u64(pct, &mut pb); let ft = fs_type_name(entry.fs_type); match needs_slash { true => println!( "/{:<9} {:<9} {:<8} {:<8} {:<8} {}%", mount_str, ft, ts, us, fs, ps ), false => println!( "{:<10} {:<9} {:<8} {:<8} {:<8} {}%", mount_str, ft, ts, us, fs, ps ), }; } }); syscall::exit() }