PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/barebox-2012.10.0/commands/test.c

https://bitbucket.org/barebox/barebox
C | 244 lines | 192 code | 24 blank | 28 comment | 47 complexity | 82d26429ac22a07e7456936bca95c876 MD5 | raw file
Possible License(s): AGPL-1.0
  1. /*
  2. * test.c - sh like test
  3. *
  4. * Originally based on bareboxs do_test, but mostly reimplemented
  5. * for smaller binary size
  6. *
  7. * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
  8. *
  9. * See file CREDITS for list of people who contributed to this
  10. * project.
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License version 2
  14. * as published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. */
  25. #include <common.h>
  26. #include <command.h>
  27. #include <fs.h>
  28. #include <linux/stat.h>
  29. typedef enum {
  30. OPT_EQUAL,
  31. OPT_NOT_EQUAL,
  32. OPT_ARITH_EQUAL,
  33. OPT_ARITH_NOT_EQUAL,
  34. OPT_ARITH_GREATER_EQUAL,
  35. OPT_ARITH_GREATER_THAN,
  36. OPT_ARITH_LESS_EQUAL,
  37. OPT_ARITH_LESS_THAN,
  38. OPT_OR,
  39. OPT_AND,
  40. OPT_ZERO,
  41. OPT_NONZERO,
  42. OPT_DIRECTORY,
  43. OPT_FILE,
  44. OPT_EXISTS,
  45. OPT_SYMBOLIC_LINK,
  46. OPT_MAX,
  47. } test_opts;
  48. static char *test_options[] = {
  49. [OPT_EQUAL] = "=",
  50. [OPT_NOT_EQUAL] = "!=",
  51. [OPT_ARITH_EQUAL] = "-eq",
  52. [OPT_ARITH_NOT_EQUAL] = "-ne",
  53. [OPT_ARITH_GREATER_EQUAL] = "-ge",
  54. [OPT_ARITH_GREATER_THAN] = "-gt",
  55. [OPT_ARITH_LESS_EQUAL] = "-le",
  56. [OPT_ARITH_LESS_THAN] = "-lt",
  57. [OPT_OR] = "-o",
  58. [OPT_AND] = "-a",
  59. [OPT_ZERO] = "-z",
  60. [OPT_NONZERO] = "-n",
  61. [OPT_FILE] = "-f",
  62. [OPT_DIRECTORY] = "-d",
  63. [OPT_EXISTS] = "-e",
  64. [OPT_SYMBOLIC_LINK] = "-L",
  65. };
  66. static int parse_opt(const char *opt)
  67. {
  68. char **opts = test_options;
  69. int i;
  70. for (i = 0; i < OPT_MAX; i++) {
  71. if (!strcmp(opts[i], opt))
  72. return i;
  73. }
  74. return -1;
  75. }
  76. static int do_test(int argc, char *argv[])
  77. {
  78. char **ap;
  79. int left, adv, expr, last_expr, neg, last_cmp, opt, zero;
  80. ulong a, b;
  81. struct stat statbuf;
  82. if (*argv[0] == '[') {
  83. if (*argv[argc - 1] != ']') {
  84. printf("[: missing `]'\n");
  85. return 1;
  86. }
  87. argc--;
  88. }
  89. /* args? */
  90. if (argc < 2)
  91. return 1;
  92. last_expr = 0;
  93. left = argc - 1;
  94. ap = argv + 1;
  95. if (strcmp(ap[0], "!") == 0) {
  96. neg = 1;
  97. ap++;
  98. left--;
  99. } else
  100. neg = 0;
  101. expr = -1;
  102. last_cmp = -1;
  103. last_expr = -1;
  104. adv = 0;
  105. while (left - adv > 0) {
  106. ap += adv; left -= adv;
  107. adv = 1;
  108. opt = parse_opt(ap[0]);
  109. switch (opt) {
  110. /* one argument options */
  111. case OPT_OR:
  112. last_expr = expr;
  113. last_cmp = 0;
  114. continue;
  115. case OPT_AND:
  116. last_expr = expr;
  117. last_cmp = 1;
  118. continue;
  119. /* two argument options */
  120. case OPT_ZERO:
  121. case OPT_NONZERO:
  122. adv = 2;
  123. zero = 1;
  124. if (ap[1] && *ap[1] != ']' && strlen(ap[1]))
  125. zero = 0;
  126. expr = (opt == OPT_ZERO) ? zero : !zero;
  127. break;
  128. case OPT_FILE:
  129. case OPT_DIRECTORY:
  130. case OPT_EXISTS:
  131. case OPT_SYMBOLIC_LINK:
  132. adv = 2;
  133. if (ap[1] && *ap[1] != ']' && strlen(ap[1])) {
  134. expr = (opt == OPT_SYMBOLIC_LINK ? lstat : stat)(ap[1], &statbuf);
  135. if (expr < 0) {
  136. expr = 0;
  137. break;
  138. }
  139. expr = 0;
  140. if (opt == OPT_EXISTS) {
  141. expr = 1;
  142. break;
  143. }
  144. if (opt == OPT_FILE && S_ISREG(statbuf.st_mode)) {
  145. expr = 1;
  146. break;
  147. }
  148. if (opt == OPT_DIRECTORY && S_ISDIR(statbuf.st_mode)) {
  149. expr = 1;
  150. break;
  151. }
  152. if (opt == OPT_SYMBOLIC_LINK && S_ISLNK(statbuf.st_mode)) {
  153. expr = 1;
  154. break;
  155. }
  156. }
  157. break;
  158. /* three argument options */
  159. default:
  160. adv = 3;
  161. if (left < 3) {
  162. expr = 1;
  163. break;
  164. }
  165. a = simple_strtol(ap[0], NULL, 0);
  166. b = simple_strtol(ap[2], NULL, 0);
  167. switch (parse_opt(ap[1])) {
  168. case OPT_EQUAL:
  169. expr = strcmp(ap[0], ap[2]) == 0;
  170. break;
  171. case OPT_NOT_EQUAL:
  172. expr = strcmp(ap[0], ap[2]) != 0;
  173. break;
  174. case OPT_ARITH_EQUAL:
  175. expr = a == b;
  176. break;
  177. case OPT_ARITH_NOT_EQUAL:
  178. expr = a != b;
  179. break;
  180. case OPT_ARITH_LESS_THAN:
  181. expr = a < b;
  182. break;
  183. case OPT_ARITH_LESS_EQUAL:
  184. expr = a <= b;
  185. break;
  186. case OPT_ARITH_GREATER_THAN:
  187. expr = a > b;
  188. break;
  189. case OPT_ARITH_GREATER_EQUAL:
  190. expr = a >= b;
  191. break;
  192. default:
  193. expr = 1;
  194. goto out;
  195. }
  196. }
  197. if (last_cmp == 0)
  198. expr = last_expr || expr;
  199. else if (last_cmp == 1)
  200. expr = last_expr && expr;
  201. last_cmp = -1;
  202. }
  203. out:
  204. if (neg)
  205. expr = !expr;
  206. expr = !expr;
  207. return expr;
  208. }
  209. static const char *test_aliases[] = { "[", NULL};
  210. static const __maybe_unused char cmd_test_help[] =
  211. "Usage: test [OPTIONS]\n"
  212. "options: !, =, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, -n, -d, -e, -f, -L\n"
  213. "see 'man test' on your PC for more information.\n";
  214. static const __maybe_unused char cmd_test_usage[] = "minimal test like /bin/sh";
  215. BAREBOX_CMD_START(test)
  216. .aliases = test_aliases,
  217. .cmd = do_test,
  218. .usage = cmd_test_usage,
  219. BAREBOX_CMD_HELP(cmd_test_help)
  220. BAREBOX_CMD_END