discover/grub2: Fix behavior of save_env -f
authorAlan Dunn <amdunn@google.com>
Tue, 12 Jan 2016 23:43:02 +0000 (15:43 -0800)
committerSam Mendoza-Jonas <sam@mendozajonas.com>
Mon, 8 Feb 2016 04:27:41 +0000 (15:27 +1100)
Currently, "save_env -f" in the GRUB2 parser only works with three
arguments, which means only commands of the form "save_env -f <path>"
that save *no* environment variables are allowed.

Allow "save_env -f <path> [<var>]*", making "save_env -f" useful.

Tested:
 Unit test test-grub2-save-env-dash-f tests this change, and the
 remaining unit tests still pass.

Signed-off-by: Alan Dunn <amdunn@google.com>
Signed-off-by: Sam Mendoza-Jonas <sam@mendozajonas.com>
discover/grub2/env.c
test/parser/Makefile.am
test/parser/test-grub2-save-env-dash-f.c [new file with mode: 0644]

index 1336824d1d92fb2bbc9d16945b4d3330135db6e1..3598927e0f295c5656e2fa93ee3192d32a18b92e 100644 (file)
@@ -214,6 +214,7 @@ int builtin_save_env(struct grub2_script *script,
        int i, rc, len, siglen;
        char *buf, *envpath;
        const char *envfile;
        int i, rc, len, siglen;
        char *buf, *envpath;
        const char *envfile;
+       bool using_dash_f = false;
 
        /* we only support local filesystems */
        if (!dev->mounted) {
 
        /* we only support local filesystems */
        if (!dev->mounted) {
@@ -222,9 +223,15 @@ int builtin_save_env(struct grub2_script *script,
                return -1;
        }
 
                return -1;
        }
 
-       if (argc == 3 && !strcmp(argv[1], "-f"))
+       if (argc >= 2 && !strcmp(argv[1], "-f")) {
+               if (argc < 3) {
+                       pb_log("save_env: for -f, need argument\n");
+                       return -1;
+               }
+
                envfile = argv[2];
                envfile = argv[2];
-       else
+               using_dash_f = true;
+       } else
                envfile = default_envfile;
 
        envpath = talloc_asprintf(script, "%s/%s",
                envfile = default_envfile;
 
        envpath = talloc_asprintf(script, "%s/%s",
@@ -241,7 +248,11 @@ int builtin_save_env(struct grub2_script *script,
        if (rc || len < siglen || memcmp(buf, signature, siglen))
                goto err;
 
        if (rc || len < siglen || memcmp(buf, signature, siglen))
                goto err;
 
-       for (i = 1; i < argc; i++) {
+       /* For "-f", skip the "-f <file>" arguments in picking the
+        * variables to save. */
+       i = (using_dash_f ? 3 : 1);
+
+       for (; i < argc; i++) {
                const char *name, *value;
 
                name = argv[i];
                const char *name, *value;
 
                name = argv[i];
index d69ca7f83f1299b81400d719a068824f4d176b36..dddb4722109fb134caad769383d5167eef25dee5 100644 (file)
@@ -28,6 +28,7 @@ parser_TESTS = \
        test/parser/test-grub2-single-line-if \
        test/parser/test-grub2-load-env \
        test/parser/test-grub2-save-env \
        test/parser/test-grub2-single-line-if \
        test/parser/test-grub2-load-env \
        test/parser/test-grub2-save-env \
+       test/parser/test-grub2-save-env-dash-f \
        test/parser/test-grub2-saved-default \
        test/parser/test-grub2-nondefault-prefix \
        test/parser/test-grub2-f18-ppc64 \
        test/parser/test-grub2-saved-default \
        test/parser/test-grub2-nondefault-prefix \
        test/parser/test-grub2-f18-ppc64 \
diff --git a/test/parser/test-grub2-save-env-dash-f.c b/test/parser/test-grub2-save-env-dash-f.c
new file mode 100644 (file)
index 0000000..7d48f67
--- /dev/null
@@ -0,0 +1,37 @@
+
+#include <string.h>
+
+#include <talloc/talloc.h>
+
+#include "parser-test.h"
+
+#if 0 /* PARSER_EMBEDDED_CONFIG */
+hello=world
+save_env -f env_file hello
+#endif
+
+static const char *envsig = "# GRUB Environment Block\n";
+
+void run_test(struct parser_test *test)
+{
+       const char *env_before, *env_after;
+
+       /* The environment file must be preallocated */
+
+       /* The padding at the end of the environment block is the length of
+        * "hello=world\n" */
+       env_before = talloc_asprintf(test, "%s%s", envsig,
+                                       "############");
+       test_add_file_data(test, test->ctx->device, "/boot/grub/env_file",
+                               env_before, strlen(env_before));
+
+       env_after = talloc_asprintf(test, "%s%s", envsig,
+                                       "hello=world\n");
+
+       test_read_conf_embedded(test, "/boot/grub/grub.cfg");
+
+       test_run_parser(test, "grub2");
+
+       check_file_contents(test, test->ctx->device, "/boot/grub/env_file",
+                               env_after, strlen(env_after));
+}