aboutsummaryrefslogtreecommitdiff
path: root/coreutils/test.c
diff options
context:
space:
mode:
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2007-03-30 18:23:36 +0000
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2007-03-30 18:23:36 +0000
commitcc890264d9a0d3c2898c20d5d45cd43959339da4 (patch)
tree8385cdb209b12e65d76c1400242145fbff69cbc8 /coreutils/test.c
parenteceecea568a483a3acec2d4c03228b39ae2d6501 (diff)
downloadbusybox-w32-cc890264d9a0d3c2898c20d5d45cd43959339da4.tar.gz
busybox-w32-cc890264d9a0d3c2898c20d5d45cd43959339da4.tar.bz2
busybox-w32-cc890264d9a0d3c2898c20d5d45cd43959339da4.zip
- debloat test. untested.
text data bss dec hex filename 3154 0 172 3326 cfe test.o.oorig 2683 0 172 2855 b27 test.o This applet should be rewritten not to use such odd lexer semantics. It duplicates code from all over the place (see XXX). brrr
Diffstat (limited to 'coreutils/test.c')
-rw-r--r--coreutils/test.c227
1 files changed, 116 insertions, 111 deletions
diff --git a/coreutils/test.c b/coreutils/test.c
index 6e0d5d38e..813cde47c 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -12,6 +12,7 @@
12 * modified by Herbert Xu to be used as built-in in ash. 12 * modified by Herbert Xu to be used as built-in in ash.
13 * modified by Erik Andersen <andersen@codepoet.org> to be used 13 * modified by Erik Andersen <andersen@codepoet.org> to be used
14 * in busybox. 14 * in busybox.
15 * modified by Bernhard Fischer to be useable (i.e. a bit less bloaty).
15 * 16 *
16 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 17 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
17 * 18 *
@@ -85,7 +86,12 @@ enum token {
85 RPAREN, 86 RPAREN,
86 OPERAND 87 OPERAND
87}; 88};
88 89#define __is_int_op(a) (((unsigned char)((a) - INTEQ)) <= 5)
90#define __is_str_op(a) (((unsigned char)((a) - STREZ)) <= 5)
91#define __is_file_op(a) (((unsigned char)((a) - FILNT)) <= 2)
92#define __is_file_access(a) (((unsigned char)((a) - FILRD)) <= 2)
93#define __is_file_type(a) (((unsigned char)((a) - FILREG)) <= 5)
94#define __is_file_bit(a) (((unsigned char)((a) - FILSUID)) <= 2)
89enum token_types { 95enum token_types {
90 UNOP, 96 UNOP,
91 BINOP, 97 BINOP,
@@ -95,8 +101,8 @@ enum token_types {
95}; 101};
96 102
97static const struct t_op { 103static const struct t_op {
98 const char *op_text; 104 const char * const op_text;
99 short op_num, op_type; 105 unsigned char op_num, op_type;
100} ops[] = { 106} ops[] = {
101 { 107 {
102 "-r", FILRD, UNOP}, { 108 "-r", FILRD, UNOP}, {
@@ -206,34 +212,21 @@ int bb_test(int argc, char **argv)
206 ngroups = 0; 212 ngroups = 0;
207 213
208 /* Implement special cases from POSIX.2, section 4.62.4 */ 214 /* Implement special cases from POSIX.2, section 4.62.4 */
209 switch (argc) { 215 if (argc == 1)
210 case 1:
211 return 1; 216 return 1;
212 case 2: 217 if (argc == 2)
213 return *argv[1] == '\0'; 218 return *argv[1] == '\0';
214 case 3: 219//assert(argc);
215 if (argv[1][0] == '!' && argv[1][1] == '\0') { 220 if (LONE_CHAR(argv[1], '!')) {
221 bool _off;
222 if (argc == 3)
216 return *argv[2] != '\0'; 223 return *argv[2] != '\0';
224 _off = argc - 4;
225 if (t_lex(argv[2+_off]), t_wp_op && t_wp_op->op_type == BINOP) {
226 t_wp = &argv[1+_off];
227 return binop() == 0;
217 } 228 }
218 break;
219 case 4:
220 if (argv[1][0] != '!' || argv[1][1] != '\0') {
221 if (t_lex(argv[2]), t_wp_op && t_wp_op->op_type == BINOP) {
222 t_wp = &argv[1];
223 return binop() == 0;
224 }
225 }
226 break;
227 case 5:
228 if (argv[1][0] == '!' && argv[1][1] == '\0') {
229 if (t_lex(argv[3]), t_wp_op && t_wp_op->op_type == BINOP) {
230 t_wp = &argv[2];
231 return binop() != 0;
232 }
233 }
234 break;
235 } 229 }
236
237 t_wp = &argv[1]; 230 t_wp = &argv[1];
238 res = !oexpr(t_lex(*t_wp)); 231 res = !oexpr(t_lex(*t_wp));
239 232
@@ -301,16 +294,14 @@ static arith_t primary(enum token n)
301 /* unary expression */ 294 /* unary expression */
302 if (*++t_wp == NULL) 295 if (*++t_wp == NULL)
303 syntax(t_wp_op->op_text, "argument expected"); 296 syntax(t_wp_op->op_text, "argument expected");
304 switch (n) { 297 if (n == STREZ)
305 case STREZ:
306 return strlen(*t_wp) == 0; 298 return strlen(*t_wp) == 0;
307 case STRNZ: 299 else if (n == STRNZ)
308 return strlen(*t_wp) != 0; 300 return strlen(*t_wp) != 0;
309 case FILTT: 301 else if (n == FILTT)
310 return isatty(getn(*t_wp)); 302 return isatty(getn(*t_wp));
311 default: 303 else
312 return filstat(*t_wp, n); 304 return filstat(*t_wp, n);
313 }
314 } 305 }
315 306
316 if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { 307 if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) {
@@ -324,6 +315,7 @@ static int binop(void)
324{ 315{
325 const char *opnd1, *opnd2; 316 const char *opnd1, *opnd2;
326 struct t_op const *op; 317 struct t_op const *op;
318 smallint val1, val2;
327 319
328 opnd1 = *t_wp; 320 opnd1 = *t_wp;
329 (void) t_lex(*++t_wp); 321 (void) t_lex(*++t_wp);
@@ -332,42 +324,56 @@ static int binop(void)
332 if ((opnd2 = *++t_wp) == (char *) 0) 324 if ((opnd2 = *++t_wp) == (char *) 0)
333 syntax(op->op_text, "argument expected"); 325 syntax(op->op_text, "argument expected");
334 326
335 switch (op->op_num) { 327 if (__is_int_op(op->op_num)) {
336 case STREQ: 328 val1 = getn(opnd1);
337 return strcmp(opnd1, opnd2) == 0; 329 val2 = getn(opnd2);
338 case STRNE: 330 if (op->op_num == INTEQ)
339 return strcmp(opnd1, opnd2) != 0; 331 return val1 == val2;
340 case STRLT: 332 if (op->op_num == INTNE)
341 return strcmp(opnd1, opnd2) < 0; 333 return val1 != val2;
342 case STRGT: 334 if (op->op_num == INTGE)
343 return strcmp(opnd1, opnd2) > 0; 335 return val1 >= val2;
344 case INTEQ: 336 if (op->op_num == INTGT)
345 return getn(opnd1) == getn(opnd2); 337 return val1 > val2;
346 case INTNE: 338 if (op->op_num == INTLE)
347 return getn(opnd1) != getn(opnd2); 339 return val1 <= val2;
348 case INTGE: 340 if (op->op_num == INTLT)
349 return getn(opnd1) >= getn(opnd2); 341 return val1 < val2;
350 case INTGT: 342 }
351 return getn(opnd1) > getn(opnd2); 343 if (__is_str_op(op->op_num)) {
352 case INTLE: 344 val1 = strcmp(opnd1, opnd2);
353 return getn(opnd1) <= getn(opnd2); 345 if (op->op_num == STREQ)
354 case INTLT: 346 return val1 == 0;
355 return getn(opnd1) < getn(opnd2); 347 if (op->op_num == STRNE)
356 case FILNT: 348 return val1 != 0;
357 return newerf(opnd1, opnd2); 349 if (op->op_num == STRLT)
358 case FILOT: 350 return val1 < 0;
359 return olderf(opnd1, opnd2); 351 if (op->op_num == STRGT)
360 case FILEQ: 352 return val1 > 0;
361 return equalf(opnd1, opnd2);
362 } 353 }
363 /* NOTREACHED */ 354 /* We are sure that these three are by now the only binops we didn't check
364 return 1; 355 * yet, so we do not check if the class is correct:
356 */
357/* if (__is_file_op(op->op_num)) */
358 {
359 struct stat b1, b2;
360
361 if (!(!stat(opnd1, &b1) && !stat(opnd2, &b2)))
362 return 0; /* false, since stat failed */
363 if (op->op_num == FILNT)
364 return b1.st_mtime > b2.st_mtime;
365 if (op->op_num == FILOT)
366 return b1.st_mtime < b2.st_mtime;
367 if (op->op_num == FILEQ)
368 return b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino;
369 }
370 return 1; /* NOTREACHED */
365} 371}
366 372
367static int filstat(char *nm, enum token mode) 373static int filstat(char *nm, enum token mode)
368{ 374{
369 struct stat s; 375 struct stat s;
370 unsigned int i; 376 int i;
371 377
372 if (mode == FILSYM) { 378 if (mode == FILSYM) {
373#ifdef S_IFLNK 379#ifdef S_IFLNK
@@ -381,66 +387,61 @@ static int filstat(char *nm, enum token mode)
381 387
382 if (stat(nm, &s) != 0) 388 if (stat(nm, &s) != 0)
383 return 0; 389 return 0;
384 390 if (mode == FILEXIST)
385 switch (mode) {
386 case FILRD:
387 return test_eaccess(nm, R_OK) == 0;
388 case FILWR:
389 return test_eaccess(nm, W_OK) == 0;
390 case FILEX:
391 return test_eaccess(nm, X_OK) == 0;
392 case FILEXIST:
393 return 1; 391 return 1;
394 case FILREG: 392 else if (__is_file_access(mode)) {
395 i = S_IFREG; 393 if (mode == FILRD)
396 goto filetype; 394 i = R_OK;
397 case FILDIR: 395 if (mode == FILWR)
398 i = S_IFDIR; 396 i = W_OK;
399 goto filetype; 397 if (mode == FILEX)
400 case FILCDEV: 398 i = X_OK;
401 i = S_IFCHR; 399 return test_eaccess(nm, i) == 0;
402 goto filetype; 400 }
403 case FILBDEV: 401 else if (__is_file_type(mode)) {
404 i = S_IFBLK; 402 if (mode == FILREG)
405 goto filetype; 403 i = S_IFREG;
406 case FILFIFO: 404 if (mode == FILDIR)
405 i = S_IFDIR;
406 if (mode == FILCDEV)
407 i = S_IFCHR;
408 if (mode == FILBDEV)
409 i = S_IFBLK;
410 if (mode == FILFIFO) {
407#ifdef S_IFIFO 411#ifdef S_IFIFO
408 i = S_IFIFO; 412 i = S_IFIFO;
409 goto filetype;
410#else 413#else
411 return 0; 414 return 0;
412#endif 415#endif
413 case FILSOCK: 416 }
417 if (mode == FILSOCK) {
414#ifdef S_IFSOCK 418#ifdef S_IFSOCK
415 i = S_IFSOCK; 419 i = S_IFSOCK;
416 goto filetype;
417#else 420#else
418 return 0; 421 return 0;
419#endif 422#endif
420 case FILSUID: 423 }
421 i = S_ISUID; 424filetype:
422 goto filebit; 425 return ((s.st_mode & S_IFMT) == i);
423 case FILSGID: 426 }
424 i = S_ISGID; 427 else if (__is_file_bit(mode)) {
425 goto filebit; 428 if (mode == FILSUID)
426 case FILSTCK: 429 i = S_ISUID;
427 i = S_ISVTX; 430 if (mode == FILSGID)
428 goto filebit; 431 i = S_ISGID;
429 case FILGZ: 432 if (mode == FILSTCK)
433 i = S_ISVTX;
434 return ((s.st_mode & i) != 0);
435 }
436 else if (mode == FILGZ)
430 return s.st_size > 0L; 437 return s.st_size > 0L;
431 case FILUID: 438 else if (mode == FILUID)
432 return s.st_uid == geteuid(); 439 return s.st_uid == geteuid();
433 case FILGID: 440 else if (mode == FILGID)
434 return s.st_gid == getegid(); 441 return s.st_gid == getegid();
435 default: 442 else
436 return 1; 443 return 1; /* NOTREACHED */
437 }
438
439 filetype:
440 return ((s.st_mode & S_IFMT) == i);
441 444
442 filebit:
443 return ((s.st_mode & i) != 0);
444} 445}
445 446
446static enum token t_lex(char *s) 447static enum token t_lex(char *s)
@@ -463,6 +464,7 @@ static enum token t_lex(char *s)
463} 464}
464 465
465/* atoi with error detection */ 466/* atoi with error detection */
467//XXX: FIXME: duplicate of existing libbb function?
466static arith_t getn(const char *s) 468static arith_t getn(const char *s)
467{ 469{
468 char *p; 470 char *p;
@@ -556,6 +558,9 @@ static void initialize_group_array(void)
556} 558}
557 559
558/* Return non-zero if GID is one that we have in our groups list. */ 560/* Return non-zero if GID is one that we have in our groups list. */
561//XXX: FIXME: duplicate of existing libbb function?
562// see toplevel TODO file:
563// possible code duplication ingroup() and is_a_group_member()
559static int is_a_group_member(gid_t gid) 564static int is_a_group_member(gid_t gid)
560{ 565{
561 int i; 566 int i;