You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.6 KiB
118 lines
3.6 KiB
6 years ago
|
diff -urNp coreutils-8.22-orig/src/df.c coreutils-8.22/src/df.c
|
||
|
--- coreutils-8.22-orig/src/df.c 2015-07-03 15:51:44.293116375 +0200
|
||
|
+++ coreutils-8.22/src/df.c 2015-07-03 16:02:48.743390691 +0200
|
||
|
@@ -1057,6 +1057,33 @@ get_dev (char const *disk, char const *m
|
||
|
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
|
||
|
@@ -1064,27 +1091,57 @@ 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);
|
||
|
- if (resolved && resolved[0] == '/')
|
||
|
+ if (resolved && IS_ABSOLUTE_FILE_NAME (resolved))
|
||
|
disk = resolved;
|
||
|
|
||
|
size_t best_match_len = SIZE_MAX;
|
||
|
for (me = mount_list; me; me = me->me_next)
|
||
|
{
|
||
|
- if (STREQ (disk, me->me_devname))
|
||
|
+ /* TODO: Should cache canon_dev in the mount_entry struct. */
|
||
|
+ char *devname = me->me_devname;
|
||
|
+ char *canon_dev = canonicalize_file_name (me->me_devname);
|
||
|
+ if (canon_dev && IS_ABSOLUTE_FILE_NAME (canon_dev))
|
||
|
+ devname = canon_dev;
|
||
|
+
|
||
|
+ 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 (len < best_match_len)
|
||
|
+
|
||
|
+ if (! eclipsed_device
|
||
|
+ && (! best_match_accessible || len < best_match_len))
|
||
|
{
|
||
|
- best_match = me;
|
||
|
- if (len == 1) /* Traditional root. */
|
||
|
- break;
|
||
|
- else
|
||
|
- best_match_len = len;
|
||
|
+ struct stat disk_stats;
|
||
|
+ bool this_match_accessible = false;
|
||
|
+
|
||
|
+ if (stat (me->me_mountdir, &disk_stats) == 0)
|
||
|
+ best_match_accessible = this_match_accessible = true;
|
||
|
+
|
||
|
+ if (this_match_accessible
|
||
|
+ || (! best_match_accessible && len < best_match_len))
|
||
|
+ {
|
||
|
+ best_match = me;
|
||
|
+ if (len == 1) /* Traditional root. */
|
||
|
+ {
|
||
|
+ free (last_device);
|
||
|
+ free (canon_dev);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ best_match_len = len;
|
||
|
+ }
|
||
|
}
|
||
|
+
|
||
|
+ free (last_device);
|
||
|
}
|
||
|
+
|
||
|
+ free (canon_dev);
|
||
|
}
|
||
|
|
||
|
free (resolved);
|
||
|
@@ -1096,6 +1153,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;
|
||
|
}
|