Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 27 additions & 57 deletions src/uu/df/src/df.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use blocks::HumanReadable;
use clap::builder::ValueParser;
use table::HeaderMode;
use uucore::display::Quotable;
use uucore::error::{UError, UResult, USimpleError};
use uucore::error::{UError, UResult, USimpleError, get_exit_code};
use uucore::fsext::{MountInfo, read_fs_list};
use uucore::parse_size::ParseSizeError;
use uucore::{format_usage, help_about, help_section, help_usage, show};
Expand Down Expand Up @@ -243,7 +243,10 @@ fn is_included(mi: &MountInfo, opt: &Options) -> bool {
}

// Don't show pseudo filesystems unless `--all` has been given.
if mi.dummy && !opt.show_all_fs {
// The "lofs" filesystem is a loopback
// filesystem present on Solaris and FreeBSD systems. It
// is similar to a symbolic link.
if (mi.dummy || mi.fs_type == "lofs") && !opt.show_all_fs {
return false;
}

Expand Down Expand Up @@ -306,28 +309,6 @@ fn is_best(previous: &[MountInfo], mi: &MountInfo) -> bool {
true
}

/// Keep only the specified subset of [`MountInfo`] instances.
///
/// The `opt` argument specifies a variety of ways of excluding
/// [`MountInfo`] instances; see [`Options`] for more information.
///
/// Finally, if there are duplicate entries, the one with the shorter
/// path is kept.
fn filter_mount_list(vmi: Vec<MountInfo>, opt: &Options) -> Vec<MountInfo> {
let mut result = vec![];
for mi in vmi {
// 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(&result, &mi) {
result.push(mi);
}
}
result
}

/// Get all currently mounted filesystems.
///
/// `opt` excludes certain filesystems from consideration and allows for the synchronization of filesystems before running; see
Expand All @@ -344,11 +325,17 @@ fn get_all_filesystems(opt: &Options) -> UResult<Vec<Filesystem>> {
}
}

// The list of all mounted filesystems.
//
// Filesystems excluded by the command-line options are
// not considered.
let mounts: Vec<MountInfo> = filter_mount_list(read_fs_list()?, opt);
let mut mounts = vec![];
for 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) {
mounts.push(mi);
}
}

// Convert each `MountInfo` into a `Filesystem`, which contains
// both the mount information and usage information.
Expand Down Expand Up @@ -379,29 +366,19 @@ where
P: AsRef<Path>,
{
// The list of all mounted filesystems.
//
// Filesystems marked as `dummy` or of type "lofs" are not
// considered. The "lofs" filesystem is a loopback
// filesystem present on Solaris and FreeBSD systems. It
// is similar to a symbolic link.
let mounts: Vec<MountInfo> = filter_mount_list(read_fs_list()?, opt)
.into_iter()
.filter(|mi| mi.fs_type != "lofs" && !mi.dummy)
.collect();
let mounts: Vec<MountInfo> = read_fs_list()?;

let mut result = vec![];

// this happens if the file system type doesn't exist
if mounts.is_empty() {
show!(USimpleError::new(1, "no file systems processed"));
return Ok(result);
}

// Convert each path into a `Filesystem`, which contains
// both the mount information and usage information.
for path in paths {
match Filesystem::from_path(&mounts, path) {
Ok(fs) => result.push(fs),
Ok(fs) => {
if is_included(&fs.mount_info, opt) {
result.push(fs);
}
}
Err(FsError::InvalidPath) => {
show!(USimpleError::new(
1,
Expand All @@ -423,6 +400,11 @@ where
}
}
}
if get_exit_code() == 0 && result.is_empty() {
show!(USimpleError::new(1, "no file systems processed"));
return Ok(result);
}

Ok(result)
}

Expand Down Expand Up @@ -883,16 +865,4 @@ mod tests {
assert!(is_included(&m, &opt));
}
}

mod filter_mount_list {

use crate::{Options, filter_mount_list};

#[test]
fn test_empty() {
let opt = Options::default();
let mount_infos = vec![];
assert!(filter_mount_list(mount_infos, &opt).is_empty());
}
}
}
6 changes: 6 additions & 0 deletions tests/by-util/test_df.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,12 @@ fn test_type_option_with_file() {
.fails()
.stderr_contains("no file systems processed");

// Assume the mount point at /dev has a different filesystem type to the mount point at /
new_ucmd!()
.args(&["-t", fs_type, "/dev"])
.fails()
.stderr_contains("no file systems processed");

let fs_types = new_ucmd!()
.arg("--output=fstype")
.succeeds()
Expand Down
Loading