Skip to content

Commit

Permalink
Add size unit options to commands (#434)
Browse files Browse the repository at this point in the history
* Add SizeUnit

* Add -b option to list

* Add -b option to disk usage

* Add -b option to memory usage

* Align size to the right

* Update net command

* Add decimal units
  • Loading branch information
vinc authored Nov 11, 2022
1 parent d0c8e16 commit b51b060
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 58 deletions.
1 change: 1 addition & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,6 @@ pub mod random;
pub mod regex;
pub mod syscall;
pub mod time;
pub mod unit;
pub mod vga;
// TODO: add mod wildcard
48 changes: 48 additions & 0 deletions src/api/unit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use alloc::format;
use alloc::string::String;

#[derive(Clone)]
pub enum SizeUnit {
None,
Binary,
Decimal,
}

impl SizeUnit {
pub fn format(&self, size: usize) -> String {
match self {
SizeUnit::None => format!("{}", size),
SizeUnit::Binary => binary_size(size),
SizeUnit::Decimal => decimal_size(size),
}
}
}

const PREFIXES: [&str; 5] = ["", "K", "M", "G", "T"];

fn binary_size(size: usize) -> String {
let n = PREFIXES.len();
for i in 0..n {
let prefix = PREFIXES[i];
if size < (1 << ((i + 1) * 10)) || i == n - 1 {
let s = ((size * 10) >> (i * 10)) as f64 / 10.0;
let s = if s >= 10.0 { libm::round(s) } else { s };
return format!("{}{}", s, prefix);
}
}
unreachable!();
}

fn decimal_size(size: usize) -> String {
let size = size;
let n = PREFIXES.len();
for i in 0..n {
let prefix = PREFIXES[i];
if size < usize::pow(10, 3 * (i + 1) as u32) || i == n - 1 {
let s = (size as f64) / libm::pow(10.0, 3.0 * (i as f64));
let precision = if s >= 10.0 { 0 } else { 1 };
return format!("{:.2$}{}", s, prefix, precision);
}
}
unreachable!();
}
76 changes: 59 additions & 17 deletions src/usr/disk.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::api::console::Style;
use crate::api::io;
use crate::api::process::ExitCode;
use crate::api::unit::SizeUnit;
use crate::sys;
use crate::sys::ata::Drive;

Expand All @@ -11,15 +12,27 @@ use alloc::vec::Vec;
use alloc::vec;

pub fn main(args: &[&str]) -> Result<(), ExitCode> {
if args.len() == 1 {
return usage();
}
match args[1] {
"format" if args.len() == 3 => format(args[2]),
"erase" if args.len() == 3 => erase(args[2]),
"usage" => usage(),
"list" => list(),
_ => help(),
match *args.get(1).unwrap_or(&"") {
"f" | "format" if args.len() == 3 => {
format(args[2])
}
"e" | "erase" if args.len() == 3 => {
erase(args[2])
}
"u" | "usage" => {
usage(&args[2..])
}
"l" | "list" => {
list()
}
"-h" | "--help" => {
help();
Ok(())
}
_ => {
help();
Err(ExitCode::UsageError)
}
}
}

Expand Down Expand Up @@ -92,21 +105,51 @@ fn list() -> Result<(), ExitCode> {
Ok(())
}

fn usage() -> Result<(), ExitCode> {
fn usage(args: &[&str]) -> Result<(), ExitCode> {
let mut unit = SizeUnit::None;
for arg in args {
match *arg {
"-b" | "--binary-size" => {
unit = SizeUnit::Binary;
}
"-d" | "--decimal-size" => {
unit = SizeUnit::Decimal;
}
"-h" | "--help" => {
help_usage();
return Ok(());
}
_ => {
help_usage();
return Err(ExitCode::Failure);
}
}
}
let size = sys::fs::disk_size();
let used = sys::fs::disk_used();
let free = size - used;

let width = size.to_string().len();
let width = [size, used, free].iter().fold(0, |acc, num| {
core::cmp::max(acc, unit.format(*num).len())
});
let color = Style::color("LightCyan");
let reset = Style::reset();
println!("{}size:{} {:width$} bytes", color, reset, size, width = width);
println!("{}used:{} {:width$} bytes", color, reset, used, width = width);
println!("{}free:{} {:width$} bytes", color, reset, free, width = width);
println!("{}size:{} {:>width$}", color, reset, unit.format(size), width = width);
println!("{}used:{} {:>width$}", color, reset, unit.format(used), width = width);
println!("{}free:{} {:>width$}", color, reset, unit.format(free), width = width);
Ok(())
}

fn help() -> Result<(), ExitCode> {
fn help_usage() {
let csi_option = Style::color("LightCyan");
let csi_title = Style::color("Yellow");
let csi_reset = Style::reset();
println!("{}Usage:{} disk usage {}<options>{}", csi_title, csi_reset, csi_option, csi_reset);
println!();
println!("{}Options:{}", csi_title, csi_reset);
println!(" {0}-b{1},{0} --binary-size{1} Use binary size", csi_option, csi_reset);
}

fn help() {
let csi_option = Style::color("LightCyan");
let csi_title = Style::color("Yellow");
let csi_reset = Style::reset();
Expand All @@ -117,5 +160,4 @@ fn help() -> Result<(), ExitCode> {
println!(" {}usage{} List disk usage", csi_option, csi_reset);
println!(" {}format <path>{} Format disk", csi_option, csi_reset);
println!(" {}erase <path>{} Erase disk", csi_option, csi_reset);
Ok(())
}
27 changes: 15 additions & 12 deletions src/usr/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use crate::api::clock::DATE_TIME;
use crate::api::console::Style;
use crate::api::time;
use crate::api::fs;
use crate::api::fs::FileInfo;
use crate::api::process::ExitCode;
use crate::api::syscall;
use crate::api::fs::FileInfo;
use crate::api::unit::SizeUnit;

use alloc::string::ToString;
use alloc::vec::Vec;
Expand All @@ -14,6 +15,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
let mut path: &str = &sys::process::dir(); // TODO: use '.'
let mut sort = "name";
let mut hide_dot_files = true;
let mut unit = SizeUnit::None;

let n = args.len();
for i in 1..n {
Expand All @@ -23,6 +25,8 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
"-n" | "--name" => sort = "name",
"-s" | "--size" => sort = "size",
"-t" | "--time" => sort = "time",
"-b" | "--binary-size" => unit = SizeUnit::Binary,
"-d" | "--decimal-size" => unit = SizeUnit::Decimal,
_ => path = args[i],
}
}
Expand Down Expand Up @@ -50,23 +54,21 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
}
}

let mut max_size = 0;
for file in &files {
max_size = core::cmp::max(max_size, file.size());
}
let width = max_size.to_string().len();

let width = files.iter().fold(0, |max_len, file| {
let len = unit.format(file.size() as usize).len();
core::cmp::max(max_len, len)
});

for file in files {
print_file(file, width);
print_file(file, width, unit.clone());
}
Ok(())
} else {
error!("Could not read directory '{}'", path);
Err(ExitCode::Failure)
}
} else {
print_file(&info, info.size().to_string().len());
print_file(&info, info.size().to_string().len(), unit);
Ok(())
}
} else {
Expand All @@ -75,20 +77,21 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
}
}

fn print_file(file: &FileInfo, width: usize) {
fn print_file(file: &FileInfo, width: usize, unit: SizeUnit) {
let csi_dir_color = Style::color("LightCyan");
let csi_dev_color = Style::color("Yellow");
let csi_reset = Style::reset();

let time = time::from_timestamp(file.time() as i64);
let size = unit.format(file.size() as usize);
let time = time::from_timestamp(file.time() as i64).format(DATE_TIME);
let color = if file.is_dir() {
csi_dir_color
} else if file.is_device() {
csi_dev_color
} else {
csi_reset
};
println!("{:width$} {} {}{}{}", file.size(), time.format(DATE_TIME), color, file.name(), csi_reset, width = width);
println!("{:>width$} {} {}{}{}", size, time, color, file.name(), csi_reset, width = width);
}

fn help() -> Result<(), ExitCode> {
Expand Down
77 changes: 57 additions & 20 deletions src/usr/memory.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,73 @@
use crate::sys;
use crate::api::console::Style;
use crate::api::process::ExitCode;

use alloc::string::ToString;
use crate::api::unit::SizeUnit;

pub fn main(args: &[&str]) -> Result<(), ExitCode> {
if args.len() == 1 || args[1] == "usage" {
usage();
Ok(())
} else if args[1] == "format" {
sys::fs::mount_mem();
sys::fs::format_mem();
println!("Memory successfully formatted");
println!("MFS is now mounted to '/'");
Ok(())
} else {
help();
Err(ExitCode::Failure)
match *args.get(1).unwrap_or(&"") {
"u" | "usage" => {
usage(&args[2..])
}
"f" | "format" => {
sys::fs::mount_mem();
sys::fs::format_mem();
println!("Memory successfully formatted");
println!("MFS is now mounted to '/'");
Ok(())
}
"-h" | "--help" => {
help();
Ok(())
}
_ => {
help();
Err(ExitCode::UsageError)
}
}
}

fn usage() {
fn usage(args: &[&str]) -> Result<(), ExitCode> {
let mut unit = SizeUnit::None;
for arg in args {
match *arg {
"-b" | "--binary-size" => {
unit = SizeUnit::Binary;
}
"-d" | "--decimal-size" => {
unit = SizeUnit::Decimal;
}
"-h" | "--help" => {
help_usage();
return Ok(());
}
_ => {
help_usage();
return Err(ExitCode::Failure);
}
}
}
let size = sys::allocator::memory_size();
let used = sys::allocator::memory_used();
let free = size - used;

let width = size.to_string().len();
let width = [size, used, free].iter().fold(0, |acc, num| {
core::cmp::max(acc, unit.format(*num).len())
});
let color = Style::color("LightCyan");
let reset = Style::reset();
println!("{}size:{} {:width$} bytes", color, reset, size, width = width);
println!("{}used:{} {:width$} bytes", color, reset, used, width = width);
println!("{}free:{} {:width$} bytes", color, reset, free, width = width);
println!("{}size:{} {:>width$}", color, reset, unit.format(size), width = width);
println!("{}used:{} {:>width$}", color, reset, unit.format(used), width = width);
println!("{}free:{} {:>width$}", color, reset, unit.format(free), width = width);
Ok(())
}

fn help_usage() {
let csi_option = Style::color("LightCyan");
let csi_title = Style::color("Yellow");
let csi_reset = Style::reset();
println!("{}Usage:{} memory usage {}<options>{}", csi_title, csi_reset, csi_option, csi_reset);
println!();
println!("{}Options:{}", csi_title, csi_reset);
println!(" {0}-b{1},{0} --binary-size{1} Use binary size", csi_option, csi_reset);
}

fn help() {
Expand Down
13 changes: 4 additions & 9 deletions src/usr/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,12 @@ use smoltcp::time::Instant;
use smoltcp::phy::Device;

pub fn main(args: &[&str]) -> Result<(), ExitCode> {
if args.len() == 1 {
help();
return Err(ExitCode::UsageError);
}

match args[1] {
match *args.get(1).unwrap_or(&"") {
"-h" | "--help" => {
help();
return Ok(());
}
"config" => {
"c" | "config" => {
if args.len() < 3 {
print_config("mac");
print_config("ip");
Expand All @@ -43,7 +38,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
set_config(args[2], args[3]);
}
}
"stat" => {
"s" | "stat" => {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
let stats = iface.device().stats();
let csi_color = Style::color("LightCyan");
Expand All @@ -54,7 +49,7 @@ pub fn main(args: &[&str]) -> Result<(), ExitCode> {
error!("Network error");
}
}
"monitor" => {
"m" | "monitor" => {
if let Some(ref mut iface) = *sys::net::IFACE.lock() {
iface.device_mut().config().enable_debug();

Expand Down

0 comments on commit b51b060

Please sign in to comment.