Skip to content

Commit

Permalink
implement the first version of free
Browse files Browse the repository at this point in the history
  • Loading branch information
sylvestre committed Jan 26, 2024
1 parent 21ce645 commit dc06ab7
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ default = ["feat_common_core"]

feat_common_core = [
"pwdx",
"free",
]

[workspace.dependencies]
Expand Down Expand Up @@ -54,6 +55,7 @@ textwrap = { workspace = true }

#
pwdx = { optional = true, version = "0.0.1", package = "uu_pwdx", path = "src/uu/pwdx" }
free = { optional = true, version = "0.0.1", package = "uu_free", path = "src/uu/free" }

[dev-dependencies]
pretty_assertions = "1"
Expand Down
17 changes: 17 additions & 0 deletions src/uu/free/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "uu_free"
version = "0.0.1"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
uucore = { workspace = true }
clap = { workspace = true }

[lib]
path = "src/free.rs"

[[bin]]
name = "free"
path = "src/main.rs"
7 changes: 7 additions & 0 deletions src/uu/free/free.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# free

```
free [options]
```

Display amount of free and used memory in the system
151 changes: 151 additions & 0 deletions src/uu/free/src/free.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// This file is part of the uutils procps package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

use clap::Arg;
use clap::ArgAction;
use clap::{crate_version, Command};
use std::env;
use std::fs;
use std::process;
use uucore::{error::UResult, format_usage, help_about, help_usage};

const ABOUT: &str = help_about!("free.md");
const USAGE: &str = help_usage!("free.md");

fn parse_meminfo() -> Result<(u64, u64, u64, u64, u64, u64, u64, u64, u64, u64), std::io::Error> {
let contents = fs::read_to_string("/proc/meminfo")?;
let mut total = 0;
let mut free = 0;
let mut available = 0;
let mut shared = 0;
let mut buffers = 0;
let mut cached = 0;
let mut swap_total = 0;
let mut swap_free = 0;
let mut reclaimable = 0;

for line in contents.lines() {
if let Some((key, value)) = line.split_once(':') {
let parsed_value = parse_meminfo_value(value)?;
match key.trim() {
"MemTotal" => total = parsed_value,
"MemFree" => free = parsed_value,
"MemAvailable" => available = parsed_value,
"Shmem" => shared = parsed_value,
"Buffers" => buffers = parsed_value,
"Cached" => cached = parsed_value,
"SwapTotal" => swap_total = parsed_value,
"SwapFree" => swap_free = parsed_value,
"SReclaimable" => reclaimable = parsed_value,
_ => {}
}
}
}

Ok((
total,
free,
available,
shared,
buffers,
cached,
swap_total,
swap_free,
swap_total - swap_free,
reclaimable,
))
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().try_get_matches_from(args)?;
let wide = matches.get_flag("wide");

match parse_meminfo() {
Ok((
total,
free,
available,
shared,
buffers,
cached,
swap_total,
swap_free,
swap_used,
reclaimable,
)) => {
let buff_cache = if wide { buffers } else { buffers + cached };
let cache = if wide { cached } else { 0 };
let used = total - free;

if wide {
println!(" total used free shared buffers cache available");
println!(
"Mem: {:12} {:12} {:12} {:12} {:12} {:12} {:12}",
total,
used,
free,
shared,
buff_cache,
cache + reclaimable,
available
);
} else {
println!(" total used free shared buff/cache available");
println!(
"Mem: {:12} {:12} {:12} {:12} {:12} {:12}",
total,
used,
free,
shared,
buff_cache + reclaimable,
available
);
}
println!("Swap: {:12} {:12} {:12}", swap_total, swap_used, swap_free);
}
Err(e) => {
eprintln!("free: failed to read memory info: {}", e);
process::exit(1);
}
}

Ok(())
}

pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.version(crate_version!())
.about(ABOUT)
.override_usage(format_usage(USAGE))
.infer_long_args(true)
.arg(
Arg::new("wide")
.short('w')
.long("wide")
.help("wide output")
.action(ArgAction::SetTrue),
)
}

fn parse_meminfo_value(value: &str) -> Result<u64, std::io::Error> {
value
.split_whitespace()
.next()
.ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Invalid memory info format",
)
})
.and_then(|v| {
v.parse::<u64>().map_err(|_| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Invalid memory info format",
)
})
})
}
1 change: 1 addition & 0 deletions src/uu/free/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uucore::bin!(uu_free);
27 changes: 27 additions & 0 deletions tests/by-util/test_free.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// This file is part of the uutils procps package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore (words) symdir somefakedir

use std::path::PathBuf;

use crate::common::util::{TestScenario, UCommand};

#[test]
fn test_invalid_arg() {
new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
}

#[test]
fn test_free() {
let result = new_ucmd!().succeeds();
assert!(result.stdout_str().contains("Mem:"))
}

#[test]
fn test_free_wide() {
let result = new_ucmd!().arg("--wide").succeeds();
assert!(result.stdout_str().contains("Mem:"));
assert!(!result.stdout_str().contains("buff/cache"));
}
4 changes: 4 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ mod common;
#[cfg(feature = "pwdx")]
#[path = "by-util/test_pwdx.rs"]
mod test_pwdx;

#[cfg(feature = "free")]
#[path = "by-util/test_free.rs"]
mod test_free;

0 comments on commit dc06ab7

Please sign in to comment.