Blame SOURCES/coreutils-8.22-df-getdisk.patch

f180de
diff -urNp coreutils-8.22-orig/src/df.c coreutils-8.22/src/df.c
f180de
--- coreutils-8.22-orig/src/df.c	2015-07-03 15:51:44.293116375 +0200
f180de
+++ coreutils-8.22/src/df.c	2015-07-03 16:02:48.743390691 +0200
f180de
@@ -1057,6 +1057,33 @@ get_dev (char const *disk, char const *m
f180de
   free (dev_name);
f180de
 }
f180de
 
f180de
+/* Scan the mount list returning the _last_ device found for MOUNT.
f180de
+   NULL is returned if MOUNT not found.  The result is malloced.  */
f180de
+static char *
f180de
+last_device_for_mount (char const* mount)
f180de
+{
f180de
+  struct mount_entry const *me;
f180de
+  struct mount_entry const *le = NULL;
f180de
+
f180de
+  for (me = mount_list; me; me = me->me_next)
f180de
+    {
f180de
+      if (STREQ (me->me_mountdir, mount))
f180de
+        le = me;
f180de
+    }
f180de
+
f180de
+  if (le)
f180de
+    {
f180de
+      char *devname = le->me_devname;
f180de
+      char *canon_dev = canonicalize_file_name (devname);
f180de
+      if (canon_dev && IS_ABSOLUTE_FILE_NAME (canon_dev))
f180de
+        return canon_dev;
f180de
+      free (canon_dev);
f180de
+      return xstrdup (le->me_devname);
f180de
+    }
f180de
+  else
f180de
+    return NULL;
f180de
+}
f180de
+
f180de
 /* If DISK corresponds to a mount point, show its usage
f180de
    and return true.  Otherwise, return false.  */
f180de
 static bool
f180de
@@ -1064,27 +1091,57 @@ get_disk (char const *disk)
f180de
 {
f180de
   struct mount_entry const *me;
f180de
   struct mount_entry const *best_match = NULL;
f180de
+  bool best_match_accessible = false;
f180de
+  bool eclipsed_device = false;
f180de
   char const *file = disk;
f180de
 
f180de
   char *resolved = canonicalize_file_name (disk);
f180de
-  if (resolved && resolved[0] == '/')
f180de
+  if (resolved && IS_ABSOLUTE_FILE_NAME (resolved))
f180de
     disk = resolved;
f180de
 
f180de
   size_t best_match_len = SIZE_MAX;
f180de
   for (me = mount_list; me; me = me->me_next)
f180de
     {
f180de
-      if (STREQ (disk, me->me_devname))
f180de
+      /* TODO: Should cache canon_dev in the mount_entry struct.  */
f180de
+      char *devname = me->me_devname;
f180de
+      char *canon_dev = canonicalize_file_name (me->me_devname);
f180de
+      if (canon_dev && IS_ABSOLUTE_FILE_NAME (canon_dev))
f180de
+        devname = canon_dev;
f180de
+
f180de
+      if (STREQ (disk, devname))
f180de
         {
f180de
+          char *last_device = last_device_for_mount (me->me_mountdir);
f180de
+          eclipsed_device = last_device && ! STREQ (last_device, devname);
f180de
           size_t len = strlen (me->me_mountdir);
f180de
-          if (len < best_match_len)
f180de
+
f180de
+          if (! eclipsed_device
f180de
+              && (! best_match_accessible || len < best_match_len))
f180de
             {
f180de
-              best_match = me;
f180de
-              if (len == 1) /* Traditional root.  */
f180de
-                break;
f180de
-              else
f180de
-                best_match_len = len;
f180de
+              struct stat disk_stats;
f180de
+              bool this_match_accessible = false;
f180de
+
f180de
+              if (stat (me->me_mountdir, &disk_stats) == 0)
f180de
+                best_match_accessible = this_match_accessible = true;
f180de
+
f180de
+              if (this_match_accessible
f180de
+                  || (! best_match_accessible && len < best_match_len))
f180de
+                {
f180de
+                  best_match = me;
f180de
+                  if (len == 1) /* Traditional root.  */
f180de
+                    {
f180de
+                      free (last_device);
f180de
+                      free (canon_dev);
f180de
+                      break;
f180de
+                    }
f180de
+                  else
f180de
+                    best_match_len = len;
f180de
+                }
f180de
             }
f180de
+
f180de
+          free (last_device);
f180de
         }
f180de
+
f180de
+      free (canon_dev);
f180de
     }
f180de
 
f180de
   free (resolved);
f180de
@@ -1096,6 +1153,13 @@ get_disk (char const *disk)
f180de
                best_match->me_remote, NULL, false);
f180de
       return true;
f180de
     }
f180de
+  else if (eclipsed_device)
f180de
+    {
f180de
+      error (0, 0, _("cannot access %s: over-mounted by another device"),
f180de
+             quote (file));
f180de
+      exit_status = EXIT_FAILURE;
f180de
+      return true;
f180de
+    }
f180de
 
f180de
   return false;
f180de
 }