Annotation of coherent/e/bin/pax/namelist.c, revision 1.1.1.1

1.1       root        1: /* $Source: /src386/usr/bin/pax/namelist.c,v $
                      2:  *
                      3:  * $Revision: 1.1 $
                      4:  *
                      5:  * namelist.c - track filenames given as arguments to tar/cpio/pax
                      6:  *
                      7:  * DESCRIPTION
                      8:  *
                      9:  *     Arguments may be regular expressions, therefore all agurments will
                     10:  *     be treated as if they were regular expressions, even if they are
                     11:  *     not.
                     12:  *
                     13:  * AUTHOR
                     14:  *
                     15:  *     Mark H. Colburn, NAPS International ([email protected])
                     16:  *
                     17:  * Sponsored by The USENIX Association for public distribution. 
                     18:  *
                     19:  * Copyright (c) 1989 Mark H. Colburn.
                     20:  * All rights reserved.
                     21:  *
                     22:  * Redistribution and use in source and binary forms are permitted
                     23:  * provided that the above copyright notice is duplicated in all such 
                     24:  * forms and that any documentation, advertising materials, and other 
                     25:  * materials related to such distribution and use acknowledge that the 
                     26:  * software was developed by Mark H. Colburn and sponsored by The 
                     27:  * USENIX Association. 
                     28:  *
                     29:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     30:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     31:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     32:  *
                     33:  * $Log:       namelist.c,v $
                     34:  * Revision 1.1  92/08/28  08:02:19  bin
                     35:  * Initial revision
                     36:  * 
                     37:  * Revision 1.1  89/02/14  16:48:02  jep
                     38:  * Initial revision
                     39:  * 
                     40:  * Revision 1.1  88/12/23  18:02:17  mark
                     41:  * Initial revision
                     42:  * 
                     43:  */
                     44: 
                     45: #ifndef lint
                     46: static char *ident = "$Id: namelist.c,v 1.1 92/08/28 08:02:19 bin Exp Locker: bin $";
                     47: static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
                     48: #endif /* ! lint */
                     49: 
                     50: 
                     51: /* Headers */
                     52: #include "pax.h"
                     53: 
                     54: 
                     55: /* Type Definitions */
                     56: 
                     57: /*
                     58:  * Structure for keeping track of filenames and lists thereof. 
                     59:  */
                     60: struct nm_list {
                     61:     struct nm_list *next;
                     62:     short           length;    /* cached strlen(name) */
                     63:     char            found;     /* A matching file has been found */
                     64:     char            firstch;   /* First char is literally matched */
                     65:     char            regexp;    /* regexp pattern for item */
                     66:     char            name[1];   /* name of file or rexexp */
                     67: };
                     68: 
                     69: struct dirinfo {
                     70:     char            dirname[PATH_MAX + 1];     /* name of directory */
                     71:     OFFSET         where;      /* current location in directory */
                     72:     struct dirinfo *next;
                     73: };
                     74: 
                     75: 
                     76: /* Static Variables */
                     77: 
                     78: static struct dirinfo *stack_head = (struct dirinfo *)NULL;
                     79: 
                     80: 
                     81: /* Function Prototypes */
                     82: 
                     83: #ifndef __STDC__
                     84: 
                     85: static void pushdir();
                     86: static struct dirinfo *popdir();
                     87: 
                     88: #else
                     89: 
                     90: static void pushdir(struct dirinfo *info);
                     91: static struct dirinfo *popdir(void);
                     92: 
                     93: #endif
                     94: 
                     95: 
                     96: /* Internal Identifiers */
                     97: 
                     98: static struct nm_list *namelast;       /* Points to last name in list */
                     99: static struct nm_list *namelist;       /* Points to first name in list */
                    100: 
                    101: 
                    102: /* addname -  add a name to the namelist. 
                    103:  *
                    104:  * DESCRIPTION
                    105:  *
                    106:  *     Addname adds the name given to the name list.  Memory for the
                    107:  *     namelist structure is dynamically allocated.  If the space for 
                    108:  *     the structure cannot be allocated, then the program will exit
                    109:  *     the an out of memory error message and a non-zero return code
                    110:  *     will be returned to the caller.
                    111:  *
                    112:  * PARAMETERS
                    113:  *
                    114:  *     char *name      - A pointer to the name to add to the list
                    115:  */
                    116: 
                    117: #if __STDC__
                    118: 
                    119: void add_name(char *name)
                    120: 
                    121: #else
                    122:     
                    123: void add_name(name)
                    124: char           *name;          /* pointer to name */
                    125: 
                    126: #endif
                    127: {
                    128:     int             i;         /* Length of string */
                    129:     struct nm_list *p;         /* Current struct pointer */
                    130: 
                    131:     i = strlen(name);
                    132:     p = (struct nm_list *) malloc((unsigned) (i + sizeof(struct nm_list)));
                    133:     if (!p) {
                    134:        fatal("cannot allocate memory for namelist entry\n");
                    135:     }
                    136:     p->next = (struct nm_list *)NULL;
                    137:     p->length = i;
                    138:     strncpy(p->name, name, i);
                    139:     p->name[i] = '\0';         /* Null term */
                    140:     p->found = 0;
                    141:     p->firstch = isalpha(name[0]);
                    142:     if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) {
                    143:         p->regexp = 1;
                    144:     }
                    145:     if (namelast) {
                    146:        namelast->next = p;
                    147:     }
                    148:     namelast = p;
                    149:     if (!namelist) {
                    150:        namelist = p;
                    151:     }
                    152: }
                    153: 
                    154: 
                    155: /* name_match - match a name from an archive with a name from the namelist 
                    156:  *
                    157:  * DESCRIPTION
                    158:  *
                    159:  *     Name_match attempts to find a name pointed at by p in the namelist.
                    160:  *     If no namelist is available, then all filenames passed in are
                    161:  *     assumed to match the filename criteria.  Name_match knows how to
                    162:  *     match names with regular expressions, etc.
                    163:  *
                    164:  * PARAMETERS
                    165:  *
                    166:  *     char    *p      - the name to match
                    167:  *
                    168:  * RETURNS
                    169:  *
                    170:  *     Returns 1 if the name is in the namelist, or no name list is
                    171:  *     available, otherwise returns 0
                    172:  *
                    173:  */
                    174: 
                    175: #if __STDC__
                    176: 
                    177: int name_match(char *p)
                    178: 
                    179: #else
                    180:     
                    181: int name_match(p)
                    182: char           *p;
                    183: 
                    184: #endif
                    185: {
                    186:     struct nm_list *nlp;
                    187:     int             len;
                    188: 
                    189:     if ((nlp = namelist) == 0) {/* Empty namelist is easy */
                    190:        return (1);
                    191:     }
                    192:     len = strlen(p);
                    193:     for (; nlp != 0; nlp = nlp->next) {
                    194:        /* If first chars don't match, quick skip */
                    195:        if (nlp->firstch && nlp->name[0] != p[0]) {
                    196:            continue;
                    197:        }
                    198:        /* Regular expressions */
                    199:        if (nlp->regexp) {
                    200:            if (wildmat(nlp->name, p)) {
                    201:                nlp->found = 1; /* Remember it matched */
                    202:                return (1);     /* We got a match */
                    203:            }
                    204:            continue;
                    205:        }
                    206:        /* Plain Old Strings */
                    207:        if (nlp->length <= len  /* Archive len >= specified */
                    208:            && (p[nlp->length] == '\0' || p[nlp->length] == '/')
                    209:            && strncmp(p, nlp->name, nlp->length) == 0) {
                    210:            /* Name compare */
                    211:            nlp->found = 1;     /* Remember it matched */
                    212:            return (1);         /* We got a match */
                    213:        }
                    214:     }
                    215:     return (0);
                    216: }
                    217: 
                    218: 
                    219: /* names_notfound - print names of files in namelist that were not found 
                    220:  *
                    221:  * DESCRIPTION
                    222:  *
                    223:  *     Names_notfound scans through the namelist for any files which were
                    224:  *     named, but for which a matching file was not processed by the
                    225:  *     archive.  Each of the files is listed on the standard error.
                    226:  *
                    227:  */
                    228: 
                    229: #if __STDC__
                    230: 
                    231: void names_notfound(void)
                    232: 
                    233: #else
                    234:     
                    235: void names_notfound()
                    236: 
                    237: #endif
                    238: {
                    239:     struct nm_list *nlp;
                    240: 
                    241:     for (nlp = namelist; nlp != 0; nlp = nlp->next) {
                    242:        if (!nlp->found) {
                    243:            fprintf(stderr, "%s: %s not found in archive\n",
                    244:                    myname, nlp->name);
                    245:        }
                    246:        free(nlp);
                    247:     }
                    248:     namelist = (struct nm_list *)NULL;
                    249:     namelast = (struct nm_list *)NULL;
                    250: }
                    251: 
                    252: 
                    253: /* name_init - set up to gather file names 
                    254:  *
                    255:  * DESCRIPTION
                    256:  *
                    257:  *     Name_init sets up the namelist pointers so that we may access the
                    258:  *     command line arguments.  At least the first item of the command
                    259:  *     line (argv[0]) is assumed to be stripped off, prior to the
                    260:  *     name_init call.
                    261:  *
                    262:  * PARAMETERS
                    263:  *
                    264:  *     int     argc    - number of items in argc
                    265:  *     char    **argv  - pointer to the command line arguments
                    266:  */
                    267: 
                    268: #if __STDC__
                    269: 
                    270: void name_init(int argc, char **argv)
                    271: 
                    272: #else
                    273:     
                    274: void name_init(argc, argv)
                    275: int             argc;
                    276: char          **argv;
                    277: 
                    278: #endif
                    279: {
                    280:     /* Get file names from argv, after options. */
                    281:     n_argc = argc;
                    282:     n_argv = argv;
                    283: }
                    284: 
                    285: 
                    286: /* name_next - get the next name from argv or the name file. 
                    287:  *
                    288:  * DESCRIPTION
                    289:  *
                    290:  *     Name next finds the next name which is to be processed in the
                    291:  *     archive.  If the named file is a directory, then the directory
                    292:  *     is recursively traversed for additional file names.  Directory
                    293:  *     names and locations within the directory are kept track of by
                    294:  *     using a directory stack.  See the pushdir/popdir function for
                    295:  *     more details.
                    296:  *
                    297:  *     The names come from argv, after options or from the standard input.  
                    298:  *
                    299:  * PARAMETERS
                    300:  *
                    301:  *     name - a pointer to a buffer of at least MAX_PATH + 1 bytes long;
                    302:  *     statbuf - a pointer to a stat structure
                    303:  *
                    304:  * RETURNS
                    305:  *
                    306:  *     Returns -1 if there are no names left, (e.g. EOF), otherwise returns 
                    307:  *     0 
                    308:  */
                    309: 
                    310: #if __STDC__
                    311: 
                    312: int name_next(char *name, Stat *statbuf)
                    313: 
                    314: #else
                    315:     
                    316: int name_next(name, statbuf)
                    317: char           *name;
                    318: Stat           *statbuf;
                    319: 
                    320: #endif
                    321: {
                    322:     int             err = -1;
                    323:     static int      in_subdir = 0;
                    324:     int                        len;
                    325:     struct dirent  *d;
                    326:     static struct dirinfo *curr_dir;
                    327:     static DIR     *dirp;
                    328: 
                    329:     do {
                    330:        if (names_from_stdin) {
                    331:            if (lineget(stdin, name) < 0) {
                    332:                return (-1);
                    333:            }
                    334:            if (nameopt(name) < 0) {
                    335:                continue;
                    336:            }
                    337:        } else {
                    338:            if (in_subdir) {
                    339:                if ((d = readdir(dirp)) != (struct dirent *)NULL) {
                    340:                    /* Skip . and .. */
                    341:                    if (strcmp(d->d_name, ".") == 0 ||
                    342:                        strcmp(d->d_name, "..") == 0) {
                    343:                            continue;
                    344:                    }
                    345:                    if (strlen(d->d_name) + 
                    346:                        strlen(curr_dir->dirname) >= PATH_MAX) {
                    347:                        warn("name too long", d->d_name);
                    348:                        continue;
                    349:                    }
                    350:                    strcpy(name, curr_dir->dirname);
                    351:                    strcat(name, d->d_name);
                    352:                } else {
                    353:                    closedir(dirp);
                    354:                    in_subdir--;
                    355:                    curr_dir = popdir();
                    356:                    if (in_subdir) {
                    357:                        errno = 0;
                    358:                        if ((dirp=opendir(curr_dir->dirname)) == (DIR *)NULL) {
                    359:                            warn(curr_dir->dirname, "error opening directory (1)");
                    360:                            in_subdir--;
                    361:                        }
                    362:                        seekdir(dirp, curr_dir->where);
                    363:                    }
                    364:                    continue;
                    365:                }
                    366:            } else if (optind >= n_argc) {
                    367:                return (-1);
                    368:            } else {
                    369:                strcpy(name, n_argv[optind++]);
                    370:            }
                    371:        }
                    372:        if ((err = LSTAT(name, statbuf)) < 0) {
                    373:            warn(name, strerror());
                    374:            continue;
                    375:        }
                    376:        if (!names_from_stdin && (statbuf->sb_mode & S_IFMT) == S_IFDIR) {
                    377:            if (in_subdir) {
                    378:                curr_dir->where = telldir(dirp);
                    379:                pushdir(curr_dir);
                    380:                closedir(dirp);
                    381:            } 
                    382:            in_subdir++;
                    383: 
                    384:            /* Build new prototype name */
                    385:            if ((curr_dir = (struct dirinfo *) mem_get(sizeof(struct dirinfo))) 
                    386:                          == (struct dirinfo *)NULL) {
                    387:                exit(2);
                    388:            }
                    389:            strcpy(curr_dir->dirname, name);
                    390:            len = strlen(curr_dir->dirname);
                    391:            while (len >= 1 && curr_dir->dirname[len - 1] == '/') {
                    392:                len--;          /* Delete trailing slashes */
                    393:            }
                    394:            curr_dir->dirname[len++] = '/';     /* Now add exactly one back */
                    395:            curr_dir->dirname[len] = '\0';/* Make sure null-terminated */
                    396:             curr_dir->where = 0;
                    397:            
                    398:             errno = 0;
                    399:             do {
                    400:                 if ((dirp = opendir(curr_dir->dirname)) == (DIR *)NULL) {
                    401:                      warn(curr_dir->dirname, "error opening directory (2)");
                    402:                      if (in_subdir > 1) {
                    403:                           curr_dir = popdir();
                    404:                      }
                    405:                      in_subdir--;
                    406:                      err = -1;
                    407:                      continue;
                    408:                 } else {
                    409:                      seekdir(dirp, curr_dir->where);
                    410:                }
                    411:            } while (in_subdir && (! dirp));
                    412:        }
                    413:     } while (err < 0);
                    414:     return (0);
                    415: }
                    416: 
                    417: 
                    418: /* name_gather - gather names in a list for scanning. 
                    419:  *
                    420:  * DESCRIPTION
                    421:  *
                    422:  *     Name_gather takes names from the command line and adds them to
                    423:  *     the name list.
                    424:  *
                    425:  * FIXME
                    426:  *
                    427:  *     We could hash the names if we really care about speed here.
                    428:  */
                    429: 
                    430: #if __STDC__
                    431: 
                    432: void name_gather(void)
                    433: 
                    434: #else
                    435:     
                    436: void name_gather()
                    437: 
                    438: #endif
                    439: {
                    440:      while (optind < n_argc) { 
                    441:         add_name(n_argv[optind++]); 
                    442:      } 
                    443: }
                    444: 
                    445: 
                    446: /* pushdir - pushes a directory name on the directory stack
                    447:  *
                    448:  * DESCRIPTION
                    449:  *
                    450:  *     The pushdir function puses the directory structure which is pointed
                    451:  *     to by "info" onto a stack for later processing.  The information
                    452:  *     may be retrieved later with a call to popdir().
                    453:  *
                    454:  * PARAMETERS
                    455:  *
                    456:  *     dirinfo *info   - pointer to directory structure to save
                    457:  */
                    458: 
                    459: #if __STDC__
                    460: 
                    461: static void pushdir(struct dirinfo *info)
                    462: 
                    463: #else
                    464:     
                    465: static void pushdir(info)
                    466: struct dirinfo *info;
                    467: 
                    468: #endif
                    469: {
                    470:     if  (stack_head == (struct dirinfo *)NULL) {
                    471:        stack_head = info;
                    472:        stack_head->next = (struct dirinfo *)NULL;
                    473:     } else {
                    474:        info->next = stack_head;
                    475:        stack_head = info;
                    476:     } 
                    477: }
                    478: 
                    479: 
                    480: /* popdir - pop a directory structure off the directory stack.
                    481:  *
                    482:  * DESCRIPTION
                    483:  *
                    484:  *     The popdir function pops the most recently pushed directory
                    485:  *     structure off of the directory stack and returns it to the calling
                    486:  *     function.
                    487:  *
                    488:  * RETURNS
                    489:  *
                    490:  *     Returns a pointer to the most recently pushed directory structure
                    491:  *     or NULL if the stack is empty.
                    492:  */
                    493: 
                    494: #if __STDC__
                    495: 
                    496: static struct dirinfo *popdir(void)
                    497: 
                    498: #else
                    499:     
                    500: static struct dirinfo *popdir()
                    501: 
                    502: #endif
                    503: {
                    504:     struct dirinfo     *tmp;
                    505: 
                    506:     if (stack_head == (struct dirinfo *)NULL) {
                    507:        return((struct dirinfo *)NULL);
                    508:     } else {
                    509:        tmp = stack_head;
                    510:        stack_head = stack_head->next;
                    511:     }
                    512:     return(tmp);
                    513: }

unix.superglobalmegacorp.com

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