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