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