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;
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;
&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] != '/'))
free (ret);
ret = NULL;
- if (major != 0)
- continue; /* not a virtual device */
-
sep = strstr (buf + count, " - ");
if (!sep)
continue;
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);
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__ */
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)
}
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__
}
#endif
+ parsedir:
/* Remove trailing slashes, return empty string if root directory. */
len = strlen (buf3);
while (len > 0 && buf3[len - 1] == '/')