From e253406026b64080a78335896caf28f06afa242d Mon Sep 17 00:00:00 2001 From: bootandy Date: Tue, 20 Mar 2018 12:10:05 -0400 Subject: [PATCH] du: Fix incorrect block size assumption. du and other tools like stat assume a 512 byte block. ls is the only tool to use 1024. Add Simple set of tests --- Cargo.lock | 3 ++ src/du/du.rs | 20 ++++++-- tests/fixtures/du/subdir/subwords.txt | Bin 0 -> 5120 bytes tests/fixtures/du/subdir/subwords2.txt | 1 + tests/fixtures/du/words.txt | 1 + tests/test_du.rs | 62 +++++++++++++++++++++++++ tests/tests.rs | 1 + 7 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 tests/fixtures/du/subdir/subwords.txt create mode 100644 tests/fixtures/du/subdir/subwords2.txt create mode 100644 tests/fixtures/du/words.txt create mode 100644 tests/test_du.rs diff --git a/Cargo.lock b/Cargo.lock index 512e39651..e5d0b4285 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -791,6 +791,8 @@ version = "0.0.1" dependencies = [ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "uucore 0.0.1", ] @@ -1430,6 +1432,7 @@ dependencies = [ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "uucore 0.0.1", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/du/du.rs b/src/du/du.rs index e87308952..a78b8b56d 100644 --- a/src/du/du.rs +++ b/src/du/du.rs @@ -27,7 +27,7 @@ const LONG_HELP: &'static str = " Display values are in units of the first available SIZE from --block-size, and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environ‐ ment variables. Otherwise, units default to 1024 bytes (or 512 if - POSIXLY_CORRECT is set). + POSIXLY_CORRECT is set or if OS is Apple). SIZE is an integer and optional unit (example: 10M is 10*1024*1024). Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (pow‐ @@ -69,6 +69,16 @@ impl Stat { } } +#[cfg(target_os = "macos")] +fn get_default_blocks() -> u64 { + 512 +} + +#[cfg(not(target_os = "macos"))] +fn get_default_blocks() -> u64 { + 1024 +} + // this takes `my_stat` to avoid having to stat files multiple times. // XXX: this should use the impl Trait return type when it is stabilized fn du(mut my_stat: Stat, options: &Options, depth: usize) -> Box> { @@ -285,7 +295,7 @@ pub fn uumain(args: Vec) -> i32 { }; number * multiple } - None => 1024, + None => get_default_blocks(), }; let convert_size = |size: u64| -> String { @@ -332,7 +342,7 @@ Try '{} --help' for more information.", let mut grand_total = 0; for path_str in strs.into_iter() { - let path = PathBuf::from(path_str); + let path = PathBuf::from(&path_str); match Stat::new(path) { Ok(stat) => { let iter = du(stat, &options, 0).into_iter(); @@ -398,7 +408,9 @@ Try '{} --help' for more information.", } } } - Err(error) => show_error!("{}", error), + Err(_) => { + show_info!("{}: {}", path_str, "No such file or directory"); + } } } diff --git a/tests/fixtures/du/subdir/subwords.txt b/tests/fixtures/du/subdir/subwords.txt new file mode 100644 index 0000000000000000000000000000000000000000..e7f3c2d40ecc31921643a456cda2de3a907b680a GIT binary patch literal 5120 zcmZP=1*0J_8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Un*M F1OOBO00961 literal 0 HcmV?d00001 diff --git a/tests/fixtures/du/subdir/subwords2.txt b/tests/fixtures/du/subdir/subwords2.txt new file mode 100644 index 000000000..ce0136250 --- /dev/null +++ b/tests/fixtures/du/subdir/subwords2.txt @@ -0,0 +1 @@ +hello diff --git a/tests/fixtures/du/words.txt b/tests/fixtures/du/words.txt new file mode 100644 index 000000000..ce0136250 --- /dev/null +++ b/tests/fixtures/du/words.txt @@ -0,0 +1 @@ +hello diff --git a/tests/test_du.rs b/tests/test_du.rs new file mode 100644 index 000000000..f9eeb388b --- /dev/null +++ b/tests/test_du.rs @@ -0,0 +1,62 @@ +use common::util::*; +use std::fs::set_permissions; + +static SUB_DIR: &str = "subdir"; +static SUB_FILE: &str = "subdir/subwords.txt"; +static SUB_LINK: &str = "subdir/sublink.txt"; + +#[test] +fn test_du_basics() { + let (_at, mut ucmd) = at_and_ucmd!(); + + let result = ucmd.run(); + assert!(result.success); + assert_eq!(result.stderr, ""); + assert_eq!(result.stdout, "24\t./subdir\n32\t./\n"); +} + +#[test] +fn test_du_basics_subdir() { + let (_at, mut ucmd) = at_and_ucmd!(); + + let result = ucmd.arg(SUB_DIR).run(); + assert!(result.success); + assert_eq!(result.stderr, ""); + assert_eq!(result.stdout, "24\tsubdir\n"); +} + +#[test] +fn test_du_basics_bad_name() { + let (_at, mut ucmd) = at_and_ucmd!(); + + let result = ucmd.arg("bad_name").run(); + assert_eq!(result.stdout, ""); + assert_eq!(result.stderr, "du: bad_name: No such file or directory\n"); +} + +#[test] +fn test_du_soft_link() { + let ts = TestScenario::new("du"); + + let link = ts.cmd("ln").arg("-s").arg(SUB_FILE).arg(SUB_LINK).run(); + assert!(link.success); + + let result = ts.ucmd().arg(SUB_DIR).run(); + assert!(result.success); + assert_eq!(result.stderr, ""); + assert_eq!(result.stdout, "32\tsubdir\n"); +} + +// todo: +// du on file with no permissions +// du on soft link +// du on hard link +// du on multi dir with '-d' +// +/* + * let mut permissions = at.make_file(TEST_HELLO_WORLD_DEST) + * .metadata() + * .unwrap() + * .permissions(); + * permissions.set_readonly(true); + */ diff --git a/tests/tests.rs b/tests/tests.rs index cb164a91c..b1362dd0a 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -52,6 +52,7 @@ generic! { "cut", test_cut; "dircolors", test_dircolors; "dirname", test_dirname; + "du", test_du; "echo", test_echo; "env", test_env; "expr", test_expr;