Annotation of 43BSDReno/usr.bin/find/function.c, revision 1.1.1.1

1.1       root        1: /*-
                      2:  * Copyright (c) 1990 The Regents of the University of California.
                      3:  * 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 are permitted provided
                      9:  * that: (1) source distributions retain this entire copyright notice and
                     10:  * comment, and (2) distributions including binaries display the following
                     11:  * acknowledgement:  ``This product includes software developed by the
                     12:  * University of California, Berkeley and its contributors'' in the
                     13:  * documentation or other materials provided with the distribution and in
                     14:  * all advertising materials mentioning features or use of this software.
                     15:  * Neither the name of the University nor the names of its contributors may
                     16:  * be used to endorse or promote products derived from this software without
                     17:  * specific prior written permission.
                     18:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     19:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     20:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     21:  */
                     22: 
                     23: #ifndef lint
                     24: static char sccsid[] = "@(#)function.c 5.8 (Berkeley) 6/30/90";
                     25: #endif /* not lint */
                     26: 
                     27: #include <sys/types.h>
                     28: #include <sys/stat.h>
                     29: #include <sys/wait.h>
                     30: #include <sys/mount.h>
                     31: #include <grp.h>
                     32: #include <pwd.h>
                     33: #include <fts.h>
                     34: #include <unistd.h>
                     35: #include <tzfile.h>
                     36: #include <stdio.h>
                     37: #include <string.h>
                     38: #include "find.h"
                     39: 
                     40: #define        FIND_EQUAL      0
                     41: #define        FIND_LESSTHAN   1
                     42: #define        FIND_GREATER    2
                     43: 
                     44: #define        COMPARE(a, b) { \
                     45:        switch(plan->flags) { \
                     46:        case FIND_EQUAL: \
                     47:                return(a == b); \
                     48:        case FIND_LESSTHAN: \
                     49:                return(a < b); \
                     50:        case FIND_GREATER: \
                     51:                return(a > b); \
                     52:        } \
                     53:        return(0); \
                     54: }
                     55: 
                     56: #define NEW(t, f) { \
                     57:        new = (PLAN *)emalloc(sizeof(PLAN)); \
                     58:        new->type = t; \
                     59:        new->eval = f; \
                     60:        new->flags = 0; \
                     61:        new->next = NULL; \
                     62: }
                     63: 
                     64: /*
                     65:  * find_parsenum --
                     66:  *     Parse a string of the form [+-]# and return the value.
                     67:  */
                     68: long
                     69: find_parsenum(plan, option, str, endch)
                     70:        PLAN *plan;
                     71:        char *option, *str, *endch;
                     72: {
                     73:        long value;
                     74:        char *endchar;          /* pointer to character ending conversion */
                     75:     
                     76:        /* determine comparison from leading + or - */
                     77:        switch(*str) {
                     78:        case '+':
                     79:                ++str;
                     80:                plan->flags = FIND_GREATER;
                     81:                break;
                     82:        case '-':
                     83:                ++str;
                     84:                plan->flags = FIND_LESSTHAN;
                     85:                break;
                     86:        default:
                     87:                plan->flags = FIND_EQUAL;
                     88:                break;
                     89:        }
                     90:     
                     91:        /*
                     92:         * convert the string with strtol().  Note, if strtol() returns zero
                     93:         * and endchar points to the beginning of the string we know we have
                     94:         * a syntax error.
                     95:         */
                     96:        value = strtol(str, &endchar, 10);
                     97:        if (!value && endchar == str ||
                     98:            endchar[0] && (!endch || endchar[0] != *endch))
                     99:                bad_arg(option, "illegal numeric value");
                    100:        if (endch)
                    101:                *endch = endchar[0];
                    102:        return(value);
                    103: }
                    104: 
                    105: /*
                    106:  * -atime n functions --
                    107:  *
                    108:  *     True if the difference between the file access time and the
                    109:  *     current time is n 24 hour periods.
                    110:  *
                    111:  */
                    112: f_atime(plan, entry)
                    113:        PLAN *plan;
                    114:        FTSENT *entry;
                    115: {
                    116:        extern time_t now;
                    117: 
                    118:        COMPARE((now - entry->fts_statb.st_atime +
                    119:            SECSPERDAY - 1) / SECSPERDAY, plan->t_data);
                    120: }
                    121:  
                    122: PLAN *
                    123: c_atime(arg)
                    124:        char *arg;
                    125: {
                    126:        PLAN *new;
                    127: 
                    128:        ftsoptions &= ~FTS_NOSTAT;
                    129: 
                    130:        NEW(T_ATIME, f_atime);
                    131:        new->t_data = find_parsenum(new, "-atime", arg, (char *)NULL);
                    132:        return(new);
                    133: }
                    134: /*
                    135:  * -ctime n functions --
                    136:  *
                    137:  *     True if the difference between the last change of file
                    138:  *     status information and the current time is n 24 hour periods.
                    139:  */
                    140: f_ctime(plan, entry)
                    141:        PLAN *plan;
                    142:        FTSENT *entry;
                    143: {
                    144:        extern time_t now;
                    145: 
                    146:        COMPARE((now - entry->fts_statb.st_ctime +
                    147:            SECSPERDAY - 1) / SECSPERDAY, plan->t_data);
                    148: }
                    149:  
                    150: PLAN *
                    151: c_ctime(arg)
                    152:        char *arg;
                    153: {
                    154:        PLAN *new;
                    155: 
                    156:        ftsoptions &= ~FTS_NOSTAT;
                    157: 
                    158:        NEW(T_CTIME, f_ctime);
                    159:        new->t_data = find_parsenum(new, "-ctime", arg, (char *)NULL);
                    160:        return(new);
                    161: }
                    162: 
                    163: /*
                    164:  * -depth functions --
                    165:  *
                    166:  *     Always true, causes descent of the directory hierarchy to be done
                    167:  *     so that all entries in a directory are acted on before the directory
                    168:  *     itself.
                    169:  */
                    170: /* ARGSUSED */
                    171: f_always_true(plan, entry)
                    172:        PLAN *plan;
                    173:        FTSENT *entry;
                    174: {
                    175:        return(1);
                    176: }
                    177:  
                    178: PLAN *
                    179: c_depth()
                    180: {
                    181:        extern int depth;
                    182:        PLAN *new;
                    183:     
                    184:        depth = 1;
                    185: 
                    186:        NEW(T_DEPTH, f_always_true);
                    187:        return(new);
                    188: }
                    189:  
                    190: /*
                    191:  * [-exec | -ok] utility [arg ... ] ; functions --
                    192:  *
                    193:  *     True if the executed utility returns a zero value as exit status.
                    194:  *     The end of the primary expression is delimited by a semicolon.  If
                    195:  *     "{}" occurs anywhere, it gets replaced by the current pathname.
                    196:  *     The current directory for the execution of utility is the same as
                    197:  *     the current directory when the find utility was started.
                    198:  *
                    199:  *     The primary -ok is different in that it requests affirmation of the
                    200:  *     user before executing the utility.
                    201:  */
                    202: f_exec(plan, entry)
                    203:        register PLAN *plan;
                    204:        FTSENT *entry;
                    205: {
                    206:        register int cnt;
                    207:        char *find_subst();
                    208:        union wait pstat;
                    209:        pid_t pid, waitpid();
                    210: 
                    211:        for (cnt = 0; plan->e_argv[cnt]; ++cnt)
                    212:                if (plan->e_len[cnt])
                    213:                        find_subst(plan->e_orig[cnt], &plan->e_argv[cnt],
                    214:                            entry->fts_path, plan->e_len[cnt]);
                    215: 
                    216:        if (plan->flags && !find_queryuser(plan->e_argv))
                    217:                return(0);
                    218: 
                    219:        switch(pid = vfork()) {
                    220:        case -1:
                    221:                (void)fprintf(stderr, "find: fork: %s.\n", strerror(errno));
                    222:                exit(1);
                    223:                /* NOTREACHED */
                    224:        case 0:
                    225:                execvp(plan->e_argv[0], plan->e_argv);
                    226:                (void)fprintf(stderr,
                    227:                    "find: %s: %s.\n", plan->e_argv[0], strerror(errno));
                    228:                exit(1);
                    229:                /* NOTREACHED */
                    230:        }
                    231:        pid = waitpid(pid, &pstat, 0);
                    232:        return(pid != -1 && !pstat.w_status);
                    233: }
                    234:  
                    235: /*
                    236:  * c_exec --
                    237:  *     build three parallel arrays, one with pointers to the strings passed
                    238:  *     on the command line, one with (possibly duplicated) pointers to the
                    239:  *     argv array, and one with integer values that are lengths of the
                    240:  *     strings, but also flags meaning that the string has to be massaged.
                    241:  */
                    242: PLAN *
                    243: c_exec(argvp, isok)
                    244:        char ***argvp;
                    245:        int isok;
                    246: {
                    247:        PLAN *new;                      /* node returned */
                    248:        register int cnt;
                    249:        register char **argv, **ap, *p;
                    250: 
                    251:        ftsoptions |= FTS_NOCHDIR;
                    252:        output_specified = 1;
                    253:     
                    254:        NEW(T_EXEC, f_exec);
                    255:        new->flags = isok;
                    256: 
                    257:        for (ap = argv = *argvp;; ++ap) {
                    258:                if (!*ap)
                    259:                        bad_arg(isok ? "-ok" : "-exec", "no terminating \";\"");
                    260:                if (**ap == ';')
                    261:                        break;
                    262:        }
                    263: 
                    264:        cnt = ap - *argvp + 1;
                    265:        new->e_argv = (char **)emalloc((u_int)cnt * sizeof(char *));
                    266:        new->e_orig = (char **)emalloc((u_int)cnt * sizeof(char *));
                    267:        new->e_len = (int *)emalloc((u_int)cnt * sizeof(u_char));
                    268: 
                    269:        for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) {
                    270:                new->e_orig[cnt] = *argv;
                    271:                for (p = *argv; *p; ++p)
                    272:                        if (p[0] == '{' && p[1] == '}') {
                    273:                                new->e_argv[cnt] = emalloc((u_int)1024);
                    274:                                new->e_len[cnt] = 1024;
                    275:                                break;
                    276:                        }
                    277:                if (!*p) {
                    278:                        new->e_argv[cnt] = *argv;
                    279:                        new->e_len[cnt] = 0;
                    280:                }
                    281:        }
                    282:        new->e_argv[cnt] = new->e_orig[cnt] = NULL;
                    283: 
                    284:        *argvp = argv + 1;
                    285:        return(new);
                    286: }
                    287:  
                    288: /*
                    289:  * -follow functions --
                    290:  *
                    291:  *     Always true, causes symbolic links to be followed on a global
                    292:  *     basis.
                    293:  */
                    294: PLAN *
                    295: c_follow()
                    296: {
                    297:        PLAN *new;
                    298:     
                    299:        ftsoptions &= ~FTS_PHYSICAL;
                    300:        ftsoptions |= FTS_LOGICAL;
                    301: 
                    302:        NEW(T_FOLLOW, f_always_true);
                    303:        return(new);
                    304: }
                    305:  
                    306: /*
                    307:  * -fstype functions --
                    308:  *
                    309:  *     True if the file is of a certain type.
                    310:  */
                    311: f_fstype(plan, entry)
                    312:        PLAN *plan;
                    313:        FTSENT *entry;
                    314: {
                    315:        static dev_t curdev;    /* need a guaranteed illegal dev value */
                    316:        static int first = 1;
                    317:        struct statfs sb;
                    318:        static short val;
                    319: 
                    320:        /* only check when we cross mount point */
                    321:        if (first || curdev != entry->fts_statb.st_dev) {
                    322:                curdev = entry->fts_statb.st_dev;
                    323:                if (statfs(entry->fts_accpath, &sb)) {
                    324:                        (void)fprintf(stderr, "find: %s: %s.\n",
                    325:                            entry->fts_accpath, strerror(errno));
                    326:                        exit(1);
                    327:                }
                    328:                first = 0;
                    329:                val = plan->flags == MOUNT_NONE ? sb.f_flags : sb.f_type;
                    330:        }
                    331:        return(plan->flags == MOUNT_NONE ?
                    332:            val & MNT_LOCAL : val == plan->flags);
                    333: }
                    334:  
                    335: PLAN *
                    336: c_fstype(arg)
                    337:        char *arg;
                    338: {
                    339:        register PLAN *new;
                    340:     
                    341:        ftsoptions &= ~FTS_NOSTAT;
                    342:     
                    343:        NEW(T_FSTYPE, f_fstype);
                    344:        switch(*arg) {
                    345:        case 'l':
                    346:                if (!strcmp(arg, "local")) {
                    347:                        new->flags = MOUNT_NONE;
                    348:                        return(new);
                    349:                }
                    350:                break;
                    351:        case 'm':
                    352:                if (!strcmp(arg, "mfs")) {
                    353:                        new->flags = MOUNT_MFS;
                    354:                        return(new);
                    355:                }
                    356:                break;
                    357:        case 'n':
                    358:                if (!strcmp(arg, "nfs")) {
                    359:                        new->flags = MOUNT_NFS;
                    360:                        return(new);
                    361:                }
                    362:                break;
                    363:        case 'p':
                    364:                if (!strcmp(arg, "pc")) {
                    365:                        new->flags = MOUNT_PC;
                    366:                        return(new);
                    367:                }
                    368:                break;
                    369:        case 'u':
                    370:                if (!strcmp(arg, "ufs")) {
                    371:                        new->flags = MOUNT_UFS;
                    372:                        return(new);
                    373:                }
                    374:                break;
                    375:        }
                    376:        (void)fprintf(stderr, "find: unknown file type %s.\n", arg);
                    377:        exit(1);
                    378:        /* NOTREACHED */
                    379: }
                    380:  
                    381: /*
                    382:  * -group gname functions --
                    383:  *
                    384:  *     True if the file belongs to the group gname.  If gname is numeric and
                    385:  *     an equivalent of the getgrnam() function does not return a valid group
                    386:  *     name, gname is taken as a group ID.
                    387:  */
                    388: f_group(plan, entry)
                    389:        PLAN *plan;
                    390:        FTSENT *entry;
                    391: {
                    392:        return(entry->fts_statb.st_gid == plan->g_data);
                    393: }
                    394:  
                    395: PLAN *
                    396: c_group(gname)
                    397:        char *gname;
                    398: {
                    399:        PLAN *new;
                    400:        struct group *g;
                    401:        gid_t gid;
                    402:     
                    403:        ftsoptions &= ~FTS_NOSTAT;
                    404: 
                    405:        g = getgrnam(gname);
                    406:        if (g == NULL) {
                    407:                gid = atoi(gname);
                    408:                if (gid == 0 && gname[0] != '0')
                    409:                        bad_arg("-group", "no such group");
                    410:        } else
                    411:                gid = g->gr_gid;
                    412:     
                    413:        NEW(T_GROUP, f_group);
                    414:        new->g_data = gid;
                    415:        return(new);
                    416: }
                    417: 
                    418: /*
                    419:  * -inum n functions --
                    420:  *
                    421:  *     True if the file has inode # n.
                    422:  */
                    423: f_inum(plan, entry)
                    424:        PLAN *plan;
                    425:        FTSENT *entry;
                    426: {
                    427:        COMPARE(entry->fts_statb.st_ino, plan->i_data);
                    428: }
                    429:  
                    430: PLAN *
                    431: c_inum(arg)
                    432:        char *arg;
                    433: {
                    434:        PLAN *new;
                    435:     
                    436:        ftsoptions &= ~FTS_NOSTAT;
                    437:     
                    438:        NEW(T_INUM, f_inum);
                    439:        new->i_data = find_parsenum(new, "-inum", arg, (char *)NULL);
                    440:        return(new);
                    441: }
                    442:  
                    443: /*
                    444:  * -links n functions --
                    445:  *
                    446:  *     True if the file has n links.
                    447:  */
                    448: f_links(plan, entry)
                    449:        PLAN *plan;
                    450:        FTSENT *entry;
                    451: {
                    452:        COMPARE(entry->fts_statb.st_nlink, plan->l_data);
                    453: }
                    454:  
                    455: PLAN *
                    456: c_links(arg)
                    457:        char *arg;
                    458: {
                    459:        PLAN *new;
                    460:     
                    461:        ftsoptions &= ~FTS_NOSTAT;
                    462:     
                    463:        NEW(T_LINKS, f_links);
                    464:        new->l_data = find_parsenum(new, "-links", arg, (char *)NULL);
                    465:        return(new);
                    466: }
                    467:  
                    468: /*
                    469:  * -ls functions --
                    470:  *
                    471:  *     Always true - prints the current entry to stdout in "ls" format.
                    472:  */
                    473: /* ARGSUSED */
                    474: f_ls(plan, entry)
                    475:        PLAN *plan;
                    476:        FTSENT *entry;
                    477: {
                    478:        printlong(entry->fts_path, entry->fts_accpath, &entry->fts_statb);
                    479:        return(1);
                    480: }
                    481:  
                    482: PLAN *
                    483: c_ls()
                    484: {
                    485:        PLAN *new;
                    486:     
                    487:        ftsoptions &= ~FTS_NOSTAT;
                    488:        output_specified = 1;
                    489:     
                    490:        NEW(T_LS, f_ls);
                    491:        return(new);
                    492: }
                    493: 
                    494: /*
                    495:  * -name functions --
                    496:  *
                    497:  *     True if the basename of the filename being examined
                    498:  *     matches pattern using Pattern Matching Notation S3.14
                    499:  */
                    500: f_name(plan, entry)
                    501:        PLAN *plan;
                    502:        FTSENT *entry;
                    503: {
                    504:        return(fnmatch(plan->c_data, entry->fts_name, FNM_QUOTE));
                    505: }
                    506:  
                    507: PLAN *
                    508: c_name(pattern)
                    509:        char *pattern;
                    510: {
                    511:        PLAN *new;
                    512: 
                    513:        NEW(T_NAME, f_name);
                    514:        new->c_data = pattern;
                    515:        return(new);
                    516: }
                    517:  
                    518: /*
                    519:  * -newer file functions --
                    520:  *
                    521:  *     True if the current file has been modified more recently
                    522:  *     then the modification time of the file named by the pathname
                    523:  *     file.
                    524:  */
                    525: f_newer(plan, entry)
                    526:        PLAN *plan;
                    527:        FTSENT *entry;
                    528: {
                    529:        return(entry->fts_statb.st_mtime > plan->t_data);
                    530: }
                    531:  
                    532: PLAN *
                    533: c_newer(filename)
                    534:        char *filename;
                    535: {
                    536:        PLAN *new;
                    537:        struct stat sb;
                    538:     
                    539:        ftsoptions &= ~FTS_NOSTAT;
                    540: 
                    541:        if (stat(filename, &sb)) {
                    542:                (void)fprintf(stderr, "find: %s: %s.\n",
                    543:                    filename, strerror(errno));
                    544:                exit(1);
                    545:        }
                    546:        NEW(T_NEWER, f_newer);
                    547:        new->t_data = sb.st_mtime;
                    548:        return(new);
                    549: }
                    550:  
                    551: /*
                    552:  * -nogroup functions --
                    553:  *
                    554:  *     True if file belongs to a user ID for which the equivalent
                    555:  *     of the getgrnam() 9.2.1 [POSIX.1] function returns NULL.
                    556:  */
                    557: /* ARGSUSED */
                    558: f_nogroup(plan, entry)
                    559:        PLAN *plan;
                    560:        FTSENT *entry;
                    561: {
                    562:        return(group_from_gid(entry->fts_statb.st_gid, 1));
                    563: }
                    564:  
                    565: PLAN *
                    566: c_nogroup()
                    567: {
                    568:        PLAN *new;
                    569:     
                    570:        ftsoptions &= ~FTS_NOSTAT;
                    571: 
                    572:        NEW(T_NOGROUP, f_nogroup);
                    573:        return(new);
                    574: }
                    575:  
                    576: /*
                    577:  * -nouser functions --
                    578:  *
                    579:  *     True if file belongs to a user ID for which the equivalent
                    580:  *     of the getpwuid() 9.2.2 [POSIX.1] function returns NULL.
                    581:  */
                    582: /* ARGSUSED */
                    583: f_nouser(plan, entry)
                    584:        PLAN *plan;
                    585:        FTSENT *entry;
                    586: {
                    587:        return(user_from_uid(entry->fts_statb.st_uid, 1));
                    588: }
                    589:  
                    590: PLAN *
                    591: c_nouser()
                    592: {
                    593:        PLAN *new;
                    594:     
                    595:        ftsoptions &= ~FTS_NOSTAT;
                    596: 
                    597:        NEW(T_NOUSER, f_nouser);
                    598:        return(new);
                    599: }
                    600:  
                    601: /*
                    602:  * -perm functions --
                    603:  *
                    604:  *     The mode argument is used to represent file mode bits.  If it starts
                    605:  *     with a leading digit, it's treated as an octal mode, otherwise as a
                    606:  *     symbolic mode.
                    607:  */
                    608: f_perm(plan, entry)
                    609:        PLAN *plan;
                    610:        FTSENT *entry;
                    611: {
                    612:        mode_t mode;
                    613: 
                    614:        mode = entry->fts_statb.st_mode &
                    615:            (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO);
                    616:        if (plan->flags)
                    617:                return((plan->m_data | mode) == mode);
                    618:        else
                    619:                return(mode == plan->m_data);
                    620:        /* NOTREACHED */
                    621: }
                    622:  
                    623: PLAN *
                    624: c_perm(perm)
                    625:        char *perm;
                    626: {
                    627:        PLAN *new;
                    628:        mode_t *set, *setmode();
                    629: 
                    630:        ftsoptions &= ~FTS_NOSTAT;
                    631: 
                    632:        NEW(T_PERM, f_perm);
                    633: 
                    634:        if (*perm == '-') {
                    635:                new->flags = 1;
                    636:                ++perm;
                    637:        }
                    638: 
                    639:        if ((set = setmode(perm)) == NULL)
                    640:                bad_arg("-perm", "illegal mode string");
                    641: 
                    642:        new->m_data = getmode(set, 0);
                    643:        return(new);
                    644: }
                    645:  
                    646: /*
                    647:  * -print functions --
                    648:  *
                    649:  *     Always true, causes the current pathame to be written to
                    650:  *     standard output.
                    651:  */
                    652: /* ARGSUSED */
                    653: f_print(plan, entry)
                    654:        PLAN *plan;
                    655:        FTSENT *entry;
                    656: {
                    657:        (void)printf("%s\n", entry->fts_path);
                    658:        return(1);
                    659: }
                    660:  
                    661: PLAN *
                    662: c_print()
                    663: {
                    664:        PLAN *new;
                    665:     
                    666:        output_specified = 1;
                    667: 
                    668:        NEW(T_PRINT, f_print);
                    669:        return(new);
                    670: }
                    671:  
                    672: /*
                    673:  * -prune functions --
                    674:  *
                    675:  *     Prune a portion of the hierarchy.
                    676:  */
                    677: /* ARGSUSED */
                    678: f_prune(plan, entry)
                    679:        PLAN *plan;
                    680:        FTSENT *entry;
                    681: {
                    682:        extern FTS *tree;
                    683: 
                    684:        if (ftsset(tree, entry, FTS_SKIP)) {
                    685:                (void)fprintf(stderr,
                    686:                    "find: %s: %s.\n", entry->fts_path, strerror(errno));
                    687:                exit(1);
                    688:        }
                    689:        return(1);
                    690: }
                    691:  
                    692: PLAN *
                    693: c_prune()
                    694: {
                    695:        PLAN *new;
                    696: 
                    697:        NEW(T_PRUNE, f_prune);
                    698:        return(new);
                    699: }
                    700:  
                    701: /*
                    702:  * -size n[c] functions --
                    703:  *
                    704:  *     True if the file size in bytes, divided by an implementation defined
                    705:  *     value and rounded up to the next integer, is n.  If n is followed by
                    706:  *     a c, the size is in bytes.
                    707:  */
                    708: #define        FIND_SIZE       512
                    709: static int divsize = 1;
                    710: 
                    711: f_size(plan, entry)
                    712:        PLAN *plan;
                    713:        FTSENT *entry;
                    714: {
                    715:        off_t size;
                    716: 
                    717:        size = divsize ? (entry->fts_statb.st_size + FIND_SIZE - 1) /
                    718:            FIND_SIZE : entry->fts_statb.st_size;
                    719:        COMPARE(size, plan->o_data);
                    720: }
                    721:  
                    722: PLAN *
                    723: c_size(arg)
                    724:        char *arg;
                    725: {
                    726:        PLAN *new;
                    727:        char endch;
                    728:     
                    729:        ftsoptions &= ~FTS_NOSTAT;
                    730: 
                    731:        NEW(T_SIZE, f_size);
                    732:        new->o_data = find_parsenum(new, "-size", arg, &endch);
                    733:        if (endch == 'c')
                    734:                divsize = 0;
                    735:        return(new);
                    736: }
                    737:  
                    738: /*
                    739:  * -type c functions --
                    740:  *
                    741:  *     True if the type of the file is c, where c is b, c, d, p, or f for
                    742:  *     block special file, character special file, directory, FIFO, or
                    743:  *     regular file, respectively.
                    744:  */
                    745: f_type(plan, entry)
                    746:        PLAN *plan;
                    747:        FTSENT *entry;
                    748: {
                    749:        return((entry->fts_statb.st_mode & S_IFMT) == plan->m_data);
                    750: }
                    751:  
                    752: PLAN *
                    753: c_type(typestring)
                    754:        char *typestring;
                    755: {
                    756:        PLAN *new;
                    757:        mode_t  mask;
                    758:     
                    759:        ftsoptions &= ~FTS_NOSTAT;
                    760: 
                    761:        switch (typestring[0]) {
                    762:        case 'b':
                    763:                mask = S_IFBLK;
                    764:                break;
                    765:        case 'c':
                    766:                mask = S_IFCHR;
                    767:                break;
                    768:        case 'd':
                    769:                mask = S_IFDIR;
                    770:                break;
                    771:        case 'f':
                    772:                mask = S_IFREG;
                    773:                break;
                    774:        case 'l':
                    775:                mask = S_IFLNK;
                    776:                break;
                    777:        case 'p':
                    778:                mask = S_IFIFO;
                    779:                break;
                    780:        case 's':
                    781:                mask = S_IFSOCK;
                    782:                break;
                    783:        default:
                    784:                bad_arg("-type", "unknown type");
                    785:        }
                    786:     
                    787:        NEW(T_TYPE, f_type);
                    788:        new->m_data = mask;
                    789:        return(new);
                    790: }
                    791:  
                    792: /*
                    793:  * -user uname functions --
                    794:  *
                    795:  *     True if the file belongs to the user uname.  If uname is numeric and
                    796:  *     an equivalent of the getpwnam() S9.2.2 [POSIX.1] function does not
                    797:  *     return a valid user name, uname is taken as a user ID.
                    798:  */
                    799: f_user(plan, entry)
                    800:        PLAN *plan;
                    801:        FTSENT *entry;
                    802: {
                    803:        return(entry->fts_statb.st_uid == plan->u_data);
                    804: }
                    805:  
                    806: PLAN *
                    807: c_user(username)
                    808:        char *username;
                    809: {
                    810:        PLAN *new;
                    811:        struct passwd *p;
                    812:        uid_t uid;
                    813:     
                    814:        ftsoptions &= ~FTS_NOSTAT;
                    815: 
                    816:        p = getpwnam(username);
                    817:        if (p == NULL) {
                    818:                uid = atoi(username);
                    819:                if (uid == 0 && username[0] != '0')
                    820:                        bad_arg("-user", "no such user");
                    821:        } else
                    822:                uid = p->pw_uid;
                    823: 
                    824:        NEW(T_USER, f_user);
                    825:        new->u_data = uid;
                    826:        return(new);
                    827: }
                    828:  
                    829: /*
                    830:  * -xdev functions --
                    831:  *
                    832:  *     Always true, causes find not to decend past directories that have a
                    833:  *     different device ID (st_dev, see stat() S5.6.2 [POSIX.1])
                    834:  */
                    835: PLAN *
                    836: c_xdev()
                    837: {
                    838:        PLAN *new;
                    839:     
                    840:        ftsoptions &= ~FTS_NOSTAT;
                    841:        ftsoptions |= FTS_XDEV;
                    842: 
                    843:        NEW(T_XDEV, f_always_true);
                    844:        return(new);
                    845: }
                    846: 
                    847: /*
                    848:  * ( expression ) functions --
                    849:  *
                    850:  *     True if expression is true.
                    851:  */
                    852: f_expr(plan, entry)
                    853:        PLAN *plan;
                    854:        FTSENT *entry;
                    855: {
                    856:        register PLAN *p;
                    857:        register int state;
                    858: 
                    859:        for (p = plan->p_data[0];
                    860:            p && (state = (p->eval)(p, entry)); p = p->next);
                    861:        return(state);
                    862: }
                    863:  
                    864: /*
                    865:  * T_OPENPAREN and T_CLOSEPAREN nodes are temporary place markers.  They are
                    866:  * eliminated during phase 2 of find_formplan() --- the '(' node is converted
                    867:  * to a T_EXPR node containing the expression and the ')' node is discarded.
                    868:  */
                    869: PLAN *
                    870: c_openparen()
                    871: {
                    872:        PLAN *new;
                    873: 
                    874:        NEW(T_OPENPAREN, (int (*)())-1);
                    875:        return(new);
                    876: }
                    877:  
                    878: PLAN *
                    879: c_closeparen()
                    880: {
                    881:        PLAN *new;
                    882: 
                    883:        NEW(T_CLOSEPAREN, (int (*)())-1);
                    884:        return(new);
                    885: }
                    886:  
                    887: /*
                    888:  * -mtime n functions --
                    889:  *
                    890:  *     True if the difference between the file modification time and the
                    891:  *     current time is n 24 hour periods.
                    892:  */
                    893: f_mtime(plan, entry)
                    894:        PLAN *plan;
                    895:        FTSENT *entry;
                    896: {
                    897:        extern time_t now;
                    898: 
                    899:        COMPARE((now - entry->fts_statb.st_mtime + SECSPERDAY - 1) /
                    900:            SECSPERDAY, plan->t_data);
                    901: }
                    902:  
                    903: PLAN *
                    904: c_mtime(arg)
                    905:        char *arg;
                    906: {
                    907:        PLAN *new;
                    908: 
                    909:        ftsoptions &= ~FTS_NOSTAT;
                    910: 
                    911:        NEW(T_MTIME, f_mtime);
                    912:        new->t_data = find_parsenum(new, "-mtime", arg, (char *)NULL);
                    913:        return(new);
                    914: }
                    915: 
                    916: /*
                    917:  * ! expression functions --
                    918:  *
                    919:  *     Negation of a primary; the unary NOT operator.
                    920:  */
                    921: f_not(plan, entry)
                    922:        PLAN *plan;
                    923:        FTSENT *entry;
                    924: {
                    925:        register PLAN *p;
                    926:        register int state;
                    927: 
                    928:        for (p = plan->p_data[0];
                    929:            p && (state = (p->eval)(p, entry)); p = p->next);
                    930:        return(!state);
                    931: }
                    932:  
                    933: PLAN *
                    934: c_not()
                    935: {
                    936:        PLAN *new;
                    937: 
                    938:        NEW(T_NOT, f_not);
                    939:        return(new);
                    940: }
                    941:  
                    942: /*
                    943:  * expression -o expression functions --
                    944:  *
                    945:  *     Alternation of primaries; the OR operator.  The second expression is
                    946:  * not evaluated if the first expression is true.
                    947:  */
                    948: f_or(plan, entry)
                    949:        PLAN *plan;
                    950:        FTSENT *entry;
                    951: {
                    952:        register PLAN *p;
                    953:        register int state;
                    954: 
                    955:        for (p = plan->p_data[0];
                    956:            p && (state = (p->eval)(p, entry)); p = p->next);
                    957: 
                    958:        if (state)
                    959:                return(1);
                    960: 
                    961:        for (p = plan->p_data[1];
                    962:            p && (state = (p->eval)(p, entry)); p = p->next);
                    963:        return(state);
                    964: }
                    965: 
                    966: PLAN *
                    967: c_or()
                    968: {
                    969:        PLAN *new;
                    970: 
                    971:        NEW(T_OR, f_or);
                    972:        return(new);
                    973: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.