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); } } 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") {