grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Refactor grub_read_mountinfo() out of grub_find_root_devices_fro


From: Dr. Tilmann Bubeck
Subject: [PATCH] Refactor grub_read_mountinfo() out of grub_find_root_devices_from_mountinfo()
Date: Thu, 9 Jan 2014 22:07:48 +0100

The existing function grub_find_root_devices_from_mountinfo() reads
/proc/self/mountinfo AND searches for a given device. This patch moves the
code to read /proc/self/mountinfo out of this function into a new function
called grub_read_mountinfo(). This new function can then be used to read
/proc/self/mountinfo and do the filtering on its own.

The existing function grub_find_root_devices_from_mountinfo() is changed,
so that it now uses the new function grub_read_mountinfo() to do its work.
This reduces the code to basically filtering for the wanted device.

This refactoring is necessary for ext2 embedding to work but it is a
atomic change on its own and therefore put into a seperate changeset.

Signed-off-by: Dr. Tilmann Bubeck <address@hidden>
---
 grub-core/osdep/linux/getroot.c | 106 +++++++++++++++++++++++++++-------------
 include/grub/emu/getroot.h      |  16 ++++++
 2 files changed, 88 insertions(+), 34 deletions(-)

diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
index 772de0a..58c8500 100644
--- a/grub-core/osdep/linux/getroot.c
+++ b/grub-core/osdep/linux/getroot.c
@@ -119,16 +119,6 @@ struct btrfs_ioctl_search_args {
 static int
 grub_util_is_imsm (const char *os_dev);
 
-
-#define ESCAPED_PATH_MAX (4 * PATH_MAX)
-struct mountinfo_entry
-{
-  int id;
-  int major, minor;
-  char enc_root[ESCAPED_PATH_MAX + 1], enc_path[ESCAPED_PATH_MAX + 1];
-  char fstype[ESCAPED_PATH_MAX + 1], device[ESCAPED_PATH_MAX + 1];
-};
-
 static char **
 grub_util_raid_getmembers (const char *name, int bootable)
 {
@@ -365,21 +355,18 @@ get_btrfs_fs_prefix (const char *mount_path)
 }
 
 
-char **
-grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
+/* Read all entries from /proc/self/mountinfo and return them in a xmalloc'ed
+   memory which has to be freed be the caller after use.
+   The last entry is marked with mountinfo_entry.enc_root[0] = 0.
+   In case of any errors NULL is returned. */
+struct mountinfo_entry *
+grub_read_mountinfo(void)
 {
   FILE *fp;
   char *buf = NULL;
   size_t len = 0;
   grub_size_t entry_len = 0, entry_max = 4;
   struct mountinfo_entry *entries;
-  struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" };
-  int i;
-
-  if (! *dir)
-    dir = "/";
-  if (relroot)
-    *relroot = NULL;
 
   fp = grub_util_fopen ("/proc/self/mountinfo", "r");
   if (! fp)
@@ -387,31 +374,30 @@ grub_find_root_devices_from_mountinfo (const char *dir, 
char **relroot)
 
   entries = xmalloc (entry_max * sizeof (*entries));
 
-  /* First, build a list of relevant visible mounts.  */
-  while (getline (&buf, &len, fp) > 0)
+  /* First, build a list of visible mounts.  */
+  while (1)
     {
       struct mountinfo_entry entry;
       int count;
-      size_t enc_path_len;
       const char *sep;
 
+      if (entry_len >= entry_max)
+       {
+         entry_max <<= 1;
+         entries = xrealloc (entries, entry_max * sizeof (*entries));
+       }
+
+      if (getline (&buf, &len, fp) <= 0)
+         break;
+
       if (sscanf (buf, "%d %d %u:%u %s %s%n",
-                 &entry.id, &parent_entry.id, &entry.major, &entry.minor,
+                 &entry.id, &entry.parent_id, &entry.major, &entry.minor,
                  entry.enc_root, entry.enc_path, &count) < 6)
        continue;
 
       unescape (entry.enc_root);
       unescape (entry.enc_path);
 
-      enc_path_len = strlen (entry.enc_path);
-      /* Check that enc_path is a prefix of dir.  The prefix must either be
-         the entire string, or end with a slash, or be immediately followed
-         by a slash.  */
-      if (strncmp (dir, entry.enc_path, enc_path_len) != 0 ||
-         (enc_path_len && dir[enc_path_len - 1] != '/' &&
-          dir[enc_path_len] && dir[enc_path_len] != '/'))
-       continue;
-
       sep = strstr (buf + count, " - ");
       if (!sep)
        continue;
@@ -422,6 +408,58 @@ grub_find_root_devices_from_mountinfo (const char *dir, 
char **relroot)
 
       unescape (entry.device);
 
+      entries[entry_len] = entry;
+      entry_len++;
+    }
+
+  fclose (fp);
+
+  /* Mark the end of the list: */
+  entries[entry_len].enc_root[0] = 0;
+
+  return entries;
+}
+
+char **
+grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
+{
+  char *buf = NULL;
+  grub_size_t entry_len = 0, entry_max = 4;
+  struct mountinfo_entry *entries_all;
+  struct mountinfo_entry *entries;
+  struct mountinfo_entry parent_entry = { 0, 0, 0, 0, "", "", "", "" };
+  int i;
+  int entry_no;
+
+  if (! *dir)
+    dir = "/";
+  if (relroot)
+    *relroot = NULL;
+
+  entries_all = grub_read_mountinfo();
+  if (! entries_all)
+    return NULL; /* fall through to other methods */
+
+  entries = xmalloc (entry_max * sizeof (*entries));
+
+  /* First, build a list of relevant visible mounts.  */
+  for (entry_no = 0; entries_all[entry_no].enc_root[0] != 0; entry_no++)
+    {
+      struct mountinfo_entry entry;
+      size_t enc_path_len;
+
+      entry = entries_all[entry_no];
+      parent_entry.id = entry.parent_id;
+
+      enc_path_len = strlen (entry.enc_path);
+      /* Check that enc_path is a prefix of dir.  The prefix must either be
+         the entire string, or end with a slash, or be immediately followed
+         by a slash.  */
+      if (strncmp (dir, entries[i].enc_path, enc_path_len) != 0 ||
+         (enc_path_len && dir[enc_path_len - 1] != '/' &&
+          dir[enc_path_len] && dir[enc_path_len] != '/'))
+       continue;
+
       /* Using the mount IDs, find out where this fits in the list of
         visible mount entries we've seen so far.  There are three
         interesting cases.  Firstly, it may be inserted at the end: this is
@@ -469,6 +507,8 @@ grub_find_root_devices_from_mountinfo (const char *dir, 
char **relroot)
        }
     }
 
+  free (entries_all);
+
   /* Now scan visible mounts for the ones we're interested in.  */
   for (i = entry_len - 1; i >= 0; i--)
     {
@@ -534,13 +574,11 @@ grub_find_root_devices_from_mountinfo (const char *dir, 
char **relroot)
        free (fs_prefix);
       free (buf);
       free (entries);
-      fclose (fp);
       return ret;
     }
 
   free (buf);
   free (entries);
-  fclose (fp);
   return NULL;
 }
 
diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h
index 73fa2d3..0c4ef6d 100644
--- a/include/grub/emu/getroot.h
+++ b/include/grub/emu/getroot.h
@@ -25,6 +25,10 @@
 #include <sys/types.h>
 #include <stdio.h>
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
 enum grub_dev_abstraction_types {
   GRUB_DEV_ABSTRACTION_NONE,
   GRUB_DEV_ABSTRACTION_LVM,
@@ -49,6 +53,18 @@ void grub_util_follow_gpart_up (const char *name, 
grub_disk_addr_t *off_out,
 #include <sys/stat.h>
 
 #ifdef __linux__
+
+#define ESCAPED_PATH_MAX (4 * PATH_MAX)
+struct mountinfo_entry
+{
+  int id, parent_id;
+  int major, minor;
+  char enc_root[ESCAPED_PATH_MAX + 1], enc_path[ESCAPED_PATH_MAX + 1];
+  char fstype[ESCAPED_PATH_MAX + 1], device[ESCAPED_PATH_MAX + 1];
+};
+
+struct mountinfo_entry *
+grub_read_mountinfo(void);
 char **
 grub_find_root_devices_from_mountinfo (const char *dir, char **relroot);
 #endif
-- 
1.8.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]