|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.