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.
117 lines
3.6 KiB
117 lines
3.6 KiB
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; |
|
}
|
|
|