From 6e7f99f26673e932a7c6e45a31727d4a82dd2c8c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 28 Jan 2020 14:07:59 +0100 Subject: commands/test: Bail out on incomplete command line options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes test emit an error (and fail) on e.g. test -f and also on unimplemented options like test -c /dev/null . Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- commands/test.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'commands') diff --git a/commands/test.c b/commands/test.c index c4f493860f..ab108fc845 100644 --- a/commands/test.c +++ b/commands/test.c @@ -208,6 +208,11 @@ static int do_test(int argc, char *argv[]) } } + if (left < adv) { + printf("test: failed to parse arguments\n"); + return 1; + } + if (last_cmp == 0) expr = last_expr || expr; else if (last_cmp == 1) -- cgit v1.2.3 From 7b95857a7ad911e698dc18261deceffdfd7d9fdb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 28 Jan 2020 14:08:00 +0100 Subject: commands/test: Improve option parsing to handle "]" less special MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Testing for *ap[1] != ']' is bogus during option processing. Instead test if there are options left to be processed. This fixes the return value for e.g. test -z ']lala' Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- commands/test.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'commands') diff --git a/commands/test.c b/commands/test.c index ab108fc845..9070e49074 100644 --- a/commands/test.c +++ b/commands/test.c @@ -129,8 +129,11 @@ static int do_test(int argc, char *argv[]) case OPT_ZERO: case OPT_NONZERO: adv = 2; + if (left < 2) + break; zero = 1; - if (ap[1] && *ap[1] != ']' && strlen(ap[1])) + + if (strlen(ap[1])) zero = 0; expr = (opt == OPT_ZERO) ? zero : !zero; @@ -141,7 +144,9 @@ static int do_test(int argc, char *argv[]) case OPT_EXISTS: case OPT_SYMBOLIC_LINK: adv = 2; - if (ap[1] && *ap[1] != ']' && strlen(ap[1])) { + if (left < 2) + break; + if (strlen(ap[1])) { expr = (opt == OPT_SYMBOLIC_LINK ? lstat : stat)(ap[1], &statbuf); if (expr < 0) { expr = 0; @@ -170,10 +175,8 @@ static int do_test(int argc, char *argv[]) /* three argument options */ default: adv = 3; - if (left < 3) { - expr = 1; + if (left < 3) break; - } a = simple_strtol(ap[0], NULL, 0); b = simple_strtol(ap[2], NULL, 0); -- cgit v1.2.3 From 359fc72149bc30f471405e5495e8aa8d69d728c6 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 28 Jan 2020 14:08:01 +0100 Subject: commands/test: Implement -b and -c to test for character and block devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These match the same options on coreutil's test(1). Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- commands/test.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'commands') diff --git a/commands/test.c b/commands/test.c index 9070e49074..86636de1c2 100644 --- a/commands/test.c +++ b/commands/test.c @@ -40,6 +40,8 @@ typedef enum { OPT_DIRECTORY, OPT_FILE, OPT_EXISTS, + OPT_BLOCK, + OPT_CHAR, OPT_SYMBOLIC_LINK, OPT_MAX, } test_opts; @@ -60,6 +62,8 @@ static char *test_options[] = { [OPT_FILE] = "-f", [OPT_DIRECTORY] = "-d", [OPT_EXISTS] = "-e", + [OPT_BLOCK] = "-b", + [OPT_CHAR] = "-c", [OPT_SYMBOLIC_LINK] = "-L", }; @@ -142,6 +146,8 @@ static int do_test(int argc, char *argv[]) case OPT_FILE: case OPT_DIRECTORY: case OPT_EXISTS: + case OPT_BLOCK: + case OPT_CHAR: case OPT_SYMBOLIC_LINK: adv = 2; if (left < 2) @@ -169,6 +175,14 @@ static int do_test(int argc, char *argv[]) expr = 1; break; } + if (opt == OPT_BLOCK && S_ISBLK(statbuf.st_mode)) { + expr = 1; + break; + } + if (opt == OPT_CHAR && S_ISCHR(statbuf.st_mode)) { + expr = 1; + break; + } } break; -- cgit v1.2.3 From 4c368ee077b8918bf68979e8079439fcf55ac13f Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 12 Feb 2020 15:16:37 +0100 Subject: commands: boot: refactor boot entry creation to use iterators We currently create all boot entries before attempting boot. This is less than optimal, because this may involve probing devices that won't be used for actual boot. In preparation for changing this, refactor the code, so we only have one loop we need to touch. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- commands/boot.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'commands') diff --git a/commands/boot.c b/commands/boot.c index 0257b3dd4f..ce4eeac653 100644 --- a/commands/boot.c +++ b/commands/boot.c @@ -21,13 +21,29 @@ #include +static char *next_argv(void *context) +{ + char ***argv = context; + char *next = **argv; + (*argv)++; + return next; +} + +static char *next_word(void *context) +{ + return strsep(context, " "); +} + static int do_boot(int argc, char *argv[]) { char *freep = NULL; int opt, ret = 0, do_list = 0, do_menu = 0; - int i, dryrun = 0, verbose = 0, timeout = -1; + int dryrun = 0, verbose = 0, timeout = -1; struct bootentries *entries; struct bootentry *entry; + void *handle; + const char *name; + char *(*next)(void *); while ((opt = getopt(argc, argv, "vldmt:w:")) > 0) { switch (opt) { @@ -54,31 +70,26 @@ static int do_boot(int argc, char *argv[]) } } - entries = bootentries_alloc(); - if (optind < argc) { - for (i = optind; i < argc; i++) { - ret = bootentry_create_from_name(entries, argv[i]); - if (ret <= 0) - printf("Nothing bootable found on '%s'\n", argv[i]); - } + handle = &argv[optind]; + next = next_argv; } else { const char *def; - char *sep, *name; def = getenv("global.boot.default"); if (!def) return 0; - sep = freep = xstrdup(def); + handle = freep = xstrdup(def); + next = next_word; + } - while ((name = strsep(&sep, " ")) != NULL) { - ret = bootentry_create_from_name(entries, name); - if (ret <= 0) - printf("Nothing bootable found on '%s'\n", name); - } + entries = bootentries_alloc(); - free(freep); + while ((name = next(&handle)) != NULL) { + ret = bootentry_create_from_name(entries, name); + if (ret <= 0) + printf("Nothing bootable found on '%s'\n", name); } if (list_empty(&entries->entries)) { @@ -104,6 +115,7 @@ static int do_boot(int argc, char *argv[]) out: bootentries_free(entries); + free(freep); return ret; } -- cgit v1.2.3 From e43eed6606e44574d665b3338b701da1035c504e Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 12 Feb 2020 15:16:38 +0100 Subject: commands: boot: create boot entries on demand We currently create all boot entries before attempting boot. This is less than optimal, because this may involve probing devices that won't be used for actual boot. Fix this by not creating boot entries till the previous boot argument (command line argument or boot.default word) was found to be unbootable. This means that "boot mmc1 mmc0" will now not touch mmc0 if mmc1 had a bootable entry. This is only done when no menu or list was requested. As the boot entries are in a linked list, the allocation done for each boot argument could be omitted, but as the saving from skipping an allocation is easily dwarfed by the boot medium access, we just reallocate and enjoy the improved code clarity. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- commands/boot.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'commands') diff --git a/commands/boot.c b/commands/boot.c index ce4eeac653..aeaba3992e 100644 --- a/commands/boot.c +++ b/commands/boot.c @@ -90,6 +90,18 @@ static int do_boot(int argc, char *argv[]) ret = bootentry_create_from_name(entries, name); if (ret <= 0) printf("Nothing bootable found on '%s'\n", name); + + if (do_list || do_menu) + continue; + + bootentries_for_each_entry(entries, entry) { + ret = boot_entry(entry, verbose, dryrun); + if (!ret) + break; + } + + bootentries_free(entries); + entries = bootentries_alloc(); } if (list_empty(&entries->entries)) { @@ -107,12 +119,6 @@ static int do_boot(int argc, char *argv[]) goto out; } - bootentries_for_each_entry(entries, entry) { - ret = boot_entry(entry, verbose, dryrun); - if (!ret) - break; - } - out: bootentries_free(entries); free(freep); -- cgit v1.2.3 From f246b4079c746f80e29b07252c546d37a359105f Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 14 Feb 2020 11:33:35 +0100 Subject: i2c_probe command: Use kstrtoint Use kstrtoint rather than simple_strtoul to catch erroneous input like "i2c1" which previously was silently interpreted as "0". Signed-off-by: Sascha Hauer --- commands/i2c.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'commands') diff --git a/commands/i2c.c b/commands/i2c.c index 77d65e3fa3..77a8f7ff97 100644 --- a/commands/i2c.c +++ b/commands/i2c.c @@ -45,17 +45,37 @@ static int do_i2c_probe(int argc, char *argv[]) { struct i2c_adapter *adapter = NULL; int startaddr = 4, stopaddr = 0x77; + int ret; if (argc > 1) { - adapter = i2c_get_adapter(simple_strtoul(argv[1], NULL, 0)); + int busnum; + + ret = kstrtoint(argv[1], 0, &busnum); + if (ret) { + printf("Cannot parse \"%s\" as a number\n", argv[1]); + return ret; + } + + adapter = i2c_get_adapter(busnum); if (!adapter) return -ENODEV; } - if (argc > 2) - startaddr = simple_strtol(argv[2], NULL, 0); - if (argc > 3) - stopaddr = simple_strtol(argv[3], NULL, 0); + if (argc > 2) { + ret = kstrtoint(argv[2], 0, &startaddr); + if (ret) { + printf("Cannot parse \"%s\" as a number\n", argv[1]); + return ret; + } + } + + if (argc > 3) { + ret = kstrtoint(argv[3], 0, &stopaddr); + if (ret) { + printf("Cannot parse \"%s\" as a number\n", argv[1]); + return ret; + } + } if (stopaddr > 0x7f) stopaddr = 0x7f; -- cgit v1.2.3