# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: address@hidden # target_branch: ../cmdlist/ # testament_sha1: 34e1d2ffaa9793e3440e6d6b1e3ec0b590a8ea6f # timestamp: 2010-07-30 03:40:48 +0530 # base_revision_id: address@hidden # q6dgo7psbg1vzkkd # # Begin patch === modified file 'commands/regexp.c' --- commands/regexp.c 2010-05-01 18:28:07 +0000 +++ commands/regexp.c 2010-07-29 18:02:56 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include static grub_err_t @@ -69,9 +70,14 @@ GRUB_MOD_INIT(regexp) { + extern struct grub_script_wildcard_translator translator; + cmd = grub_register_command ("regexp", grub_cmd_regexp, N_("REGEXP STRING"), N_("Test if REGEXP matches STRING.")); + + /* Setup GRUB script wildcard translator. */ + wildcard_translator = &translator; } GRUB_MOD_FINI(regexp) === added file 'commands/wildcard.c' --- commands/wildcard.c 1970-01-01 00:00:00 +0000 +++ commands/wildcard.c 2010-07-29 22:10:33 +0000 @@ -0,0 +1,493 @@ +/* wildcard.c - Wildcard character expansion for GRUB script. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include + +static inline int isregexop (char ch); +static char ** merge (char **lhs, char **rhs); +static char *make_dir (const char *prefix, const char *start, const char *end); +static int make_regex (const char *regex_start, const char *regex_end, + regex_t *regexp); +static void split_path (const char *path, const char **suffix_end, const char **regex_end); +static char ** match_devices (const regex_t *regexp, int noparts); +static char ** match_files (const char *prefix, const char *suffix_start, + const char *suffix_end, const regex_t *regexp); + +static char* wildcard_escape (const char *s); +static char* wildcard_unescape (const char *s); +static grub_err_t wildcard_expand (const char *s, char ***strs); + +struct grub_script_wildcard_translator translator = { + .expand = wildcard_expand, + .escape = wildcard_escape, + .unescape = wildcard_unescape +}; + +static char ** +merge (char **dest, char **ps) +{ + int i; + int j; + char **p; + + if (! dest) + return ps; + + if (! ps) + return dest; + + for (i = 0; dest[i]; i++) + ; + for (j = 0; ps[j]; j++) + ; + + p = grub_realloc (dest, sizeof (char*) * (i + j + 1)); + if (! p) + { + grub_free (dest); + grub_free (ps); + return 0; + } + + for (j = 0; ps[j]; j++) + dest[i++] = ps[j]; + dest[i] = 0; + + grub_free (ps); + return dest; +} + +static inline int +isregexop (char ch) +{ + return grub_strchr ("*.\\", ch) ? 1 : 0; +} + +static char * +make_dir (const char *prefix, const char *start, const char *end) +{ + char ch; + unsigned i; + unsigned n; + char *result; + + i = grub_strlen (prefix); + n = i + end - start; + + result = grub_malloc (n + 1); + if (! result) + return 0; + + grub_strcpy (result, prefix); + while (start < end && (ch = *start++)) + if (ch == '\\' && isregexop (*start)) + result[i++] = *start++; + else + result[i++] = ch; + + result[i] = '\0'; + return result; +} + +static int +make_regex (const char *start, const char *end, regex_t *regexp) +{ + char ch; + int i = 0; + unsigned len = end - start; + char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */ + + if (! buffer) + return 1; + + buffer[i++] = '^'; + while (start < end) + { + /* XXX Only * expansion for now. */ + switch ((ch = *start++)) + { + case '\\': + buffer[i++] = ch; + if (*start != '\0') + buffer[i++] = *start++; + break; + + case '.': + buffer[i++] = '\\'; + buffer[i++] = '.'; + break; + + case '*': + buffer[i++] = '.'; + buffer[i++] = '*'; + break; + + default: + buffer[i++] = ch; + } + } + buffer[i++] = '$'; + buffer[i] = '\0'; + + if (regcomp (regexp, buffer, RE_SYNTAX_GNU_AWK)) + { + grub_free (buffer); + return 1; + } + + grub_free (buffer); + return 0; +} + +/* Split `str' into two parts: (1) dirname that is regexop free (2) + dirname that has a regexop. */ +static void +split_path (const char *str, const char **noregexop, const char **regexop) +{ + char ch = 0; + int regex = 0; + + const char *end; + const char *split; /* points till the end of dirnaname that doesn't + need expansion. */ + + split = end = str; + while ((ch = *end)) + { + if (ch == '\\' && end[1]) + end++; + + else if (isregexop (ch)) + regex = 1; + + else if (ch == '/' && ! regex) + split = end + 1; /* forward to next regexop-free dirname */ + + else if (ch == '/' && regex) + break; /* stop at the first dirname with a regexop */ + + end++; + } + + *regexop = end; + if (! regex) + *noregexop = end; + else + *noregexop = split; +} + +static char ** +match_devices (const regex_t *regexp, int noparts) +{ + int i; + int ndev; + char **devs; + + auto int match (const char *name); + int match (const char *name) + { + char **t; + char *buffer; + + /* skip partitions if asked to. */ + if (noparts && grub_strchr(name, ',')) + return 0; + + buffer = grub_xasprintf ("(%s)", name); + if (! buffer) + return 1; + + grub_dprintf ("expand", "matching: %s\n", buffer); + if (regexec (regexp, buffer, 0, 0, 0)) + { + grub_free (buffer); + return 0; + } + + t = grub_realloc (devs, sizeof (char*) * (ndev + 2)); + if (! t) + return 1; + + devs = t; + devs[ndev++] = buffer; + devs[ndev] = 0; + return 0; + } + + ndev = 0; + devs = 0; + + if (grub_device_iterate (match)) + goto fail; + + return devs; + + fail: + + for (i = 0; devs && devs[i]; i++) + grub_free (devs[i]); + + if (devs) + grub_free (devs); + + return 0; +} + +static char ** +match_files (const char *prefix, const char *suffix, const char *end, + const regex_t *regexp) +{ + int i; + int error; + char **files; + unsigned nfile; + char *dir; + const char *path; + char *device_name; + grub_fs_t fs; + grub_device_t dev; + + auto int match (const char *name, const struct grub_dirhook_info *info); + int match (const char *name, const struct grub_dirhook_info *info) + { + char **t; + char *buffer; + + /* skip hidden files, . and .. */ + if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0) + return 0; + + grub_dprintf ("expand", "matching: %s in %s\n", name, dir); + if (regexec (regexp, name, 0, 0, 0)) + return 0; + + buffer = grub_xasprintf ("%s%s", dir, name); + if (! buffer) + return 1; + + t = grub_realloc (files, sizeof (char*) * (nfile + 2)); + if (! t) + { + grub_free (buffer); + return 1; + } + + files = t; + files[nfile++] = buffer; + files[nfile] = 0; + return 0; + } + + nfile = 0; + files = 0; + dev = 0; + device_name = 0; + grub_error_push (); + + dir = make_dir (prefix, suffix, end); + if (! dir) + goto fail; + + device_name = grub_file_get_device_name (dir); + dev = grub_device_open (device_name); + if (! dev) + goto fail; + + fs = grub_fs_probe (dev); + if (! fs) + goto fail; + + path = grub_strchr (dir, ')'); + if (! path) + goto fail; + path++; + + if (fs->dir (dev, path, match)) + goto fail; + + grub_free (dir); + grub_device_close (dev); + grub_free (device_name); + grub_error_pop (); + return files; + + fail: + + if (dir) + grub_free (dir); + + for (i = 0; files && files[i]; i++) + grub_free (files[i]); + + if (files) + grub_free (files); + + if (dev) + grub_device_close (dev); + + if (device_name) + grub_free (device_name); + + grub_error_pop (); + return 0; +} + +static char* +wildcard_escape (const char *s) +{ + int i; + int len; + char ch; + char *p; + + len = grub_strlen (s); + p = grub_malloc (len * 2 + 1); + if (! p) + return NULL; + + i = 0; + while ((ch = *s++)) + { + if (isregexop (ch)) + p[i++] = '\\'; + p[i++] = ch; + } + p[i] = '\0'; + return p; +} + +static char* +wildcard_unescape (const char *s) +{ + int i; + int len; + char ch; + char *p; + + len = grub_strlen (s); + p = grub_malloc (len + 1); + if (! p) + return NULL; + + i = 0; + while ((ch = *s++)) + { + if (ch == '\\' && isregexop (*s)) + p[i++] = *s++; + else + p[i++] = ch; + } + p[i] = '\0'; + return p; +} + +static grub_err_t +wildcard_expand (const char *s, char ***strs) +{ + const char *start; + const char *regexop; + const char *noregexop; + char **paths = 0; + + unsigned i; + regex_t regexp; + + start = s; + while (*start) + { + split_path (start, &noregexop, ®exop); + if (noregexop >= regexop) /* no more wildcards */ + break; + + if (make_regex (noregexop, regexop, ®exp)) + goto fail; + + if (paths == 0) + { + if (start == noregexop) /* device part has regexop */ + paths = match_devices (®exp, *start != '('); + + else if (*start == '(') /* device part explicit wo regexop */ + paths = match_files ("", start, noregexop, ®exp); + + else if (*start == '/') /* no device part */ + { + char **r; + unsigned n; + char *root; + char *prefix; + + root = grub_env_get ("root"); + if (! root) + goto fail; + + prefix = grub_xasprintf ("(%s)", root); + if (! prefix) + goto fail; + + paths = match_files (prefix, start, noregexop, ®exp); + grub_free (prefix); + } + } + else + { + char **r = 0; + + for (i = 0; paths[i]; i++) + { + char **p; + + p = match_files (paths[i], start, noregexop, ®exp); + if (! p) + continue; + + r = merge (r, p); + if (! r) + goto fail; + } + paths = r; + } + + regfree (®exp); + if (! paths) + goto done; + + start = regexop; + } + + done: + + *strs = paths; + return 0; + + fail: + + for (i = 0; paths && paths[i]; i++) + grub_free (paths[i]); + grub_free (paths[i]); + regfree (®exp); + return grub_errno; +} === modified file 'conf/common.rmk' --- conf/common.rmk 2010-07-11 15:44:18 +0000 +++ conf/common.rmk 2010-07-29 18:02:56 +0000 @@ -764,7 +764,7 @@ setjmp_mod_LDFLAGS = $(COMMON_LDFLAGS) pkglib_MODULES += regexp.mod -regexp_mod_SOURCES = gnulib/regex.c commands/regexp.c +regexp_mod_SOURCES = gnulib/regex.c commands/regexp.c commands/wildcard.c regexp_mod_CFLAGS = $(COMMON_CFLAGS) $(GNULIB_CFLAGS) regexp_mod_LDFLAGS = $(COMMON_LDFLAGS) === modified file 'conf/tests.rmk' --- conf/tests.rmk 2010-05-05 09:17:50 +0000 +++ conf/tests.rmk 2010-05-18 15:33:35 +0000 @@ -74,6 +74,9 @@ check_SCRIPTS += grub_script_functions grub_script_functions_SOURCES = tests/grub_script_functions.in +check_SCRIPTS += grub_script_expansion +grub_script_expansion_SOURCES = tests/grub_script_expansion.in + # List of tests to execute on "make check" # SCRIPTED_TESTS = example_scripted_test # SCRIPTED_TESTS += example_grub_script_test @@ -91,6 +94,7 @@ SCRIPTED_TESTS += grub_script_dollar SCRIPTED_TESTS += grub_script_comments SCRIPTED_TESTS += grub_script_functions +SCRIPTED_TESTS += grub_script_expansion # dependencies between tests and testing-tools $(SCRIPTED_TESTS): grub-shell grub-shell-tester === modified file 'include/grub/script_sh.h' --- include/grub/script_sh.h 2010-06-12 11:02:06 +0000 +++ include/grub/script_sh.h 2010-07-29 17:22:09 +0000 @@ -70,6 +70,15 @@ char **args; }; +/* Pluggable wildcard translator. */ +struct grub_script_wildcard_translator +{ + char *(*escape) (const char *str); + char *(*unescape) (const char *str); + grub_err_t (*expand) (const char *str, char ***expansions); +}; +extern struct grub_script_wildcard_translator *wildcard_translator; + /* A complete argument. It consists of a list of one or more `struct grub_script_arg's. */ struct grub_script_arglist === modified file 'script/argv.c' --- script/argv.c 2010-05-21 10:04:36 +0000 +++ script/argv.c 2010-07-29 18:02:56 +0000 @@ -18,6 +18,7 @@ */ #include +#include #include static unsigned @@ -82,7 +83,8 @@ int grub_script_argv_append (struct grub_script_argv *argv, const char *s) { - int a, b; + int a; + int b; char *p = argv->args[argv->argc - 1]; if (! s) @@ -97,6 +99,7 @@ grub_strcpy (p + a, s); argv->args[argv->argc - 1] = p; + return 0; } === modified file 'script/execute.c' --- script/execute.c 2010-05-21 10:13:24 +0000 +++ script/execute.c 2010-07-29 18:02:56 +0000 @@ -37,6 +37,9 @@ }; static struct grub_script_scope *scope = 0; +/* Wildcard translator for GRUB script. */ +struct grub_script_wildcard_translator *wildcard_translator; + static int grub_env_special (const char *name) { @@ -161,7 +164,7 @@ return grub_env_set (name, val); } -/* Expand arguments in ARGLIST into multiple arguments. */ +/* Convert arguments in ARGLIST into ARGV form. */ static int grub_script_arglist_to_argv (struct grub_script_arglist *arglist, struct grub_script_argv *argv) @@ -171,6 +174,28 @@ struct grub_script_arg *arg = 0; struct grub_script_argv result = { 0, 0 }; + auto int append (char *s, int escape_type); + int append (char *s, int escape_type) + { + int r; + char *p = 0; + + if (! wildcard_translator || escape_type == 0) + return grub_script_argv_append (&result, s); + + if (escape_type > 0) + p = wildcard_translator->escape (s); + else if (escape_type < 0) + p = wildcard_translator->unescape (s); + + if (! p) + return 1; + + r = grub_script_argv_append (&result, p); + grub_free (p); + return r; + } + for (; arglist && arglist->arg; arglist = arglist->next) { if (grub_script_argv_next (&result)) @@ -189,8 +214,18 @@ if (i != 0 && grub_script_argv_next (&result)) goto fail; - if (grub_script_argv_append (&result, values[i])) - goto fail; + if (arg->type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (grub_script_argv_append (&result, values[i])) + goto fail; + } + else + { + if (append (values[i], 1)) + goto fail; + } + + grub_free (values[i]); } grub_free (values); break; @@ -214,6 +249,50 @@ if (! result.args[result.argc - 1]) result.argc--; + /* Perform wildcard expansion. */ + + if (wildcard_translator) + { + int j; + int failed = 0; + char **expansions = 0; + struct grub_script_argv unexpanded = result; + + result.argc = 0; + result.args = 0; + for (i = 0; unexpanded.args[i]; i++) + { + if (wildcard_translator->expand (unexpanded.args[i], &expansions)) + { + grub_script_argv_free (&unexpanded); + goto fail; + } + + if (! expansions) + { + grub_script_argv_next (&result); + append (unexpanded.args[i], -1); + } + else + { + for (j = 0; expansions[j]; j++) + { + failed = (failed || grub_script_argv_next (&result) || + append (expansions[j], -1)); + grub_free (expansions[j]); + } + grub_free (expansions); + + if (failed) + { + grub_script_argv_free (&unexpanded); + goto fail; + } + } + } + grub_script_argv_free (&unexpanded); + } + *argv = result; return 0; @@ -429,7 +508,6 @@ cmd_menuentry->sourcecode); grub_script_argv_free (&argv); - return grub_errno; } === added file 'tests/grub_script_expansion.in' --- tests/grub_script_expansion.in 1970-01-01 00:00:00 +0000 +++ tests/grub_script_expansion.in 2010-07-29 18:02:56 +0000 @@ -0,0 +1,42 @@ +#! /bin/bash -e + +# Run GRUB script in a Qemu instance +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +disks=`echo ls | @builddir@/grub-shell` +other=`echo insmod regexp\; echo \* | @builddir@/grub-shell` +for d in $disks; do + if echo "$d" |grep ',' >/dev/null; then + if echo "$other" | grep "$d" >/dev/null; then + echo "$d should not occur in * expansion" >&2 + exit 1 + fi + else + if ! echo "$other" | grep "$d" >/dev/null; then + echo "$d missing from * expansion" >&2 + exit 1 + fi + fi +done + +other=`echo insmod regexp\; echo '(*)' | @builddir@/grub-shell` +for d in $disks; do + if ! echo "$other" | grep "$d" >/dev/null; then + echo "$d missing from (*) expansion" >&2 + exit 1 + fi +done + === modified file 'tests/util/grub-shell.in' --- tests/util/grub-shell.in 2010-07-07 15:51:26 +0000 +++ tests/util/grub-shell.in 2010-07-22 21:27:02 +0000 @@ -95,7 +95,7 @@ if [ "x${source}" = x ] ; then tmpfile=`mktemp` while read REPLY; do - echo $REPLY >> ${tmpfile} + echo "$REPLY" >> ${tmpfile} done source=${tmpfile} fi # Begin bundle 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