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

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