diff options
Diffstat (limited to 'commands/test.c')
-rw-r--r-- | commands/test.c | 122 |
1 files changed, 83 insertions, 39 deletions
diff --git a/commands/test.c b/commands/test.c index 86636de1c2..13005b97de 100644 --- a/commands/test.c +++ b/commands/test.c @@ -1,31 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: © 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + /* * test.c - sh like test * - * Originally based on bareboxs do_test, but mostly reimplemented + * Originally based on barebox's do_test, but mostly reimplemented * for smaller binary size - * - * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program 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. - * */ #include <common.h> #include <command.h> +#include <fnmatch.h> #include <fs.h> #include <linux/stat.h> typedef enum { OPT_EQUAL, + OPT_EQUAL_BASH, OPT_NOT_EQUAL, OPT_ARITH_EQUAL, OPT_ARITH_NOT_EQUAL, @@ -48,6 +38,7 @@ typedef enum { static char *test_options[] = { [OPT_EQUAL] = "=", + [OPT_EQUAL_BASH] = "==", [OPT_NOT_EQUAL] = "!=", [OPT_ARITH_EQUAL] = "-eq", [OPT_ARITH_NOT_EQUAL] = "-ne", @@ -79,26 +70,87 @@ static int parse_opt(const char *opt) return -1; } +static int string_comp(const char *left_op, const char *right_op, bool bash_test) +{ + if (bash_test) + return fnmatch(right_op, left_op, 0); + + return strcmp(left_op, right_op); +} + +static int parse_number(const char *str, long *num, bool signedcmp) +{ + int ret; + + ret = signedcmp ? kstrtol(str, 0, num) : kstrtoul(str, 0, num); + if (ret) + printf("test: %s: integer expression expected\n", str); + + return ret; +} + +#define __do_arith_cmp(x, op, y, signedcmp) \ + ((signedcmp) ? (long)(x) op (long)(y) : (x) op (y)) + +static int arith_comp(const char *a_str, const char *b_str, int op) +{ + ulong a, b; + bool signedcmp = a_str[0] == '-' || b_str[0] == '-'; + int ret; + + ret = parse_number(a_str, &a, signedcmp); + if (ret) + return ret; + + ret = parse_number(b_str, &b, signedcmp); + if (ret) + return ret; + + switch (op) { + case OPT_ARITH_EQUAL: + return __do_arith_cmp(a, ==, b, signedcmp); + case OPT_ARITH_NOT_EQUAL: + return __do_arith_cmp(a, !=, b, signedcmp); + case OPT_ARITH_GREATER_EQUAL: + return __do_arith_cmp(a, >=, b, signedcmp); + case OPT_ARITH_GREATER_THAN: + return __do_arith_cmp(a, >, b, signedcmp); + case OPT_ARITH_LESS_EQUAL: + return __do_arith_cmp(a, <=, b, signedcmp); + case OPT_ARITH_LESS_THAN: + return __do_arith_cmp(a, <, b, signedcmp); + } + + return -EINVAL; +} + static int do_test(int argc, char *argv[]) { char **ap; int left, adv, expr, last_expr, neg, last_cmp, opt, zero; - ulong a, b; struct stat statbuf; + bool bash_test = false; if (*argv[0] == '[') { - if (*argv[argc - 1] != ']') { - printf("[: missing `]'\n"); - return 1; - } argc--; + if (!strncmp(argv[0], "[[", 2)) { + if (strncmp(argv[argc], "]]", 2) != 0) { + printf("[[: missing `]]'\n"); + return 1; + } + bash_test = true; + } else { + if (*argv[argc] != ']') { + printf("[: missing `]'\n"); + return 1; + } + } } /* args? */ if (argc < 2) return 1; - last_expr = 0; left = argc - 1; ap = argv + 1; @@ -192,32 +244,24 @@ static int do_test(int argc, char *argv[]) if (left < 3) break; - a = simple_strtol(ap[0], NULL, 0); - b = simple_strtol(ap[2], NULL, 0); - switch (parse_opt(ap[1])) { + opt = parse_opt(ap[1]); + switch (opt) { case OPT_EQUAL: - expr = strcmp(ap[0], ap[2]) == 0; + case OPT_EQUAL_BASH: + expr = string_comp(ap[0], ap[2], bash_test) == 0; break; case OPT_NOT_EQUAL: - expr = strcmp(ap[0], ap[2]) != 0; + expr = string_comp(ap[0], ap[2], bash_test) != 0; break; case OPT_ARITH_EQUAL: - expr = a == b; - break; case OPT_ARITH_NOT_EQUAL: - expr = a != b; - break; case OPT_ARITH_LESS_THAN: - expr = a < b; - break; case OPT_ARITH_LESS_EQUAL: - expr = a <= b; - break; case OPT_ARITH_GREATER_THAN: - expr = a > b; - break; case OPT_ARITH_GREATER_EQUAL: - expr = a >= b; + expr = arith_comp(ap[0], ap[2], opt); + if (expr < 0) + return 1; break; default: expr = 1; @@ -246,7 +290,7 @@ out: return expr; } -static const char * const test_aliases[] = { "[", NULL}; +static const char * const test_aliases[] = { "[", "[[", NULL}; BAREBOX_CMD_HELP_START(test) BAREBOX_CMD_HELP_TEXT("Options:") |