mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
fix: df: filter filesystem types after mount point resolution (#7452)
Closes: #6194
This commit is contained in:
parent
d68e288602
commit
4190fe22ef
2 changed files with 33 additions and 57 deletions
|
@ -12,7 +12,7 @@ use blocks::HumanReadable;
|
||||||
use clap::builder::ValueParser;
|
use clap::builder::ValueParser;
|
||||||
use table::HeaderMode;
|
use table::HeaderMode;
|
||||||
use uucore::display::Quotable;
|
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::fsext::{MountInfo, read_fs_list};
|
||||||
use uucore::parser::parse_size::ParseSizeError;
|
use uucore::parser::parse_size::ParseSizeError;
|
||||||
use uucore::{format_usage, help_about, help_section, help_usage, show};
|
use uucore::{format_usage, help_about, help_section, help_usage, show};
|
||||||
|
@ -222,7 +222,10 @@ fn is_included(mi: &MountInfo, opt: &Options) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't show pseudo filesystems unless `--all` has been given.
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,28 +288,6 @@ fn is_best(previous: &[MountInfo], mi: &MountInfo) -> bool {
|
||||||
true
|
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.
|
/// Get all currently mounted filesystems.
|
||||||
///
|
///
|
||||||
/// `opt` excludes certain filesystems from consideration and allows for the synchronization of filesystems before running; see
|
/// `opt` excludes certain filesystems from consideration and allows for the synchronization of filesystems before running; see
|
||||||
|
@ -323,11 +304,17 @@ fn get_all_filesystems(opt: &Options) -> UResult<Vec<Filesystem>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The list of all mounted filesystems.
|
let mut mounts = vec![];
|
||||||
//
|
for mi in read_fs_list()? {
|
||||||
// Filesystems excluded by the command-line options are
|
// TODO The running time of the `is_best()` function is linear
|
||||||
// not considered.
|
// in the length of `result`. That makes the running time of
|
||||||
let mounts: Vec<MountInfo> = filter_mount_list(read_fs_list()?, opt);
|
// 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
|
// Convert each `MountInfo` into a `Filesystem`, which contains
|
||||||
// both the mount information and usage information.
|
// both the mount information and usage information.
|
||||||
|
@ -358,29 +345,19 @@ where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
{
|
{
|
||||||
// The list of all mounted filesystems.
|
// The list of all mounted filesystems.
|
||||||
//
|
let mounts: Vec<MountInfo> = read_fs_list()?;
|
||||||
// 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 mut result = vec![];
|
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
|
// Convert each path into a `Filesystem`, which contains
|
||||||
// both the mount information and usage information.
|
// both the mount information and usage information.
|
||||||
for path in paths {
|
for path in paths {
|
||||||
match Filesystem::from_path(&mounts, path) {
|
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) => {
|
Err(FsError::InvalidPath) => {
|
||||||
show!(USimpleError::new(
|
show!(USimpleError::new(
|
||||||
1,
|
1,
|
||||||
|
@ -402,6 +379,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if get_exit_code() == 0 && result.is_empty() {
|
||||||
|
show!(USimpleError::new(1, "no file systems processed"));
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,16 +835,4 @@ mod tests {
|
||||||
assert!(is_included(&m, &opt));
|
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,6 +303,12 @@ fn test_type_option_with_file() {
|
||||||
.fails()
|
.fails()
|
||||||
.stderr_contains("no file systems processed");
|
.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!()
|
let fs_types = new_ucmd!()
|
||||||
.arg("--output=fstype")
|
.arg("--output=fstype")
|
||||||
.succeeds()
|
.succeeds()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue