]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
support bind and subvolume mount
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 2 Dec 2010 13:26:46 +0000 (14:26 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 2 Dec 2010 13:26:46 +0000 (14:26 +0100)
grub-core/kern/emu/getroot.c
grub-core/kern/emu/misc.c
include/grub/emu/misc.h

index f51dcd7707432dfc28fd6cca19f3d6271c93ab39..373834127756848c0a06ee4f253b11a21e7d58e9 100644 (file)
@@ -103,8 +103,8 @@ xgetcwd (void)
    can't deal with the multiple-device case yet, but in the meantime, we can
    at least cope with the single-device case by scanning
    /proc/self/mountinfo.  */
-static char *
-find_root_device_from_mountinfo (const char *dir)
+char *
+grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
 {
   FILE *fp;
   char *buf = NULL;
@@ -115,6 +115,9 @@ find_root_device_from_mountinfo (const char *dir)
   if (! fp)
     return NULL; /* fall through to other methods */
 
+  if (relroot)
+    *relroot = NULL;
+
   while (getline (&buf, &len, fp) > 0)
     {
       int mnt_id, parent_mnt_id;
@@ -131,9 +134,6 @@ find_root_device_from_mountinfo (const char *dir)
                  &count) < 6)
        continue;
 
-      if (strcmp (enc_root, "/") != 0)
-       continue; /* only a subtree is mounted */
-
       enc_path_len = strlen (enc_path);
       if (strncmp (dir, enc_path, enc_path_len) != 0 ||
          (dir[enc_path_len] && dir[enc_path_len] != '/'))
@@ -147,9 +147,6 @@ find_root_device_from_mountinfo (const char *dir)
       free (ret);
       ret = NULL;
 
-      if (major != 0)
-       continue; /* not a virtual device */
-
       sep = strstr (buf + count, " - ");
       if (!sep)
        continue;
@@ -158,13 +155,9 @@ find_root_device_from_mountinfo (const char *dir)
       if (sscanf (sep, "%s %s", fstype, device) != 2)
        continue;
 
-      if (stat (device, &st) < 0)
-       continue;
-
-      if (!S_ISBLK (st.st_mode))
-       continue; /* not a block device */
-
       ret = strdup (device);
+      if (relroot)
+       *relroot = strdup (enc_root);
     }
 
   free (buf);
@@ -531,7 +524,7 @@ grub_guess_root_device (const char *dir)
   struct stat st;
 
 #ifdef __linux__
-  os_dev = find_root_device_from_mountinfo (dir);
+  os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
   if (os_dev)
     return os_dev;
 #endif /* __linux__ */
index c8b95443b22fd2ed6b3b5b98ba31bf7739d196bf..44c40b01039c433ab10240de8271643135eb64a6 100644 (file)
@@ -415,6 +415,18 @@ grub_make_system_path_relative_to_its_root (const char *path)
          if (offset == 0)
            {
              free (buf);
+#ifdef __linux__
+             {
+               char *bind;
+               grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
+               if (bind && bind[0] && bind[1])
+                 {
+                   buf3 = bind;
+                   goto parsedir;
+                 }
+               grub_free (bind);
+             }
+#endif
              free (buf2);
 #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
              if (poolfs)
@@ -437,6 +449,21 @@ grub_make_system_path_relative_to_its_root (const char *path)
     }
   free (buf);
   buf3 = xstrdup (buf2 + offset);
+  buf2[offset] = 0;
+#ifdef __linux__
+  {
+    char *bind;
+    grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
+    if (bind && bind[0] && bind[1])
+      {
+       char *temp = buf3;
+       buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3);
+       grub_free (temp);
+      }
+    grub_free (bind);
+  }
+#endif
+  
   free (buf2);
 
 #ifdef __CYGWIN__
@@ -452,6 +479,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
     }
 #endif
 
+ parsedir:
   /* Remove trailing slashes, return empty string if root directory.  */
   len = strlen (buf3);
   while (len > 0 && buf3[len - 1] == '/')
index ef0d18300b625843a4d5d6fac3c54cb299c7423e..d4ebcb0d1f0b53ca96bb4fe6dd6d886d3391c6c5 100644 (file)
@@ -78,4 +78,6 @@ extern char * canonicalize_file_name (const char *path);
 int grub_device_mapper_supported (void);
 #endif
 
+char *grub_find_root_device_from_mountinfo (const char *dir, char **relroot);
+
 #endif /* GRUB_EMU_MISC_H */