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