d2d9f60
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
d2d9f60
From: Marta Lewandowska <mlewando@redhat.com>
d2d9f60
Date: Mon, 9 Oct 2023 08:53:18 +0200
d2d9f60
Subject: [PATCH] add flag to only search root dev
d2d9f60
d2d9f60
fixes bz#2223437
d2d9f60
d2d9f60
Signed-off-by: Marta Lewandowska <mlewando@redhat.com>
d2d9f60
---
d2d9f60
 grub-core/commands/search.c      | 36 ++++++++++++++++++++++++++++++++++++
d2d9f60
 grub-core/commands/search_wrap.c |  5 +++++
d2d9f60
 grub-core/kern/misc.c            | 30 ++++++++++++++++++++++++++++++
d2d9f60
 include/grub/misc.h              |  1 +
d2d9f60
 include/grub/search.h            |  3 ++-
d2d9f60
 5 files changed, 74 insertions(+), 1 deletion(-)
d2d9f60
d2d9f60
diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
d2d9f60
index 57d26ced8a8e..819231751c38 100644
d2d9f60
--- a/grub-core/commands/search.c
d2d9f60
+++ b/grub-core/commands/search.c
d2d9f60
@@ -85,6 +85,42 @@ iterate_device (const char *name, void *data)
d2d9f60
       grub_device_close (dev);
d2d9f60
     }
d2d9f60
 
d2d9f60
+  /* Skip it if it's not the root device when requested. */
d2d9f60
+  if (ctx->flags & SEARCH_FLAGS_ROOTDEV_ONLY)
d2d9f60
+    {
d2d9f60
+      const char *root_dev;
d2d9f60
+      root_dev = grub_env_get ("root");
d2d9f60
+      if (root_dev != NULL && *root_dev != '\0')
d2d9f60
+      {
d2d9f60
+        char *root_disk = grub_malloc (grub_strlen(root_dev) + 1);
d2d9f60
+        char *name_disk = grub_malloc (grub_strlen(name) + 1);
d2d9f60
+        char *rem_1 = grub_malloc(grub_strlen(root_dev) + 1);
d2d9f60
+        char *rem_2 = grub_malloc(grub_strlen(name) + 1);
d2d9f60
+
d2d9f60
+	if (root_disk != NULL && name_disk != NULL && 
d2d9f60
+	    rem_1 != NULL && rem_2 != NULL)
d2d9f60
+  	  {
d2d9f60
+            /* get just the disk name; partitions will be different. */
d2d9f60
+            grub_str_sep (root_dev, root_disk, ',', rem_1);
d2d9f60
+            grub_str_sep (name, name_disk, ',', rem_2);
d2d9f60
+            if (root_disk != NULL && *root_disk != '\0' &&
d2d9f60
+    	        name_disk != NULL && *name_disk != '\0')
d2d9f60
+              if (grub_strcmp(root_disk, name_disk) != 0)
d2d9f60
+                {
d2d9f60
+                  grub_free (root_disk);
d2d9f60
+                  grub_free (name_disk);
d2d9f60
+                  grub_free (rem_1);
d2d9f60
+                  grub_free (rem_2);
d2d9f60
+                  return 0;
d2d9f60
+                }
d2d9f60
+	  }
d2d9f60
+        grub_free (root_disk);
d2d9f60
+        grub_free (name_disk);
d2d9f60
+        grub_free (rem_1);
d2d9f60
+        grub_free (rem_2);
d2d9f60
+      }
d2d9f60
+    }
d2d9f60
+
d2d9f60
 #ifdef DO_SEARCH_FS_UUID
d2d9f60
 #define compare_fn grub_strcasecmp
d2d9f60
 #else
d2d9f60
diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c
d2d9f60
index 0b62acf85359..06b5f51eefb5 100644
d2d9f60
--- a/grub-core/commands/search_wrap.c
d2d9f60
+++ b/grub-core/commands/search_wrap.c
d2d9f60
@@ -41,6 +41,7 @@ static const struct grub_arg_option options[] =
d2d9f60
      ARG_TYPE_STRING},
d2d9f60
     {"no-floppy",	'n', 0, N_("Do not probe any floppy drive."), 0, 0},
d2d9f60
     {"efidisk-only",	0, 0, N_("Only probe EFI disks."), 0, 0},
d2d9f60
+    {"root-dev-only",  'r', 0, N_("Only probe root device."), 0, 0},
d2d9f60
     {"hint",	        'h', GRUB_ARG_OPTION_REPEATABLE,
d2d9f60
      N_("First try the device HINT. If HINT ends in comma, "
d2d9f60
 	"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
d2d9f60
@@ -75,6 +76,7 @@ enum options
d2d9f60
     SEARCH_SET,
d2d9f60
     SEARCH_NO_FLOPPY,
d2d9f60
     SEARCH_EFIDISK_ONLY,
d2d9f60
+    SEARCH_ROOTDEV_ONLY,
d2d9f60
     SEARCH_HINT,
d2d9f60
     SEARCH_HINT_IEEE1275,
d2d9f60
     SEARCH_HINT_BIOS,
d2d9f60
@@ -189,6 +191,9 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
d2d9f60
   if (state[SEARCH_EFIDISK_ONLY].set)
d2d9f60
     flags |= SEARCH_FLAGS_EFIDISK_ONLY;
d2d9f60
 
d2d9f60
+  if (state[SEARCH_ROOTDEV_ONLY].set)
d2d9f60
+    flags |= SEARCH_FLAGS_ROOTDEV_ONLY;
d2d9f60
+
d2d9f60
   if (state[SEARCH_LABEL].set)
d2d9f60
     grub_search_label (id, var, flags, hints, nhints);
d2d9f60
   else if (state[SEARCH_FS_UUID].set)
d2d9f60
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
d2d9f60
index cb454614022f..c0ac7fee6cc2 100644
d2d9f60
--- a/grub-core/kern/misc.c
d2d9f60
+++ b/grub-core/kern/misc.c
d2d9f60
@@ -619,6 +619,36 @@ grub_reverse (char *str)
d2d9f60
     }
d2d9f60
 }
d2d9f60
 
d2d9f60
+/* Separate string into two parts, broken up by delimiter delim. */
d2d9f60
+void
d2d9f60
+grub_str_sep (const char *s, char *p, char delim, char *r)
d2d9f60
+{
d2d9f60
+  char* t = grub_strndup(s, grub_strlen(s));
d2d9f60
+
d2d9f60
+  if (t != NULL && *t != '\0')
d2d9f60
+  {
d2d9f60
+    char* tmp = t;
d2d9f60
+  
d2d9f60
+    while (((*p = *t) != '\0') && ((*p = *t) != delim))
d2d9f60
+    {
d2d9f60
+      p++;
d2d9f60
+      t++;
d2d9f60
+    }
d2d9f60
+    *p = '\0';
d2d9f60
+  
d2d9f60
+    if (*t != '\0')
d2d9f60
+    {
d2d9f60
+      t++;
d2d9f60
+      while ((*r++ = *t++) != '\0')
d2d9f60
+        ;
d2d9f60
+      *r = '\0';
d2d9f60
+    }
d2d9f60
+    grub_free (tmp);
d2d9f60
+  }
d2d9f60
+  else
d2d9f60
+    grub_free (t);
d2d9f60
+}
d2d9f60
+
d2d9f60
 /* Divide N by D, return the quotient, and store the remainder in *R.  */
d2d9f60
 grub_uint64_t
d2d9f60
 grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
d2d9f60
diff --git a/include/grub/misc.h b/include/grub/misc.h
d2d9f60
index faae0ae8606c..981526644d29 100644
d2d9f60
--- a/include/grub/misc.h
d2d9f60
+++ b/include/grub/misc.h
d2d9f60
@@ -314,6 +314,7 @@ void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n);
d2d9f60
 grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) WARN_UNUSED_RESULT;
d2d9f60
 int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2)));
d2d9f60
 int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2)));
d2d9f60
+void EXPORT_FUNC(grub_str_sep) (const char *s, char *p, char delim, char *r);
d2d9f60
 
d2d9f60
 /* Replace all `ch' characters of `input' with `with' and copy the
d2d9f60
    result into `output'; return EOS address of `output'. */
d2d9f60
diff --git a/include/grub/search.h b/include/grub/search.h
d2d9f60
index 4190aeb2cbf5..321d1400e451 100644
d2d9f60
--- a/include/grub/search.h
d2d9f60
+++ b/include/grub/search.h
d2d9f60
@@ -22,7 +22,8 @@
d2d9f60
 enum search_flags
d2d9f60
   {
d2d9f60
     SEARCH_FLAGS_NO_FLOPPY	= 1,
d2d9f60
-    SEARCH_FLAGS_EFIDISK_ONLY	= 2
d2d9f60
+    SEARCH_FLAGS_EFIDISK_ONLY	= 2,
d2d9f60
+    SEARCH_FLAGS_ROOTDEV_ONLY	= 4
d2d9f60
   };
d2d9f60
 
d2d9f60
 void grub_search_fs_file (const char *key, const char *var,