function.c (0da30e9aa76c5df66cd092f30b904824b0594ccc) | function.c (841484cd4291e19802fb976f22b28d5dc6706468) |
---|---|
1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Cimarron D. Taylor of the University of California, Berkeley. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 39 unchanged lines hidden (view full) --- 48#include <errno.h> 49#include <fnmatch.h> 50#include <fts.h> 51#include <grp.h> 52#include <pwd.h> 53#include <stdio.h> 54#include <stdlib.h> 55#include <string.h> | 1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Cimarron D. Taylor of the University of California, Berkeley. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 39 unchanged lines hidden (view full) --- 48#include <errno.h> 49#include <fnmatch.h> 50#include <fts.h> 51#include <grp.h> 52#include <pwd.h> 53#include <stdio.h> 54#include <stdlib.h> 55#include <string.h> |
56#include <tzfile.h> | |
57#include <unistd.h> 58 59#include "find.h" 60 61#define COMPARE(a, b) { \ 62 switch (plan->flags) { \ 63 case F_EQUAL: \ 64 return (a == b); \ --- 7 unchanged lines hidden (view full) --- 72} 73 74static PLAN *palloc __P((enum ntype, int (*) __P((PLAN *, FTSENT *)))); 75 76/* 77 * find_parsenum -- 78 * Parse a string of the form [+-]# and return the value. 79 */ | 56#include <unistd.h> 57 58#include "find.h" 59 60#define COMPARE(a, b) { \ 61 switch (plan->flags) { \ 62 case F_EQUAL: \ 63 return (a == b); \ --- 7 unchanged lines hidden (view full) --- 71} 72 73static PLAN *palloc __P((enum ntype, int (*) __P((PLAN *, FTSENT *)))); 74 75/* 76 * find_parsenum -- 77 * Parse a string of the form [+-]# and return the value. 78 */ |
80static long | 79static long long |
81find_parsenum(plan, option, vp, endch) 82 PLAN *plan; 83 char *option, *vp, *endch; 84{ | 80find_parsenum(plan, option, vp, endch) 81 PLAN *plan; 82 char *option, *vp, *endch; 83{ |
85 long value; | 84 long long value; |
86 char *endchar, *str; /* Pointer to character ending conversion. */ | 85 char *endchar, *str; /* Pointer to character ending conversion. */ |
87 | 86 |
88 /* Determine comparison from leading + or -. */ 89 str = vp; 90 switch (*str) { 91 case '+': 92 ++str; 93 plan->flags = F_GREATER; 94 break; 95 case '-': 96 ++str; 97 plan->flags = F_LESSTHAN; 98 break; 99 default: 100 plan->flags = F_EQUAL; 101 break; 102 } | 87 /* Determine comparison from leading + or -. */ 88 str = vp; 89 switch (*str) { 90 case '+': 91 ++str; 92 plan->flags = F_GREATER; 93 break; 94 case '-': 95 ++str; 96 plan->flags = F_LESSTHAN; 97 break; 98 default: 99 plan->flags = F_EQUAL; 100 break; 101 } |
103 | 102 |
104 /* | 103 /* |
105 * Convert the string with strtol(). Note, if strtol() returns zero | 104 * Convert the string with strtoq(). Note, if strtoq() returns zero |
106 * and endchar points to the beginning of the string we know we have 107 * a syntax error. 108 */ | 105 * and endchar points to the beginning of the string we know we have 106 * a syntax error. 107 */ |
109 value = strtol(str, &endchar, 10); | 108 value = strtoq(str, &endchar, 10); |
110 if (value == 0 && endchar == str) 111 errx(1, "%s: %s: illegal numeric value", option, vp); 112 if (endchar[0] && (endch == NULL || endchar[0] != *endch)) 113 errx(1, "%s: %s: illegal trailing character", option, vp); 114 if (endch) 115 *endch = endchar[0]; 116 return (value); 117} --- 17 unchanged lines hidden (view full) --- 135int 136f_atime(plan, entry) 137 PLAN *plan; 138 FTSENT *entry; 139{ 140 extern time_t now; 141 142 COMPARE((now - entry->fts_statp->st_atime + | 109 if (value == 0 && endchar == str) 110 errx(1, "%s: %s: illegal numeric value", option, vp); 111 if (endchar[0] && (endch == NULL || endchar[0] != *endch)) 112 errx(1, "%s: %s: illegal trailing character", option, vp); 113 if (endch) 114 *endch = endchar[0]; 115 return (value); 116} --- 17 unchanged lines hidden (view full) --- 134int 135f_atime(plan, entry) 136 PLAN *plan; 137 FTSENT *entry; 138{ 139 extern time_t now; 140 141 COMPARE((now - entry->fts_statp->st_atime + |
143 SECSPERDAY - 1) / SECSPERDAY, plan->t_data); | 142 86400 - 1) / 86400, plan->t_data); |
144} | 143} |
145 | 144 |
146PLAN * 147c_atime(arg) 148 char *arg; 149{ 150 PLAN *new; 151 152 ftsoptions &= ~FTS_NOSTAT; 153 --- 11 unchanged lines hidden (view full) --- 165int 166f_ctime(plan, entry) 167 PLAN *plan; 168 FTSENT *entry; 169{ 170 extern time_t now; 171 172 COMPARE((now - entry->fts_statp->st_ctime + | 145PLAN * 146c_atime(arg) 147 char *arg; 148{ 149 PLAN *new; 150 151 ftsoptions &= ~FTS_NOSTAT; 152 --- 11 unchanged lines hidden (view full) --- 164int 165f_ctime(plan, entry) 166 PLAN *plan; 167 FTSENT *entry; 168{ 169 extern time_t now; 170 171 COMPARE((now - entry->fts_statp->st_ctime + |
173 SECSPERDAY - 1) / SECSPERDAY, plan->t_data); | 172 86400 - 1) / 86400, plan->t_data); |
174} | 173} |
175 | 174 |
176PLAN * 177c_ctime(arg) 178 char *arg; 179{ 180 PLAN *new; 181 182 ftsoptions &= ~FTS_NOSTAT; 183 --- 12 unchanged lines hidden (view full) --- 196 */ 197int 198f_always_true(plan, entry) 199 PLAN *plan; 200 FTSENT *entry; 201{ 202 return (1); 203} | 175PLAN * 176c_ctime(arg) 177 char *arg; 178{ 179 PLAN *new; 180 181 ftsoptions &= ~FTS_NOSTAT; 182 --- 12 unchanged lines hidden (view full) --- 195 */ 196int 197f_always_true(plan, entry) 198 PLAN *plan; 199 FTSENT *entry; 200{ 201 return (1); 202} |
204 | 203 |
205PLAN * 206c_depth() 207{ 208 isdepth = 1; 209 210 return (palloc(N_DEPTH, f_always_true)); 211} | 204PLAN * 205c_depth() 206{ 207 isdepth = 1; 208 209 return (palloc(N_DEPTH, f_always_true)); 210} |
212 | 211 |
213/* 214 * [-exec | -ok] utility [arg ... ] ; functions -- 215 * 216 * True if the executed utility returns a zero value as exit status. 217 * The end of the primary expression is delimited by a semicolon. If 218 * "{}" occurs anywhere, it gets replaced by the current pathname. 219 * The current directory for the execution of utility is the same as 220 * the current directory when the find utility was started. --- 14 unchanged lines hidden (view full) --- 235 for (cnt = 0; plan->e_argv[cnt]; ++cnt) 236 if (plan->e_len[cnt]) 237 brace_subst(plan->e_orig[cnt], &plan->e_argv[cnt], 238 entry->fts_path, plan->e_len[cnt]); 239 240 if (plan->flags == F_NEEDOK && !queryuser(plan->e_argv)) 241 return (0); 242 | 212/* 213 * [-exec | -ok] utility [arg ... ] ; functions -- 214 * 215 * True if the executed utility returns a zero value as exit status. 216 * The end of the primary expression is delimited by a semicolon. If 217 * "{}" occurs anywhere, it gets replaced by the current pathname. 218 * The current directory for the execution of utility is the same as 219 * the current directory when the find utility was started. --- 14 unchanged lines hidden (view full) --- 234 for (cnt = 0; plan->e_argv[cnt]; ++cnt) 235 if (plan->e_len[cnt]) 236 brace_subst(plan->e_orig[cnt], &plan->e_argv[cnt], 237 entry->fts_path, plan->e_len[cnt]); 238 239 if (plan->flags == F_NEEDOK && !queryuser(plan->e_argv)) 240 return (0); 241 |
242 /* make sure find output is interspersed correctly with subprocesses */ 243 fflush(stdout); 244 |
|
243 switch (pid = vfork()) { 244 case -1: 245 err(1, "fork"); 246 /* NOTREACHED */ 247 case 0: 248 if (fchdir(dotfd)) { 249 warn("chdir"); 250 _exit(1); 251 } 252 execvp(plan->e_argv[0], plan->e_argv); 253 warn("%s", plan->e_argv[0]); 254 _exit(1); 255 } 256 pid = waitpid(pid, &status, 0); 257 return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status)); 258} | 245 switch (pid = vfork()) { 246 case -1: 247 err(1, "fork"); 248 /* NOTREACHED */ 249 case 0: 250 if (fchdir(dotfd)) { 251 warn("chdir"); 252 _exit(1); 253 } 254 execvp(plan->e_argv[0], plan->e_argv); 255 warn("%s", plan->e_argv[0]); 256 _exit(1); 257 } 258 pid = waitpid(pid, &status, 0); 259 return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status)); 260} |
259 | 261 |
260/* 261 * c_exec -- 262 * build three parallel arrays, one with pointers to the strings passed 263 * on the command line, one with (possibly duplicated) pointers to the 264 * argv array, and one with integer values that are lengths of the 265 * strings, but also flags meaning that the string has to be massaged. 266 */ 267PLAN * 268c_exec(argvp, isok) 269 char ***argvp; 270 int isok; 271{ 272 PLAN *new; /* node returned */ 273 register int cnt; 274 register char **argv, **ap, *p; 275 276 isoutput = 1; | 262/* 263 * c_exec -- 264 * build three parallel arrays, one with pointers to the strings passed 265 * on the command line, one with (possibly duplicated) pointers to the 266 * argv array, and one with integer values that are lengths of the 267 * strings, but also flags meaning that the string has to be massaged. 268 */ 269PLAN * 270c_exec(argvp, isok) 271 char ***argvp; 272 int isok; 273{ 274 PLAN *new; /* node returned */ 275 register int cnt; 276 register char **argv, **ap, *p; 277 278 isoutput = 1; |
277 | 279 |
278 new = palloc(N_EXEC, f_exec); 279 if (isok) 280 new->flags = F_NEEDOK; 281 282 for (ap = argv = *argvp;; ++ap) { 283 if (!*ap) 284 errx(1, 285 "%s: no terminating \";\"", isok ? "-ok" : "-exec"); --- 19 unchanged lines hidden (view full) --- 305 new->e_len[cnt] = 0; 306 } 307 } 308 new->e_argv[cnt] = new->e_orig[cnt] = NULL; 309 310 *argvp = argv + 1; 311 return (new); 312} | 280 new = palloc(N_EXEC, f_exec); 281 if (isok) 282 new->flags = F_NEEDOK; 283 284 for (ap = argv = *argvp;; ++ap) { 285 if (!*ap) 286 errx(1, 287 "%s: no terminating \";\"", isok ? "-ok" : "-exec"); --- 19 unchanged lines hidden (view full) --- 307 new->e_len[cnt] = 0; 308 } 309 } 310 new->e_argv[cnt] = new->e_orig[cnt] = NULL; 311 312 *argvp = argv + 1; 313 return (new); 314} |
313 | 315 |
314/* 315 * -follow functions -- 316 * 317 * Always true, causes symbolic links to be followed on a global 318 * basis. 319 */ 320PLAN * 321c_follow() 322{ 323 ftsoptions &= ~FTS_PHYSICAL; 324 ftsoptions |= FTS_LOGICAL; 325 326 return (palloc(N_FOLLOW, f_always_true)); 327} | 316/* 317 * -follow functions -- 318 * 319 * Always true, causes symbolic links to be followed on a global 320 * basis. 321 */ 322PLAN * 323c_follow() 324{ 325 ftsoptions &= ~FTS_PHYSICAL; 326 ftsoptions |= FTS_LOGICAL; 327 328 return (palloc(N_FOLLOW, f_always_true)); 329} |
328 | 330 |
329/* 330 * -fstype functions -- 331 * 332 * True if the file is of a certain type. 333 */ 334int 335f_fstype(plan, entry) 336 PLAN *plan; --- 18 unchanged lines hidden (view full) --- 355 if ((p = strrchr(entry->fts_accpath, '/')) != NULL) 356 ++p; 357 else 358 p = entry->fts_accpath; 359 save[0] = p[0]; 360 p[0] = '.'; 361 save[1] = p[1]; 362 p[1] = '\0'; | 331/* 332 * -fstype functions -- 333 * 334 * True if the file is of a certain type. 335 */ 336int 337f_fstype(plan, entry) 338 PLAN *plan; --- 18 unchanged lines hidden (view full) --- 357 if ((p = strrchr(entry->fts_accpath, '/')) != NULL) 358 ++p; 359 else 360 p = entry->fts_accpath; 361 save[0] = p[0]; 362 p[0] = '.'; 363 save[1] = p[1]; 364 p[1] = '\0'; |
363 364 } else | 365 366 } else |
365 p = NULL; 366 367 if (statfs(entry->fts_accpath, &sb)) 368 err(1, "%s", entry->fts_accpath); 369 370 if (p) { 371 p[0] = save[0]; 372 p[1] = save[1]; --- 5 unchanged lines hidden (view full) --- 378 * Further tests may need both of these values, so 379 * always copy both of them. 380 */ 381 val = sb.f_flags; 382 val = sb.f_type; 383 } 384 switch (plan->flags) { 385 case F_MTFLAG: | 367 p = NULL; 368 369 if (statfs(entry->fts_accpath, &sb)) 370 err(1, "%s", entry->fts_accpath); 371 372 if (p) { 373 p[0] = save[0]; 374 p[1] = save[1]; --- 5 unchanged lines hidden (view full) --- 380 * Further tests may need both of these values, so 381 * always copy both of them. 382 */ 383 val = sb.f_flags; 384 val = sb.f_type; 385 } 386 switch (plan->flags) { 387 case F_MTFLAG: |
386 return (val & plan->mt_data); | 388 return (val & plan->mt_data); |
387 case F_MTTYPE: 388 return (val == plan->mt_data); 389 default: 390 abort(); 391 } 392} | 389 case F_MTTYPE: 390 return (val == plan->mt_data); 391 default: 392 abort(); 393 } 394} |
393 | 395 |
394PLAN * 395c_fstype(arg) 396 char *arg; 397{ 398 register PLAN *new; 399 struct vfsconf vfc; 400 401 ftsoptions &= ~FTS_NOSTAT; | 396PLAN * 397c_fstype(arg) 398 char *arg; 399{ 400 register PLAN *new; 401 struct vfsconf vfc; 402 403 ftsoptions &= ~FTS_NOSTAT; |
402 | 404 |
403 new = palloc(N_FSTYPE, f_fstype); 404 405 /* 406 * Check first for a filesystem name. 407 */ 408 if (getvfsbyname(arg, &vfc) == 0) { 409 new->flags = F_MTTYPE; 410 new->mt_data = vfc.vfc_typenum; --- 14 unchanged lines hidden (view full) --- 425 new->mt_data = MNT_RDONLY; 426 return (new); 427 } 428 break; 429 } 430 errx(1, "%s: unknown file type", arg); 431 /* NOTREACHED */ 432} | 405 new = palloc(N_FSTYPE, f_fstype); 406 407 /* 408 * Check first for a filesystem name. 409 */ 410 if (getvfsbyname(arg, &vfc) == 0) { 411 new->flags = F_MTTYPE; 412 new->mt_data = vfc.vfc_typenum; --- 14 unchanged lines hidden (view full) --- 427 new->mt_data = MNT_RDONLY; 428 return (new); 429 } 430 break; 431 } 432 errx(1, "%s: unknown file type", arg); 433 /* NOTREACHED */ 434} |
433 | 435 |
434/* 435 * -group gname functions -- 436 * 437 * True if the file belongs to the group gname. If gname is numeric and 438 * an equivalent of the getgrnam() function does not return a valid group 439 * name, gname is taken as a group ID. 440 */ 441int 442f_group(plan, entry) 443 PLAN *plan; 444 FTSENT *entry; 445{ 446 return (entry->fts_statp->st_gid == plan->g_data); 447} | 436/* 437 * -group gname functions -- 438 * 439 * True if the file belongs to the group gname. If gname is numeric and 440 * an equivalent of the getgrnam() function does not return a valid group 441 * name, gname is taken as a group ID. 442 */ 443int 444f_group(plan, entry) 445 PLAN *plan; 446 FTSENT *entry; 447{ 448 return (entry->fts_statp->st_gid == plan->g_data); 449} |
448 | 450 |
449PLAN * 450c_group(gname) 451 char *gname; 452{ 453 PLAN *new; 454 struct group *g; 455 gid_t gid; | 451PLAN * 452c_group(gname) 453 char *gname; 454{ 455 PLAN *new; 456 struct group *g; 457 gid_t gid; |
456 | 458 |
457 ftsoptions &= ~FTS_NOSTAT; 458 459 g = getgrnam(gname); 460 if (g == NULL) { 461 gid = atoi(gname); 462 if (gid == 0 && gname[0] != '0') 463 errx(1, "-group: %s: no such group", gname); 464 } else 465 gid = g->gr_gid; | 459 ftsoptions &= ~FTS_NOSTAT; 460 461 g = getgrnam(gname); 462 if (g == NULL) { 463 gid = atoi(gname); 464 if (gid == 0 && gname[0] != '0') 465 errx(1, "-group: %s: no such group", gname); 466 } else 467 gid = g->gr_gid; |
466 | 468 |
467 new = palloc(N_GROUP, f_group); 468 new->g_data = gid; 469 return (new); 470} 471 472/* 473 * -inum n functions -- 474 * 475 * True if the file has inode # n. 476 */ 477int 478f_inum(plan, entry) 479 PLAN *plan; 480 FTSENT *entry; 481{ 482 COMPARE(entry->fts_statp->st_ino, plan->i_data); 483} | 469 new = palloc(N_GROUP, f_group); 470 new->g_data = gid; 471 return (new); 472} 473 474/* 475 * -inum n functions -- 476 * 477 * True if the file has inode # n. 478 */ 479int 480f_inum(plan, entry) 481 PLAN *plan; 482 FTSENT *entry; 483{ 484 COMPARE(entry->fts_statp->st_ino, plan->i_data); 485} |
484 | 486 |
485PLAN * 486c_inum(arg) 487 char *arg; 488{ 489 PLAN *new; | 487PLAN * 488c_inum(arg) 489 char *arg; 490{ 491 PLAN *new; |
490 | 492 |
491 ftsoptions &= ~FTS_NOSTAT; | 493 ftsoptions &= ~FTS_NOSTAT; |
492 | 494 |
493 new = palloc(N_INUM, f_inum); 494 new->i_data = find_parsenum(new, "-inum", arg, NULL); 495 return (new); 496} | 495 new = palloc(N_INUM, f_inum); 496 new->i_data = find_parsenum(new, "-inum", arg, NULL); 497 return (new); 498} |
497 | 499 |
498/* 499 * -links n functions -- 500 * 501 * True if the file has n links. 502 */ 503int 504f_links(plan, entry) 505 PLAN *plan; 506 FTSENT *entry; 507{ 508 COMPARE(entry->fts_statp->st_nlink, plan->l_data); 509} | 500/* 501 * -links n functions -- 502 * 503 * True if the file has n links. 504 */ 505int 506f_links(plan, entry) 507 PLAN *plan; 508 FTSENT *entry; 509{ 510 COMPARE(entry->fts_statp->st_nlink, plan->l_data); 511} |
510 | 512 |
511PLAN * 512c_links(arg) 513 char *arg; 514{ 515 PLAN *new; | 513PLAN * 514c_links(arg) 515 char *arg; 516{ 517 PLAN *new; |
516 | 518 |
517 ftsoptions &= ~FTS_NOSTAT; | 519 ftsoptions &= ~FTS_NOSTAT; |
518 | 520 |
519 new = palloc(N_LINKS, f_links); 520 new->l_data = (nlink_t)find_parsenum(new, "-links", arg, NULL); 521 return (new); 522} | 521 new = palloc(N_LINKS, f_links); 522 new->l_data = (nlink_t)find_parsenum(new, "-links", arg, NULL); 523 return (new); 524} |
523 | 525 |
524/* 525 * -ls functions -- 526 * 527 * Always true - prints the current entry to stdout in "ls" format. 528 */ 529int 530f_ls(plan, entry) 531 PLAN *plan; 532 FTSENT *entry; 533{ 534 printlong(entry->fts_path, entry->fts_accpath, entry->fts_statp); 535 return (1); 536} | 526/* 527 * -ls functions -- 528 * 529 * Always true - prints the current entry to stdout in "ls" format. 530 */ 531int 532f_ls(plan, entry) 533 PLAN *plan; 534 FTSENT *entry; 535{ 536 printlong(entry->fts_path, entry->fts_accpath, entry->fts_statp); 537 return (1); 538} |
537 | 539 |
538PLAN * 539c_ls() 540{ 541 ftsoptions &= ~FTS_NOSTAT; 542 isoutput = 1; | 540PLAN * 541c_ls() 542{ 543 ftsoptions &= ~FTS_NOSTAT; 544 isoutput = 1; |
543 | 545 |
544 return (palloc(N_LS, f_ls)); 545} 546 547/* 548 * -mtime n functions -- 549 * 550 * True if the difference between the file modification time and the 551 * current time is n 24 hour periods. 552 */ 553int 554f_mtime(plan, entry) 555 PLAN *plan; 556 FTSENT *entry; 557{ 558 extern time_t now; 559 | 546 return (palloc(N_LS, f_ls)); 547} 548 549/* 550 * -mtime n functions -- 551 * 552 * True if the difference between the file modification time and the 553 * current time is n 24 hour periods. 554 */ 555int 556f_mtime(plan, entry) 557 PLAN *plan; 558 FTSENT *entry; 559{ 560 extern time_t now; 561 |
560 COMPARE((now - entry->fts_statp->st_mtime + SECSPERDAY - 1) / 561 SECSPERDAY, plan->t_data); | 562 COMPARE((now - entry->fts_statp->st_mtime + 86400 - 1) / 563 86400, plan->t_data); |
562} | 564} |
563 | 565 |
564PLAN * 565c_mtime(arg) 566 char *arg; 567{ 568 PLAN *new; 569 570 ftsoptions &= ~FTS_NOSTAT; 571 --- 11 unchanged lines hidden (view full) --- 583 */ 584int 585f_name(plan, entry) 586 PLAN *plan; 587 FTSENT *entry; 588{ 589 return (!fnmatch(plan->c_data, entry->fts_name, 0)); 590} | 566PLAN * 567c_mtime(arg) 568 char *arg; 569{ 570 PLAN *new; 571 572 ftsoptions &= ~FTS_NOSTAT; 573 --- 11 unchanged lines hidden (view full) --- 585 */ 586int 587f_name(plan, entry) 588 PLAN *plan; 589 FTSENT *entry; 590{ 591 return (!fnmatch(plan->c_data, entry->fts_name, 0)); 592} |
591 | 593 |
592PLAN * 593c_name(pattern) 594 char *pattern; 595{ 596 PLAN *new; 597 598 new = palloc(N_NAME, f_name); 599 new->c_data = pattern; 600 return (new); 601} | 594PLAN * 595c_name(pattern) 596 char *pattern; 597{ 598 PLAN *new; 599 600 new = palloc(N_NAME, f_name); 601 new->c_data = pattern; 602 return (new); 603} |
602 | 604 |
603/* 604 * -newer file functions -- 605 * 606 * True if the current file has been modified more recently 607 * then the modification time of the file named by the pathname 608 * file. 609 */ 610int 611f_newer(plan, entry) 612 PLAN *plan; 613 FTSENT *entry; 614{ 615 return (entry->fts_statp->st_mtime > plan->t_data); 616} | 605/* 606 * -newer file functions -- 607 * 608 * True if the current file has been modified more recently 609 * then the modification time of the file named by the pathname 610 * file. 611 */ 612int 613f_newer(plan, entry) 614 PLAN *plan; 615 FTSENT *entry; 616{ 617 return (entry->fts_statp->st_mtime > plan->t_data); 618} |
617 | 619 |
618PLAN * 619c_newer(filename) 620 char *filename; 621{ 622 PLAN *new; 623 struct stat sb; | 620PLAN * 621c_newer(filename) 622 char *filename; 623{ 624 PLAN *new; 625 struct stat sb; |
624 | 626 |
625 ftsoptions &= ~FTS_NOSTAT; 626 627 if (stat(filename, &sb)) 628 err(1, "%s", filename); 629 new = palloc(N_NEWER, f_newer); 630 new->t_data = sb.st_mtime; 631 return (new); 632} | 627 ftsoptions &= ~FTS_NOSTAT; 628 629 if (stat(filename, &sb)) 630 err(1, "%s", filename); 631 new = palloc(N_NEWER, f_newer); 632 new->t_data = sb.st_mtime; 633 return (new); 634} |
633 | 635 |
634/* 635 * -nogroup functions -- 636 * 637 * True if file belongs to a user ID for which the equivalent 638 * of the getgrnam() 9.2.1 [POSIX.1] function returns NULL. 639 */ 640int 641f_nogroup(plan, entry) 642 PLAN *plan; 643 FTSENT *entry; 644{ 645 char *group_from_gid(); 646 647 return (group_from_gid(entry->fts_statp->st_gid, 1) ? 0 : 1); 648} | 636/* 637 * -nogroup functions -- 638 * 639 * True if file belongs to a user ID for which the equivalent 640 * of the getgrnam() 9.2.1 [POSIX.1] function returns NULL. 641 */ 642int 643f_nogroup(plan, entry) 644 PLAN *plan; 645 FTSENT *entry; 646{ 647 char *group_from_gid(); 648 649 return (group_from_gid(entry->fts_statp->st_gid, 1) ? 0 : 1); 650} |
649 | 651 |
650PLAN * 651c_nogroup() 652{ 653 ftsoptions &= ~FTS_NOSTAT; 654 655 return (palloc(N_NOGROUP, f_nogroup)); 656} | 652PLAN * 653c_nogroup() 654{ 655 ftsoptions &= ~FTS_NOSTAT; 656 657 return (palloc(N_NOGROUP, f_nogroup)); 658} |
657 | 659 |
658/* 659 * -nouser functions -- 660 * 661 * True if file belongs to a user ID for which the equivalent 662 * of the getpwuid() 9.2.2 [POSIX.1] function returns NULL. 663 */ 664int 665f_nouser(plan, entry) 666 PLAN *plan; 667 FTSENT *entry; 668{ 669 char *user_from_uid(); 670 671 return (user_from_uid(entry->fts_statp->st_uid, 1) ? 0 : 1); 672} | 660/* 661 * -nouser functions -- 662 * 663 * True if file belongs to a user ID for which the equivalent 664 * of the getpwuid() 9.2.2 [POSIX.1] function returns NULL. 665 */ 666int 667f_nouser(plan, entry) 668 PLAN *plan; 669 FTSENT *entry; 670{ 671 char *user_from_uid(); 672 673 return (user_from_uid(entry->fts_statp->st_uid, 1) ? 0 : 1); 674} |
673 | 675 |
674PLAN * 675c_nouser() 676{ 677 ftsoptions &= ~FTS_NOSTAT; 678 679 return (palloc(N_NOUSER, f_nouser)); 680} | 676PLAN * 677c_nouser() 678{ 679 ftsoptions &= ~FTS_NOSTAT; 680 681 return (palloc(N_NOUSER, f_nouser)); 682} |
681 | 683 |
682/* 683 * -path functions -- 684 * 685 * True if the path of the filename being examined 686 * matches pattern using Pattern Matching Notation S3.14 687 */ 688int 689f_path(plan, entry) 690 PLAN *plan; 691 FTSENT *entry; 692{ 693 return (!fnmatch(plan->c_data, entry->fts_path, 0)); 694} | 684/* 685 * -path functions -- 686 * 687 * True if the path of the filename being examined 688 * matches pattern using Pattern Matching Notation S3.14 689 */ 690int 691f_path(plan, entry) 692 PLAN *plan; 693 FTSENT *entry; 694{ 695 return (!fnmatch(plan->c_data, entry->fts_path, 0)); 696} |
695 | 697 |
696PLAN * 697c_path(pattern) 698 char *pattern; 699{ 700 PLAN *new; 701 702 new = palloc(N_NAME, f_path); 703 new->c_data = pattern; 704 return (new); 705} | 698PLAN * 699c_path(pattern) 700 char *pattern; 701{ 702 PLAN *new; 703 704 new = palloc(N_NAME, f_path); 705 new->c_data = pattern; 706 return (new); 707} |
706 | 708 |
707/* 708 * -perm functions -- 709 * 710 * The mode argument is used to represent file mode bits. If it starts 711 * with a leading digit, it's treated as an octal mode, otherwise as a 712 * symbolic mode. 713 */ 714int --- 6 unchanged lines hidden (view full) --- 721 mode = entry->fts_statp->st_mode & 722 (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO); 723 if (plan->flags == F_ATLEAST) 724 return ((plan->m_data | mode) == mode); 725 else 726 return (mode == plan->m_data); 727 /* NOTREACHED */ 728} | 709/* 710 * -perm functions -- 711 * 712 * The mode argument is used to represent file mode bits. If it starts 713 * with a leading digit, it's treated as an octal mode, otherwise as a 714 * symbolic mode. 715 */ 716int --- 6 unchanged lines hidden (view full) --- 723 mode = entry->fts_statp->st_mode & 724 (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO); 725 if (plan->flags == F_ATLEAST) 726 return ((plan->m_data | mode) == mode); 727 else 728 return (mode == plan->m_data); 729 /* NOTREACHED */ 730} |
729 | 731 |
730PLAN * 731c_perm(perm) 732 char *perm; 733{ 734 PLAN *new; 735 mode_t *set; 736 737 ftsoptions &= ~FTS_NOSTAT; --- 6 unchanged lines hidden (view full) --- 744 } 745 746 if ((set = setmode(perm)) == NULL) 747 err(1, "-perm: %s: illegal mode string", perm); 748 749 new->m_data = getmode(set, 0); 750 return (new); 751} | 732PLAN * 733c_perm(perm) 734 char *perm; 735{ 736 PLAN *new; 737 mode_t *set; 738 739 ftsoptions &= ~FTS_NOSTAT; --- 6 unchanged lines hidden (view full) --- 746 } 747 748 if ((set = setmode(perm)) == NULL) 749 err(1, "-perm: %s: illegal mode string", perm); 750 751 new->m_data = getmode(set, 0); 752 return (new); 753} |
752 | 754 |
753/* 754 * -print functions -- 755 * 756 * Always true, causes the current pathame to be written to 757 * standard output. 758 */ 759int 760f_print(plan, entry) 761 PLAN *plan; 762 FTSENT *entry; 763{ | 755/* 756 * -print functions -- 757 * 758 * Always true, causes the current pathame to be written to 759 * standard output. 760 */ 761int 762f_print(plan, entry) 763 PLAN *plan; 764 FTSENT *entry; 765{ |
764 (void)printf("%s\n", entry->fts_path); | 766 (void)puts(entry->fts_path); |
765 return (1); 766} | 767 return (1); 768} |
767 | 769 |
768PLAN * 769c_print() 770{ 771 isoutput = 1; 772 773 return (palloc(N_PRINT, f_print)); 774} | 770PLAN * 771c_print() 772{ 773 isoutput = 1; 774 775 return (palloc(N_PRINT, f_print)); 776} |
775 | 777 |
776/* | 778/* |
779 * -print0 functions -- 780 * 781 * Always true, causes the current pathame to be written to 782 * standard output followed by a NUL character 783 */ 784int 785f_print0(plan, entry) 786 PLAN *plan; 787 FTSENT *entry; 788{ 789 fputs(entry->fts_path, stdout); 790 fputc('\0', stdout); 791 return (1); 792} 793 794PLAN * 795c_print0() 796{ 797 isoutput = 1; 798 799 return (palloc(N_PRINT0, f_print0)); 800} 801 802/* |
|
777 * -prune functions -- 778 * 779 * Prune a portion of the hierarchy. 780 */ 781int 782f_prune(plan, entry) 783 PLAN *plan; 784 FTSENT *entry; 785{ 786 extern FTS *tree; 787 788 if (fts_set(tree, entry, FTS_SKIP)) 789 err(1, "%s", entry->fts_path); 790 return (1); 791} | 803 * -prune functions -- 804 * 805 * Prune a portion of the hierarchy. 806 */ 807int 808f_prune(plan, entry) 809 PLAN *plan; 810 FTSENT *entry; 811{ 812 extern FTS *tree; 813 814 if (fts_set(tree, entry, FTS_SKIP)) 815 err(1, "%s", entry->fts_path); 816 return (1); 817} |
792 | 818 |
793PLAN * 794c_prune() 795{ 796 return (palloc(N_PRUNE, f_prune)); 797} | 819PLAN * 820c_prune() 821{ 822 return (palloc(N_PRUNE, f_prune)); 823} |
798 | 824 |
799/* 800 * -size n[c] functions -- 801 * 802 * True if the file size in bytes, divided by an implementation defined 803 * value and rounded up to the next integer, is n. If n is followed by 804 * a c, the size is in bytes. 805 */ 806#define FIND_SIZE 512 --- 5 unchanged lines hidden (view full) --- 812 FTSENT *entry; 813{ 814 off_t size; 815 816 size = divsize ? (entry->fts_statp->st_size + FIND_SIZE - 1) / 817 FIND_SIZE : entry->fts_statp->st_size; 818 COMPARE(size, plan->o_data); 819} | 825/* 826 * -size n[c] functions -- 827 * 828 * True if the file size in bytes, divided by an implementation defined 829 * value and rounded up to the next integer, is n. If n is followed by 830 * a c, the size is in bytes. 831 */ 832#define FIND_SIZE 512 --- 5 unchanged lines hidden (view full) --- 838 FTSENT *entry; 839{ 840 off_t size; 841 842 size = divsize ? (entry->fts_statp->st_size + FIND_SIZE - 1) / 843 FIND_SIZE : entry->fts_statp->st_size; 844 COMPARE(size, plan->o_data); 845} |
820 | 846 |
821PLAN * 822c_size(arg) 823 char *arg; 824{ 825 PLAN *new; 826 char endch; | 847PLAN * 848c_size(arg) 849 char *arg; 850{ 851 PLAN *new; 852 char endch; |
827 | 853 |
828 ftsoptions &= ~FTS_NOSTAT; 829 830 new = palloc(N_SIZE, f_size); 831 endch = 'c'; 832 new->o_data = find_parsenum(new, "-size", arg, &endch); 833 if (endch == 'c') 834 divsize = 0; 835 return (new); 836} | 854 ftsoptions &= ~FTS_NOSTAT; 855 856 new = palloc(N_SIZE, f_size); 857 endch = 'c'; 858 new->o_data = find_parsenum(new, "-size", arg, &endch); 859 if (endch == 'c') 860 divsize = 0; 861 return (new); 862} |
837 | 863 |
838/* 839 * -type c functions -- 840 * 841 * True if the type of the file is c, where c is b, c, d, p, f or w 842 * for block special file, character special file, directory, FIFO, 843 * regular file or whiteout respectively. 844 */ 845int 846f_type(plan, entry) 847 PLAN *plan; 848 FTSENT *entry; 849{ 850 return ((entry->fts_statp->st_mode & S_IFMT) == plan->m_data); 851} | 864/* 865 * -type c functions -- 866 * 867 * True if the type of the file is c, where c is b, c, d, p, f or w 868 * for block special file, character special file, directory, FIFO, 869 * regular file or whiteout respectively. 870 */ 871int 872f_type(plan, entry) 873 PLAN *plan; 874 FTSENT *entry; 875{ 876 return ((entry->fts_statp->st_mode & S_IFMT) == plan->m_data); 877} |
852 | 878 |
853PLAN * 854c_type(typestring) 855 char *typestring; 856{ 857 PLAN *new; 858 mode_t mask; | 879PLAN * 880c_type(typestring) 881 char *typestring; 882{ 883 PLAN *new; 884 mode_t mask; |
859 | 885 |
860 ftsoptions &= ~FTS_NOSTAT; 861 862 switch (typestring[0]) { 863 case 'b': 864 mask = S_IFBLK; 865 break; 866 case 'c': 867 mask = S_IFCHR; --- 17 unchanged lines hidden (view full) --- 885 case 'w': 886 mask = S_IFWHT; 887 ftsoptions |= FTS_WHITEOUT; 888 break; 889#endif /* FTS_WHITEOUT */ 890 default: 891 errx(1, "-type: %s: unknown type", typestring); 892 } | 886 ftsoptions &= ~FTS_NOSTAT; 887 888 switch (typestring[0]) { 889 case 'b': 890 mask = S_IFBLK; 891 break; 892 case 'c': 893 mask = S_IFCHR; --- 17 unchanged lines hidden (view full) --- 911 case 'w': 912 mask = S_IFWHT; 913 ftsoptions |= FTS_WHITEOUT; 914 break; 915#endif /* FTS_WHITEOUT */ 916 default: 917 errx(1, "-type: %s: unknown type", typestring); 918 } |
893 | 919 |
894 new = palloc(N_TYPE, f_type); 895 new->m_data = mask; 896 return (new); 897} | 920 new = palloc(N_TYPE, f_type); 921 new->m_data = mask; 922 return (new); 923} |
898 | 924 |
899/* | 925/* |
926 * -delete functions -- 927 * 928 * True always. Makes it's best shot and continues on regardless. 929 */ 930int 931f_delete(plan, entry) 932 PLAN *plan; 933 FTSENT *entry; 934{ 935 /* ignore these from fts */ 936 if (strcmp(entry->fts_accpath, ".") == 0 || 937 strcmp(entry->fts_accpath, "..") == 0) 938 return (1); 939 940 /* sanity check */ 941 if (isdepth == 0 || /* depth off */ 942 (ftsoptions & FTS_NOSTAT) || /* not stat()ing */ 943 !(ftsoptions & FTS_PHYSICAL) || /* physical off */ 944 (ftsoptions & FTS_LOGICAL)) /* or finally, logical on */ 945 errx(1, "-delete: insecure options got turned on"); 946 947 /* Potentially unsafe - do not accept relative paths whatsoever */ 948 if (strchr(entry->fts_accpath, '/') != NULL) 949 errx(1, "-delete: %s: relative path potentially not safe", 950 entry->fts_accpath); 951 952 /* Turn off user immutable bits if running as root */ 953 if ((entry->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && 954 !(entry->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && 955 geteuid() == 0) 956 chflags(entry->fts_accpath, 957 entry->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)); 958 959 /* rmdir directories, unlink everything else */ 960 if (S_ISDIR(entry->fts_statp->st_mode)) { 961 if (rmdir(entry->fts_accpath) < 0 && errno != ENOTEMPTY) 962 warn("-delete: rmdir(%s)", entry->fts_path); 963 } else { 964 if (unlink(entry->fts_accpath) < 0) 965 warn("-delete: unlink(%s)", entry->fts_path); 966 } 967 968 /* "succeed" */ 969 return (1); 970} 971 972PLAN * 973c_delete() 974{ 975 976 ftsoptions &= ~FTS_NOSTAT; /* no optimise */ 977 ftsoptions |= FTS_PHYSICAL; /* disable -follow */ 978 ftsoptions &= ~FTS_LOGICAL; /* disable -follow */ 979 isoutput = 1; /* possible output */ 980 isdepth = 1; /* -depth implied */ 981 982 return (palloc(N_DELETE, f_delete)); 983} 984 985/* |
|
900 * -user uname functions -- 901 * 902 * True if the file belongs to the user uname. If uname is numeric and 903 * an equivalent of the getpwnam() S9.2.2 [POSIX.1] function does not 904 * return a valid user name, uname is taken as a user ID. 905 */ 906int 907f_user(plan, entry) 908 PLAN *plan; 909 FTSENT *entry; 910{ 911 return (entry->fts_statp->st_uid == plan->u_data); 912} | 986 * -user uname functions -- 987 * 988 * True if the file belongs to the user uname. If uname is numeric and 989 * an equivalent of the getpwnam() S9.2.2 [POSIX.1] function does not 990 * return a valid user name, uname is taken as a user ID. 991 */ 992int 993f_user(plan, entry) 994 PLAN *plan; 995 FTSENT *entry; 996{ 997 return (entry->fts_statp->st_uid == plan->u_data); 998} |
913 | 999 |
914PLAN * 915c_user(username) 916 char *username; 917{ 918 PLAN *new; 919 struct passwd *p; 920 uid_t uid; | 1000PLAN * 1001c_user(username) 1002 char *username; 1003{ 1004 PLAN *new; 1005 struct passwd *p; 1006 uid_t uid; |
921 | 1007 |
922 ftsoptions &= ~FTS_NOSTAT; 923 924 p = getpwnam(username); 925 if (p == NULL) { 926 uid = atoi(username); 927 if (uid == 0 && username[0] != '0') 928 errx(1, "-user: %s: no such user", username); 929 } else 930 uid = p->pw_uid; 931 932 new = palloc(N_USER, f_user); 933 new->u_data = uid; 934 return (new); 935} | 1008 ftsoptions &= ~FTS_NOSTAT; 1009 1010 p = getpwnam(username); 1011 if (p == NULL) { 1012 uid = atoi(username); 1013 if (uid == 0 && username[0] != '0') 1014 errx(1, "-user: %s: no such user", username); 1015 } else 1016 uid = p->pw_uid; 1017 1018 new = palloc(N_USER, f_user); 1019 new->u_data = uid; 1020 return (new); 1021} |
936 | 1022 |
937/* 938 * -xdev functions -- 939 * 940 * Always true, causes find not to decend past directories that have a 941 * different device ID (st_dev, see stat() S5.6.2 [POSIX.1]) 942 */ 943PLAN * 944c_xdev() --- 15 unchanged lines hidden (view full) --- 960{ 961 register PLAN *p; 962 register int state; 963 964 for (p = plan->p_data[0]; 965 p && (state = (p->eval)(p, entry)); p = p->next); 966 return (state); 967} | 1023/* 1024 * -xdev functions -- 1025 * 1026 * Always true, causes find not to decend past directories that have a 1027 * different device ID (st_dev, see stat() S5.6.2 [POSIX.1]) 1028 */ 1029PLAN * 1030c_xdev() --- 15 unchanged lines hidden (view full) --- 1046{ 1047 register PLAN *p; 1048 register int state; 1049 1050 for (p = plan->p_data[0]; 1051 p && (state = (p->eval)(p, entry)); p = p->next); 1052 return (state); 1053} |
968 | 1054 |
969/* 970 * N_OPENPAREN and N_CLOSEPAREN nodes are temporary place markers. They are 971 * eliminated during phase 2 of find_formplan() --- the '(' node is converted 972 * to a N_EXPR node containing the expression and the ')' node is discarded. 973 */ 974PLAN * 975c_openparen() 976{ 977 return (palloc(N_OPENPAREN, (int (*)())-1)); 978} | 1055/* 1056 * N_OPENPAREN and N_CLOSEPAREN nodes are temporary place markers. They are 1057 * eliminated during phase 2 of find_formplan() --- the '(' node is converted 1058 * to a N_EXPR node containing the expression and the ')' node is discarded. 1059 */ 1060PLAN * 1061c_openparen() 1062{ 1063 return (palloc(N_OPENPAREN, (int (*)())-1)); 1064} |
979 | 1065 |
980PLAN * 981c_closeparen() 982{ 983 return (palloc(N_CLOSEPAREN, (int (*)())-1)); 984} | 1066PLAN * 1067c_closeparen() 1068{ 1069 return (palloc(N_CLOSEPAREN, (int (*)())-1)); 1070} |
985 | 1071 |
986/* 987 * ! expression functions -- 988 * 989 * Negation of a primary; the unary NOT operator. 990 */ 991int 992f_not(plan, entry) 993 PLAN *plan; 994 FTSENT *entry; 995{ 996 register PLAN *p; 997 register int state; 998 999 for (p = plan->p_data[0]; 1000 p && (state = (p->eval)(p, entry)); p = p->next); 1001 return (!state); 1002} | 1072/* 1073 * ! expression functions -- 1074 * 1075 * Negation of a primary; the unary NOT operator. 1076 */ 1077int 1078f_not(plan, entry) 1079 PLAN *plan; 1080 FTSENT *entry; 1081{ 1082 register PLAN *p; 1083 register int state; 1084 1085 for (p = plan->p_data[0]; 1086 p && (state = (p->eval)(p, entry)); p = p->next); 1087 return (!state); 1088} |
1003 | 1089 |
1004PLAN * 1005c_not() 1006{ 1007 return (palloc(N_NOT, f_not)); 1008} | 1090PLAN * 1091c_not() 1092{ 1093 return (palloc(N_NOT, f_not)); 1094} |
1009 | 1095 |
1010/* 1011 * expression -o expression functions -- 1012 * 1013 * Alternation of primaries; the OR operator. The second expression is 1014 * not evaluated if the first expression is true. 1015 */ 1016int 1017f_or(plan, entry) --- 38 unchanged lines hidden --- | 1096/* 1097 * expression -o expression functions -- 1098 * 1099 * Alternation of primaries; the OR operator. The second expression is 1100 * not evaluated if the first expression is true. 1101 */ 1102int 1103f_or(plan, entry) --- 38 unchanged lines hidden --- |