15a2072
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
15a2072
From: Hans de Goede <hdegoede@redhat.com>
15a2072
Date: Mon, 4 Jun 2018 19:49:47 +0200
15a2072
Subject: [PATCH] grub-editenv: Add "incr" command to increment integer value
15a2072
 env. variables
15a2072
15a2072
To be able to automatically detect if the last boot was successful,
15a2072
We want to keep count of succesful / failed boots in some integer
15a2072
environment variable.
15a2072
15a2072
This commit adds a grub-editenvt "incr" command to increment such
15a2072
integer value env. variables by 1 for use from various boot scripts.
15a2072
15a2072
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
15a2072
---
15a2072
 util/grub-editenv.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
15a2072
 1 file changed, 50 insertions(+)
15a2072
15a2072
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
15a2072
index 118e89fe57f..2918bb71cfe 100644
15a2072
--- a/util/grub-editenv.c
15a2072
+++ b/util/grub-editenv.c
15a2072
@@ -53,6 +53,9 @@ static struct argp_option options[] = {
15a2072
   /* TRANSLATORS: "unset" is a keyword. It's a summary of "unset" subcommand.  */
15a2072
   {N_("unset [NAME ...]"),    0, 0, OPTION_DOC|OPTION_NO_USAGE,
15a2072
    N_("Delete variables."), 0},
15a2072
+  /* TRANSLATORS: "incr" is a keyword. It's a summary of "incr" subcommand.  */
15a2072
+  {N_("incr [NAME ...]"),     0, 0, OPTION_DOC|OPTION_NO_USAGE,
15a2072
+   N_("Increase value of integer variables."), 0},
15a2072
 
15a2072
   {0,         0, 0, OPTION_DOC, N_("Options:"), -1},
15a2072
   {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
15a2072
@@ -246,6 +249,51 @@ unset_variables (const char *name, int argc, char *argv[])
15a2072
   grub_envblk_close (envblk);
15a2072
 }
15a2072
 
15a2072
+struct get_int_value_params {
15a2072
+  char *varname;
15a2072
+  int value;
15a2072
+};
15a2072
+
15a2072
+static int
15a2072
+get_int_value (const char *varname, const char *value, void *hook_data)
15a2072
+{
15a2072
+  struct get_int_value_params *params = hook_data;
15a2072
+
15a2072
+  if (strcmp (varname, params->varname) == 0) {
15a2072
+    params->value = strtol (value, NULL, 10);
15a2072
+    return 1;
15a2072
+  }
15a2072
+  return 0;
15a2072
+}
15a2072
+
15a2072
+static void
15a2072
+incr_variables (const char *name, int argc, char *argv[])
15a2072
+{
15a2072
+  grub_envblk_t envblk;
15a2072
+  char buf[16];
15a2072
+
15a2072
+  envblk = open_envblk_file (name);
15a2072
+  while (argc)
15a2072
+    {
15a2072
+      struct get_int_value_params params = {
15a2072
+        .varname = argv[0],
15a2072
+        .value = 0, /* Consider unset variables 0 */
15a2072
+      };
15a2072
+
15a2072
+      grub_envblk_iterate (envblk, &params, get_int_value);
15a2072
+      snprintf(buf, sizeof(buf), "%d", params.value + 1);
15a2072
+
15a2072
+      if (! grub_envblk_set (envblk, argv[0], buf))
15a2072
+        grub_util_error ("%s", _("environment block too small"));
15a2072
+
15a2072
+      argc--;
15a2072
+      argv++;
15a2072
+    }
15a2072
+
15a2072
+  write_envblk (name, envblk);
15a2072
+  grub_envblk_close (envblk);
15a2072
+}
15a2072
+
15a2072
 int
15a2072
 main (int argc, char *argv[])
15a2072
 {
15a2072
@@ -285,6 +333,8 @@ main (int argc, char *argv[])
15a2072
     set_variables (filename, argc - curindex, argv + curindex);
15a2072
   else if (strcmp (command, "unset") == 0)
15a2072
     unset_variables (filename, argc - curindex, argv + curindex);
15a2072
+  else if (strcmp (command, "incr") == 0)
15a2072
+    incr_variables (filename, argc - curindex, argv + curindex);
15a2072
   else
15a2072
     {
15a2072
       char *program = xstrdup(program_name);