home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / utils / unix / pdtar / part0~ba < prev    next >
Encoding:
Text File  |  1988-09-11  |  53.0 KB  |  2,309 lines

  1. Subject:  v12i069:  Public-domain TAR, Part02/03
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: John Gilmore <hoptoad!gnu@UUNET.UU.NET>
  7. Posting-number: Volume 12, Issue 69
  8. Archive-name: pdtar/part02
  9.  
  10.  
  11. : To unbundle, sh this file
  12. echo tar.c
  13. cat >tar.c <<'@@@ Fin de tar.c'
  14. /*
  15.  * A public domain tar(1) program.
  16.  * 
  17.  * Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
  18.  *
  19.  * @(#)tar.c 1.34 11/6/87 Public Domain - gnu
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <sys/types.h>        /* Needed for typedefs in tar.h */
  24.  
  25. extern char     *malloc();
  26. extern char     *getenv();
  27. extern char    *strncpy();
  28. extern char    *optarg;    /* Pointer to argument */
  29. extern int    optind;        /* Global argv index from getopt */
  30.  
  31. /*
  32.  * The following causes "tar.h" to produce definitions of all the
  33.  * global variables, rather than just "extern" declarations of them.
  34.  */
  35. #define TAR_EXTERN /**/
  36. #include "tar.h"
  37.  
  38. /*
  39.  * We should use a conversion routine that does reasonable error
  40.  * checking -- atoi doesn't.  For now, punt.  FIXME.
  41.  */
  42. #define intconv    atoi
  43. extern int    getoldopt();
  44. extern void    read_and();
  45. extern void    list_archive();
  46. extern void    extract_archive();
  47. extern void    diff_archive();
  48. extern void    create_archive();
  49.  
  50. static FILE    *namef;        /* File to read names from */
  51. static char    **n_argv;    /* Argv used by name routines */
  52. static int    n_argc;    /* Argc used by name routines */
  53.                 /* They also use "optind" from getopt(). */
  54.  
  55. void    describe();
  56.  
  57.  
  58. /*
  59.  * Main routine for tar.
  60.  */
  61. main(argc, argv)
  62.     int    argc;
  63.     char    **argv;
  64. {
  65.  
  66.     /* Uncomment this message in particularly buggy versions...
  67.     fprintf(stderr,
  68.      "tar: You are running an experimental PD tar, maybe use /bin/tar.\n");
  69.      */
  70.  
  71.     tar = "tar";        /* Set program name */
  72.  
  73.     options(argc, argv);
  74.  
  75.     name_init(argc, argv);
  76.  
  77.     if (f_create) {
  78.         if (f_extract || f_list || f_diff) goto dupflags;
  79.         create_archive();
  80.     } else if (f_extract) {
  81.         if (f_list || f_diff) goto dupflags;
  82.         extr_init();
  83.         read_and(extract_archive);
  84.     } else if (f_list) {
  85.         if (f_diff) goto dupflags;
  86.         read_and(list_archive);
  87.     } else if (f_diff) {
  88.         diff_init();
  89.         read_and(diff_archive);
  90.     } else {
  91. dupflags:
  92.         fprintf (stderr,
  93. "tar: you must specify exactly one of the c, t, x, or d options\n");
  94.         describe();
  95.         exit(EX_ARGSBAD);
  96.     }
  97.     exit(0);
  98.     /* NOTREACHED */
  99. }
  100.  
  101.  
  102. /*
  103.  * Parse the options for tar.
  104.  */
  105. int
  106. options(argc, argv)
  107.     int    argc;
  108.     char    **argv;
  109. {
  110.     register int    c;        /* Option letter */
  111.  
  112.     /* Set default option values */
  113.     blocking = DEFBLOCKING;        /* From Makefile */
  114.     ar_file = getenv("TAPE");    /* From environment, or */
  115.     if (ar_file == 0)
  116.         ar_file = DEF_AR_FILE;    /* From Makefile */
  117.  
  118.     /* Parse options */
  119.     while ((c = getoldopt(argc, argv, "b:BcdDf:hiklmopRstT:vxzZ")
  120.         ) != EOF) {
  121.         switch (c) {
  122.  
  123.         case 'b':
  124.             blocking = intconv(optarg);
  125.             break;
  126.  
  127.         case 'B':
  128.             f_reblock++;        /* For reading 4.2BSD pipes */
  129.             break;
  130.  
  131.         case 'c':
  132.             f_create++;
  133.             break;
  134.  
  135.         case 'd':
  136.             f_diff++;        /* Find difference tape/disk */
  137.             break;
  138.  
  139.         case 'D':
  140.             f_dironly++;        /* Dump dir, not contents */
  141.             break;
  142.  
  143.         case 'f':
  144.             ar_file = optarg;
  145.             break;
  146.  
  147.         case 'h':
  148.             f_follow_links++;    /* follow symbolic links */
  149.             break;
  150.  
  151.         case 'i':
  152.             f_ignorez++;        /* Ignore zero records (eofs) */
  153.             /*
  154.              * This can't be the default, because Unix tar
  155.              * writes two records of zeros, then pads out the
  156.              * block with garbage.
  157.              */
  158.             break;
  159.  
  160.         case 'k':            /* Don't overwrite files */
  161. #ifdef NO_OPEN3
  162.             fprintf(stderr,
  163.                 "tar: can't do -k option on this system\n");
  164.             exit(EX_ARGSBAD);
  165. #else
  166.             f_keep++;
  167. #endif
  168.             break;
  169.  
  170.         case 'l':
  171.             f_local_filesys++;
  172.             break;
  173.  
  174.         case 'm':
  175.             f_modified++;
  176.             break;
  177.  
  178.         case 'o':            /* Generate old archive */
  179.             f_oldarch++;
  180.             break;
  181.  
  182.         case 'p':
  183.             f_use_protection++;
  184.             break;
  185.  
  186.         case 'R':
  187.             f_sayblock++;        /* Print block #s for debug */
  188.             break;            /* of bad tar archives */
  189.  
  190.         case 's':
  191.             f_sorted_names++;    /* Names to extr are sorted */
  192.             break;
  193.  
  194.         case 't':
  195.             f_list++;
  196.             f_verbose++;        /* "t" output == "cv" or "xv" */
  197.             break;
  198.  
  199.         case 'T':
  200.             name_file = optarg;
  201.             f_namefile++;
  202.             break;
  203.  
  204.         case 'v':
  205.             f_verbose++;
  206.             break;
  207.  
  208.         case 'x':
  209.             f_extract++;
  210.             break;
  211.  
  212.         case 'z':        /* Easy to type */
  213.         case 'Z':        /* Like the filename extension .Z */
  214.             f_compress++;
  215.             break;
  216.  
  217.         case '?':
  218.             describe();
  219.             exit(EX_ARGSBAD);
  220.  
  221.         }
  222.     }
  223.  
  224.     blocksize = blocking * RECORDSIZE;
  225. }
  226.  
  227.  
  228. /* 
  229.  * Print as much help as the user's gonna get.
  230.  *
  231.  * We have to sprinkle in the KLUDGE lines because too many compilers
  232.  * cannot handle character strings longer than about 512 bytes.  Yuk!
  233.  * In particular, MSDOS MSC 4.0 (and 5.0) and PDP-11 V7 Unix have this
  234.  * problem.
  235.  */
  236. void
  237. describe()
  238. {
  239.  
  240.     fputs("\
  241. tar: valid options:\n\
  242. -b N    blocking factor N (block size = Nx512 bytes)\n\
  243. -B    reblock as we read (for reading 4.2BSD pipes)\n\
  244. -c    create an archive\n\
  245. -d    find differences between archive and file system\n\
  246. -D    don't dump the contents of directories, just the directory\n\
  247. ", stderr); /* KLUDGE */ fputs("\
  248. -f F    read/write archive from file or device F (or hostname:/ForD)\n\
  249. -h    don't dump symbolic links; dump the files they point to\n\
  250. -i    ignore blocks of zeros in the archive, which normally mean EOF\n\
  251. -k    keep existing files, don't overwrite them from the archive\n\
  252. -l    stay in the local file system (like dump(8)) when creating an archive\n\
  253. ", stderr); /* KLUDGE */ fputs("\
  254. -m    don't extract file modified time\n\
  255. -o    write an old V7 format archive, rather than ANSI [draft 6] format\n\
  256. -p    do extract all protection information\n\
  257. -R    dump record number within archive with each message\n\
  258. -s    list of names to extract is sorted to match the archive\n\
  259. -t    list a table of contents of an archive\n\
  260. ", stderr); /* KLUDGE */ fputs("\
  261. -T F    get names to extract or create from file F\n\
  262. -v    verbosely list what files we process\n\
  263. -x    extract files from an archive\n\
  264. -z or Z    run the archive through compress(1)\n\
  265. ", stderr);
  266. }
  267.  
  268.  
  269. /*
  270.  * Set up to gather file names for tar.
  271.  *
  272.  * They can either come from stdin or from argv.
  273.  */
  274. name_init(argc, argv)
  275.     int    argc;
  276.     char    **argv;
  277. {
  278.  
  279.     if (f_namefile) {
  280.         if (optind < argc) {
  281.             fprintf(stderr, "tar: too many args with -T option\n");
  282.             exit(EX_ARGSBAD);
  283.         }
  284.         if (!strcmp(name_file, "-")) {
  285.             namef = stdin;
  286.         } else {
  287.             namef = fopen(name_file, "r");
  288.             if (namef == NULL) {
  289.                 fprintf(stderr, "tar: ");
  290.                 perror(name_file);
  291.                 exit(EX_BADFILE);
  292.             }
  293.         }
  294.     } else {
  295.         /* Get file names from argv, after options. */
  296.         n_argc = argc;
  297.         n_argv = argv;
  298.     }
  299. }
  300.  
  301. /*
  302.  * Get the next name from argv or the name file.
  303.  *
  304.  * Result is in static storage and can't be relied upon across two calls.
  305.  */
  306. char *
  307. name_next()
  308. {
  309.     static char    buffer[NAMSIZ+2];    /* Holding pattern */
  310.     register char    *p;
  311.     register char    *q;
  312.  
  313.     if (namef == NULL) {
  314.         /* Names come from argv, after options */
  315.         if (optind < n_argc)
  316.             return n_argv[optind++];
  317.         return (char *)NULL;
  318.     }
  319.     for (;;) {
  320.         p = fgets(buffer, NAMSIZ+1 /*nl*/, namef);
  321.         if (p == NULL) return p;    /* End of file */
  322.         q = p+strlen(p)-1;        /* Find the newline */
  323.         if (q <= p) continue;        /* Ignore empty lines */
  324.         *q-- = '\0';            /* Zap the newline */
  325.         while (q > p && *q == '/')  *q-- = '\0'; /* Zap trailing /s */
  326.         return p;
  327.     }
  328.     /* NOTREACHED */
  329. }
  330.  
  331.  
  332. /*
  333.  * Close the name file, if any.
  334.  */
  335. name_close()
  336. {
  337.  
  338.     if (namef != NULL && namef != stdin) fclose(namef);
  339. }
  340.  
  341.  
  342. /*
  343.  * Gather names in a list for scanning.
  344.  * Could hash them later if we really care.
  345.  *
  346.  * If the names are already sorted to match the archive, we just
  347.  * read them one by one.  name_gather reads the first one, and it
  348.  * is called by name_match as appropriate to read the next ones.
  349.  * At EOF, the last name read is just left in the buffer.
  350.  * This option lets users of small machines extract an arbitrary
  351.  * number of files by doing "tar t" and editing down the list of files.
  352.  */
  353. name_gather()
  354. {
  355.     register char *p;
  356.     static struct name namebuf[1];    /* One-name buffer */
  357.  
  358.     if (f_sorted_names) {
  359.         p = name_next();
  360.         if (p) {
  361.             namebuf[0].length = strlen(p);
  362.             if (namebuf[0].length >= sizeof namebuf[0].name) {
  363.                 fprintf(stderr, "Argument name too long: %s\n",
  364.                     p);
  365.                 namebuf[0].length = (sizeof namebuf[0].name) - 1;
  366.             }
  367.             strncpy(namebuf[0].name, p, namebuf[0].length);
  368.             namebuf[0].name[ namebuf[0].length ] = 0;
  369.             namebuf[0].next = (struct name *)NULL;
  370.             namebuf[0].found = 0;
  371.             namelist = namebuf;
  372.             namelast = namelist;
  373.         }
  374.         return;
  375.     }
  376.  
  377.     /* Non sorted names -- read them all in */
  378.     while (NULL != (p = name_next())) {
  379.         addname(p);
  380.     }
  381. }
  382.  
  383. /*
  384.  * Add a name to the namelist.
  385.  */
  386. addname(name)
  387.     char    *name;            /* pointer to name */
  388. {
  389.     register int    i;        /* Length of string */
  390.     register struct name    *p;    /* Current struct pointer */
  391.  
  392.     i = strlen(name);
  393.     /*NOSTRICT*/
  394.     p = (struct name *)
  395.         malloc((unsigned)(i + sizeof(struct name) - NAMSIZ));
  396.     if (!p) {
  397.         fprintf(stderr,"tar: cannot allocate mem for namelist entry\n");
  398.         exit(EX_SYSTEM);
  399.     }
  400.     p->next = (struct name *)NULL;
  401.     p->length = i;
  402.     strncpy(p->name, name, i);
  403.     p->name[i] = '\0';    /* Null term */
  404.     p->found = 0;
  405.     p->regexp = 0;        /* Assume not a regular expression */
  406.     p->firstch = 1;        /* Assume first char is literal */
  407.     if (index(name, '*') || index(name, '[') || index(name, '?')) {
  408.         p->regexp = 1;    /* No, it's a regexp */
  409.         if (name[0] == '*' || name[0] == '[' || name[0] == '?')
  410.             p->firstch = 0;        /* Not even 1st char literal */
  411.     }
  412.  
  413.     if (namelast) namelast->next = p;
  414.     namelast = p;
  415.     if (!namelist) namelist = p;
  416. }
  417.  
  418.  
  419. /*
  420.  * Match a name from an archive, p, with a name from the namelist.
  421.  */
  422. name_match(p)
  423.     register char *p;
  424. {
  425.     register struct name    *nlp;
  426.     register int        len;
  427.  
  428. again:
  429.     if (0 == (nlp = namelist))    /* Empty namelist is easy */
  430.         return 1;
  431.     len = strlen(p);
  432.     for (; nlp != 0; nlp = nlp->next) {
  433.         /* If first chars don't match, quick skip */
  434.         if (nlp->firstch && nlp->name[0] != p[0])
  435.             continue;
  436.  
  437.         /* Regular expressions */
  438.         if (nlp->regexp) {
  439.             if (wildmat(p, nlp->name)) {
  440.                 nlp->found = 1;    /* Remember it matched */
  441.                 return 1;    /* We got a match */
  442.             }
  443.             continue;
  444.         }
  445.  
  446.         /* Plain Old Strings */
  447.         if (nlp->length <= len        /* Archive len >= specified */
  448.          && (p[nlp->length] == '\0' || p[nlp->length] == '/')
  449.                         /* Full match on file/dirname */
  450.          && strncmp(p, nlp->name, nlp->length) == 0) /* Name compare */
  451.         {
  452.             nlp->found = 1;        /* Remember it matched */
  453.             return 1;        /* We got a match */
  454.         }
  455.     }
  456.  
  457.     /*
  458.      * Filename from archive not found in namelist.
  459.      * If we have the whole namelist here, just return 0.
  460.      * Otherwise, read the next name in and compare it.
  461.      * If this was the last name, namelist->found will remain on.
  462.      * If not, we loop to compare the newly read name.
  463.      */
  464.     if (f_sorted_names && namelist->found) {
  465.         name_gather();        /* Read one more */
  466.         if (!namelist->found) goto again;
  467.     }
  468.     return 0;
  469. }
  470.  
  471.  
  472. /*
  473.  * Print the names of things in the namelist that were not matched.
  474.  */
  475. names_notfound()
  476. {
  477.     register struct name    *nlp;
  478.     register char        *p;
  479.  
  480.     for (nlp = namelist; nlp != 0; nlp = nlp->next) {
  481.         if (!nlp->found) {
  482.             fprintf(stderr, "tar: %s not found in archive\n",
  483.                 nlp->name);
  484.         }
  485.         /*
  486.          * We could free() the list, but the process is about
  487.          * to die anyway, so save some CPU time.  Amigas and
  488.          * other similarly broken software will need to waste
  489.          * the time, though.
  490.          */
  491. #ifndef unix
  492.         if (!f_sorted_names)
  493.             free(nlp);
  494. #endif
  495.     }
  496.     namelist = (struct name *)NULL;
  497.     namelast = (struct name *)NULL;
  498.  
  499.     if (f_sorted_names) {
  500.         while (0 != (p = name_next()))
  501.             fprintf(stderr, "tar: %s not found in archive\n", p);
  502.     }
  503. }
  504. @@@ Fin de tar.c
  505. echo create.c
  506. cat >create.c <<'@@@ Fin de create.c'
  507. /*
  508.  * Create a tar archive.
  509.  *
  510.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  511.  *
  512.  * @(#)create.c 1.36 11/6/87 Public Domain - gnu
  513.  */
  514. #include <sys/types.h>
  515. #include <sys/stat.h>
  516. #include <stdio.h>
  517.  
  518. #ifndef V7
  519. #include <fcntl.h>
  520. #endif
  521.  
  522. #ifndef    MSDOS
  523. #include <pwd.h>
  524. #include <grp.h>
  525. #endif
  526.  
  527. #ifdef BSD42
  528. #include <sys/dir.h>
  529. #else
  530. #ifdef MSDOS
  531. #include <sys/dir.h>
  532. #else
  533. /*
  534.  * FIXME: On other systems there is no standard place for the header file
  535.  * for the portable directory access routines.  Change the #include line
  536.  * below to bring it in from wherever it is.
  537.  */
  538. #include "ndir.h"
  539. #endif
  540. #endif
  541.  
  542. #ifdef USG
  543. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  544. #endif
  545.  
  546. /*
  547.  * V7 doesn't have a #define for this.
  548.  */
  549. #ifndef O_RDONLY
  550. #define    O_RDONLY    0
  551. #endif
  552.  
  553. /*
  554.  * Most people don't have a #define for this.
  555.  */
  556. #ifndef    O_BINARY
  557. #define    O_BINARY    0
  558. #endif
  559.  
  560. #include "tar.h"
  561. #include "port.h"
  562.  
  563. extern union record *head;        /* Points to current tape header */
  564. extern struct stat hstat;        /* Stat struct corresponding */
  565. extern int head_standard;        /* Tape header is in ANSI format */
  566.  
  567. /*
  568.  * If there are no symbolic links, there is no lstat().  Use stat().
  569.  */
  570. #ifndef S_IFLNK
  571. #define lstat stat
  572. #endif
  573.  
  574. extern char    *malloc();
  575. extern char    *strcpy();
  576. extern char    *strncpy();
  577. extern void    bzero();
  578. extern void    bcopy();
  579. extern int    errno;
  580.  
  581. extern void print_header();
  582.  
  583. union record *start_header();
  584. void finish_header();
  585. void finduname();
  586. void findgname();
  587. char *name_next();
  588. void to_oct();
  589. void dump_file();
  590.  
  591. static nolinks;            /* Gets set if we run out of RAM */
  592.  
  593. void
  594. create_archive()
  595. {
  596.     register char    *p;
  597.  
  598.     open_archive(0);        /* Open for writing */
  599.  
  600.     while (p = name_next()) {
  601.         dump_file(p, -1);
  602.     }
  603.  
  604.     write_eot();
  605.     close_archive();
  606.     name_close();
  607. }        
  608.  
  609. /*
  610.  * Dump a single file.  If it's a directory, recurse.
  611.  * Result is 1 for success, 0 for failure.
  612.  * Sets global "hstat" to stat() output for this file.
  613.  */
  614. void
  615. dump_file(p, curdev)
  616.     char    *p;            /* File name to dump */
  617.     int    curdev;            /* Device our parent dir was on */
  618. {
  619.     union record    *header;
  620.     char type;
  621.  
  622.     /*
  623.      * Use stat if following (rather than dumping) 4.2BSD's
  624.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  625.      * systems, is #define'd to stat anyway.
  626.      */
  627.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  628.     {
  629. badperror:
  630.         perror(p);
  631. badfile:
  632.         errors++;
  633.         return;
  634.     }
  635.  
  636.     /*
  637.      * See if we are crossing from one file system to another,
  638.      * and avoid doing so if the user only wants to dump one file system.
  639.      */
  640.     if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
  641.         annorec(stderr, tar);
  642.         fprintf(stderr,
  643.             "%s: is on a different filesystem; not dumped\n",
  644.             p);
  645.         return;
  646.     }
  647.  
  648.     /*
  649.      * Check for multiple links.
  650.      *
  651.      * We maintain a list of all such files that we've written so
  652.      * far.  Any time we see another, we check the list and
  653.      * avoid dumping the data again if we've done it once already.
  654.      */
  655.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  656.         register struct link    *lp;
  657.  
  658.     case S_IFREG:            /* Regular file */
  659. #ifdef S_IFCTG
  660.     case S_IFCTG:            /* Contigous file */
  661. #endif
  662. #ifdef S_IFCHR
  663.     case S_IFCHR:            /* Character special file */
  664. #endif
  665.  
  666. #ifdef S_IFBLK
  667.     case S_IFBLK:            /* Block     special file */
  668. #endif
  669.  
  670. #ifdef S_IFIFO
  671.     case S_IFIFO:            /* Fifo      special file */
  672. #endif
  673.  
  674.         /* First quick and dirty.  Hashing, etc later FIXME */
  675.         for (lp = linklist; lp; lp = lp->next) {
  676.             if (lp->ino == hstat.st_ino &&
  677.                 lp->dev == hstat.st_dev) {
  678.                 /* We found a link. */
  679.                 hstat.st_size = 0;
  680.                 header = start_header(p, &hstat);
  681.                 if (header == NULL) goto badfile;
  682.                 strcpy(header->header.linkname,
  683.                     lp->name);
  684.                 header->header.linkflag = LF_LINK;
  685.                 finish_header(header);
  686.         /* FIXME: Maybe remove from list after all links found? */
  687.                 return;        /* We dumped it */
  688.             }
  689.         }
  690.  
  691.         /* Not found.  Add it to the list of possible links. */
  692.         lp = (struct link *) malloc( (unsigned)
  693.             (strlen(p) + sizeof(struct link) - NAMSIZ));
  694.         if (!lp) {
  695.             if (!nolinks) {
  696.                 fprintf(stderr,
  697.     "tar: no memory for links, they will be dumped as separate files\n");
  698.                 nolinks++;
  699.             }
  700.         }
  701.         lp->ino = hstat.st_ino;
  702.         lp->dev = hstat.st_dev;
  703.         strcpy(lp->name, p);
  704.         lp->next = linklist;
  705.         linklist = lp;
  706.     }
  707.  
  708.     /*
  709.      * This is not a link to a previously dumped file, so dump it.
  710.      */
  711.     switch (hstat.st_mode & S_IFMT) {
  712.  
  713.     case S_IFREG:            /* Regular file */
  714. #ifdef S_IFCTG
  715.     case S_IFCTG:            /* Contigous file */
  716. #endif
  717.     {
  718.         int    f;        /* File descriptor */
  719.         int    bufsize, count;
  720.         register long    sizeleft;
  721.         register union record     *start;
  722.  
  723.         sizeleft = hstat.st_size;
  724.         /* Don't bother opening empty, world readable files. */
  725.         if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
  726.             f = open(p, O_RDONLY|O_BINARY);
  727.             if (f < 0) goto badperror;
  728.         } else {
  729.             f = -1;
  730.         }
  731.         header = start_header(p, &hstat);
  732.         if (header == NULL) goto badfile;
  733. #ifdef S_IFCTG
  734.         /* Mark contiguous files, if we support them */
  735.         if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
  736.             header->header.linkflag = LF_CONTIG;
  737.         }
  738. #endif
  739.         finish_header(header);
  740.         while (sizeleft > 0) {
  741.             start = findrec();
  742.             bufsize = endofrecs()->charptr - start->charptr;
  743.             if (sizeleft < bufsize) {
  744.                 /* Last read -- zero out area beyond */
  745.                 bufsize = (int)sizeleft;
  746.                 count = bufsize % RECORDSIZE;
  747.                 if (count) 
  748.                     bzero(start->charptr + sizeleft,
  749.                         RECORDSIZE - count);
  750.             }
  751.             count = read(f, start->charptr, bufsize);
  752.             if (count < 0) {
  753.                 annorec(stderr, tar);
  754.                 fprintf(stderr,
  755.                   "read error at byte %ld, reading %d bytes, in file ",
  756.                     hstat.st_size - sizeleft,
  757.                     bufsize);
  758.                 perror(p);    /* FIXME */
  759.                 goto padit;
  760.             }
  761.             sizeleft -= count;
  762.             /* This is nonportable (the type of userec's arg). */
  763.             userec(start+(count-1)/RECORDSIZE);
  764.             if (count == bufsize) continue;
  765.             annorec(stderr, tar);
  766.             fprintf(stderr,
  767.               "%s: file shrunk by %d bytes, padding with zeros.\n",
  768.                 p, sizeleft);
  769.             goto padit;        /* Short read */
  770.         }
  771.         if (f >= 0)
  772.             (void)close(f);
  773.  
  774.         break;
  775.  
  776.         /*
  777.          * File shrunk or gave error, pad out tape to match
  778.          * the size we specified in the header.
  779.          */
  780.     padit:
  781.         abort();
  782.     }
  783.  
  784. #ifdef S_IFLNK
  785.     case S_IFLNK:            /* Symbolic link */
  786.     {
  787.         int size;
  788.  
  789.         hstat.st_size = 0;        /* Force 0 size on symlink */
  790.         header = start_header(p, &hstat);
  791.         if (header == NULL) goto badfile;
  792.         size = readlink(p, header->header.linkname, NAMSIZ);
  793.         if (size < 0) goto badperror;
  794.         if (size == NAMSIZ) {
  795.             annorec(stderr, tar);
  796.             fprintf(stderr,
  797.                 "%s: symbolic link too long\n", p);
  798.             break;
  799.         }
  800.         header->header.linkname[size] = '\0';
  801.         header->header.linkflag = LF_SYMLINK;
  802.         finish_header(header);        /* Nothing more to do to it */
  803.     }
  804.         break;
  805. #endif
  806.  
  807.     case S_IFDIR:            /* Directory */
  808.     {
  809.         register DIR *dirp;
  810.         register struct direct *d;
  811.         char namebuf[NAMSIZ+2];
  812.         register int len;
  813.         int our_device = hstat.st_dev;
  814.  
  815.         /* Build new prototype name */
  816.         strncpy(namebuf, p, sizeof (namebuf));
  817.         len = strlen(namebuf);
  818.         while (len >= 1 && '/' == namebuf[len-1]) 
  819.             len--;            /* Delete trailing slashes */
  820.         namebuf[len++] = '/';        /* Now add exactly one back */
  821.         namebuf[len] = '\0';        /* Make sure null-terminated */
  822.  
  823.         /*
  824.          * Output directory header record with permissions
  825.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  826.          * If old archive format, don't write record at all.
  827.          */
  828.         if (!f_oldarch) {
  829.             hstat.st_size = 0;    /* Force 0 size on dir */
  830.             /*
  831.              * If people could really read standard archives,
  832.              * this should be:        (FIXME)
  833.             header = start_header(f_standard? p: namebuf, &hstat);
  834.              * but since they'd interpret LF_DIR records as
  835.              * regular files, we'd better put the / on the name.
  836.              */
  837.             header = start_header(namebuf, &hstat);
  838.             if (header == NULL)
  839.                 goto badfile;    /* eg name too long */
  840.             if (f_standard) {
  841.                 header->header.linkflag = LF_DIR;
  842.             }
  843.             finish_header(header);    /* Done with directory header */
  844.         }
  845.  
  846.         /* Hack to remove "./" from the front of all the file names */
  847.         if (len == 2 && namebuf[0] == '.') {
  848.             len = 0;
  849.         }
  850.  
  851.         /* Now output all the files in the directory */
  852.         if (f_dironly)
  853.             break;        /* Unless the user says no */
  854.         errno = 0;
  855.         dirp = opendir(p);
  856.         if (!dirp) {
  857.             if (errno) {
  858.                 perror (p);
  859.             } else {
  860.                 annorec(stderr, tar);
  861.                 fprintf(stderr, "%s: error opening directory",
  862.                     p);
  863.             }
  864.             break;
  865.         }
  866.         
  867.         /* Should speed this up by cd-ing into the dir, FIXME */
  868.         while (NULL != (d=readdir(dirp))) {
  869.             /* Skip . and .. */
  870.             if (d->d_name[0] == '.') {
  871.                 if (d->d_name[1] == '\0') continue;
  872.                 if (d->d_name[1] == '.') {
  873.                     if (d->d_name[2] == '\0') continue;
  874.                 }
  875.             }
  876.             if (d->d_namlen + len >= NAMSIZ) {
  877.                 annorec(stderr, tar);
  878.                 fprintf(stderr, "%s%s: name too long\n", 
  879.                     namebuf, d->d_name);
  880.                 continue;
  881.             }
  882.             strcpy(namebuf+len, d->d_name);
  883.             dump_file(namebuf, our_device);
  884.         }
  885.  
  886.         closedir(dirp);
  887.     }
  888.         break;
  889.  
  890. #ifdef S_IFCHR
  891.     case S_IFCHR:            /* Character special file */
  892.         type = LF_CHR;
  893.         goto easy;
  894. #endif
  895.  
  896. #ifdef S_IFBLK
  897.     case S_IFBLK:            /* Block     special file */
  898.         type = LF_BLK;
  899.         goto easy;
  900. #endif
  901.  
  902. #ifdef S_IFIFO
  903.     case S_IFIFO:            /* Fifo      special file */
  904.         type = LF_FIFO;
  905. #endif
  906.  
  907.     easy:
  908.         if (!f_standard) goto unknown;
  909.  
  910.         hstat.st_size = 0;        /* Force 0 size */
  911.         header = start_header(p, &hstat);
  912.         if (header == NULL) goto badfile;    /* eg name too long */
  913.  
  914.         header->header.linkflag = type;
  915.         if (type != LF_FIFO) {
  916.             to_oct((long) major(hstat.st_rdev), 8,
  917.                 header->header.devmajor);
  918.             to_oct((long) minor(hstat.st_rdev), 8,
  919.                 header->header.devminor);
  920.         }
  921.  
  922.         finish_header(header);
  923.         break;
  924.  
  925.     default:
  926.     unknown:
  927.         annorec(stderr, tar);
  928.         fprintf(stderr,
  929.             "%s: Unknown file type; file ignored.\n", p);
  930.         break;
  931.     }
  932. }
  933.  
  934.  
  935. /*
  936.  * Make a header block for the file  name  whose stat info is  st .
  937.  * Return header pointer for success, NULL if the name is too long.
  938.  */
  939. union record *
  940. start_header(name, st)
  941.     char    *name;
  942.     register struct stat *st;
  943. {
  944.     register union record *header;
  945.  
  946.     header = (union record *) findrec();
  947.     bzero(header->charptr, sizeof(*header)); /* XXX speed up */
  948.  
  949.     /*
  950.      * Check the file name and put it in the record.
  951.      */
  952.     while ('/' == *name) {
  953.         static int warned_once = 0;
  954.  
  955.         name++;                /* Force relative path */
  956.         if (!warned_once++) {
  957.             annorec(stderr, tar);
  958.             fprintf(stderr,
  959.     "Removing leading / from absolute path names in the archive.\n");
  960.         }
  961.     }
  962.     strcpy(header->header.name, name);
  963.     if (header->header.name[NAMSIZ-1]) {
  964.         annorec(stderr, tar);
  965.         fprintf(stderr, "%s: name too long\n", name);
  966.         return NULL;
  967.     }
  968.  
  969.     to_oct((long) (st->st_mode & ~S_IFMT),
  970.                     8,  header->header.mode);
  971.     to_oct((long) st->st_uid,    8,  header->header.uid);
  972.     to_oct((long) st->st_gid,    8,  header->header.gid);
  973.     to_oct((long) st->st_size,    1+12, header->header.size);
  974.     to_oct((long) st->st_mtime,    1+12, header->header.mtime);
  975.     /* header->header.linkflag is left as null */
  976.  
  977. #ifndef NONAMES
  978.     /* Fill in new Unix Standard fields if desired. */
  979.     if (f_standard) {
  980.         header->header.linkflag = LF_NORMAL;    /* New default */
  981.         strcpy(header->header.magic, TMAGIC);    /* Mark as Unix Std */
  982.         finduname(header->header.uname, st->st_uid);
  983.         findgname(header->header.gname, st->st_gid);
  984.     }
  985. #endif
  986.     return header;
  987. }
  988.  
  989. /* 
  990.  * Finish off a filled-in header block and write it out.
  991.  * We also print the file name and/or full info if verbose is on.
  992.  */
  993. void
  994. finish_header(header)
  995.     register union record *header;
  996. {
  997.     register int    i, sum;
  998.     register char    *p;
  999.  
  1000.     bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  1001.  
  1002.     sum = 0;
  1003.     p = header->charptr;
  1004.     for (i = sizeof(*header); --i >= 0; ) {
  1005.         /*
  1006.          * We can't use unsigned char here because of old compilers,
  1007.          * e.g. V7.
  1008.          */
  1009.         sum += 0xFF & *p++;
  1010.     }
  1011.  
  1012.     /*
  1013.      * Fill in the checksum field.  It's formatted differently
  1014.      * from the other fields:  it has [6] digits, a null, then a
  1015.      * space -- rather than digits, a space, then a null.
  1016.      * We use to_oct then write the null in over to_oct's space.
  1017.      * The final space is already there, from checksumming, and
  1018.      * to_oct doesn't modify it.
  1019.      *
  1020.      * This is a fast way to do:
  1021.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1022.      */
  1023.     to_oct((long) sum,    8,  header->header.chksum);
  1024.     header->header.chksum[6] = '\0';    /* Zap the space */
  1025.  
  1026.     userec(header);
  1027.  
  1028.     if (f_verbose) {
  1029.         /* These globals are parameters to print_header, sigh */
  1030.         head = header;
  1031.         /* hstat is already set up */
  1032.         head_standard = f_standard;
  1033.         print_header(stderr);
  1034.     }
  1035.  
  1036.     return;
  1037. }
  1038.  
  1039.  
  1040. /*
  1041.  * Quick and dirty octal conversion.
  1042.  * Converts long "value" into a "digs"-digit field at "where",
  1043.  * including a trailing space and room for a null.  "digs"==3 means
  1044.  * 1 digit, a space, and room for a null.
  1045.  *
  1046.  * We assume the trailing null is already there and don't fill it in.
  1047.  * This fact is used by start_header and finish_header, so don't change it!
  1048.  *
  1049.  * This should be equivalent to:
  1050.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1051.  * except that sprintf fills in the trailing null and we don't.
  1052.  */
  1053. void
  1054. to_oct(value, digs, where)
  1055.     register long    value;
  1056.     register int    digs;
  1057.     register char    *where;
  1058. {
  1059.     
  1060.     --digs;                /* Trailing null slot is left alone */
  1061.     where[--digs] = ' ';        /* Put in the space, though */
  1062.  
  1063.     /* Produce the digits -- at least one */
  1064.     do {
  1065.         where[--digs] = '0' + (char)(value & 7); /* one octal digit */
  1066.         value >>= 3;
  1067.     } while (digs > 0 && value != 0);
  1068.  
  1069.     /* Leading spaces, if necessary */
  1070.     while (digs > 0)
  1071.         where[--digs] = ' ';
  1072.  
  1073. }
  1074.  
  1075.  
  1076. /*
  1077.  * Write the EOT record(s).
  1078.  * We actually zero at least one record, through the end of the block.
  1079.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1080.  */
  1081. write_eot()
  1082. {
  1083.     union record *p;
  1084.     int bufsize;
  1085.  
  1086.     p = findrec();
  1087.     bufsize = endofrecs()->charptr - p->charptr;
  1088.     bzero(p->charptr, bufsize);
  1089.     userec(p);
  1090. }
  1091. @@@ Fin de create.c
  1092. echo extract.c
  1093. cat >extract.c <<'@@@ Fin de extract.c'
  1094. /*
  1095.  * Extract files from a tar archive.
  1096.  *
  1097.  * Written 19 Nov 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  1098.  *
  1099.  * @(#) extract.c 1.32 87/11/11 Public Domain - gnu
  1100.  */
  1101.  
  1102. #include <stdio.h>
  1103. #include <errno.h>
  1104. #include <sys/types.h>
  1105. #include <sys/stat.h>
  1106.  
  1107. #ifdef BSD42
  1108. #include <sys/file.h>
  1109. #endif
  1110.  
  1111. #ifdef USG
  1112. #include <fcntl.h>
  1113. #endif
  1114.  
  1115. #ifdef    MSDOS
  1116. #include <fcntl.h>
  1117. #endif    /* MSDOS */
  1118.  
  1119. /*
  1120.  * Some people don't have a #define for these.
  1121.  */
  1122. #ifndef    O_BINARY
  1123. #define    O_BINARY    0
  1124. #endif
  1125. #ifndef O_NDELAY
  1126. #define    O_NDELAY    0
  1127. #endif
  1128.  
  1129. #ifdef NO_OPEN3
  1130. /* We need the #define's even though we don't use them. */
  1131. #include "open3.h"
  1132. #endif
  1133.  
  1134. #ifdef EMUL_OPEN3
  1135. /* Simulated 3-argument open for systems that don't have it */
  1136. #include "open3.h"
  1137. #endif
  1138.  
  1139. extern int errno;            /* From libc.a */
  1140. extern time_t time();            /* From libc.a */
  1141. extern char *index();            /* From libc.a or port.c */
  1142.  
  1143. #include "tar.h"
  1144. #include "port.h"
  1145.  
  1146. extern union record *head;        /* Points to current tape header */
  1147. extern struct stat hstat;        /* Stat struct corresponding */
  1148. extern int head_standard;        /* Tape header is in ANSI format */
  1149.  
  1150. extern void print_header();
  1151. extern void skip_file();
  1152. extern void pr_mkdir();
  1153.  
  1154. int make_dirs();            /* Makes required directories */
  1155.  
  1156. static time_t now = 0;            /* Current time */
  1157. static we_are_root = 0;            /* True if our effective uid == 0 */
  1158. static int notumask = ~0;        /* Masks out bits user doesn't want */
  1159.  
  1160. /*
  1161.  * Set up to extract files.
  1162.  */
  1163. extr_init()
  1164. {
  1165.     int ourmask;
  1166.  
  1167.     now = time((time_t *)0);
  1168.     if (geteuid() == 0)
  1169.         we_are_root = 1;
  1170.  
  1171.     /*
  1172.      * We need to know our umask.  But if f_use_protection is set,
  1173.      * leave our kernel umask at 0, and our "notumask" at ~0.
  1174.      */
  1175.     ourmask = umask(0);        /* Read it */
  1176.     if (!f_use_protection) {
  1177.         (void) umask (ourmask);    /* Set it back how it was */
  1178.         notumask = ~ourmask;    /* Make umask override permissions */
  1179.     }
  1180. }
  1181.  
  1182.  
  1183. /*
  1184.  * Extract a file from the archive.
  1185.  */
  1186. void
  1187. extract_archive()
  1188. {
  1189.     register char *data;
  1190.     int fd, check, namelen, written, openflag;
  1191.     long size;
  1192.     time_t acc_upd_times[2];
  1193.     register int skipcrud;
  1194.  
  1195.     saverec(&head);            /* Make sure it sticks around */
  1196.     userec(head);            /* And go past it in the archive */
  1197.     decode_header(head, &hstat, &head_standard, 1);    /* Snarf fields */
  1198.  
  1199.     /* Print the record from 'head' and 'hstat' */
  1200.     if (f_verbose)
  1201.         print_header(stdout);
  1202.  
  1203.     /*
  1204.      * Check for fully specified pathnames and other atrocities.
  1205.      *
  1206.      * Note, we can't just make a pointer to the new file name,
  1207.      * since saverec() might move the header and adjust "head".
  1208.      * We have to start from "head" every time we want to touch
  1209.      * the header record.
  1210.      */
  1211.     skipcrud = 0;
  1212.     while ('/' == head->header.name[skipcrud]) {
  1213.         static int warned_once = 0;
  1214.  
  1215.         skipcrud++;    /* Force relative path */
  1216.         if (!warned_once++) {
  1217.             annorec(stderr, tar);
  1218.             fprintf(stderr,
  1219.     "Removing leading / from absolute path names in the archive.\n");
  1220.         }
  1221.     }
  1222.  
  1223.     switch (head->header.linkflag) {
  1224.  
  1225.     default:
  1226.         annofile(stderr, tar);
  1227.         fprintf(stderr,
  1228.            "Unknown file type '%c' for %s, extracted as normal file\n",
  1229.             head->header.linkflag, skipcrud+head->header.name);
  1230.         /* FALL THRU */
  1231.  
  1232.     case LF_OLDNORMAL:
  1233.     case LF_NORMAL:
  1234.     case LF_CONTIG:
  1235.         /*
  1236.          * Appears to be a file.
  1237.          * See if it's really a directory.
  1238.          */
  1239.         namelen = strlen(skipcrud+head->header.name)-1;
  1240.         if (head->header.name[skipcrud+namelen] == '/')
  1241.             goto really_dir;
  1242.  
  1243.         /* FIXME, deal with protection issues */
  1244.     again_file:
  1245.         openflag = f_keep?
  1246.             O_BINARY|O_NDELAY|O_WRONLY|O_APPEND|O_CREAT|O_EXCL:
  1247.             O_BINARY|O_NDELAY|O_WRONLY|O_APPEND|O_CREAT|O_TRUNC;
  1248. #ifdef O_CTG
  1249.         /*
  1250.          * Contiguous files (on the Masscomp) have to specify
  1251.          * the size in the open call that creates them.
  1252.          */
  1253.         if (head->header.lnkflag == LF_CONTIG)
  1254.             fd = open(skipcrud+head->header.name, openflag | O_CTG,
  1255.                 hstat.st_mode, hstat.st_size);
  1256.         else
  1257. #endif
  1258.         {
  1259. #ifdef NO_OPEN3
  1260.             /*
  1261.              * On raw V7 we won't let them specify -k (f_keep), but
  1262.              * we just bull ahead and create the files.
  1263.              */
  1264.             fd = creat(skipcrud+head->header.name, 
  1265.                 hstat.st_mode);
  1266. #else
  1267.             /*
  1268.              * With 3-arg open(), we can do this up right.
  1269.              */
  1270.             fd = open(skipcrud+head->header.name, openflag,
  1271.                 hstat.st_mode);
  1272. #endif
  1273.         }
  1274.  
  1275.         if (fd < 0) {
  1276.             if (make_dirs(skipcrud+head->header.name))
  1277.                 goto again_file;
  1278.             annofile(stderr, tar);
  1279.             fprintf(stderr, "Could not make file ");
  1280.             perror(skipcrud+head->header.name);
  1281.             skip_file((long)hstat.st_size);
  1282.             goto quit;
  1283.         }
  1284.  
  1285.         for (size = hstat.st_size;
  1286.              size > 0;
  1287.              size -= written) {
  1288.             /*
  1289.              * Locate data, determine max length
  1290.              * writeable, write it, record that
  1291.              * we have used the data, then check
  1292.              * if the write worked.
  1293.              */
  1294.             data = findrec()->charptr;
  1295.             if (data == NULL) {    /* Check it... */
  1296.                 annorec(stderr, tar);
  1297.                 fprintf(stderr, "Unexpected EOF on archive file\n");
  1298.                 break;
  1299.             }
  1300.             written = endofrecs()->charptr - data;
  1301.             if (written > size) written = size;
  1302.             errno = 0;
  1303.             check = write(fd, data, written);
  1304.             /*
  1305.              * The following is in violation of strict
  1306.              * typing, since the arg to userec
  1307.              * should be a struct rec *.  FIXME.
  1308.              */
  1309.             userec(data + written - 1);
  1310.             if (check == written) continue;
  1311.             /*
  1312.              * Error in writing to file.
  1313.              * Print it, skip to next file in archive.
  1314.              */
  1315.             annofile(stderr, tar);
  1316.             fprintf(stderr,
  1317.     "Tried to write %d bytes to file, could only write %d:\n",
  1318.                 written, check);
  1319.             perror(skipcrud+head->header.name);
  1320.             skip_file((long)(size - written));
  1321.             break;    /* Still do the close, mod time, chmod, etc */
  1322.         }
  1323.  
  1324.         check = close(fd);
  1325.         if (check < 0) {
  1326.             annofile(stderr, tar);
  1327.             fprintf(stderr, "Error while closing ");
  1328.             perror(skipcrud+head->header.name);
  1329.         }
  1330.         
  1331.     set_filestat:
  1332.         /*
  1333.          * Set the modified time of the file.
  1334.          * 
  1335.          * Note that we set the accessed time to "now", which
  1336.          * is really "the time we started extracting files".
  1337.          */
  1338.         if (!f_modified) {
  1339.             acc_upd_times[0] = now;             /* Accessed now */
  1340.             acc_upd_times[1] = hstat.st_mtime; /* Mod'd */
  1341.             if (utime(skipcrud+head->header.name,
  1342.                 acc_upd_times) < 0) {
  1343.                 annofile(stderr, tar);
  1344.                 perror(skipcrud+head->header.name);
  1345.             }
  1346.         }
  1347.  
  1348.         /*
  1349.          * If we are root, set the owner and group of the extracted
  1350.          * file.  This does what is wanted both on real Unix and on
  1351.          * System V.  If we are running as a user, we extract as that
  1352.          * user; if running as root, we extract as the original owner.
  1353.          */
  1354.         if (we_are_root) {
  1355.             if (chown(skipcrud+head->header.name, hstat.st_uid,
  1356.                   hstat.st_gid) < 0) {
  1357.                 annofile(stderr, tar);
  1358.                 perror(skipcrud+head->header.name);
  1359.             }
  1360.         }
  1361.  
  1362.         /*
  1363.          * If '-k' is not set, open() or creat() could have saved
  1364.          * the permission bits from a previously created file,
  1365.          * ignoring the ones we specified.
  1366.          * Even if -k is set, if the file has abnormal
  1367.          * mode bits, we must chmod since writing or chown() has
  1368.          * probably reset them.
  1369.          *
  1370.          * If -k is set, we know *we* created this file, so the mode
  1371.          * bits were set by our open().   If the file is "normal", we
  1372.          * skip the chmod.  This works because we did umask(0) if -p
  1373.          * is set, so umask will have left the specified mode alone.
  1374.          */
  1375.         if ((!f_keep)
  1376.             || (hstat.st_mode & (S_ISUID|S_ISGID|S_ISVTX))) {
  1377.             if (chmod(skipcrud+head->header.name,
  1378.                   notumask & (int)hstat.st_mode) < 0) {
  1379.                 annofile(stderr, tar);
  1380.                 perror(skipcrud+head->header.name);
  1381.             }
  1382.         }
  1383.  
  1384.     quit:
  1385.         break;
  1386.  
  1387.     case LF_LINK:
  1388.     again_link:
  1389.         check = link (head->header.linkname,
  1390.                   skipcrud+head->header.name);
  1391.         if (check == 0)
  1392.             break;
  1393.         if (make_dirs(skipcrud+head->header.name))
  1394.             goto again_link;
  1395.         annofile(stderr, tar);
  1396.         fprintf(stderr, "Could not link %s to ",
  1397.             skipcrud+head->header.name);
  1398.         perror(head->header.linkname);
  1399.         break;
  1400.  
  1401. #ifdef S_IFLNK
  1402.     case LF_SYMLINK:
  1403.     again_symlink:
  1404.         check = symlink(head->header.linkname,
  1405.                     skipcrud+head->header.name);
  1406.         /* FIXME, don't worry uid, gid, etc... */
  1407.         if (check == 0)
  1408.             break;
  1409.         if (make_dirs(skipcrud+head->header.name))
  1410.             goto again_symlink;
  1411.         annofile(stderr, tar);
  1412.         fprintf(stderr, "Could not create symlink ");
  1413.         perror(head->header.linkname);
  1414.         break;
  1415. #endif
  1416.  
  1417. #ifdef S_IFCHR
  1418.     case LF_CHR:
  1419.         hstat.st_mode |= S_IFCHR;
  1420.         goto make_node;
  1421. #endif
  1422.  
  1423. #ifdef S_IFBLK
  1424.     case LF_BLK:
  1425.         hstat.st_mode |= S_IFBLK;
  1426.         goto make_node;
  1427. #endif
  1428.  
  1429. #ifdef S_IFIFO
  1430.     /* If local system doesn't support FIFOs, use default case */
  1431.     case LF_FIFO:
  1432.         hstat.st_mode |= S_IFIFO;
  1433.         hstat.st_rdev = 0;        /* FIXME, do we need this? */
  1434.         goto make_node;
  1435. #endif
  1436.  
  1437.     make_node:
  1438.         check = mknod(skipcrud+head->header.name,
  1439.                   (int) hstat.st_mode, (int) hstat.st_rdev);
  1440.         if (check != 0) {
  1441.             if (make_dirs(skipcrud+head->header.name))
  1442.                 goto make_node;
  1443.             annofile(stderr, tar);
  1444.             fprintf(stderr, "Could not make ");
  1445.             perror(skipcrud+head->header.name);
  1446.             break;
  1447.         };
  1448.         goto set_filestat;
  1449.  
  1450.     case LF_DIR:
  1451.         namelen = strlen(skipcrud+head->header.name)-1;
  1452.     really_dir:
  1453.         /* Check for trailing /, and zap as many as we find. */
  1454.         while (namelen && head->header.name[skipcrud+namelen] == '/')
  1455.             head->header.name[skipcrud+namelen--] = '\0';
  1456.         
  1457.     again_dir:
  1458.         check = mkdir(skipcrud+head->header.name,
  1459.                   0300 | (int)hstat.st_mode);
  1460.         if (check != 0) {
  1461.             if (make_dirs(skipcrud+head->header.name))
  1462.                 goto again_dir;
  1463.             /* If we're trying to create '.', let it be. */
  1464.             if (head->header.name[skipcrud+namelen] == '.' && 
  1465.                 (namelen==0 ||
  1466.                  head->header.name[skipcrud+namelen-1]=='/'))
  1467.                 goto check_perms;
  1468.             annofile(stderr, tar);
  1469.             fprintf(stderr, "Could not make directory ");
  1470.             perror(skipcrud+head->header.name);
  1471.             break;
  1472.         }
  1473.         
  1474.     check_perms:
  1475.         if (0300 != (0300 & (int) hstat.st_mode)) {
  1476.             hstat.st_mode |= 0300;
  1477.             annofile(stderr, tar);
  1478.             fprintf(stderr,
  1479.               "Added write & execute permission to directory %s\n",
  1480.               skipcrud+head->header.name);
  1481.         }
  1482.  
  1483.         goto set_filestat;
  1484.         /* FIXME, Remember timestamps for after files created? */
  1485.         /* FIXME, change mode after files created (if was R/O dir) */
  1486.  
  1487.     }
  1488.  
  1489.     /* We don't need to save it any longer. */
  1490.     saverec((union record **) 0);    /* Unsave it */
  1491. }
  1492.  
  1493. /*
  1494.  * After a file/link/symlink/dir creation has failed, see if
  1495.  * it's because some required directory was not present, and if
  1496.  * so, create all required dirs.
  1497.  */
  1498. int
  1499. make_dirs(pathname)
  1500.     char *pathname;
  1501. {
  1502.     char *p;            /* Points into path */
  1503.     int madeone = 0;        /* Did we do anything yet? */
  1504.     int save_errno = errno;        /* Remember caller's errno */
  1505.     int check;
  1506.  
  1507.     if (errno != ENOENT)
  1508.         return 0;        /* Not our problem */
  1509.  
  1510.     for (p = index(pathname, '/'); p != NULL; p = index(p+1, '/')) {
  1511.         /* Avoid mkdir of empty string, if leading or double '/' */
  1512.         if (p == pathname || p[-1] == '/')
  1513.             continue;
  1514.         /* Avoid mkdir where last part of path is '.' */
  1515.         if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
  1516.             continue;
  1517.         *p = 0;                /* Truncate the path there */
  1518.         check = mkdir (pathname, 0777);    /* Try to create it as a dir */
  1519.         if (check == 0) {
  1520.             /* Fix ownership */
  1521.             if (we_are_root) {
  1522.                 if (chown(pathname, hstat.st_uid,
  1523.                       hstat.st_gid) < 0) {
  1524.                     annofile(stderr, tar);
  1525.                     perror(pathname);
  1526.                 }
  1527.             }
  1528.             pr_mkdir(pathname, p-pathname, notumask&0777, stdout);
  1529.             madeone++;        /* Remember if we made one */
  1530.             *p = '/';
  1531.             continue;
  1532.         }
  1533.         *p = '/';
  1534.         if (errno == EEXIST)        /* Directory already exists */
  1535.             continue;
  1536.         /*
  1537.          * Some other error in the mkdir.  We return to the caller.
  1538.          */
  1539.         break;
  1540.     }
  1541.  
  1542.     errno = save_errno;        /* Restore caller's errno */
  1543.     return madeone;            /* Tell them to retry if we made one */
  1544. }
  1545. @@@ Fin de extract.c
  1546. echo buffer.c
  1547. cat >buffer.c <<'@@@ Fin de buffer.c'
  1548. /*
  1549.  * Buffer management for public domain tar.
  1550.  *
  1551.  * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
  1552.  *
  1553.  * @(#) buffer.c 1.28 11/6/87 Public Domain - gnu
  1554.  */
  1555.  
  1556. #include <stdio.h>
  1557. #include <errno.h>
  1558. #include <sys/types.h>        /* For non-Berkeley systems */
  1559. #include <sys/stat.h>
  1560. #include <signal.h>
  1561.  
  1562. #ifdef    MSDOS
  1563. # include <fcntl.h>
  1564. #else
  1565. # ifdef XENIX
  1566. #  include <sys/inode.h>
  1567. # endif
  1568. # include <sys/file.h>
  1569. #endif
  1570.  
  1571. #include "tar.h"
  1572. #include "port.h"
  1573.  
  1574. #define    STDIN    0        /* Standard input  file descriptor */
  1575. #define    STDOUT    1        /* Standard output file descriptor */
  1576.  
  1577. #define    PREAD    0        /* Read  file descriptor from pipe() */
  1578. #define    PWRITE    1        /* Write file descriptor from pipe() */
  1579.  
  1580. extern char    *valloc();
  1581. extern char    *index(), *strcat();
  1582.  
  1583. /*
  1584.  * V7 doesn't have a #define for this.
  1585.  */
  1586. #ifndef O_RDONLY
  1587. #define    O_RDONLY    0
  1588. #endif
  1589.  
  1590. #define    MAGIC_STAT    105    /* Magic status returned by child, if
  1591.                    it can't exec.  We hope compress/sh
  1592.                    never return this status! */
  1593. /*
  1594.  * The record pointed to by save_rec should not be overlaid
  1595.  * when reading in a new tape block.  Copy it to record_save_area first, and
  1596.  * change the pointer in *save_rec to point to record_save_area.
  1597.  * Saved_recno records the record number at the time of the save.
  1598.  * This is used by annofile() to print the record number of a file's
  1599.  * header record.
  1600.  */
  1601. static union record **save_rec;
  1602. static union record record_save_area;
  1603. static long        saved_recno;
  1604.  
  1605. /*
  1606.  * PID of child program, if f_compress or remote archive access.
  1607.  */
  1608. static int    childpid = 0;
  1609.  
  1610. /*
  1611.  * Record number of the start of this block of records
  1612.  */
  1613. static long    baserec;
  1614.  
  1615. /*
  1616.  * Error recovery stuff
  1617.  */
  1618. static int    r_error_count;
  1619.  
  1620. /*
  1621.  * Have we hit EOF yet?
  1622.  */
  1623. static int    eof;
  1624.  
  1625.  
  1626. /*
  1627.  * Return the location of the next available input or output record.
  1628.  * Return NULL for EOF.  Once we have returned NULL, we just keep returning
  1629.  * it, to avoid accidentally going on to the next file on the "tape".
  1630.  */
  1631. union record *
  1632. findrec()
  1633. {
  1634.     if (ar_record == ar_last) {
  1635.         if (eof)
  1636.             return (union record *)NULL;    /* EOF */
  1637.         flush_archive();
  1638.         if (ar_record == ar_last) {
  1639.             eof++;
  1640.             return (union record *)NULL;    /* EOF */
  1641.         }
  1642.     }
  1643.     return ar_record;
  1644. }
  1645.  
  1646.  
  1647. /*
  1648.  * Indicate that we have used all records up thru the argument.
  1649.  * (should the arg have an off-by-1? XXX FIXME)
  1650.  */
  1651. void
  1652. userec(rec)
  1653.     union record *rec;
  1654. {
  1655.     while(rec >= ar_record)
  1656.         ar_record++;
  1657.     /*
  1658.      * Do NOT flush the archive here.  If we do, the same
  1659.      * argument to userec() could mean the next record (if the
  1660.      * input block is exactly one record long), which is not what
  1661.      * is intended.
  1662.      */
  1663.     if (ar_record > ar_last)
  1664.         abort();
  1665. }
  1666.  
  1667.  
  1668. /*
  1669.  * Return a pointer to the end of the current records buffer.
  1670.  * All the space between findrec() and endofrecs() is available
  1671.  * for filling with data, or taking data from.
  1672.  */
  1673. union record *
  1674. endofrecs()
  1675. {
  1676.     return ar_last;
  1677. }
  1678.  
  1679.  
  1680. /* 
  1681.  * Duplicate a file descriptor into a certain slot.
  1682.  * Equivalent to BSD "dup2" with error reporting.
  1683.  */
  1684. void
  1685. dupto(from, to, msg)
  1686.     int from, to;
  1687.     char *msg;
  1688. {
  1689.     int err;
  1690.  
  1691.     if (from != to) {
  1692.         (void) close(to);
  1693.         err = dup(from);
  1694.         if (err != to) {
  1695.             fprintf(stderr, "tar: cannot dup ");
  1696.             perror(msg);
  1697.             exit(EX_SYSTEM);
  1698.         }
  1699.         (void) close(from);
  1700.     }
  1701. }
  1702.  
  1703.  
  1704. /*
  1705.  * Fork a child to deal with remote files or compression.
  1706.  * If rem_host is zero, we are called only for compression.
  1707.  */
  1708. void
  1709. child_open(rem_host, rem_file)
  1710.     char *rem_host, *rem_file;
  1711. {
  1712.  
  1713. #ifdef    MSDOS
  1714.     fprintf(stderr,
  1715.       "MSDOS %s cannot deal with compressed or remote archives\n", tar);
  1716.     exit(EX_ARGSBAD);
  1717. #else
  1718.     
  1719.     int pipes[2];
  1720.     int err;
  1721.     struct stat arstat;
  1722.     char cmdbuf[1000];        /* For big file and host names */
  1723.  
  1724.     /* Create a pipe to talk to the child over */
  1725.     err = pipe(pipes);
  1726.     if (err < 0) {
  1727.         perror ("tar: cannot create pipe to child");
  1728.         exit(EX_SYSTEM);
  1729.     }
  1730.     
  1731.     /* Fork child process */
  1732.     childpid = fork();
  1733.     if (childpid < 0) {
  1734.         perror("tar: cannot fork");
  1735.         exit(EX_SYSTEM);
  1736.     }
  1737.  
  1738.     /*
  1739.      * Parent process.  Clean up.
  1740.      *
  1741.      * We always close the archive file (stdin, stdout, or opened file)
  1742.      * since the child will end up reading or writing that for us.
  1743.      * Note that this may leave standard input closed.
  1744.      * We close the child's end of the pipe since they will handle
  1745.      * that too; and we set <archive> to the other end of the pipe.
  1746.      *
  1747.      * If reading, we set f_reblock since reading pipes or network
  1748.      * sockets produces odd length data.
  1749.      */
  1750.     if (childpid > 0) {
  1751.         (void) close (archive);    
  1752.         if (ar_reading) {
  1753.             (void) close (pipes[PWRITE]);
  1754.             archive = pipes[PREAD];
  1755.             f_reblock++;
  1756.         } else {
  1757.             (void) close (pipes[PREAD]);
  1758.             archive = pipes[PWRITE];
  1759.         }
  1760.         return;
  1761.     }
  1762.  
  1763.     /*
  1764.      * Child process.
  1765.      */
  1766.     if (ar_reading) {
  1767.         /*
  1768.          * Reading from the child...
  1769.          *
  1770.          * Close the read-side of the pipe, which our parent will use.
  1771.          * Move the write-side of pipe to stdout,
  1772.          * If local, move archive input to child's stdin,
  1773.          * then run the child.
  1774.          */
  1775.         (void) close (pipes[PREAD]);
  1776.         dupto(pipes[PWRITE], STDOUT, "to stdout");
  1777.         if (rem_host) {
  1778.             (void) close (STDIN);    /* rsh abuses stdin */
  1779.             if (STDIN != open("/dev/null"))
  1780.                 perror("Can't open /dev/null");
  1781.             sprintf(cmdbuf,
  1782.                 "rsh '%s' dd '<%s' bs=%db",
  1783.                 rem_host, rem_file, blocking);
  1784.             if (f_compress)
  1785.                 strcat(cmdbuf, "| compress -d");
  1786. #ifdef DEBUG
  1787.             fprintf(stderr, "Exec-ing: %s\n", cmdbuf);
  1788. #endif
  1789.             execlp("sh", "sh", "-c", cmdbuf, (char *)0);
  1790.             perror("tar: cannot exec sh");
  1791.         } else {
  1792.             /*
  1793.              * If we are reading a disk file, compress is OK;
  1794.              * otherwise, we have to reblock the input in case it's
  1795.              * coming from a tape drive.  This is an optimization.
  1796.              */
  1797.             dupto(archive, STDIN, "to stdin");
  1798.             err = fstat(STDIN, &arstat);
  1799.             if (err != 0) {
  1800.                 perror("tar: can't fstat archive");
  1801.                 exit(EX_SYSTEM);
  1802.             }
  1803.             if ((arstat.st_mode & S_IFMT) == S_IFREG) {
  1804.                 execlp("compress", "compress", "-d", (char *)0);
  1805.                 perror("tar: cannot exec compress");
  1806.             } else {
  1807.                 /* Non-regular file needs dd before compress */
  1808.                 sprintf(cmdbuf,
  1809.                     "dd bs=%db | compress -d",
  1810.                     blocking);
  1811. #ifdef DEBUG
  1812.                 fprintf(stderr, "Exec-ing: %s\n", cmdbuf);
  1813. #endif
  1814.                 execlp("sh", "sh", "-c", cmdbuf, (char *)0);
  1815.                 perror("tar: cannot exec sh");
  1816.             }
  1817.         }
  1818.         exit(MAGIC_STAT);
  1819.     } else {
  1820.         /*
  1821.          * Writing archive to the child.
  1822.          * It would like to run either:
  1823.          *    compress
  1824.          *    compress |            dd obs=20b
  1825.          *           rsh 'host' dd obs=20b '>foo'
  1826.          * or    compress | rsh 'host' dd obs=20b '>foo'
  1827.          *
  1828.          * We need the dd to reblock the output to the
  1829.          * user's specs, if writing to a device or over
  1830.          * the net.  However, it produces a stupid
  1831.          * message about how many blocks it processed.
  1832.          * Because the shell on the remote end could be just
  1833.          * about any shell, we can't depend on it to do
  1834.          * redirect stderr properly for us -- the csh
  1835.          * doesn't use the same syntax as the Bourne shell.
  1836.          * On the other hand, if we just ignore stderr on
  1837.          * this end, we won't see errors from rsh, or from
  1838.          * the inability of "dd" to write its output file.
  1839.          * The combination of the local sh, the rsh, the
  1840.          * remote csh, and maybe a remote sh conspires to mess
  1841.          * up any possible quoting method, so grumble! we
  1842.          * punt and just accept the fucking "xxx blocks"
  1843.          * messages.  The real fix would be a "dd" that
  1844.          * would shut up.
  1845.          * 
  1846.          * Close the write-side of the pipe, which our parent will use.
  1847.          * Move the read-side of the pipe to stdin,
  1848.          * If local, move archive output to the child's stdout.
  1849.          * then run the child.
  1850.          */
  1851.         (void) close (pipes[PWRITE]);
  1852.         dupto(pipes[PREAD], STDIN, "to stdin");
  1853.         if (!rem_host)
  1854.             dupto(archive, STDOUT, "to stdout");
  1855.  
  1856.         cmdbuf[0] = '\0';
  1857.         if (f_compress) {
  1858.             if (!rem_host) {
  1859.                 err = fstat(STDOUT, &arstat);
  1860.                 if (err != 0) {
  1861.                     perror("tar: can't fstat archive");
  1862.                     exit(EX_SYSTEM);
  1863.                 }
  1864.                 if ((arstat.st_mode & S_IFMT) == S_IFREG) {
  1865.                     execlp("compress", "compress", (char *)0);
  1866.                     perror("tar: cannot exec compress");
  1867.                 }
  1868.             }
  1869.             strcat(cmdbuf, "compress | ");
  1870.         }
  1871.         if (rem_host) {
  1872.             sprintf(cmdbuf+strlen(cmdbuf),
  1873.               "rsh '%s' dd obs=%db '>%s'",
  1874.                  rem_host, blocking, rem_file);
  1875.         } else {
  1876.             sprintf(cmdbuf+strlen(cmdbuf),
  1877.                 "dd obs=%db",
  1878.                 blocking);
  1879.         }
  1880. #ifdef DEBUG
  1881.         fprintf(stderr, "Exec-ing: %s\n", cmdbuf);
  1882. #endif
  1883.         execlp("sh", "sh", "-c", cmdbuf, (char *)0);
  1884.         perror("tar: cannot exec sh");
  1885.         exit(MAGIC_STAT);
  1886.     }
  1887. #endif    /* MSDOS */
  1888. }
  1889.  
  1890.  
  1891. /*
  1892.  * Open an archive file.  The argument specifies whether we are
  1893.  * reading or writing.
  1894.  */
  1895. open_archive(read)
  1896.     int read;
  1897. {
  1898.     char *colon, *slash;
  1899.     char *rem_host = 0, *rem_file;
  1900.  
  1901.     colon = index(ar_file, ':');
  1902.     if (colon) {
  1903.         slash = index(ar_file, '/');
  1904.         if (slash && slash > colon) {
  1905.             /*
  1906.              * Remote file specified.  Parse out separately,
  1907.              * and don't try to open it on the local system.
  1908.              */
  1909.             rem_file = colon + 1;
  1910.             rem_host = ar_file;
  1911.             *colon = '\0';
  1912.             goto gotit;
  1913.         }
  1914.     }
  1915.  
  1916.     if (ar_file[0] == '-' && ar_file[1] == '\0') {
  1917.         f_reblock++;    /* Could be a pipe, be safe */
  1918.         if (read)    archive = STDIN;
  1919.         else        archive = STDOUT;
  1920.     } else if (read) {
  1921.         archive = open(ar_file, O_RDONLY);
  1922.     } else {
  1923.         archive = creat(ar_file, 0666);
  1924.     }
  1925.  
  1926.     if (archive < 0) {
  1927.         perror(ar_file);
  1928.         exit(EX_BADARCH);
  1929.     }
  1930.  
  1931. #ifdef    MSDOS
  1932.     setmode(archive, O_BINARY);
  1933. #endif
  1934.  
  1935. gotit:
  1936.     if (blocksize == 0) {
  1937.         fprintf(stderr, "tar: invalid value for blocksize\n");
  1938.         exit(EX_ARGSBAD);
  1939.     }
  1940.  
  1941.     /*NOSTRICT*/
  1942.     ar_block = (union record *) valloc((unsigned)blocksize);
  1943.     if (!ar_block) {
  1944.         fprintf(stderr,
  1945.         "tar: could not allocate memory for blocking factor %d\n",
  1946.             blocking);
  1947.         exit(EX_ARGSBAD);
  1948.     }
  1949.  
  1950.     ar_record = ar_block;
  1951.     ar_last   = ar_block + blocking;
  1952.     ar_reading = read;
  1953.  
  1954.     if (f_compress || rem_host) 
  1955.         child_open(rem_host, rem_file);
  1956.  
  1957.     if (read) {
  1958.         ar_last = ar_block;        /* Set up for 1st block = # 0 */
  1959.         (void) findrec();        /* Read it in, check for EOF */
  1960.     }
  1961. }
  1962.  
  1963.  
  1964. /*
  1965.  * Remember a union record * as pointing to something that we
  1966.  * need to keep when reading onward in the file.  Only one such
  1967.  * thing can be remembered at once, and it only works when reading
  1968.  * an archive.
  1969.  *
  1970.  * We calculate "offset" then add it because some compilers end up
  1971.  * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
  1972.  * subtracting ar_block from that, shifting it back, losing the top 9 bits.
  1973.  */
  1974. saverec(pointer)
  1975.     union record **pointer;
  1976. {
  1977.     long offset;
  1978.  
  1979.     save_rec = pointer;
  1980.     offset = ar_record - ar_block;
  1981.     saved_recno = baserec + offset;
  1982. }
  1983.  
  1984. /*
  1985.  * Perform a write to flush the buffer.
  1986.  */
  1987. fl_write()
  1988. {
  1989.     int err;
  1990.  
  1991.     err = write(archive, ar_block->charptr, blocksize);
  1992.     if (err == blocksize) return;
  1993.     /* FIXME, multi volume support on write goes here */
  1994.     if (err < 0)
  1995.         perror(ar_file);
  1996.     else
  1997.         fprintf(stderr, "tar: %s: write failed, short %d bytes\n",
  1998.             ar_file, blocksize - err);
  1999.     exit(EX_BADARCH);
  2000. }
  2001.  
  2002.  
  2003. /*
  2004.  * Handle read errors on the archive.
  2005.  *
  2006.  * If the read should be retried, readerror() returns to the caller.
  2007.  */
  2008. void
  2009. readerror()
  2010. {
  2011. #    define    READ_ERROR_MAX    10
  2012.  
  2013.     read_error_flag++;        /* Tell callers */
  2014.  
  2015.     annorec(stderr, tar);
  2016.     fprintf(stderr, "Read error on ");
  2017.     perror(ar_file);
  2018.  
  2019.     if (baserec == 0) {
  2020.         /* First block of tape.  Probably stupidity error */
  2021.         exit(EX_BADARCH);
  2022.     }    
  2023.  
  2024.     /*
  2025.      * Read error in mid archive.  We retry up to READ_ERROR_MAX times
  2026.      * and then give up on reading the archive.  We set read_error_flag
  2027.      * for our callers, so they can cope if they want.
  2028.      */
  2029.     if (r_error_count++ > READ_ERROR_MAX) {
  2030.         annorec(stderr, tar);
  2031.         fprintf(stderr, "Too many errors, quitting.\n");
  2032.         exit(EX_BADARCH);
  2033.     }
  2034.     return;
  2035. }
  2036.  
  2037.  
  2038. /*
  2039.  * Perform a read to flush the buffer.
  2040.  */
  2041. fl_read()
  2042. {
  2043.     int err;        /* Result from system call */
  2044.     int left;        /* Bytes left */
  2045.     char *more;        /* Pointer to next byte to read */
  2046.  
  2047.     /*
  2048.      * Clear the count of errors.  This only applies to a single
  2049.      * call to fl_read.  We leave read_error_flag alone; it is
  2050.      * only turned off by higher level software.
  2051.      */
  2052.     r_error_count = 0;    /* Clear error count */
  2053.  
  2054.     /*
  2055.      * If we are about to wipe out a record that
  2056.      * somebody needs to keep, copy it out to a holding
  2057.      * area and adjust somebody's pointer to it.
  2058.      */
  2059.     if (save_rec &&
  2060.         *save_rec >= ar_record &&
  2061.         *save_rec < ar_last) {
  2062.         record_save_area = **save_rec;
  2063.         *save_rec = &record_save_area;
  2064.     }
  2065. error_loop:
  2066.     err = read(archive, ar_block->charptr, blocksize);
  2067.     if (err == blocksize) return;
  2068.     if (err < 0) {
  2069.         readerror();
  2070.         goto error_loop;    /* Try again */
  2071.     }
  2072.  
  2073.     more = ar_block->charptr + err;
  2074.     left = blocksize - err;
  2075.  
  2076. again:
  2077.     if (0 == (((unsigned)left) % RECORDSIZE)) {
  2078.         /* FIXME, for size=0, multi vol support */
  2079.         /* On the first block, warn about the problem */
  2080.         if (!f_reblock && baserec == 0 && f_verbose && err > 0) {
  2081.             annorec(stderr, tar);
  2082.             fprintf(stderr, "Blocksize = %d record%s\n",
  2083.                 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");
  2084.         }
  2085.         ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE;
  2086.         return;
  2087.     }
  2088.     if (f_reblock) {
  2089.         /*
  2090.          * User warned us about this.  Fix up.
  2091.          */
  2092.         if (left > 0) {
  2093. error2loop:
  2094.             err = read(archive, more, left);
  2095.             if (err < 0) {
  2096.                 readerror();
  2097.                 goto error2loop;    /* Try again */
  2098.             }
  2099.             if (err == 0) {
  2100.                 annorec(stderr, tar);
  2101.                 fprintf(stderr,
  2102.         "%s: eof not on block boundary, strange...\n",
  2103.                     ar_file);
  2104.                 exit(EX_BADARCH);
  2105.             }
  2106.             left -= err;
  2107.             more += err;
  2108.             goto again;
  2109.         }
  2110.     } else {
  2111.         annorec(stderr, tar);
  2112.         fprintf(stderr, "%s: read %d bytes, strange...\n",
  2113.             ar_file, err);
  2114.         exit(EX_BADARCH);
  2115.     }
  2116. }
  2117.  
  2118.  
  2119. /*
  2120.  * Flush the current buffer to/from the archive.
  2121.  */
  2122. flush_archive()
  2123. {
  2124.  
  2125.     baserec += ar_last - ar_block;    /* Keep track of block #s */
  2126.     ar_record = ar_block;        /* Restore pointer to start */
  2127.     ar_last = ar_block + blocking;    /* Restore pointer to end */
  2128.  
  2129.     if (!ar_reading) 
  2130.         fl_write();
  2131.     else
  2132.         fl_read();
  2133. }
  2134.  
  2135. /*
  2136.  * Close the archive file.
  2137.  */
  2138. close_archive()
  2139. {
  2140.     int child;
  2141.     int status;
  2142.  
  2143.     if (!ar_reading) flush_archive();
  2144.     (void) close(archive);
  2145.  
  2146. #ifndef    MSDOS
  2147.     if (childpid) {
  2148.         /*
  2149.          * Loop waiting for the right child to die, or for
  2150.          * no more kids.
  2151.          */
  2152.         while (((child = wait(&status)) != childpid) && child != -1)
  2153.             ;
  2154.  
  2155.         if (child != -1) {
  2156.             switch (TERM_SIGNAL(status)) {
  2157.             case 0:
  2158.                 /* Child voluntarily terminated  -- but why? */
  2159.                 if (TERM_VALUE(status) == MAGIC_STAT) {
  2160.                     exit(EX_SYSTEM);/* Child had trouble */
  2161.                 }
  2162.                 if (TERM_VALUE(status) == (SIGPIPE + 128)) {
  2163.                     /*
  2164.                      * /bin/sh returns this if its child
  2165.                      * dies with SIGPIPE.  'Sok.
  2166.                      */
  2167.                     break;
  2168.                 } else if (TERM_VALUE(status))
  2169.                     fprintf(stderr,
  2170.                   "tar: child returned status %d\n",
  2171.                         TERM_VALUE(status));
  2172.             case SIGPIPE:
  2173.                 break;        /* This is OK. */
  2174.  
  2175.             default:
  2176.                 fprintf(stderr,
  2177.                  "tar: child died with signal %d%s\n",
  2178.                  TERM_SIGNAL(status),
  2179.                  TERM_COREDUMP(status)? " (core dumped)": "");
  2180.             }
  2181.         }
  2182.     }
  2183. #endif    /* MSDOS */
  2184. }
  2185.  
  2186.  
  2187. /*
  2188.  * Message management.
  2189.  *
  2190.  * anno writes a message prefix on stream (eg stdout, stderr).
  2191.  *
  2192.  * The specified prefix is normally output followed by a colon and a space.
  2193.  * However, if other command line options are set, more output can come
  2194.  * out, such as the record # within the archive.
  2195.  *
  2196.  * If the specified prefix is NULL, no output is produced unless the
  2197.  * command line option(s) are set.
  2198.  *
  2199.  * If the third argument is 1, the "saved" record # is used; if 0, the
  2200.  * "current" record # is used.
  2201.  */
  2202. void
  2203. anno(stream, prefix, savedp)
  2204.     FILE    *stream;
  2205.     char    *prefix;
  2206.     int    savedp;
  2207. {
  2208. #    define    MAXANNO    50
  2209.     char    buffer[MAXANNO];    /* Holds annorecment */
  2210. #    define    ANNOWIDTH 13
  2211.     int    space;
  2212.     long    offset;
  2213.  
  2214.     /* Make sure previous output gets out in sequence */
  2215.     if (stream == stderr)
  2216.         fflush(stdout);
  2217.     if (f_sayblock) {
  2218.         if (prefix) {
  2219.             fputs(prefix, stream);
  2220.             putc(' ', stream);
  2221.         }
  2222.         offset = ar_record - ar_block;
  2223.         sprintf(buffer, "rec %d: ",
  2224.             savedp?    saved_recno:
  2225.                 baserec + offset);
  2226.         fputs(buffer, stream);
  2227.         space = ANNOWIDTH - strlen(buffer);
  2228.         if (space > 0) {
  2229.             fprintf(stream, "%*s", space, "");
  2230.         }
  2231.     } else if (prefix) {
  2232.         fputs(prefix, stream);
  2233.         fputs(": ", stream);
  2234.     }
  2235. }
  2236. @@@ Fin de buffer.c
  2237. echo getoldopt.c
  2238. cat >getoldopt.c <<'@@@ Fin de getoldopt.c'
  2239. /*
  2240.  * Plug-compatible replacement for getopt() for parsing tar-like
  2241.  * arguments.  If the first argument begins with "-", it uses getopt;
  2242.  * otherwise, it uses the old rules used by tar, dump, and ps.
  2243.  *
  2244.  * Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu) and placed
  2245.  * in the Pubic Domain for your edification and enjoyment.
  2246.  *
  2247.  * @(#)getoldopt.c 1.4 2/4/86 Public Domain - gnu
  2248.  */
  2249.  
  2250. #include <stdio.h>
  2251.  
  2252.  
  2253. int
  2254. getoldopt(argc, argv, optstring)
  2255.     int    argc;
  2256.     char    **argv;
  2257.     char    *optstring;
  2258. {
  2259.     extern char    *optarg;    /* Points to next arg */
  2260.     extern int    optind;        /* Global argv index */
  2261.     static char    *key;        /* Points to next keyletter */
  2262.     static char    use_getopt;    /* !=0 if argv[1][0] was '-' */
  2263.     extern char    *index();
  2264.     char        c;
  2265.     char        *place;
  2266.  
  2267.     optarg = NULL;
  2268.     
  2269.     if (key == NULL) {        /* First time */
  2270.         if (argc < 2) return EOF;
  2271.         key = argv[1];
  2272.         if (*key == '-')
  2273.             use_getopt++;
  2274.         else
  2275.             optind = 2;
  2276.     }
  2277.  
  2278.     if (use_getopt)
  2279.         return getopt(argc, argv, optstring);
  2280.  
  2281.     c = *key++;
  2282.     if (c == '\0') {
  2283.         key--;
  2284.         return EOF;
  2285.     }
  2286.     place = index(optstring, c);
  2287.  
  2288.     if (place == NULL || c == ':') {
  2289.         fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
  2290.         return('?');
  2291.     }
  2292.  
  2293.     place++;
  2294.     if (*place == ':') {
  2295.         if (optind < argc) {
  2296.             optarg = argv[optind];
  2297.             optind++;
  2298.         } else {
  2299.             fprintf(stderr, "%s: %c argument missing\n",
  2300.                 argv[0], c);
  2301.             return('?');
  2302.         }
  2303.     }
  2304.  
  2305.     return(c);
  2306. }
  2307. @@@ Fin de getoldopt.c
  2308. exit 0
  2309.