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

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