diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index 3ad6e07f916..158a2a6b9fb 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -1080,6 +1080,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let (print_tx, rx) = mpsc::channel::>(); let printing_thread = thread::spawn(move || stat_printer.print_stats(&rx)); + // Track seen inodes across all arguments to avoid double-counting hard links + let mut seen_inodes: HashSet = HashSet::new(); + 'loop_file: for path in files { // Skip if we don't want to ignore anything if !&traversal_options.excludes.is_empty() { @@ -1098,9 +1101,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } } - // Check existence of path provided in argument - let mut seen_inodes: HashSet = HashSet::new(); - // Determine which traversal method to use #[cfg(all(unix, not(target_os = "redox")))] let use_safe_traversal = traversal_options.dereference != Deref::All; diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 38d64d5b8b8..e94ec52831c 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -532,6 +532,22 @@ fn du_hard_link(s: &str) { } } +#[cfg(all(unix, not(target_os = "android")))] +#[test] +fn test_du_hard_link_multiple_args() { + let (at, mut ucmd) = at_and_ucmd!(); + at.mkdir("dir1"); + at.mkdir("dir2"); + at.write("dir1/file", &"x".repeat(10000)); + at.hard_link("dir1/file", "dir2/file"); + + let result = ucmd.args(&["-b", "dir1", "dir2"]).succeeds(); + let lines: Vec<&str> = result.stdout_str().lines().collect(); + let size = |i: usize| lines[i].split('\t').next().unwrap().parse::().unwrap(); + assert!(size(0) >= 10000); + assert!(size(1) < 1000); +} + #[test] #[cfg(not(target_os = "openbsd"))] fn test_du_d_flag() {