mirror of
https://github.com/coreutils/coreutils.git
synced 2024-11-24 10:23:31 +08:00
df: report correct device in presence of eclipsed mounts
* src/df.c (last_device_for_mount): A new function to identify the last device mounted for a mount point. (get_disk): Use the above to discard mount entries for a device, where a later mount entry uses a different device name than that of the user specified device. * tests/df/over-mount-device.sh: A new root test. * tests/local.mk: Reference the new test. * NEWS: Reword for all these related recent fixes. Discussed at: http://bugs.gnu.org/16539#69
This commit is contained in:
parent
828801a174
commit
d71c12f1e4
9
NEWS
9
NEWS
@ -44,10 +44,11 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
[These dd bugs were present in "the beginning".]
|
||||
|
||||
df now elides duplicates for virtual file systems like tmpfs.
|
||||
Displays the correct device details for points mounted multiple times.
|
||||
Displays placeholder values for inaccessible file systems,
|
||||
rather than error messages or values for the wrong file system.
|
||||
df has more fixes related to the newer dynamic representation of file systems:
|
||||
Duplicates are elided for virtual file systems like tmpfs.
|
||||
Details for the correct device are output for points mounted multiple times.
|
||||
Placeholder values are output for inaccessible file systems, rather than
|
||||
than error messages or values for the wrong file system.
|
||||
[These bugs were present in "the beginning".]
|
||||
|
||||
du now silently ignores directory cycles introduced with bind mounts.
|
||||
|
42
src/df.c
42
src/df.c
@ -1114,6 +1114,33 @@ get_dev (char const *disk, char const *mount_point, char const* file,
|
||||
free (dev_name);
|
||||
}
|
||||
|
||||
/* Scan the mount list returning the _last_ device found for MOUNT.
|
||||
NULL is returned if MOUNT not found. The result is malloced. */
|
||||
static char *
|
||||
last_device_for_mount (char const* mount)
|
||||
{
|
||||
struct mount_entry const *me;
|
||||
struct mount_entry const *le = NULL;
|
||||
|
||||
for (me = mount_list; me; me = me->me_next)
|
||||
{
|
||||
if (STREQ (me->me_mountdir, mount))
|
||||
le = me;
|
||||
}
|
||||
|
||||
if (le)
|
||||
{
|
||||
char *devname = le->me_devname;
|
||||
char *canon_dev = canonicalize_file_name (devname);
|
||||
if (canon_dev && IS_ABSOLUTE_FILE_NAME (canon_dev))
|
||||
return canon_dev;
|
||||
free (canon_dev);
|
||||
return xstrdup (le->me_devname);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If DISK corresponds to a mount point, show its usage
|
||||
and return true. Otherwise, return false. */
|
||||
static bool
|
||||
@ -1122,6 +1149,7 @@ get_disk (char const *disk)
|
||||
struct mount_entry const *me;
|
||||
struct mount_entry const *best_match = NULL;
|
||||
bool best_match_accessible = false;
|
||||
bool eclipsed_device = false;
|
||||
char const *file = disk;
|
||||
|
||||
char *resolved = canonicalize_file_name (disk);
|
||||
@ -1139,9 +1167,12 @@ get_disk (char const *disk)
|
||||
|
||||
if (STREQ (disk, devname))
|
||||
{
|
||||
char *last_device = last_device_for_mount (me->me_mountdir);
|
||||
eclipsed_device = last_device && ! STREQ (last_device, devname);
|
||||
size_t len = strlen (me->me_mountdir);
|
||||
|
||||
if (! best_match_accessible || len < best_match_len)
|
||||
if (! eclipsed_device
|
||||
&& (! best_match_accessible || len < best_match_len))
|
||||
{
|
||||
struct stat disk_stats;
|
||||
bool this_match_accessible = false;
|
||||
@ -1159,6 +1190,8 @@ get_disk (char const *disk)
|
||||
best_match_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
free (last_device);
|
||||
}
|
||||
|
||||
free (canon_dev);
|
||||
@ -1173,6 +1206,13 @@ get_disk (char const *disk)
|
||||
best_match->me_remote, NULL, false);
|
||||
return true;
|
||||
}
|
||||
else if (eclipsed_device)
|
||||
{
|
||||
error (0, 0, _("cannot access %s: over-mounted by another device"),
|
||||
quote (file));
|
||||
exit_status = EXIT_FAILURE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
57
tests/df/over-mount-device.sh
Executable file
57
tests/df/over-mount-device.sh
Executable file
@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
# Ensure that df /dev/loop0 errors out if overmounted by another device
|
||||
|
||||
# Copyright (C) 2014 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ df
|
||||
require_root_
|
||||
|
||||
cwd=$(pwd)
|
||||
cleanup_() { cd /; umount "$cwd/mnt"; umount "$cwd/mnt"; }
|
||||
|
||||
skip=0
|
||||
|
||||
# Create 2 file systems
|
||||
for i in 1 2; do
|
||||
dd if=/dev/zero of=blob$i bs=8192 count=200 > /dev/null 2>&1 \
|
||||
|| skip=1
|
||||
mkfs -t ext2 -F blob$i \
|
||||
|| skip_ "failed to create ext2 file system"
|
||||
done
|
||||
|
||||
# Mount both at the same place (eclipsing the first)
|
||||
mkdir mnt || skip=1
|
||||
mount -oloop blob1 mnt || skip=1
|
||||
eclipsed_dev=$(df --o=source mnt | tail -n1) || skip=1
|
||||
mount -oloop blob2 mnt || skip=1
|
||||
|
||||
test $skip = 1 \
|
||||
&& skip_ "insufficient mount/ext2 support"
|
||||
|
||||
df . || skip_ "failed to lookup the device for the current dir"
|
||||
|
||||
echo "df: cannot access '$eclipsed_dev': over-mounted by another device" > exp
|
||||
|
||||
# We should get an error for the eclipsed device and continue
|
||||
df $eclipsed_dev . > out 2> err && fail=1
|
||||
|
||||
# header and single entry in output
|
||||
test $(wc -l < out) = 2 || fail=1
|
||||
|
||||
compare exp err || fail=1
|
||||
|
||||
Exit $fail
|
@ -115,6 +115,7 @@ all_root_tests = \
|
||||
tests/cp/sparse-fiemap.sh \
|
||||
tests/dd/skip-seek-past-dev.sh \
|
||||
tests/df/problematic-chars.sh \
|
||||
tests/df/over-mount-device.sh \
|
||||
tests/du/bind-mount-dir-cycle.sh \
|
||||
tests/id/setgid.sh \
|
||||
tests/install/install-C-root.sh \
|
||||
|
Loading…
Reference in New Issue
Block a user