home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / filutl / pdtar.arc / TAR.C < prev    next >
C/C++ Source or Header  |  1988-05-15  |  20KB  |  807 lines

  1. /*
  2.  * A public domain tar(1) program.
  3.  * 
  4.  * Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
  5.  * MS-DOS port 2/87 by Eric Roskos.
  6.  * Minix  port 3/88 by Eric Roskos.
  7.  *
  8.  * @(#)tar.c 1.21 10/29/86 Public Domain - gnu
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <sys/types.h>            /* Needed for typedefs in tar.h */
  13.  
  14. #ifdef MSDOS
  15. #include <conio.h>
  16. #include <fcntl.h>
  17. #endif
  18. #ifdef V7
  19. FILE *fopen();
  20. char *fgets();
  21. #endif
  22.  
  23. extern char    *malloc();
  24. extern char    *
  25. strncpy(), *index(), *rindex();
  26. extern char    *optarg;            /* Pointer to argument */
  27. extern int      optind;            /* Global argv index from getopt */
  28.  
  29. /*
  30.  * The following causes "tar.h" to produce definitions of all the
  31.  * global variables, rather than just "extern" declarations of them.
  32.  */
  33. #define TAR_EXTERN                /**/
  34. #include "tar.h"
  35.  
  36. /*
  37.  * We should use a conversion routine that does reasonable error
  38.  * checking -- atoi doesn't.  For now, punt.  FIXME.
  39.  */
  40. #define intconv    atoi
  41. extern int      getoldopt();
  42. extern void     read_and();
  43. extern void     list_archive();
  44. extern void     extract_archive();
  45. extern void     create_archive();
  46.  
  47. static FILE    *namef;            /* File to read names from */
  48. static char   **n_argv;            /* Argv used by name routines */
  49. static int      n_argc;            /* Argc used by name routines */
  50.  
  51.  /* They also use "optind" from getopt(). */
  52.  
  53. static char    *sccsid =
  54. "@(#)tar.c 1.21 10/29/86 Public Domain - gnu - Minix port 3/05/88 Eric Roskos (csed-1!roskos)";
  55.  
  56. #ifdef MSDOS
  57. /*
  58.  * see convmode, below.  This list is the list of files that should be
  59.  * opened with mode O_BINARY to prevent CR/LF conversions while they
  60.  * are being read in.  FIXME: it is my intent to eventually add an
  61.  * option to the command line that lets you add arbitrarily many new
  62.  * extensions to this list, so people won't have problems with the
  63.  * list being inadequate for them.  I wish there was an easier way, but
  64.  * this one is fairly consistent if you think about it.
  65.  */
  66. #define NBINEXTS    20
  67.  
  68. static char    *binexts[NBINEXTS] =        /* extensions for O_BINARY files */
  69. {
  70.     "com",
  71.     "exe",
  72.     "obj",
  73.     0                            /* required */
  74. };
  75.  
  76. #endif
  77.  
  78. void            describe();
  79.  
  80.  
  81. /*
  82.  * Main routine for tar.
  83.  */
  84. main(argc, argv)
  85. int             argc;
  86. char          **argv;
  87. {
  88.  
  89.     /*
  90.      * Uncomment this message in particularly buggy versions...
  91.      * fprintf(stderr, "tar: You are running an experimental PD tar, maybe
  92.      * use /bin/tar.\n"); 
  93.      */
  94.  
  95.     tar = "tar";                /* Set program name */
  96. #ifdef MSDOS
  97.     physdrv = 0;                /* set default drive */
  98.     devsize = 720;                /* default drive size */
  99.     ftty = open("CON", O_RDWR);        /* open console */
  100. #else /* !MSDOS */
  101.     ftty = open("/dev/tty", 2);
  102. #endif /* !MSDOS */
  103.     if (ftty < 0)
  104.     {
  105.         fprintf(stderr, "Can't open %s for I/O\n",
  106. #ifdef MSDOS
  107.         "console"
  108. #else
  109.         "/dev/tty"
  110. #endif
  111.             );
  112.         exit(EX_SYSTEM);
  113.     }
  114.  
  115.     options(argc, argv);
  116.  
  117.     name_init(argc, argv);
  118.  
  119. #ifdef MSDOS
  120.     if (f_phys)
  121.     {
  122.         uprintf(ftty,"tar: archive on %dK drive %c\n",
  123.             devsize/2, 'A' +  physdrv);
  124.         uprintf(ftty,"tar: insert %s disk in drive '%c' and press [Enter]: ",
  125.             f_create? "formatted" : "first",
  126.             'A' + physdrv);
  127.         while (ugetc(ftty)!='\n') ;
  128.     }
  129. #endif
  130.  
  131.     if (f_create)
  132.     {
  133.         if (f_extract || f_list)
  134.             goto dupflags;
  135.         create_archive();
  136.     }
  137.     else
  138.     if (f_extract)
  139.     {
  140.         if (f_list)
  141.             goto dupflags;
  142.         read_and(extract_archive);
  143.     }
  144.     else
  145.     if (f_list)
  146.     {
  147.         read_and(list_archive);
  148.     }
  149.     else
  150.     {
  151. dupflags:
  152.         fprintf(stderr,
  153.             "tar: you must specify exactly one of the c, t, or x options\n");
  154.         describe();
  155.         exit(EX_ARGSBAD);
  156.     }
  157.     putchar('\n');
  158.     fflush(stdout);
  159. #ifndef MSDOS
  160.     sync(); /* insure all floppy buffers are written out */
  161. #endif
  162.     exit(0);
  163. }
  164.  
  165.  
  166. /*
  167.  * Parse the options for tar.
  168.  */
  169. int
  170. options(argc, argv)
  171. int             argc;
  172. char          **argv;
  173. {
  174.     register int    c;            /* Option letter */
  175.     void            addbinext();
  176.  
  177.     /* Set default option values */
  178.     blocking = DEFBLOCKING;        /* From Makefile */
  179.     ar_file = DEF_AR_FILE;        /* From Makefile */
  180.  
  181.     /* Parse options */
  182.     while ((c = getoldopt(argc, argv, "b:BcdDf:hikmopsS:tT:u:vV:xzZ")
  183.         ) != EOF)
  184.     {
  185.         switch (c)
  186.         {
  187.  
  188.         case 'b':
  189.             blocking = intconv(optarg);
  190.             break;
  191.  
  192.         case 'B':
  193.             f_reblock++;        /* For reading 4.2BSD pipes */
  194.             break;
  195.  
  196.         case 'c':
  197.             f_create++;
  198.             break;
  199.  
  200.         case 'd':
  201.             f_debug++;            /* Debugging code */
  202.             break;                /* Yes, even with dbx */
  203.  
  204.         case 'D':
  205.             f_sayblock++;        /* Print block #s for debug */
  206.             break;                /* of bad tar archives */
  207.  
  208.         case 'f':
  209.             ar_file = optarg;
  210.             break;
  211.  
  212.         case 'h':
  213.             f_follow_links++;    /* follow symbolic links */
  214.             break;
  215.  
  216.         case 'i':
  217.             f_ignorez++;        /* Ignore zero records (eofs) */
  218.  
  219.             /*
  220.              * This can't be the default, because Unix tar writes two records
  221.              * of zeros, then pads out the block with garbage. 
  222.              */
  223.             break;
  224.  
  225.         case 'k':                /* Don't overwrite files */
  226.             f_keep++;
  227.             break;
  228.  
  229.         case 'm':
  230.             f_modified++;
  231.             break;
  232.  
  233.         case 'o':                /* Generate old archive */
  234.             f_oldarch++;
  235.             break;
  236.  
  237.         case 'p':
  238.             f_use_protection++;
  239.             (void) umask(0);    /* Turn off kernel "help" */
  240.             break;
  241.  
  242.         case 's':
  243.             f_sorted_names++;    /* Names to extr are sorted */
  244.             break;
  245. #ifdef MSDOS
  246.         case 'S':
  247.             devsize = atoi(optarg); /* size of DOS disk drive */
  248.             devsize <<= 1;        /* convert K to blocks */
  249.             break;
  250. #endif
  251.         case 't':
  252.             f_list++;
  253.             break;
  254.  
  255.         case 'T':
  256.             name_file = optarg;
  257.             f_namefile++;
  258.             break;
  259. #ifdef MSDOS
  260.         case 'u':
  261.             addbinext(optarg);
  262.             break;
  263. #endif
  264.         case 'v':
  265.             f_verbose++;
  266.             break;
  267. #ifdef MSDOS
  268.         case 'V':
  269.             f_phys++;
  270.             physdrv = toupper(*optarg) - 'A';
  271.             if (physdrv > 4 || physdrv < 0)
  272.             {
  273.                 fprintf(stderr, "tar: drive letter for -V must be A-D\n");
  274.                 exit(EX_ARGSBAD);
  275.             }
  276.             break;                
  277. #endif /* MSDOS */
  278.  
  279.         case 'x':
  280.             f_extract++;
  281.             break;
  282.  
  283.         case 'z':                /* Easy to type */
  284.         case 'Z':                /* Like the filename extension .Z */
  285. #ifndef MSDOS
  286.             f_compress++;
  287. #else
  288.             fprintf(stderr, "Running compress as a subprocess is not supported under DOS.\n");
  289.             fprintf(stderr, "Run compress separately instead, for same effect.\n");
  290. #endif
  291.             break;
  292.  
  293.         default:
  294.         case '?':
  295.             describe();
  296.             exit(EX_ARGSBAD);
  297.  
  298.         }
  299.     }
  300.  
  301.     blocksize = blocking * RECORDSIZE;
  302. }
  303.  
  304.  
  305. /* FIXME, describe tar options here */
  306. void
  307. describe()
  308. {
  309.  
  310.     fputs("tar: valid options:\n\
  311. -b N    blocking factor N (block size = Nx512 bytes)\n\
  312. -B    reblock as we read (for reading 4.2BSD pipes)\n\
  313. -c    create an archive\n\
  314. -D    dump record number within archive with each message\n\
  315. -f F    read/write archive from file or device F\n", stderr);
  316.     fputs("-h    don't dump symbolic links; dump the files they point to\n\
  317. -i    ignore blocks of zeros in the archive, which normally mean EOF\n\
  318. -k    keep existing files, don't overwrite them from the archive\n\
  319. -m    don't extract file modified time\n\
  320. -o    write an old V7 format archive, rather than ANSI [draft 6] format\n\
  321. -p    do extract all protection information\n", stderr);
  322. #ifdef MSDOS
  323.     fputs("-S X    device for -V option is X Kbyte drive\n", stderr);
  324. #endif
  325.     fputs("-s    list of names to extract is sorted to match the archive\n\
  326. -t    list a table of contents of an archive\n\
  327. -T F    get names to extract or create from file F\n", stderr);
  328. #ifdef MSDOS
  329.     fputs("\
  330. -u X    add X to list of file extensions to be opened in BINARY mode\n\
  331.     (use '.' to denote 'files with no extension')\n\
  332. -V X    use drive X (X=A..D) in multivolume mode; ignore -f if present\n",
  333.         stderr);
  334. #endif
  335.     fputs("\
  336. -v    verbosely list what files we process\n\
  337. -x    extract files from an archive\n", stderr);
  338. #ifndef MSDOS
  339.  
  340.     /*
  341.      * regrettably, DOS doesn't have real pipes, just artificial shell-level
  342.      * ones.  It is better to just use those. 
  343.      */
  344.     fputs("\
  345. -z or Z    run the archive through compress(1)\n", stderr);
  346. #endif
  347. }
  348.  
  349.  
  350. /*
  351.  * Set up to gather file names for tar.
  352.  *
  353.  * They can either come from stdin or from argv.
  354.  */
  355. name_init(argc, argv)
  356. int             argc;
  357. char          **argv;
  358. {
  359.  
  360.     if (f_namefile)
  361.     {
  362.         if (optind < argc)
  363.         {
  364.             fprintf(stderr, "tar: too many args with -T option\n");
  365.             exit(EX_ARGSBAD);
  366.         }
  367.         if (!strcmp(name_file, "-"))
  368.         {
  369.             namef = stdin;
  370.         }
  371.         else
  372.         {
  373.             namef = fopen(name_file, "r");
  374.             if (namef == NULL)
  375.             {
  376.                 fprintf(stderr, "tar: ");
  377.                 perror(name_file);
  378.                 exit(EX_BADFILE);
  379.             }
  380.         }
  381.     }
  382.     else
  383.     {
  384.         /* Get file names from argv, after options. */
  385.         n_argc = argc;
  386.         n_argv = argv;
  387.     }
  388. }
  389.  
  390. /*
  391.  * Name translation function for MS-DOS support; can also be
  392.  * extended via #ifdef for other os's.
  393.  *
  394.  * Convert a name to one suitable to this OS.  If this can't be done
  395.  * automatically, let the user choose a name.
  396.  *
  397.  * The user prompting is done only if stdin isatty.
  398.  *
  399.  * It is important to understand the name translation, which occurs
  400.  * in two steps.  First, the actual name string passed in s is modified
  401.  * in place to change case and direction of slashes, because DOS's
  402.  * directory routines return uppercase names with backslashes, which
  403.  * are not suitable for Unix.  This changes the string into a unix-like
  404.  * filename.  Second, this string is copied into a local buffer and
  405.  * transformed, if necessary, into a filename that is syntactically
  406.  * acceptable to DOS.  The routine returns a pointer to this string.
  407.  * The former step fixes names that come from DOS to be Unix-compatible;
  408.  * it will never change Unix filenames, except to make uppercase letters
  409.  * lowercase, because they are already Unix-compatible.  The latter step
  410.  * fixes names that come from Unix to be DOS-compatible; it will never
  411.  * change DOS filenames, because they are already DOS-compatible.
  412.  *
  413.  * The translation of uppercase letters to lowercase ones in unix filenames
  414.  * that appeared in a tar file is a side-effect of the dual purpose of
  415.  * fixname; its only effect is that listings of filenames in a tar file
  416.  * will always be lowercase.  An improvement might be to separate fixname
  417.  * into one routine to fix DOS names, and another to fix Unix names,
  418.  * but this is left for a future enhancement.
  419.  *
  420.  * Even in non-DOS environments, fixname() must at least return a pointer
  421.  * to a *copy* of the original filename, even if it is an unmodified
  422.  * copy.  This is because this name string is used by tar at times after
  423.  * the string which was pointed to by 's' has been overwritten by other
  424.  * data.  The present code does this properly.
  425.  *
  426.  * FIXME: This code is embarassingly complex and needs to be rewritten.
  427.  */
  428.  
  429. char           *
  430. fixname(s)
  431. char           *s;
  432. {
  433.     register char  *p, *q;
  434.     char           *prd;
  435.     char           *t;
  436.         char           *lsl;    
  437.     char            rpy[3];
  438.     static char     buf[256];    /* where the copy of the name is stored */
  439.  
  440. #ifdef MSDOS
  441.  
  442.     /*
  443.      * CODE TO FIX DOS NAMES: DOS's filenames are always uppercase, though
  444.      * DOS maps lowercase characters to uppercase in filenames automatically. 
  445.      * If we create the archive with these uppercase names, the files if
  446.      * un-tarred under Unix all have uppercase names. So we map the names to
  447.      * lowercase under DOS so that it works best for both.  The same for \ vs
  448.      * /: DOS takes either, Unix needs /, so we use /. This first
  449.      * transformation occurs on the actual string we were passed, rather than
  450.      * a copy of it. 
  451.      */
  452.     q = s;
  453.     strlwr(q);
  454.     for (; *q; q++)
  455.         if (*q == '\\')
  456.             *q = '/';
  457.  
  458.     /*
  459.      * CODE TO FIX UNIX NAMES: if more than one '.' in name, DOS won't create
  460.      * file.  Delete all but last '.', then see if name longer than DOS
  461.      * allows.  If so, prompt user for new name.  (It might be better to
  462.      * always do the length check, but in this case it is more likely to be a
  463.      * problem since names with multiple dots often have fellow files with
  464.      * common left substrings which the part after the dot qualifies.) 
  465.      */
  466.     t = rindex(s, '/');
  467.     if (t == NULL)
  468.         t = s;
  469.  
  470.     if (index(t, '.') != (prd = rindex(t, '.')))        /* see if name needs
  471.                                                          * xlation */
  472.     {
  473.         for (q = s, p = buf; *q; q++)
  474.         {
  475.             if (q >= t && *q == '.' && q < prd)
  476.                 continue;        /* del all but last dot */
  477.             *p++ = *q;
  478.         }
  479.         *p = '\0';
  480.  
  481.         /*
  482.          * prompt user for valid name, & check file existence, only if doing
  483.          * an "extract" operation with stdin not redirected. 
  484.          */
  485.         if (f_extract)
  486.         {
  487.             lsl = rindex(buf, '/');
  488.             if (!lsl)
  489.                 lsl = rindex(buf, '\\');
  490.             if (!lsl)
  491.                 lsl = buf;
  492.             if ((q = index(lsl, '.')) - lsl > 8 || &lsl[strlen(lsl)] - q > 4)
  493.             {
  494.                 uprintf(ftty, "tar: %s: Not a valid DOS filename.\n", buf);
  495.         getnewname:
  496.                 uprintf(ftty, "Enter new name: ");
  497.                 ugets(buf, sizeof(buf), ftty);
  498.                 *index(buf, '\n') = '\0';
  499.             }
  500.             if (!access(buf, 0))
  501.             {
  502.         askowrite:
  503.                 uprintf(ftty, "tar: Renamed file '%s' exists. Overwrite (y,n)? ",
  504.                     buf);
  505.                 ugets(rpy, sizeof(rpy), ftty);
  506.                 if (*rpy == 'n' || *rpy == 'N')
  507.                     goto getnewname;
  508.                 if (*rpy != 'y' && *rpy != 'Y')
  509.                     goto askowrite;
  510.             }
  511.         }
  512.     }
  513.     else                        /* the name was not modified, so return copy
  514.                                  * of unchanged name */
  515. #endif
  516.  
  517.         /*
  518.          * ALWAYS return pointer to our local copy of the name, even if it
  519.          * isn't modified.  We can't just say "return(s)" because the
  520.          * location of the name s points to changes in memory during the
  521.          * extract() function. 
  522.          */
  523.     {
  524.         strcpy(buf, s);
  525.     }
  526.  
  527.     return (buf);
  528. }
  529.  
  530. /*
  531.  * convmode(s) - return conversion mode bits for file with name s.
  532.  *
  533.  * This routine assumes filenames have the file type encoded in them
  534.  * in a standard way (e.g., MS/DOS extensions).  It examines the
  535.  * name of the file, and returns any mode bits that need to be or'ed
  536.  * into the mode bits for the open (O_RDWR, etc. bits) for that particular
  537.  * file to be read such that it looks like a normal Unix file.
  538.  *
  539.  * Obviously, your OS has to meet all the above implied constraints, but at
  540.  * least this is a head start, I hope...
  541.  */
  542.  
  543. int
  544. convmode(s)
  545. char           *s;
  546. {
  547.     char          **p;
  548.  
  549. #ifdef MSDOS
  550.     while (*s)
  551.     {
  552.         if (*s == '.')
  553.             break;
  554.         s++;
  555.     }
  556.  
  557.     if (*s == '\0')
  558.         s = " .";    /* special string for "no extension" */
  559.                 /* it has space in front because of  */
  560.     s++;            /* <- that increment */
  561.  
  562.     for (p = binexts; *p; p++)
  563.     {
  564.         if (strcmp(s, *p) == 0)
  565.         {
  566.             return (O_BINARY);
  567.         }
  568.     }
  569.  
  570.     return (O_TEXT);
  571. #else
  572.     /* for a Unix-like OS, always return 0 */
  573.     return (0);
  574. #endif
  575. }
  576.  
  577. #ifdef MSDOS
  578. /*
  579.  * add an extension to the "binexts" list of file extensions that
  580.  * won't get O_BINARY translation (see convmode(), above)
  581.  */
  582.  
  583. void
  584. addbinext(s)
  585. char           *s;
  586. {
  587.     register char **exts;
  588.     int             n;
  589.  
  590.     for (exts = binexts, n = 0; *exts; exts++, n++);    /* find end */
  591.  
  592.     if (n >= NBINEXTS - 1)
  593.     {
  594.         annofile(stderr, tar);
  595.         fprintf(stderr, "%s: too many extensions added (max=%d)\n",
  596.             s, NBINEXTS - 1);
  597.         exit(EX_ARGSBAD);
  598.     }
  599.  
  600.     /* optional "." on front unless string is just "." */
  601.     if (s[0] == '.' && s[1] != '\0')
  602.         s++;
  603.  
  604.     *exts++ = s;
  605.     *exts = 0;
  606. }
  607.  
  608. #endif
  609.  
  610. /*
  611.  * Get the next name from argv or the name file.
  612.  *
  613.  * Result is in static storage and can't be relied upon across two calls.
  614.  */
  615. char           *
  616. name_next()
  617. {
  618.     static char     buffer[NAMSIZ + 2];    /* Holding pattern */
  619.     register char  *p;
  620.     register char  *q;
  621.  
  622.     if (namef == NULL)
  623.     {
  624.         /* Names come from argv, after options */
  625.         if (optind < n_argc)
  626.         {
  627.             return fixname(n_argv[optind++]);
  628.         }
  629.         return (char *) NULL;
  630.     }
  631.     p = fgets(buffer, NAMSIZ + 1 /* nl */ , namef);
  632.     if (p == NULL)
  633.         return p;                /* End of file */
  634.     q = p + strlen(p) - 1;        /* Find the newline */
  635.     *q-- = '\0';                /* Zap the newline */
  636.     while (*q == '/')
  637.         *q-- = '\0';            /* Zap trailing slashes too */
  638.     return fixname(p);
  639. }
  640.  
  641.  
  642. /*
  643.  * Close the name file, if any.
  644.  */
  645. name_close()
  646. {
  647.  
  648.     if (namef != NULL && namef != stdin)
  649.         fclose(namef);
  650. }
  651.  
  652.  
  653. /*
  654.  * Gather names in a list for scanning.
  655.  * Could hash them later if we really care.
  656.  *
  657.  * If the names are already sorted to match the archive, we just
  658.  * read them one by one.  name_gather reads the first one, and it
  659.  * is called by name_match as appropriate to read the next ones.
  660.  * At EOF, the last name read is just left in the buffer.
  661.  * This option lets users of small machines extract an arbitrary
  662.  * number of files by doing "tar t" and editing down the list of files.
  663.  */
  664. name_gather()
  665. {
  666.     register char  *p;
  667.     static struct name namebuff[1];        /* One-name buffer */
  668.     struct name *namebuf = namebuff;
  669.  
  670.     if (f_sorted_names)
  671.     {
  672.         p = name_next();
  673.         if (p)
  674.         {
  675.             namebuf->length = strlen(p);
  676.             if (namebuf->length >= sizeof namebuf->name)
  677.             {
  678.                 fprintf(stderr, "Argument name too long: %s\n",
  679.                     p);
  680.                 namebuf->length = (sizeof namebuf->name) - 1;
  681.             }
  682.             strncpy(namebuf->name, p, namebuf->length);
  683.             namebuf->next = (struct name *) NULL;
  684.             namebuf->found = 0;
  685.             namelist = namebuf;
  686.             namelast = namelist;
  687.         }
  688.         return;
  689.     }
  690.  
  691.     /* Non sorted names -- read them all in */
  692.     while (NULL != (p = name_next()))
  693.     {
  694.         addname(p);
  695.     }
  696. }
  697.  
  698. /*
  699.  * A name from the namelist has been found.
  700.  * If it's just a list, 
  701.   
  702. /*
  703.  * Add a name to the namelist.
  704.  */
  705. addname(name)
  706. char           *name;            /* pointer to name */
  707. {
  708.     register int    i;            /* Length of string */
  709.     register struct name *p;    /* Current struct pointer */
  710.  
  711.     i = strlen(name);
  712.     /* NOSTRICT */
  713.     p = (struct name *)
  714.         malloc((unsigned) (i + sizeof(struct name) - NAMSIZ));
  715.     p->next = (struct name *) NULL;
  716.     p->length = i;
  717.     p->found = 0;
  718.     strncpy(p->name, name, i);
  719.     p->name[i] = '\0';            /* Null term */
  720.     if (namelast)
  721.         namelast->next = p;
  722.     namelast = p;
  723.     if (!namelist)
  724.         namelist = p;
  725. }
  726.  
  727.  
  728. /*
  729.  * Match a name from an archive, p, with a name from the namelist.
  730.  *
  731.  * FIXME: Allow regular expressions in the name list.
  732.  */
  733. name_match(p)
  734. register char  *p;
  735. {
  736.     register struct name *nlp;
  737.     register int    len;
  738.  
  739. again:
  740.     if (0 == (nlp = namelist))    /* Empty namelist is easy */
  741.         return 1;
  742.     len = strlen(p);
  743.     for (; nlp != 0; nlp = nlp->next)
  744.     {
  745.         if (nlp->name[0] == p[0]/* First chars match */
  746.             && nlp->length <= len        /* Archive len >= specified */
  747.             && (p[nlp->length] == '\0' || p[nlp->length] == '/')
  748.         /* Full match on file/dirname */
  749.             && strncmp(p, nlp->name, nlp->length) == 0)    /* Name compare */
  750.         {
  751.             nlp->found = 1;        /* Remember it matched */
  752.             return 1;            /* We got a match */
  753.         }
  754.     }
  755.  
  756.     /*
  757.      * Filename from archive not found in namelist. If we have the whole
  758.      * namelist here, just return 0. Otherwise, read the next name in and
  759.      * compare it. If this was the last name, namelist->found will remain on.
  760.      * If not, we loop to compare the newly read name. 
  761.      */
  762.     if (f_sorted_names && namelist->found)
  763.     {
  764.         name_gather();            /* Read one more */
  765.         if (!namelist->found)
  766.             goto again;
  767.     }
  768.     return 0;
  769. }
  770.  
  771.  
  772. /*
  773.  * Print the names of things in the namelist that were not matched.
  774.  */
  775. names_notfound()
  776. {
  777.     register struct name *nlp;
  778.     register char  *p;
  779.  
  780.     for (nlp = namelist; nlp != 0; nlp = nlp->next)
  781.     {
  782.         if (!nlp->found)
  783.         {
  784.             fprintf(stderr, "tar: %s not found in archive\n",
  785.                 nlp->name);
  786.         }
  787.  
  788.         /*
  789.          * We could free() the list, but the process is about to die anyway,
  790.          * so save some CPU time.  Amigas and other similarly broken software
  791.          * will need to waste the time, though. 
  792.          */
  793. #ifndef unix
  794.         if (!f_sorted_names)
  795.             free(nlp);
  796. #endif /* unix */
  797.     }
  798.     namelist = (struct name *) NULL;
  799.     namelast = (struct name *) NULL;
  800.  
  801.     if (f_sorted_names)
  802.     {
  803.         while (0 != (p = name_next()))
  804.             fprintf(stderr, "tar: %s not found in archive\n", p);
  805.     }
  806. }
  807.