From f66e65620dbe0a5148d15ba51dc4a3a5b3913e8e Mon Sep 17 00:00:00 2001 From: Alexander Bakanovskii Date: Sat, 20 Sep 2025 17:42:09 +0300 Subject: [PATCH 1/2] df: follow symlinks Signed-off-by: Alexander Bakanovskii --- src/uu/df/Cargo.toml | 2 +- src/uu/df/src/df.rs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/uu/df/Cargo.toml b/src/uu/df/Cargo.toml index 4d837edc6..8f0d7d082 100644 --- a/src/uu/df/Cargo.toml +++ b/src/uu/df/Cargo.toml @@ -19,7 +19,7 @@ path = "src/df.rs" [dependencies] clap = { workspace = true } -uucore = { workspace = true, features = ["libc", "fsext", "parser"] } +uucore = { workspace = true, features = ["libc", "fsext", "parser", "fs"] } unicode-width = { workspace = true } thiserror = { workspace = true } fluent = { workspace = true } diff --git a/src/uu/df/src/df.rs b/src/uu/df/src/df.rs index c81d260e4..b62578086 100644 --- a/src/uu/df/src/df.rs +++ b/src/uu/df/src/df.rs @@ -306,13 +306,24 @@ fn get_all_filesystems(opt: &Options) -> UResult> { } let mut mounts = vec![]; - for mi in read_fs_list()? { + for mut mi in read_fs_list()? { // TODO The running time of the `is_best()` function is linear // in the length of `result`. That makes the running time of // this loop quadratic in the length of `vmi`. This could be // improved by a more efficient implementation of `is_best()`, // but `vmi` is probably not very long in practice. if is_included(&mi, opt) && is_best(&mounts, &mi) { + let dev_path: &Path = Path::new(&mi.dev_name); + if dev_path.is_symlink() { + if let Ok(canonicalized_symlink) = uucore::fs::canonicalize( + dev_path, + uucore::fs::MissingHandling::Existing, + uucore::fs::ResolveMode::Logical, + ) { + mi.dev_name = canonicalized_symlink.to_string_lossy().to_string(); + } + } + mounts.push(mi); } } From d6985039c93296fc76d5134ff0482bbeee0b8aa3 Mon Sep 17 00:00:00 2001 From: Alexander Bakanovskii Date: Sun, 28 Sep 2025 23:05:35 +0300 Subject: [PATCH 2/2] tests/df: test follow symlinks Signed-off-by: Alexander Bakanovskii --- tests/by-util/test_df.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/by-util/test_df.rs b/tests/by-util/test_df.rs index ecb60bc5f..ec37f78b4 100644 --- a/tests/by-util/test_df.rs +++ b/tests/by-util/test_df.rs @@ -123,6 +123,22 @@ fn test_df_output() { assert_eq!(actual, expected); } +#[test] +fn test_df_follows_symlinks() { + let output = new_ucmd!() + .arg("-h") + .arg("--output=source") + .succeeds() + .stdout_str_lossy(); + + let filesystems = output.lines().skip(1).collect::>(); + assert!( + filesystems + .iter() + .all(|&x| !std::path::Path::new(x).is_symlink()) + ); +} + #[test] fn test_df_output_overridden() { let expected = if cfg!(target_os = "macos") {