home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 May / Chip_2000-05_cd2.bin / dosutils / gtar109 / create.c < prev    next >
C/C++ Source or Header  |  1991-01-14  |  30KB  |  1,223 lines

  1. /* Create a tar archive.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Create a tar archive.
  22.  *
  23.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  24.  *
  25.  * @(#)create.c 1.36 11/6/87 - gnu
  26.  */
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #ifndef MSDOS
  30. #include <sys/file.h>
  31. #endif
  32. #include <stdio.h>
  33.  
  34. /* JF: this one is my fault */
  35. /* #include "utils.h" */
  36.  
  37. #ifndef V7
  38. #include <fcntl.h>
  39. #endif
  40.  
  41. #ifndef    MSDOS
  42. #include <pwd.h>
  43. #include <grp.h>
  44. #endif
  45.  
  46. #ifdef BSD42
  47. #include <sys/dir.h>
  48. #else
  49. #ifdef MSDOS
  50. #include <sys/dir.h>
  51. #else
  52. #ifdef USG
  53. #ifdef NDIR
  54. #include <ndir.h>
  55. #else
  56. #include <dirent.h>
  57. #endif
  58. #ifndef DIRECT
  59. #define direct dirent
  60. #endif
  61. #define DP_NAMELEN(x) strlen((x)->d_name)
  62. #else
  63. /*
  64.  * FIXME: On other systems there is no standard place for the header file
  65.  * for the portable directory access routines.  Change the #include line
  66.  * below to bring it in from wherever it is.
  67.  */
  68. #include "ndir.h"
  69. #endif
  70. #endif
  71. #endif
  72.  
  73. #ifndef DP_NAMELEN
  74. #define DP_NAMELEN(x)    (x)->d_namlen
  75. #endif
  76.  
  77. #ifdef USG
  78. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  79. #endif
  80.  
  81. /*
  82.  * V7 doesn't have a #define for this.
  83.  */
  84. #ifndef O_RDONLY
  85. #define    O_RDONLY    0
  86. #endif
  87.  
  88. /*
  89.  * Most people don't have a #define for this.
  90.  */
  91. #ifndef    O_BINARY
  92. #define    O_BINARY    0
  93. #endif
  94.  
  95. #include "tar.h"
  96. #include "port.h"
  97.  
  98. extern union record *head;        /* Points to current tape header */
  99. extern struct stat hstat;        /* Stat struct corresponding */
  100. extern int head_standard;        /* Tape header is in ANSI format */
  101.  
  102. extern dev_t ar_dev;
  103. extern ino_t ar_ino;
  104.  
  105. /* JF */
  106. extern struct name *gnu_list_name;
  107.  
  108. /*
  109.  * If there are no symbolic links, there is no lstat().  Use stat().
  110.  */
  111. #ifndef S_IFLNK
  112. #define lstat stat
  113. #endif
  114.  
  115. extern char    *malloc();
  116. extern char    *strcpy();
  117. extern char    *strncpy();
  118. extern void    bzero();
  119. extern void    bcopy();
  120. extern int    errno;
  121.  
  122. extern void print_header();
  123.  
  124. union record *start_header();
  125. void finish_header();
  126. void finduname();
  127. void findgname();
  128. char *name_next();
  129. void to_oct();
  130. void dump_file();
  131.  
  132. static nolinks;            /* Gets set if we run out of RAM */
  133.  
  134. /*
  135.  * "Scratch" space to store the information about a sparse file before
  136.  * writing the info into the header or extended header
  137.  */
  138. /* struct sp_array     *sparsearray;*/
  139.  
  140. /* number of elts storable in the sparsearray */
  141. /*int     sparse_array_size = 10;*/
  142.  
  143. void
  144. create_archive()
  145. {
  146.     register char    *p;
  147.     char *name_from_list();
  148.  
  149.     open_archive(0);        /* Open for writing */
  150.  
  151.     if(f_gnudump) {
  152.         char buf[MAXNAMLEN],*q,*bufp;
  153.  
  154.         collect_and_sort_names();
  155.  
  156.         while(p=name_from_list())
  157.             dump_file(p,-1);
  158.         /* if(!f_dironly) { */
  159.             blank_name_list();
  160.             while(p=name_from_list()) {
  161.                 strcpy(buf,p);
  162.                 if(p[strlen(p)-1]!='/')
  163.                     strcat(buf,"/");
  164.                 bufp=buf+strlen(buf);
  165.                 for(q=gnu_list_name->dir_contents;q && *q;q+=strlen(q)+1) {
  166.                     if(*q=='Y') {
  167.                         strcpy(bufp,q+1);
  168.                         dump_file(buf,-1);
  169.                     }
  170.                 }
  171.             }
  172.         /* } */
  173.  
  174.     } else {
  175.         p = name_next(1);
  176.         if(!p)
  177.             dump_file(".", -1);
  178.         else {
  179.             do dump_file(p, -1);
  180.             while (p = name_next(1));
  181.         }
  182.     }
  183.  
  184.     write_eot();
  185.     close_archive();
  186.     name_close();
  187. }
  188.  
  189. /*
  190.  * Dump a single file.  If it's a directory, recurse.
  191.  * Result is 1 for success, 0 for failure.
  192.  * Sets global "hstat" to stat() output for this file.
  193.  */
  194. void
  195. dump_file (p, curdev)
  196.     char    *p;            /* File name to dump */
  197.     int    curdev;            /* Device our parent dir was on */
  198. {
  199.     union record    *header;
  200.     char type;
  201.     extern char *save_name;        /* JF for multi-volume support */
  202.     extern long save_totsize;
  203.     extern long save_sizeleft;
  204.     union record    *exhdr;
  205.     char save_linkflag;
  206.     extern time_t new_time;
  207.     int sparse_ind = 0;
  208.  
  209.  
  210.     if(f_confirm && !confirm("add",p))
  211.         return;
  212.  
  213.     /*
  214.      * Use stat if following (rather than dumping) 4.2BSD's
  215.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  216.      * systems, is #define'd to stat anyway.
  217.      */
  218.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  219.     {
  220. badperror:
  221.         msg_perror("can't add file %s",p);
  222. badfile:
  223.         errors++;
  224.         return;
  225.     }
  226.  
  227.     /* See if we only want new files, and check if this one is too old to
  228.        put in the archive. */
  229.     if(   f_new_files
  230.        && !f_gnudump
  231.         && new_time>hstat.st_mtime
  232.         && (hstat.st_mode&S_IFMT)!=S_IFDIR
  233.         && (f_new_files>1 || new_time>hstat.st_ctime)) {
  234.         if(curdev<0) {
  235.             msg("%s: is unchanged; not dumped",p);
  236.         }
  237.         return;
  238.     }
  239.  
  240.     /*
  241.      * See if we are crossing from one file system to another,
  242.      * and avoid doing so if the user only wants to dump one file system.
  243.      */
  244.     if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
  245.         if(f_verbose)
  246.             msg("%s: is on a different filesystem; not dumped",p);
  247.         return;
  248.     }
  249.  
  250. #ifndef MSDOS
  251.     /* See if we are trying to dump the archive */
  252.     if(ar_dev && hstat.st_dev==ar_dev && hstat.st_ino==ar_ino) {
  253.         msg("%s is the archive; not dumped",p);
  254.         return;
  255.     }
  256. #endif
  257.     /*
  258.      * Check for multiple links.
  259.      *
  260.      * We maintain a list of all such files that we've written so
  261.      * far.  Any time we see another, we check the list and
  262.      * avoid dumping the data again if we've done it once already.
  263.      */
  264.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  265.         register struct link    *lp;
  266.  
  267.     case S_IFREG:            /* Regular file */
  268. #ifdef S_IFCTG
  269.     case S_IFCTG:            /* Contigous file */
  270. #endif
  271. #ifdef S_IFCHR
  272.     case S_IFCHR:            /* Character special file */
  273. #endif
  274.  
  275. #ifdef S_IFBLK
  276.     case S_IFBLK:            /* Block     special file */
  277. #endif
  278.  
  279. #ifdef S_IFIFO
  280.     case S_IFIFO:            /* Fifo      special file */
  281. #endif
  282.  
  283.         /* First quick and dirty.  Hashing, etc later FIXME */
  284.         for (lp = linklist; lp; lp = lp->next) {
  285.             if (lp->ino == hstat.st_ino &&
  286.                 lp->dev == hstat.st_dev) {
  287.                 char *link_name = lp->name;
  288.  
  289.                 /* We found a link. */
  290.                 hstat.st_size = 0;
  291.                 header = start_header(p, &hstat);
  292.                 if (header == NULL) goto badfile;
  293.                 while(!f_absolute_paths && *link_name == '/') {
  294.                     static int link_warn = 0;
  295.  
  296.                     if (!link_warn) {
  297.                         msg("Removing leading / from absolute links");
  298.                         link_warn++;
  299.                     }
  300.                     link_name++;
  301.                 }
  302.                   strcpy(header->header.linkname,
  303.                     link_name);
  304.                 header->header.linkflag = LF_LINK;
  305.                 finish_header(header);
  306.         /* FIXME: Maybe remove from list after all links found? */
  307.                 return;        /* We dumped it */
  308.             }
  309.         }
  310.  
  311.         /* Not found.  Add it to the list of possible links. */
  312.         lp = (struct link *) malloc( (unsigned)
  313.             (strlen(p) + sizeof(struct link) - NAMSIZ));
  314.         if (!lp) {
  315.             if (!nolinks) {
  316.                 msg(
  317.     "no memory for links, they will be dumped as separate files");
  318.                 nolinks++;
  319.             }
  320.         }
  321.         lp->ino = hstat.st_ino;
  322.         lp->dev = hstat.st_dev;
  323.         strcpy(lp->name, p);
  324.         lp->next = linklist;
  325.         linklist = lp;
  326.     }
  327.  
  328.     /*
  329.      * This is not a link to a previously dumped file, so dump it.
  330.      */
  331.     switch (hstat.st_mode & S_IFMT) {
  332.  
  333.     case S_IFREG:            /* Regular file */
  334. #ifdef S_IFCTG
  335.     case S_IFCTG:            /* Contiguous file */
  336. #endif
  337.     {
  338.         int    f;        /* File descriptor */
  339.         long    bufsize, count;
  340.         long    sizeleft;
  341.         register union record     *start;
  342.         int     header_moved;
  343.         char    isextended = 0;
  344.         int     upperbound;
  345.         int    end_nulls = 0;
  346.  
  347.         header_moved = 0;
  348.  
  349. #ifdef BSD42
  350.         if (f_sparse_files) {
  351.         /*
  352.           * JK - This is the test for sparseness: whether the
  353.          * "size" of the file matches the number of blocks
  354.          * allocated for it.  If there is a smaller number
  355.          * of blocks that would be necessary to accommodate
  356.          * a file of this size, we have a sparse file, i.e.,
  357.          * at least one of those records in the file is just
  358.          * a useless hole.
  359.          */
  360.             if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE) {
  361.                 int    filesize = hstat.st_size;
  362.                 register int i;
  363.  
  364.                 printf("File is sparse: %s\n", p);
  365.                 header = start_header(p, &hstat);
  366.                 if (header == NULL)
  367.                     goto badfile;
  368.                 header->header.linkflag = LF_SPARSE;
  369.                 header_moved++;
  370.  
  371.             /*
  372.              * Call the routine that figures out the
  373.              * layout of the sparse file in question.
  374.              * UPPERBOUND is the index of the last
  375.              * element of the "sparsearray," i.e.,
  376.              * the number of elements it needed to
  377.              * describe the file.
  378.              */
  379.  
  380.                 upperbound = deal_with_sparse(p, header);
  381.  
  382.             /*
  383.              * See if we'll need an extended header
  384.              * later
  385.              */
  386.                 if (upperbound > SPARSE_IN_HDR-1)
  387.                      header->header.isextended++;
  388.             /*
  389.              * We store the "real" file size so
  390.              * we can show that in case someone wants
  391.              * to list the archive, i.e., tar tvf <file>.
  392.              * It might be kind of disconcerting if the
  393.              * shrunken file size was the one that showed
  394.              * up.
  395.              */
  396.                  to_oct((long) hstat.st_size, 1+12,
  397.                          header->header.realsize);
  398.  
  399.             /*
  400.              * This will be the new "size" of the
  401.              * file, i.e., the size of the file
  402.              * minus the records of holes that we're
  403.              * skipping over.
  404.              */
  405.  
  406.                 find_new_file_size(&filesize, upperbound);
  407.                 printf("File %s is now size %d\n",
  408.                             p, filesize);
  409.                 hstat.st_size = filesize;
  410.                 to_oct((long) filesize, 1+12,
  411.                          header->header.size);
  412. /*                to_oct((long) end_nulls, 1+12,
  413.                         header->header.ending_blanks);*/
  414.  
  415.                 for (i = 0; i < SPARSE_IN_HDR; i++) {
  416.                     if (!sparsearray[i].numbytes)
  417.                         break;
  418.                     to_oct(sparsearray[i].offset, 1+12,
  419.                         header->header.sp[i].offset);
  420.                     to_oct(sparsearray[i].numbytes, 1+12,
  421.                         header->header.sp[i].numbytes);
  422.                 }
  423.  
  424.             }
  425.         }
  426. #else
  427.         upperbound=SPARSE_IN_HDR-1;
  428. #endif
  429.  
  430.         sizeleft = hstat.st_size;
  431.         /* Don't bother opening empty, world readable files. */
  432.         if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
  433.             f = open(p, O_RDONLY|O_BINARY);
  434.             if (f < 0) goto badperror;
  435.         } else {
  436.             f = -1;
  437.         }
  438.  
  439.         /* If the file is sparse, we've already taken care of this */
  440.         if (!header_moved) {
  441.             header = start_header(p, &hstat);
  442.             if (header == NULL) {
  443.                 if(f>=0)
  444.                     (void)close(f);
  445.                 goto badfile;
  446.             }
  447.         }
  448. #ifdef S_IFCTG
  449.         /* Mark contiguous files, if we support them */
  450.         if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
  451.             header->header.linkflag = LF_CONTIG;
  452.         }
  453. #endif
  454.         isextended = header->header.isextended;
  455.         save_linkflag = header->header.linkflag;
  456.         finish_header(header);
  457.         if (isextended) {
  458.             int     sum = 0;
  459.             register int i;
  460. /*            register union record *exhdr;*/
  461.             int     arraybound = SPARSE_EXT_HDR;
  462.             /* static */ int index_offset = SPARSE_IN_HDR;
  463.  
  464.     extend:        exhdr = findrec();
  465.  
  466.             if (exhdr == NULL) goto badfile;
  467.             bzero(exhdr->charptr, RECORDSIZE);
  468.             for (i = 0; i < SPARSE_EXT_HDR; i++) {
  469.                 if (i+index_offset > upperbound)
  470.                     break;
  471.                 to_oct((long) sparsearray[i+index_offset].numbytes,
  472.                      1+12,
  473.                     exhdr->ext_hdr.sp[i].numbytes);
  474.                 to_oct((long) sparsearray[i+index_offset].offset,
  475.                      1+12,
  476.                     exhdr->ext_hdr.sp[i].offset);
  477.             }
  478.             userec(exhdr);
  479. /*            sum += i;
  480.             if (sum < upperbound)
  481.                 goto extend;*/
  482.             if (index_offset+i < upperbound) {
  483.                 index_offset += i;
  484.                 exhdr->ext_hdr.isextended++;
  485.                 goto extend;
  486.             }
  487.  
  488.         }
  489.         if (save_linkflag == LF_SPARSE) {
  490.             if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
  491.                 goto padit;
  492.         }
  493.         else
  494.           while (sizeleft > 0) {
  495.  
  496.             if(f_multivol) {
  497.                 save_name = p;
  498.                 save_sizeleft = sizeleft;
  499.                 save_totsize = hstat.st_size;
  500.             }
  501.             start = findrec();
  502.  
  503.             bufsize = endofrecs()->charptr - start->charptr;
  504.  
  505.             if (sizeleft < bufsize) {
  506.                 /* Last read -- zero out area beyond */
  507.                 bufsize = (int)sizeleft;
  508.                 count = bufsize % RECORDSIZE;
  509.                 if (count)
  510.                     bzero(start->charptr + sizeleft,
  511.                         (int)(RECORDSIZE - count));
  512.             }
  513.             count = read(f, start->charptr, bufsize);
  514.             if (count < 0) {
  515.                 msg_perror("read error at byte %ld, reading\
  516.  %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);
  517.                 goto padit;
  518.             }
  519.             sizeleft -= count;
  520.  
  521.             /* This is nonportable (the type of userec's arg). */
  522.             userec(start+(count-1)/RECORDSIZE);
  523.  
  524.             if (count == bufsize) continue;
  525.             msg( "file %s shrunk by %d bytes, padding with zeros.\n", p, sizeleft);
  526.             goto padit;        /* Short read */
  527.         }
  528.  
  529.         if(f_multivol)
  530.             save_name = 0;
  531.  
  532.         if (f >= 0)
  533.             (void)close(f);
  534.  
  535.         break;
  536.  
  537.         /*
  538.          * File shrunk or gave error, pad out tape to match
  539.          * the size we specified in the header.
  540.          */
  541.     padit:
  542.         while(sizeleft>0) {
  543.             save_sizeleft=sizeleft;
  544.             start=findrec();
  545.             bzero(start->charptr,RECORDSIZE);
  546.             userec(start);
  547.             sizeleft-=RECORDSIZE;
  548.         }
  549.         if(f_multivol)
  550.             save_name=0;
  551.         if(f>=0)
  552.             (void)close(f);
  553.         break;
  554. /*        abort(); */
  555.     }
  556.  
  557. #ifdef S_IFLNK
  558.     case S_IFLNK:            /* Symbolic link */
  559.     {
  560.         int size;
  561.  
  562.         hstat.st_size = 0;        /* Force 0 size on symlink */
  563.         header = start_header(p, &hstat);
  564.         if (header == NULL) goto badfile;
  565.         size = readlink(p, header->header.linkname, NAMSIZ);
  566.         if (size < 0) goto badperror;
  567.         if (size == NAMSIZ) {
  568.             msg("symbolic link %s too long\n",p);
  569.             break;
  570.         }
  571.         header->header.linkname[size] = '\0';
  572.         header->header.linkflag = LF_SYMLINK;
  573.         finish_header(header);        /* Nothing more to do to it */
  574.     }
  575.         break;
  576. #endif
  577.  
  578.     case S_IFDIR:            /* Directory */
  579.     {
  580.         register DIR *dirp;
  581.         register struct direct *d;
  582.         char namebuf[NAMSIZ+2];
  583.         register int len;
  584.         int our_device = hstat.st_dev;
  585.  
  586.         /* Build new prototype name */
  587.         strncpy(namebuf, p, sizeof (namebuf));
  588.         len = strlen(namebuf);
  589.         while (len >= 1 && '/' == namebuf[len-1])
  590.             len--;            /* Delete trailing slashes */
  591.         namebuf[len++] = '/';        /* Now add exactly one back */
  592.         namebuf[len] = '\0';        /* Make sure null-terminated */
  593.  
  594.         /*
  595.          * Output directory header record with permissions
  596.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  597.          * If old archive format, don't write record at all.
  598.          */
  599.         if (!f_oldarch) {
  600.             hstat.st_size = 0;    /* Force 0 size on dir */
  601.             /*
  602.              * If people could really read standard archives,
  603.              * this should be:        (FIXME)
  604.             header = start_header(f_standard? p: namebuf, &hstat);
  605.              * but since they'd interpret LF_DIR records as
  606.              * regular files, we'd better put the / on the name.
  607.              */
  608.             header = start_header(namebuf, &hstat);
  609.             if (header == NULL)
  610.                 goto badfile;    /* eg name too long */
  611.  
  612.             if (f_gnudump)
  613.                 header->header.linkflag = LF_DUMPDIR;
  614.             else if (f_standard)
  615.                 header->header.linkflag = LF_DIR;
  616.  
  617.             /* If we're gnudumping, we aren't done yet so don't close it. */
  618.             if(!f_gnudump)
  619.                 finish_header(header);    /* Done with directory header */
  620.         }
  621.  
  622.         /* Hack to remove "./" from the front of all the file names */
  623.         if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/') {
  624.             len = 0;
  625.         }
  626.  
  627.         if(f_gnudump) {
  628.             int sizeleft;
  629.             int totsize;
  630.             int bufsize;
  631.             union record *start;
  632.             int count;
  633.             char *buf,*p_buf;
  634.  
  635.             buf=gnu_list_name->dir_contents; /* FOO */
  636.             totsize=0;
  637.             for(p_buf=buf;p_buf && *p_buf;) {
  638.                 int tmp;
  639.  
  640.                 tmp=strlen(p_buf)+1;
  641.                 totsize+=tmp;
  642.                 p_buf+=tmp;
  643.             }
  644.             totsize++;
  645.             to_oct((long)totsize,1+12,header->header.size);
  646.             finish_header(header);
  647.             p_buf=buf;
  648.             sizeleft=totsize;
  649.             while(sizeleft>0) {
  650.                 if(f_multivol) {
  651.                     save_name=p;
  652.                     save_sizeleft=sizeleft;
  653.                     save_totsize=totsize;
  654.                 }
  655.                 start=findrec();
  656.                 bufsize=endofrecs()->charptr - start->charptr;
  657.                 if(sizeleft<bufsize) {
  658.                     bufsize=sizeleft;
  659.                     count=bufsize%RECORDSIZE;
  660.                     if(count)
  661.                         bzero(start->charptr+sizeleft,RECORDSIZE-count);
  662.                 }
  663.                 bcopy(p_buf,start->charptr,bufsize);
  664.                 sizeleft-=bufsize;
  665.                 p_buf+=bufsize;
  666.                 userec(start+(bufsize-1)/RECORDSIZE);
  667.             }
  668.             if(f_multivol)
  669.                 save_name = 0;
  670.             break;
  671.         }
  672.  
  673.         /* Now output all the files in the directory */
  674.         /* if (f_dironly)
  675.             break;        /* Unless the cmdline said not to */
  676.  
  677.  
  678.         errno = 0;
  679.         dirp = opendir(p);
  680.         if (!dirp) {
  681.             if (errno) {
  682.                 msg_perror ("can't open directory %s",p);
  683.             } else {
  684.                 msg("error opening directory %s",
  685.                     p);
  686.             }
  687.             break;
  688.         }
  689.  
  690.         /* Should speed this up by cd-ing into the dir, FIXME */
  691.         while (NULL != (d=readdir(dirp))) {
  692.             /* Skip . and .. */
  693.             if(is_dot_or_dotdot(d->d_name))
  694.                 continue;
  695.  
  696.             if (DP_NAMELEN(d) + len >= NAMSIZ) {
  697.                 namebuf[len]='\0';
  698.                 msg("file name %s%s too long\n",
  699.                     namebuf, d->d_name);
  700.                 continue;
  701.             }
  702.             strcpy(namebuf+len, d->d_name);
  703.             if(f_exclude && check_exclude(namebuf))
  704.                 continue;
  705.             dump_file(namebuf, our_device);
  706.         }
  707.  
  708.         closedir(dirp);
  709.     }
  710.         break;
  711.  
  712. #ifdef S_IFCHR
  713.     case S_IFCHR:            /* Character special file */
  714.         type = LF_CHR;
  715.         goto easy;
  716. #endif
  717.  
  718. #ifdef S_IFBLK
  719.     case S_IFBLK:            /* Block     special file */
  720.         type = LF_BLK;
  721.         goto easy;
  722. #endif
  723.  
  724. #ifdef S_IFIFO
  725.     case S_IFIFO:            /* Fifo      special file */
  726.  
  727.         type = LF_FIFO;
  728.         goto easy;
  729. #endif
  730.  
  731. #ifdef S_IFSOCK
  732.     case S_IFSOCK:            /* Socket    pretend its a fifo? */
  733.         type = LF_FIFO;
  734.         goto easy;
  735. #endif
  736.  
  737.     easy:
  738.         if (!f_standard) goto unknown;
  739.  
  740.         hstat.st_size = 0;        /* Force 0 size */
  741.         header = start_header(p, &hstat);
  742.         if (header == NULL) goto badfile;    /* eg name too long */
  743.  
  744.         header->header.linkflag = type;
  745.         if (type != LF_FIFO) {
  746.             to_oct((long) major(hstat.st_rdev), 8,
  747.                 header->header.devmajor);
  748.             to_oct((long) minor(hstat.st_rdev), 8,
  749.                 header->header.devminor);
  750.         }
  751.  
  752.         finish_header(header);
  753.         break;
  754.  
  755.     default:
  756.     unknown:
  757.         msg("%s: Unknown file type; file ignored.\n", p);
  758.         break;
  759.     }
  760. }
  761.  
  762. int
  763. finish_sparse_file(fd, sizeleft, fullsize, name)
  764.     int    fd;
  765.     long     *sizeleft,
  766.         fullsize;
  767.     char    *name;
  768. {
  769.     union record    *start;
  770.     char        tempbuf[RECORDSIZE];
  771.     int        bufsize,
  772.             sparse_ind = 0,
  773.             count;
  774.     long        pos;
  775.  
  776.  
  777.  
  778.     while (*sizeleft > 0) {
  779.         start = findrec();
  780.         bzero(start->charptr, RECORDSIZE);
  781.         bufsize = sparsearray[sparse_ind].numbytes;
  782.         if (!bufsize) {  /* we blew it, maybe */
  783.                 msg("Wrote %ld of %ld bytes to file %s",
  784.                        fullsize - *sizeleft, fullsize, name);
  785.             break;
  786.              }
  787.         pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
  788.         /*
  789.          * If the number of bytes to be written here exceeds
  790.          * the size of the temporary buffer, do it in steps.
  791.          */
  792.         while (bufsize > RECORDSIZE) {
  793. /*            if (amt_read) {
  794.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  795.                 bufsize -= RECORDSIZE - amt_read;
  796.                 amt_read = 0;
  797.                 userec(start);
  798.                 start = findrec();
  799.                 bzero(start->charptr, RECORDSIZE);
  800.             }*/
  801.             /* store the data */
  802.             count = read(fd, start->charptr, RECORDSIZE);
  803.             if (count < 0)     {
  804.                 msg_perror("read error at byte %ld, reading %d bytes, in file %s",
  805.                         fullsize - *sizeleft, bufsize, name);
  806.                 return 1;
  807.             }
  808.             bufsize -= count;
  809.             *sizeleft -= count;
  810.             userec(start);
  811.             start = findrec();
  812.             bzero(start->charptr, RECORDSIZE);
  813.         }
  814.  
  815.  
  816.         clear_buffer(tempbuf);
  817.         count = read(fd, tempbuf, bufsize);
  818.         bcopy(tempbuf, start->charptr, RECORDSIZE);
  819.         if (count < 0)     {
  820.             msg_perror("read error at byte %ld, reading %d bytes, in file %s",
  821.                     fullsize - *sizeleft, bufsize, name);
  822.             return 1;
  823.         }
  824. /*        if (amt_read >= RECORDSIZE) {
  825.             amt_read = 0;
  826.             userec(start+(count-1)/RECORDSIZE);
  827.             if (count != bufsize) {
  828.                 msg("file %s shrunk by %d bytes, padding with zeros.\n", name, sizeleft);
  829.                 return 1;
  830.             }
  831.             start = findrec();
  832.         } else
  833.             amt_read += bufsize;*/
  834.         *sizeleft -= count;
  835.         userec(start);
  836.  
  837.     }
  838.     free(sparsearray);
  839. /*    userec(start+(count-1)/RECORDSIZE);*/
  840.     return 0;
  841.  
  842. }
  843.  
  844. init_sparsearray()
  845. {
  846.     register int i;
  847.  
  848.     sp_array_size = 10;
  849.     /*
  850.      * Make room for our scratch space -- initially is 10 elts long
  851.      */
  852.     sparsearray = (struct sp_array *) malloc(sp_array_size * sizeof(struct sp_array));
  853.     for (i = 0; i < sp_array_size; i++) {
  854.         sparsearray[i].offset = 0;
  855.         sparsearray[i].numbytes = 0;
  856.     }
  857. }
  858.  
  859.  
  860.  
  861. /*
  862.  * Okay, we've got a sparse file on our hands -- now, what we need to do is
  863.  * make a pass through the file and carefully note where any data is, i.e.,
  864.  * we want to find how far into the file each instance of data is, and how
  865.  * many bytes are there.  We store this information in the sparsearray,
  866.  * which will later be translated into header information.  For now, we use
  867.  * the sparsearray as convenient storage.
  868.  *
  869.  * As a side note, this routine is a mess.  If I could have found a cleaner
  870.  * way to do it, I would have.  If anyone wants to find a nicer way to do
  871.  * this, feel free.
  872.  */
  873. int
  874. deal_with_sparse(name, header, nulls_at_end)
  875.     char        *name;
  876.     union record     *header;
  877.  
  878. {
  879.     long    numbytes = 0;
  880.     long    offset = 0;
  881.     long    save_offset;
  882.     int    fd;
  883.     int    start,
  884.         end;
  885.     int    end_nulls = 0;
  886.     int    current_size = hstat.st_size;
  887.     int    sparse_ind = 0,
  888.         cc;
  889.     char    buf[RECORDSIZE];
  890.     int    read_last_data = 0; /* did we just read the last record? */
  891.     int     amidst_data = 0;
  892.  
  893.     header->header.isextended = 0;
  894.     /*
  895.      * Can't open the file -- this problem will be caught later on,
  896.      * so just return.
  897.      */
  898.     if ((fd = open(name, O_RDONLY)) < 0)
  899.         return;
  900.  
  901.     init_sparsearray();
  902.     clear_buffer(buf);
  903.  
  904.     while ((cc = read(fd, buf, sizeof buf)) != 0) {
  905.  
  906.         if (sparse_ind > sp_array_size-1) {
  907.  
  908.         /*
  909.          * realloc the scratch area, since we've run out of room --
  910.          */
  911.             sparsearray = (struct sp_array *)
  912.                     realloc(sparsearray,
  913.                          2 * sp_array_size * (sizeof(struct sp_array)));
  914.             sp_array_size *= 2;
  915.         }
  916.         if (cc == sizeof buf) {
  917.             if (zero_record(buf)) {
  918.                 if (amidst_data) {
  919.                     sparsearray[sparse_ind++].numbytes
  920.                         = numbytes;
  921.                     amidst_data = 0;
  922.                     numbytes = 0;
  923.                 }
  924.                 offset += cc;
  925.             } else {  /* !zero_record(buf) */
  926.                 if (!amidst_data) {
  927.                         amidst_data = 1;
  928.                     where_is_data(&start, &end, buf);
  929.                     numbytes += end - start;
  930.                     offset += start;
  931.                     sparsearray[sparse_ind].offset = offset;
  932.                 } else
  933.                     numbytes += cc;
  934.                 offset += cc;
  935.             }
  936.         } else if (cc < sizeof buf) {
  937.             if (!zero_record(buf)) {
  938.                 if (!amidst_data) {
  939.                     amidst_data = 1;
  940.                     where_is_data(&start, &end, buf);
  941.                     /* In case there are nulls at the
  942.                        end that we need to remember */
  943.                     if (end < cc)
  944.                         end = cc;
  945.                     numbytes += start - end;
  946.                     offset += start;
  947. /*                    end_nulls = RECORDSIZE - end;*/
  948.                 } else {
  949.                     numbytes += cc;
  950. /*                    end_nulls = RECORDSIZE - end;*/
  951.                 }
  952.                 sparsearray[sparse_ind].numbytes = numbytes;
  953.             } /* else
  954.                 end_nulls = cc;*/
  955.         }
  956.         clear_buffer(buf);
  957.     }
  958.     if (numbytes)
  959.             sparsearray[sparse_ind].numbytes = numbytes;
  960.     close(fd);
  961. /*    printf("%d\n", end_nulls);
  962.     *nulls_at_end = end_nulls;*/
  963.  
  964.     return sparse_ind;
  965. }
  966.  
  967. /*
  968.  * Just zeroes out the buffer so we don't confuse ourselves with leftover
  969.  * data.
  970.  */
  971. clear_buffer(buf)
  972.     char    *buf;
  973. {
  974.     register int     i;
  975.  
  976.     for (i = 0; i < RECORDSIZE; i++)
  977.         buf[i] = '\0';
  978. }
  979.  
  980. /*
  981.  * JK -
  982.  * This routine takes a character array, and tells where within that array
  983.  * the data can be found.  It skips over any zeros, and sets the first
  984.  * non-zero point in the array to be the "start", and continues until it
  985.  * finds non-data again, which is marked as the "end."  This routine is
  986.  * mainly for 1) seeing how far into a file we must lseek to data, given
  987.  * that we have a sparse file, and 2) determining the "real size" of the
  988.  * file, i.e., the number of bytes in the sparse file that are data, as
  989.  * opposed to the zeros we are trying to skip.
  990.  */
  991. where_is_data(from, to, buffer)
  992.     int    *from,
  993.         *to;
  994.     char    *buffer;
  995. {
  996.     register int    i = 0;
  997.     register int    save_to = *to;
  998.     int    amidst_data = 0;
  999.  
  1000.  
  1001.     while (!buffer[i])
  1002.         i++;
  1003.     *from = i;
  1004.  
  1005.     if (*from < 16)    /* don't bother */
  1006.         *from = 0;
  1007.     /* keep going to make sure there isn't more real
  1008.        data in this record */
  1009.     while (i < RECORDSIZE) {
  1010.         if (!buffer[i]) {
  1011.             if (amidst_data) {
  1012.                 save_to = i;
  1013.                 amidst_data = 0;
  1014.             }
  1015.             i++;
  1016.         }
  1017.         else if (buffer[i]) {
  1018.             if (!amidst_data)
  1019.                 amidst_data = 1;
  1020.             i++;
  1021.         }
  1022.     }
  1023.     if (i == RECORDSIZE)
  1024.         *to = i;
  1025.     else
  1026.         *to = save_to;
  1027.  
  1028. }
  1029.  
  1030. /*
  1031.  * Takes a recordful of data and basically cruises through it to see if
  1032.  * it's made *entirely* of zeros, returning a 0 the instant it finds
  1033.  * something that is a non-zero, i.e., useful data.
  1034.  */
  1035. zero_record(buffer)
  1036.     char    *buffer;
  1037. {
  1038.     register int    i;
  1039.  
  1040.     for (i = 0; i < RECORDSIZE; i++)
  1041.         if (buffer[i] != '\000')
  1042.             return 0;
  1043.     return 1;
  1044. }
  1045.  
  1046. find_new_file_size(filesize, highest_index)
  1047.     int    *filesize;
  1048.     int    highest_index;
  1049. {
  1050.     register int     i;
  1051.  
  1052.     *filesize = 0;
  1053.     for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
  1054.         *filesize += sparsearray[i].numbytes;
  1055. }
  1056.  
  1057. /*
  1058.  * Make a header block for the file  name  whose stat info is  st .
  1059.  * Return header pointer for success, NULL if the name is too long.
  1060.  */
  1061. union record *
  1062. start_header(name, st)
  1063.     char    *name;
  1064.     register struct stat *st;
  1065. {
  1066.     register union record *header;
  1067.  
  1068.     header = (union record *) findrec();
  1069.     bzero(header->charptr, sizeof(*header)); /* XXX speed up */
  1070.  
  1071.     /*
  1072.      * Check the file name and put it in the record.
  1073.      */
  1074.     if(!f_absolute_paths) {
  1075.         static int warned_once = 0;
  1076. #ifdef MSDOS
  1077.         if(name[1]==':') {
  1078.             name+=2;
  1079.             if(!warned_once++)
  1080.                 msg("Removing drive spec from names in the archive");
  1081.         }
  1082. #endif
  1083.         while ('/' == *name) {
  1084.             name++;                /* Force relative path */
  1085.             if (!warned_once++)
  1086.                 msg("Removing leading / from absolute path names in the archive.");
  1087.         }
  1088.     }
  1089.     strcpy(header->header.name, name);
  1090.     if (header->header.name[NAMSIZ-1]) {
  1091.         msg("%s: name too long\n", name);
  1092.         return NULL;
  1093.     }
  1094.  
  1095.     to_oct((long) (st->st_mode & ~S_IFMT),
  1096.                     8,  header->header.mode);
  1097.     to_oct((long) st->st_uid,    8,  header->header.uid);
  1098.     to_oct((long) st->st_gid,    8,  header->header.gid);
  1099.     to_oct((long) st->st_size,    1+12, header->header.size);
  1100.     to_oct((long) st->st_mtime,    1+12, header->header.mtime);
  1101.     /* header->header.linkflag is left as null */
  1102.     if(f_gnudump) {
  1103.         to_oct((long) st->st_atime, 1+12, header->header.atime);
  1104.         to_oct((long) st->st_ctime, 1+12, header->header.ctime);
  1105.     }
  1106.  
  1107. #ifndef NONAMES
  1108.     /* Fill in new Unix Standard fields if desired. */
  1109.     if (f_standard) {
  1110.         header->header.linkflag = LF_NORMAL;    /* New default */
  1111.         strcpy(header->header.magic, TMAGIC);    /* Mark as Unix Std */
  1112.         finduname(header->header.uname, st->st_uid);
  1113.         findgname(header->header.gname, st->st_gid);
  1114.     }
  1115. #endif
  1116.     return header;
  1117. }
  1118.  
  1119. /*
  1120.  * Finish off a filled-in header block and write it out.
  1121.  * We also print the file name and/or full info if verbose is on.
  1122.  */
  1123. void
  1124. finish_header(header)
  1125.     register union record *header;
  1126. {
  1127.     register int    i, sum;
  1128.     register char    *p;
  1129.     void bcopy();
  1130.  
  1131.     bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  1132.  
  1133.     sum = 0;
  1134.     p = header->charptr;
  1135.     for (i = sizeof(*header); --i >= 0; ) {
  1136.         /*
  1137.          * We can't use unsigned char here because of old compilers,
  1138.          * e.g. V7.
  1139.          */
  1140.         sum += 0xFF & *p++;
  1141.     }
  1142.  
  1143.     /*
  1144.      * Fill in the checksum field.  It's formatted differently
  1145.      * from the other fields:  it has [6] digits, a null, then a
  1146.      * space -- rather than digits, a space, then a null.
  1147.      * We use to_oct then write the null in over to_oct's space.
  1148.      * The final space is already there, from checksumming, and
  1149.      * to_oct doesn't modify it.
  1150.      *
  1151.      * This is a fast way to do:
  1152.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1153.      */
  1154.     to_oct((long) sum,    8,  header->header.chksum);
  1155.     header->header.chksum[6] = '\0';    /* Zap the space */
  1156.  
  1157.     userec(header);
  1158.  
  1159.     if (f_verbose) {
  1160.         /* These globals are parameters to print_header, sigh */
  1161.         head = header;
  1162.         /* hstat is already set up */
  1163.         head_standard = f_standard;
  1164.         print_header();
  1165.     }
  1166.  
  1167.     return;
  1168. }
  1169.  
  1170.  
  1171. /*
  1172.  * Quick and dirty octal conversion.
  1173.  * Converts long "value" into a "digs"-digit field at "where",
  1174.  * including a trailing space and room for a null.  "digs"==3 means
  1175.  * 1 digit, a space, and room for a null.
  1176.  *
  1177.  * We assume the trailing null is already there and don't fill it in.
  1178.  * This fact is used by start_header and finish_header, so don't change it!
  1179.  *
  1180.  * This should be equivalent to:
  1181.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1182.  * except that sprintf fills in the trailing null and we don't.
  1183.  */
  1184. void
  1185. to_oct(value, digs, where)
  1186.     register long    value;
  1187.     register int    digs;
  1188.     register char    *where;
  1189. {
  1190.  
  1191.     --digs;                /* Trailing null slot is left alone */
  1192.     where[--digs] = ' ';        /* Put in the space, though */
  1193.  
  1194.     /* Produce the digits -- at least one */
  1195.     do {
  1196.         where[--digs] = '0' + (char)(value & 7); /* one octal digit */
  1197.         value >>= 3;
  1198.     } while (digs > 0 && value != 0);
  1199.  
  1200.     /* Leading spaces, if necessary */
  1201.     while (digs > 0)
  1202.         where[--digs] = ' ';
  1203.  
  1204. }
  1205.  
  1206.  
  1207. /*
  1208.  * Write the EOT record(s).
  1209.  * We actually zero at least one record, through the end of the block.
  1210.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1211.  */
  1212. write_eot()
  1213. {
  1214.     union record *p;
  1215.     int bufsize;
  1216.     void bzero();
  1217.  
  1218.     p = findrec();
  1219.     bufsize = endofrecs()->charptr - p->charptr;
  1220.     bzero(p->charptr, bufsize);
  1221.     userec(p);
  1222. }
  1223.