| From ecc3b2ee3645e2a79236856783d3f803121874b8 Mon Sep 17 00:00:00 2001 |
| From: Jeremy Kerr <jk@ozlabs.org> |
| Date: Mon, 11 Nov 2019 19:30:41 +0800 |
| Subject: [PATCH 11/18] discover/grub2: Allow (device)/path references in |
| general script usage |
| |
| Currently, we have support for grub2 (device)/path syntax for boot |
| resources. This change allows this syntax for general paths in grub2 |
| scripts (for example, -f tests). |
| |
| This involves exposing grub2_lookup_device, to allow the script |
| execution code to resolve pathnames. |
| |
| Signed-off-by: Jeremy Kerr <jk@ozlabs.org> |
| (cherry picked from commit b22445748f44ed6965f31f45b39abb690d24ec47) |
| Signed-off-by: Klaus Heinrich Kiwi <klaus@linux.vnet.ibm.com> |
| --- |
| discover/grub2/builtins.c | 50 ++++++++++++++++--- |
| discover/grub2/grub2.c | 4 +- |
| discover/grub2/grub2.h | 2 + |
| test/parser/Makefile.am | 1 + |
| test/parser/test-grub2-devpath-scripting.c | 56 ++++++++++++++++++++++ |
| 5 files changed, 104 insertions(+), 9 deletions(-) |
| create mode 100644 test/parser/test-grub2-devpath-scripting.c |
| |
| diff --git a/discover/grub2/builtins.c b/discover/grub2/builtins.c |
| index 765c4d7..c726216 100644 |
| --- a/discover/grub2/builtins.c |
| +++ b/discover/grub2/builtins.c |
| @@ -197,6 +197,32 @@ static int builtin_search(struct grub2_script *script, |
| return 0; |
| } |
| |
| +static int parse_to_device_path(struct grub2_script *script, |
| + const char *desc, struct discover_device **devp, |
| + char **pathp) |
| +{ |
| + struct discover_device *dev; |
| + struct grub2_file *file; |
| + |
| + file = grub2_parse_file(script, desc); |
| + if (!file) |
| + return -1; |
| + |
| + dev = script->ctx->device; |
| + if (file->dev) |
| + dev = grub2_lookup_device(script->ctx->handler, file->dev); |
| + |
| + if (!dev) |
| + return -1; |
| + |
| + *devp = dev; |
| + *pathp = talloc_strdup(script, file->path); |
| + |
| + talloc_free(file); |
| + |
| + return 0; |
| +} |
| + |
| /* Note that GRUB does not follow symlinks in evaluating all file |
| * tests but -s, unlike below. However, it seems like a bad idea to |
| * emulate GRUB's behavior (e.g., it would take extra work), so we |
| @@ -204,12 +230,17 @@ static int builtin_search(struct grub2_script *script, |
| static bool builtin_test_op_file(struct grub2_script *script, char op, |
| const char *file) |
| { |
| + struct discover_device *dev; |
| + struct stat statbuf; |
| bool result; |
| + char *path; |
| int rc; |
| - struct stat statbuf; |
| |
| - rc = parser_stat_path(script->ctx, script->ctx->device, |
| - file, &statbuf); |
| + rc = parse_to_device_path(script, file, &dev, &path); |
| + if (rc) |
| + return false; |
| + |
| + rc = parser_stat_path(script->ctx, dev, path, &statbuf); |
| if (rc) |
| return false; |
| |
| @@ -237,16 +268,21 @@ static bool builtin_test_op_file(struct grub2_script *script, char op, |
| static bool builtin_test_op_dir(struct grub2_script *script, char op, |
| const char *dir) |
| { |
| - int rc; |
| + struct discover_device *dev; |
| struct stat statbuf; |
| + char *path; |
| + int rc; |
| |
| if (op != 'd') |
| return false; |
| |
| - rc = parser_stat_path(script->ctx, script->ctx->device, dir, &statbuf); |
| - if (rc) { |
| + rc = parse_to_device_path(script, dir, &dev, &path); |
| + if (rc) |
| + return false; |
| + |
| + rc = parser_stat_path(script->ctx, dev, path, &statbuf); |
| + if (rc) |
| return false; |
| - } |
| |
| return S_ISDIR(statbuf.st_mode); |
| } |
| diff --git a/discover/grub2/grub2.c b/discover/grub2/grub2.c |
| index a08a320..a8d115f 100644 |
| --- a/discover/grub2/grub2.c |
| +++ b/discover/grub2/grub2.c |
| @@ -33,8 +33,8 @@ static const char *const grub2_conf_files[] = { |
| NULL |
| }; |
| |
| -static struct discover_device *grub2_lookup_device( |
| - struct device_handler *handler, const char *desc) |
| +struct discover_device *grub2_lookup_device(struct device_handler *handler, |
| + const char *desc) |
| { |
| struct discover_device *dev; |
| |
| diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h |
| index ef32d4b..eabd6d6 100644 |
| --- a/discover/grub2/grub2.h |
| +++ b/discover/grub2/grub2.h |
| @@ -200,6 +200,8 @@ bool resolve_grub2_resource(struct device_handler *handler, |
| /* grub-style device+path parsing */ |
| struct grub2_file *grub2_parse_file(struct grub2_script *script, |
| const char *str); |
| +struct discover_device *grub2_lookup_device(struct device_handler *handler, |
| + const char *desc); |
| |
| /* external parser api */ |
| struct grub2_parser *grub2_parser_create(struct discover_context *ctx); |
| diff --git a/test/parser/Makefile.am b/test/parser/Makefile.am |
| index 0378317..c8e059b 100644 |
| --- a/test/parser/Makefile.am |
| +++ b/test/parser/Makefile.am |
| @@ -33,6 +33,7 @@ parser_TESTS = \ |
| test/parser/test-grub2-search-uuid \ |
| test/parser/test-grub2-search-label \ |
| test/parser/test-grub2-devpath \ |
| + test/parser/test-grub2-devpath-scripting \ |
| test/parser/test-grub2-load-env \ |
| test/parser/test-grub2-save-env \ |
| test/parser/test-grub2-save-env-dash-f \ |
| diff --git a/test/parser/test-grub2-devpath-scripting.c b/test/parser/test-grub2-devpath-scripting.c |
| new file mode 100644 |
| index 0000000..9046ab6 |
| --- /dev/null |
| +++ b/test/parser/test-grub2-devpath-scripting.c |
| @@ -0,0 +1,56 @@ |
| +/* check grub2 device+path string parsing, as used in scripts */ |
| + |
| +#include "parser-test.h" |
| + |
| +#if 0 /* PARSER_EMBEDDED_CONFIG */ |
| + |
| +v= |
| + |
| +# local device, file present |
| +if [ -f "/1-present" ]; then v=${v}a; fi |
| + |
| +# local device, file absent |
| +if [ -f "/1-absent" ]; then v=${v}b; fi; |
| + |
| +# local device by UUID, file present |
| +if [ -f "(00000000-0000-0000-0000-000000000001)/1-present" ]; then v=${v}c; fi; |
| + |
| +# remote device by UUID, file present |
| +if [ -f "(00000000-0000-0000-0000-000000000002)/2-present" ]; then v=${v}d; fi; |
| + |
| +# non-existent device |
| +if [ -f "(00000000-0000-0000-0000-000000000003)/present" ]; then v=${v}e; fi; |
| + |
| +menuentry $v { |
| + linux /vmlinux |
| +} |
| + |
| +#endif |
| + |
| +void run_test(struct parser_test *test) |
| +{ |
| + struct discover_device *dev1, *dev2; |
| + struct discover_boot_option *opt; |
| + struct discover_context *ctx; |
| + |
| + ctx = test->ctx; |
| + |
| + /* set local uuid */ |
| + dev1 = test->ctx->device; |
| + dev1->uuid = "00000000-0000-0000-0000-000000000001"; |
| + |
| + dev2 = test_create_device(test, "extdev"); |
| + dev2->uuid = "00000000-0000-0000-0000-000000000002"; |
| + device_handler_add_device(ctx->handler, dev2); |
| + |
| + test_add_file_data(test, dev1, "/1-present", "x", 1); |
| + test_add_file_data(test, dev2, "/2-present", "x", 1); |
| + |
| + test_read_conf_embedded(test, "/grub/grub.cfg"); |
| + |
| + test_run_parser(test, "grub2"); |
| + |
| + check_boot_option_count(ctx, 1); |
| + opt = get_boot_option(ctx, 0); |
| + check_name(opt, "acd"); |
| +} |
| -- |
| 2.17.1 |
| |