Annotation of coherent/e/bin/pax/namelist.c, revision 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.