summaryrefslogtreecommitdiffstats
path: root/commands/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'commands/test.c')
-rw-r--r--commands/test.c122
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:")