1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 03:57:44 +00:00

df: refactor is_included(), mount_info_lt() funcs

Factor two helper functions, `is_included()` and `mount_info_lt()`,
from the `filter_mount_list()` function.
This commit is contained in:
Jeffrey Finkelstein 2022-02-12 20:54:47 -05:00
parent 4009bf9a89
commit 042e537ca8

View file

@ -161,6 +161,63 @@ impl Filesystem {
}
}
/// Whether to display the mount info given the inclusion settings.
fn is_included(mi: &MountInfo, paths: &[String], opt: &Options) -> bool {
// Don't show remote filesystems if `--local` has been given.
if mi.remote && opt.show_local_fs {
return false;
}
// Don't show pseudo filesystems unless `--all` has been given.
if mi.dummy && !opt.show_all_fs && !opt.show_listed_fs {
return false;
}
// Don't show filesystems if they have been explicitly excluded.
if !opt.fs_selector.should_select(&mi.fs_type) {
return false;
}
// Don't show filesystems other than the ones specified on the
// command line, if any.
if !paths.is_empty() && !paths.contains(&mi.mount_dir) {
return false;
}
true
}
/// Whether the mount info in `m2` should be prioritized over `m1`.
///
/// The "lt" in the function name is in analogy to the
/// [`std::cmp::PartialOrd::lt`].
fn mount_info_lt(m1: &MountInfo, m2: &MountInfo) -> bool {
// let "real" devices with '/' in the name win.
if m1.dev_name.starts_with('/') && !m2.dev_name.starts_with('/') {
return false;
}
let m1_nearer_root = m1.mount_dir.len() < m2.mount_dir.len();
// With bind mounts, prefer items nearer the root of the source
let m2_below_root = !m1.mount_root.is_empty()
&& !m2.mount_root.is_empty()
&& m1.mount_root.len() > m2.mount_root.len();
// let points towards the root of the device win.
if m1_nearer_root && !m2_below_root {
return false;
}
// let an entry over-mounted on a new device win, but only when
// matching an existing mnt point, to avoid problematic
// replacement when given inaccurate mount lists, seen with some
// chroot environments for example.
if m1.dev_name != m2.dev_name && m1.mount_dir == m2.mount_dir {
return false;
}
true
}
/// Keep only the specified subset of [`MountInfo`] instances.
///
/// If `paths` is non-empty, this function excludes any [`MountInfo`]
@ -174,24 +231,7 @@ impl Filesystem {
fn filter_mount_list(vmi: Vec<MountInfo>, paths: &[String], opt: &Options) -> Vec<MountInfo> {
let mut mount_info_by_id = HashMap::<String, Cell<MountInfo>>::new();
for mi in vmi {
// Don't show remote filesystems if `--local` has been given.
if mi.remote && opt.show_local_fs {
continue;
}
// Don't show pseudo filesystems unless `--all` has been given.
if mi.dummy && !opt.show_all_fs && !opt.show_listed_fs {
continue;
}
// Don't show filesystems if they have been explicitly excluded.
if !opt.fs_selector.should_select(&mi.fs_type) {
continue;
}
// Don't show filesystems other than the ones specified on the
// command line, if any.
if !paths.is_empty() && !paths.contains(&mi.mount_dir) {
if !is_included(&mi, paths, opt) {
continue;
}
@ -207,23 +247,7 @@ fn filter_mount_list(vmi: Vec<MountInfo>, paths: &[String], opt: &Options) -> Ve
// then check if we need to update it or keep the previously
// seen one.
let seen = mount_info_by_id[&id].replace(mi.clone());
let target_nearer_root = seen.mount_dir.len() > mi.mount_dir.len();
// With bind mounts, prefer items nearer the root of the source
let source_below_root = !seen.mount_root.is_empty()
&& !mi.mount_root.is_empty()
&& seen.mount_root.len() < mi.mount_root.len();
// let "real" devices with '/' in the name win.
if (!mi.dev_name.starts_with('/') || seen.dev_name.starts_with('/'))
// let points towards the root of the device win.
&& (!target_nearer_root || source_below_root)
// let an entry over-mounted on a new device win...
&& (seen.dev_name == mi.dev_name
/* ... but only when matching an existing mnt point,
to avoid problematic replacement when given
inaccurate mount lists, seen with some chroot
environments for example. */
|| seen.mount_dir != mi.mount_dir)
{
if mount_info_lt(&mi, &seen) {
mount_info_by_id[&id].replace(seen);
}
}