home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / g / gtak212.zip / 1.10 / create.c < prev    next >
C/C++ Source or Header  |  1993-01-10  |  39KB  |  1,531 lines

  1. /*****************************************************************************
  2.  * $Id: create.c,v 1.12 1993/01/10 11:19:33 ak Exp $
  3.  *****************************************************************************
  4.  * $Log: create.c,v $
  5.  * Revision 1.12  1993/01/10  11:19:33  ak
  6.  * J.R.: Bugfix: f_gnudump='f' sicherte doppelt.
  7.  *
  8.  * Revision 1.11  1992/12/13  09:39:45  ak
  9.  * K.U.R: f_archive/f_reset_archive added to support the "archived" bit.
  10.  *
  11.  * Revision 1.10  1992/10/31  06:58:31  ak
  12.  * *** empty log message ***
  13.  *
  14.  * Revision 1.9  1992/10/31  06:54:59  ak
  15.  * Modified -G (again) to specify the generation of increment.
  16.  *
  17.  * Revision 1.8  1992/10/25  10:20:32  ak
  18.  * Don't archive/extract ctime+atime if a single -p or --same-perm is
  19.  * specified. It make trouble on incremental backups and file transfers.
  20.  * Added an option --all-timestamps or twice -p to archive/extract
  21.  * ctime+atime.
  22.  *
  23.  * Revision 1.7  1992/09/29  09:55:35  ak
  24.  * K.U.R., once again :-)
  25.  * - removed a dup() in buffer.c
  26.  * - EMX opendir with hidden/system test in gnu.c (...dotdot)
  27.  *
  28.  * Revision 1.6  1992/09/26  08:32:09  ak
  29.  * *** empty log message ***
  30.  *
  31.  * Revision 1.5  1992/09/20  07:47:00  ak
  32.  * Fixes from Kai Uwe Rommel
  33.  *   --checkpoints instead of --semi-verbose (1.11)
  34.  *   -g filenames
  35.  *
  36.  * Revision 1.4  1992/09/12  15:57:44  ak
  37.  * - Usenet patches for GNU TAR 1.10
  38.  * - Bugfixes and patches of Kai Uwe Rommel:
  39.  *         filename conversion for FAT
  40.  *         EMX 0.8e
  41.  *         -0..1 alias for a: b:
  42.  *         -2..7 alias for +++TAPE$x
  43.  *
  44.  * Revision 1.3  1992/09/09  14:25:54  ak
  45.  * K.U.R: save atime/mtime when -p is given
  46.  *
  47.  * Revision 1.2  1992/09/02  20:07:50  ak
  48.  * Version AK200
  49.  * - Tape access
  50.  * - Quick file access
  51.  * - OS/2 extended attributes
  52.  * - Some OS/2 fixes
  53.  * - Some fixes of Kai Uwe Rommel
  54.  *
  55.  * Revision 1.1.1.1  1992/09/02  19:21:09  ak
  56.  * Original GNU Tar 1.10 with some filenames changed for FAT compatibility.
  57.  *
  58.  * Revision 1.1  1992/09/02  19:21:07  ak
  59.  * Initial revision
  60.  *
  61.  *****************************************************************************/
  62.  
  63. static char *rcsid = "$Id: create.c,v 1.12 1993/01/10 11:19:33 ak Exp $";
  64.  
  65. /*
  66.  * Modified by Andreas Kaiser July 92.
  67.  * See CHANGES.AK for info.
  68.  */
  69.  
  70. /* I fixed a bug in the handling of the f_local_filesys flag.  It was
  71.    falsely assumed that device numbers were aways non-negative, so the
  72.    case of the top-level call to dump_file could be flagged by a curdev
  73.    value of -1.  Worse yet, this was tested for as simply <0.  However,
  74.    on some systems (such as mine), legal device numbers *can* be
  75.    negative.  It would have worked around my immediate problem to just
  76.    change the test to test specifically for -1.  However, this could
  77.    still run into trouble if by bad luck someone actually had a device
  78.    numbered -1.  Therefore, I added a seperate topLevelP argument.
  79.    This change therefore propogated to update.c as well.
  80.      - Max Hailperin <max@nic.gac.edu> 8/1/91 */
  81.  
  82. /* I also commented out the bogus handling of sockets.
  83.      - Max Hailrin <max@nic.gac.edu> 8/2/91 */
  84.  
  85. /* Create a tar archive.
  86.    Copyright (C) 1988 Free Software Foundation
  87.  
  88. This file is part of GNU Tar.
  89.  
  90. GNU Tar is free software; you can redistribute it and/or modify
  91. it under the terms of the GNU General Public License as published by
  92. the Free Software Foundation; either version 1, or (at your option)
  93. any later version.
  94.  
  95. GNU Tar is distributed in the hope that it will be useful,
  96. but WITHOUT ANY WARRANTY; without even the implied warranty of
  97. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  98. GNU General Public License for more details.
  99.  
  100. You should have received a copy of the GNU General Public License
  101. along with GNU Tar; see the file COPYING.  If not, write to
  102. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  103.  
  104. /*
  105.  * Create a tar archive.
  106.  *
  107.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  108.  *
  109.  * @(#)create.c 1.36 11/6/87 - gnu
  110.  */
  111. #include <sys/types.h>
  112. #include <sys/stat.h>
  113. #include <stdio.h>
  114.  
  115. #ifndef V7
  116. #include <fcntl.h>
  117. #endif
  118.  
  119. #ifndef    MSDOS
  120. #include <sys/file.h>
  121. #include <sys/param.h>        /* for MAXPATHLEN */
  122. #include <pwd.h>
  123. #include <grp.h>
  124. #endif
  125.  
  126. #ifdef BSD42
  127.  #include <sys/dir.h>
  128. #else
  129.  #ifdef __MSDOS__
  130.   #include "msd_dir.h"
  131.  #else
  132.   #ifdef USG
  133.    #ifdef NDIR
  134.     #include <ndir.h>
  135.    #else
  136.     #include <dirent.h>
  137.    #endif
  138.    #ifndef DIRECT
  139.     #define direct dirent
  140.    #endif
  141.    #define DP_NAMELEN(x) strlen((x)->d_name)
  142.   #else
  143.    /*
  144.     * FIXME: On other systems there is no standard place for the header file
  145.     * for the portable directory access routines.  Change the #include line
  146.     * below to bring it in from wherever it is.
  147.     */
  148.    #ifdef OS2
  149.     #include "dirent.h"
  150.     #define direct dirent
  151.     #define DP_NAMELEN(x) strlen((x)->d_name)
  152.    #else
  153.     #include "ndir.h"
  154.    #endif
  155.   #endif
  156.  #endif
  157. #endif
  158.  
  159. #ifndef DP_NAMELEN
  160. #define DP_NAMELEN(x)    (x)->d_namlen
  161. #endif
  162.  
  163. #ifdef USG
  164. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  165. #endif
  166.  
  167. /*
  168.  * V7 doesn't have a #define for this.
  169.  */
  170. #ifndef O_RDONLY
  171. #define    O_RDONLY    0
  172. #endif
  173.  
  174. /*
  175.  * Most people don't have a #define for this.
  176.  */
  177. #ifndef    O_BINARY
  178. #define    O_BINARY    0
  179. #endif
  180.  
  181. #ifndef MAXPATHLEN
  182. #define MAXPATHLEN 1024
  183. #endif
  184.  
  185. #include "tar.h"
  186. #include "port.h"
  187. #include "rmt.h"
  188.  
  189. extern struct stat hstat;        /* Stat struct corresponding */
  190.  
  191. #ifndef MSDOS
  192. extern dev_t ar_dev;
  193. extern ino_t ar_ino;
  194. #endif
  195.  
  196. /* JF */
  197. extern struct name *gnu_list_name;
  198.  
  199. /*
  200.  * If there are no symbolic links, there is no lstat().  Use stat().
  201.  */
  202. #ifndef S_IFLNK
  203. #define lstat stat
  204. #endif
  205.  
  206. extern char    *malloc();
  207. extern char    *strcpy();
  208. extern char    *strncpy();
  209. extern void    bzero();
  210. extern void    bcopy();
  211. extern int    errno;
  212.  
  213. extern void print_header();
  214.  
  215. union record *start_header();
  216. void finish_header();
  217. void finduname();
  218. void findgname();
  219. char *name_next();
  220. void to_oct();
  221. void dump_file();
  222.  
  223.  
  224. /* This code moved from tar.h since create.c is the only file that cares
  225.    about 'struct link's.  This means that other files might not have to
  226.    include sys/types.h any more.
  227.  */
  228.  
  229. struct link {
  230.     struct link    *next;
  231.     dev_t        dev;
  232.     ino_t        ino;
  233.     short        linkcount;
  234.     char        name[1];
  235. };
  236.  
  237. struct link    *linklist;    /* Points to first link in list */
  238.  
  239. static nolinks;            /* Gets set if we run out of RAM */
  240.  
  241. /*
  242.  * "Scratch" space to store the information about a sparse file before
  243.  * writing the info into the header or extended header
  244.  */
  245. /* struct sp_array     *sparsearray;*/
  246.  
  247. /* number of elts storable in the sparsearray */
  248. /*int     sparse_array_size = 10;*/
  249.  
  250. /* handle multivolume mangled properly PEC 7-29-91 */
  251. static int mange;
  252. char mange_name[NAMSIZ];
  253. /* end PEC 7-29-91*/
  254.  
  255. void
  256. create_archive()
  257. {
  258.     register char    *p;
  259.     char *name_from_list();
  260.  
  261.     open_archive(0);        /* Open for writing */
  262.  
  263.     if(f_gnudump) {
  264.         char buf[MAXNAMLEN],*q,*bufp;
  265.  
  266.         collect_and_sort_names();
  267.  
  268.         while(p=name_from_list())
  269.             dump_file(p,-1,1);
  270.         /* if(!f_dironly) { */
  271.             blank_name_list();
  272.             while(p=name_from_list()) {
  273.                 strcpy(buf,p);
  274.                 if(p[strlen(p)-1]!='/')
  275.                     strcat(buf,"/");
  276.                 bufp=buf+strlen(buf);
  277.                 for(q=gnu_list_name->dir_contents;q && *q;q+=strlen(q)+1) {
  278.                     if(*q=='Y') {
  279.                         strcpy(bufp,q+1);
  280.                         dump_file(buf,-1,1);
  281.                     }
  282.                 }
  283.             }
  284.         /* } */
  285.     
  286.     } else {
  287.         p = name_next(1);
  288.         if(!p)
  289.             dump_file(".", -1,1);
  290.         else {
  291.             do dump_file(p, -1,1);
  292.             while (p = name_next(1));
  293.         }
  294.     }
  295.  
  296.     write_mangled();
  297.     write_eot();
  298.     close_archive();
  299.     if(f_gnudump)
  300.         write_dir_file();
  301.     name_close();
  302. }
  303.  
  304. /*
  305.  * Dump a single file.  If it's a directory, recurse.
  306.  * Result is 1 for success, 0 for failure.
  307.  * Sets global "hstat" to stat() output for this file.
  308.  */
  309. void
  310. dump_file (p, curdev, topLevelP)
  311.     char    *p;            /* File name to dump */
  312.     int    curdev;            /* Device our parent dir was on */
  313.         int     topLevelP;      /* 1 if top level call */
  314. {
  315.     union record    *header;
  316.     char type;
  317.     extern char *save_name;        /* JF for multi-volume support */
  318.     extern long save_totsize;
  319.     extern long save_sizeleft;
  320.     union record    *exhdr;
  321.     char save_linkflag;
  322.     extern time_t new_time;
  323.     int sparse_ind = 0;
  324.  
  325.  
  326.     if(f_confirm && !confirm("add",p))
  327.         return;
  328.  
  329.     /*
  330.      * Use stat if following (rather than dumping) 4.2BSD's
  331.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  332.      * systems, is #define'd to stat anyway.
  333.      */
  334. #ifdef AIX
  335.     if (0 != f_follow_links ?
  336.         statx (p, &hstat, STATSIZE, STX_HIDDEN):
  337.         statx (p, &hstat, STATSIZE, STX_HIDDEN|STX_LINK))
  338. #else
  339.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  340. #endif /* AIX */
  341.     {
  342. badperror:
  343.         msg_perror("can't add file %s",p);
  344. badfile:
  345.         errors++;
  346.         return;
  347.     }
  348.  
  349. #ifdef AIX
  350.     if (S_ISHIDDEN (hstat.st_mode)) {
  351.         char *new = (char *)allocate (strlen (p) + 2);
  352.         if (new) {
  353.             strcpy (new, p);
  354.             strcat (new, "@");
  355.             p = new;
  356.         }
  357.     }
  358. #endif /* AIX */
  359. #ifdef MSDOS
  360.     get_fileattr(p, &hstat);
  361. #endif
  362.  
  363.     /* See if we only want new files, and check if this one is too old to
  364.        put in the archive. */
  365.     if(   f_new_files
  366.        && !f_gnudump
  367.         && new_time>hstat.st_mtime
  368.         && (hstat.st_mode&S_IFMT)!=S_IFDIR
  369.         && (f_new_files>1 || new_time>hstat.st_ctime)) {
  370.         if(topLevelP) {
  371.             msg("%s: is unchanged; not dumped",p);
  372.         }
  373.         return;
  374.     }
  375.  
  376. #ifndef MSDOS
  377.     /* See if we are trying to dump the archive */
  378.     if(ar_dev && hstat.st_dev==ar_dev && hstat.st_ino==ar_ino) {
  379.         msg("%s is the archive; not dumped",p);
  380.         return;
  381.     }
  382.  
  383.     /*
  384.      * Check for multiple links.
  385.      *
  386.      * We maintain a list of all such files that we've written so
  387.      * far.  Any time we see another, we check the list and
  388.      * avoid dumping the data again if we've done it once already.
  389.      */
  390.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  391.         register struct link    *lp;
  392.  
  393.     case S_IFREG:            /* Regular file */
  394. #ifdef S_IFCTG
  395.     case S_IFCTG:            /* Contigous file */
  396. #endif
  397. #ifdef S_IFCHR
  398.     case S_IFCHR:            /* Character special file */
  399. #endif
  400.  
  401. #ifdef S_IFBLK
  402.     case S_IFBLK:            /* Block     special file */
  403. #endif
  404.  
  405. #ifdef S_IFIFO
  406.     case S_IFIFO:            /* Fifo      special file */
  407. #endif
  408.  
  409.         /* First quick and dirty.  Hashing, etc later FIXME */
  410.         for (lp = linklist; lp; lp = lp->next) {
  411.             if (lp->ino == hstat.st_ino &&
  412.                 lp->dev == hstat.st_dev) {
  413.                 char *link_name = lp->name;
  414.  
  415.                 /* We found a link. */
  416.                 hstat.st_size = 0;
  417.                 header = start_header(p, &hstat, 0);
  418.                 if (header == NULL) goto badfile;
  419.                 while(!f_absolute_paths && *link_name == '/') {
  420.                     static int link_warn = 0;
  421.  
  422.                     if (!link_warn) {
  423.                         msg("Removing leading / from absolute links");
  424.                         link_warn++;
  425.                     }
  426.                     link_name++;
  427.                 }
  428.                   strncpy(header->header.linkname,
  429.                     link_name,NAMSIZ);
  430.                 if(header->header.linkname[NAMSIZ-1]) {
  431.                     char *mangled;
  432.                     extern char *find_mangled();
  433.  
  434.                     mangled=find_mangled(link_name);
  435.                     msg("%s: link name too long: mangled to %s",link_name,mangled);
  436.                     strncpy(header->header.linkname,mangled,NAMSIZ);
  437.                 }
  438.                 header->header.linkflag = LF_LINK;
  439.                 finish_header(header);
  440.         /* FIXME: Maybe remove from list after all links found? */
  441.                 return;        /* We dumped it */
  442.             }
  443.         }
  444.  
  445.         /* Not found.  Add it to the list of possible links. */
  446.         lp = (struct link *)malloc((unsigned)(sizeof(struct link)+strlen(p)));
  447.         if (!lp) {
  448.             if (!nolinks) {
  449.                 msg(
  450.     "no memory for links, they will be dumped as separate files");
  451.                 nolinks++;
  452.             }
  453.         }
  454.         lp->ino = hstat.st_ino;
  455.         lp->dev = hstat.st_dev;
  456.         strcpy(lp->name, p);
  457.         lp->next = linklist;
  458.         linklist = lp;
  459.     }
  460. #endif /* MSDOS */
  461.  
  462. #ifdef OS2
  463.     if (f_use_protection && (eabuf = ea_load(p)) != NULL) {
  464.         /* have extended attributes */
  465.         char _far *ptr;
  466.         long bufsize, count;
  467.         register union record *start;
  468.         unsigned len;
  469.  
  470.         if ((header = start_header(p, &hstat, 1)) == NULL) {
  471.             ea_free(eabuf);
  472.             goto badfile;
  473.         }
  474.         len = strlen(header->header.name)-1;
  475.         if (header->header.name[len] == '/')
  476.             header->header.name[len] = '\0';
  477.         to_oct(EALength(eabuf), 1+12, header->header.size);
  478.         header->header.linkflag = LF_EATTR;
  479.         finish_header(header);
  480.  
  481.         for (len = EALength(eabuf), ptr = (char _far *)eabuf; len != 0; ) {
  482.             start = findrec();
  483.             bufsize = endofrecs()->charptr - start->charptr;
  484.             if (len < bufsize) {
  485.                 /* Last read -- zero out area beyond */
  486.                 bufsize = (int)len;
  487.                 count = bufsize % RECORDSIZE;
  488.                 if (count) 
  489.                     bzero(start->charptr + len,
  490.                         (int)(RECORDSIZE - count));
  491.             }
  492.             memcpy(start->charptr, ptr, bufsize);
  493.             ptr += bufsize;
  494.             len -= bufsize;
  495.  
  496.             /* This is nonportable (the type of userec's arg). */
  497.             userec(start+(bufsize-1)/RECORDSIZE);
  498.         }
  499.         ea_free(eabuf);
  500.     }
  501. #endif
  502.     
  503.     /*
  504.      * This is not a link to a previously dumped file, so dump it.
  505.      */
  506.     switch (hstat.st_mode & S_IFMT) {
  507.  
  508.     case S_IFREG:            /* Regular file */
  509. #ifdef S_IFCTG
  510.     case S_IFCTG:            /* Contiguous file */
  511. #endif
  512.     {
  513.         int    f;        /* File descriptor */
  514.         long    bufsize, count;
  515.         long    sizeleft;
  516.         register union record     *start;
  517.         int     header_moved;
  518.         char    isextended = 0;
  519.         int     upperbound;
  520.         int    end_nulls = 0;
  521.         
  522.         header_moved = 0;
  523.  
  524. #ifdef BSD42
  525.         if (f_sparse_files) {
  526.         /*
  527.           * JK - This is the test for sparseness: whether the
  528.          * "size" of the file matches the number of blocks
  529.          * allocated for it.  If there is a smaller number
  530.          * of blocks that would be necessary to accommodate
  531.          * a file of this size, we have a sparse file, i.e.,
  532.          * at least one of those records in the file is just
  533.          * a useless hole.
  534.          */
  535. #ifdef hpux    /* Nice of HPUX to gratuitiously change it, huh?  - mib */
  536.                 if (hstat.st_size - (hstat.st_blocks * 1024) > 1024 ) {
  537. #else
  538.             if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE) {
  539. #endif
  540.                 int    filesize = hstat.st_size;
  541.                 register int i;
  542.                 
  543.                 header = start_header(p, &hstat, 0);
  544.                 if (header == NULL)
  545.                     goto badfile;
  546.                 header->header.linkflag = LF_SPARSE;
  547.                 header_moved++;
  548.                 
  549.             /*
  550.              * Call the routine that figures out the
  551.              * layout of the sparse file in question.
  552.              * UPPERBOUND is the index of the last
  553.              * element of the "sparsearray," i.e.,
  554.              * the number of elements it needed to
  555.              * describe the file.
  556.              */
  557.                  
  558.                 upperbound = deal_with_sparse(p, header);
  559.                          
  560.             /* 
  561.              * See if we'll need an extended header
  562.              * later
  563.              */
  564.                 if (upperbound > SPARSE_IN_HDR-1)
  565.                      header->header.isextended++;
  566.             /*
  567.              * We store the "real" file size so
  568.              * we can show that in case someone wants
  569.              * to list the archive, i.e., tar tvf <file>.
  570.              * It might be kind of disconcerting if the
  571.              * shrunken file size was the one that showed
  572.              * up.
  573.              */
  574.                  to_oct((long) hstat.st_size, 1+12, 
  575.                          header->header.realsize);
  576.                     
  577.             /*
  578.              * This will be the new "size" of the
  579.              * file, i.e., the size of the file
  580.              * minus the records of holes that we're
  581.              * skipping over. 
  582.              */
  583.                  
  584.                 find_new_file_size(&filesize, upperbound);
  585.                 hstat.st_size = filesize;
  586.                 to_oct((long) filesize, 1+12,
  587.                          header->header.size);
  588. /*                to_oct((long) end_nulls, 1+12, 
  589.                         header->header.ending_blanks);*/
  590.                         
  591.                 for (i = 0; i < SPARSE_IN_HDR; i++) {
  592.                     if (!sparsearray[i].numbytes)
  593.                         break;
  594.                     to_oct(sparsearray[i].offset, 1+12,
  595.                         header->header.sp[i].offset);
  596.                     to_oct(sparsearray[i].numbytes, 1+12,
  597.                         header->header.sp[i].numbytes);
  598.                 }
  599.                     
  600.             }
  601.         }
  602. #else
  603.         upperbound=SPARSE_IN_HDR-1;
  604. #endif
  605.         
  606.         sizeleft = hstat.st_size;
  607.         /* Don't bother opening empty, world readable files. */
  608.         if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
  609.             f = open(p, O_RDONLY|O_BINARY);
  610.             if (f < 0) goto badperror;
  611.         } else {
  612.             f = -1;
  613.         }
  614.         
  615.         /* If the file is sparse, we've already taken care of this */
  616.         if (!header_moved) {
  617.             header = start_header(p, &hstat, 0);
  618.             if (header == NULL) {
  619.                 if(f>=0)
  620.                     (void)close(f);
  621.                 goto badfile;
  622.             }
  623.         }
  624. #ifdef S_IFCTG
  625.         /* Mark contiguous files, if we support them */
  626.         if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
  627.             header->header.linkflag = LF_CONTIG;
  628.         }
  629. #endif
  630.         isextended = header->header.isextended;
  631.         save_linkflag = header->header.linkflag;
  632.         finish_header(header);
  633.         if (isextended) {
  634.             int     sum = 0;
  635.             register int i;
  636. /*            register union record *exhdr;*/
  637.             int     arraybound = SPARSE_EXT_HDR;
  638.             /* static */ int index_offset = SPARSE_IN_HDR;
  639.             
  640.     extend:        exhdr = findrec();
  641.             
  642.             if (exhdr == NULL) goto badfile;
  643.             bzero(exhdr->charptr, RECORDSIZE);
  644.             for (i = 0; i < SPARSE_EXT_HDR; i++) {
  645.                 if (i+index_offset > upperbound)
  646.                     break;
  647.                 to_oct((long) sparsearray[i+index_offset].numbytes,
  648.                      1+12,
  649.                     exhdr->ext_hdr.sp[i].numbytes);
  650.                 to_oct((long) sparsearray[i+index_offset].offset,
  651.                      1+12,
  652.                     exhdr->ext_hdr.sp[i].offset);
  653.             }
  654.             userec(exhdr);
  655. /*            sum += i;
  656.             if (sum < upperbound)
  657.                 goto extend;*/
  658.             if (index_offset+i < upperbound) {
  659.                 index_offset += i;
  660.                 exhdr->ext_hdr.isextended++;
  661.                 goto extend;
  662.             }
  663.                 
  664.         }
  665.         if (save_linkflag == LF_SPARSE) {
  666.             if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
  667.                 goto padit;
  668.         }
  669.         else
  670.           while (sizeleft > 0) {
  671.             
  672.             if(f_multivol) {   
  673.                                 /* PEC 7-29-91 */
  674.                 if (mange)
  675.                     save_name = mange_name;
  676.                 else
  677.                     save_name = p;
  678.                 /* end PEC 7-29-91 */
  679.                 save_sizeleft = sizeleft;
  680.                 save_totsize = hstat.st_size;
  681.             }
  682.             start = findrec();
  683.  
  684.             bufsize = endofrecs()->charptr - start->charptr;
  685.                 
  686.             if (sizeleft < bufsize) {
  687.                 /* Last read -- zero out area beyond */
  688.                 bufsize = (int)sizeleft;
  689.                 count = bufsize % RECORDSIZE;
  690.                 if (count) 
  691.                     bzero(start->charptr + sizeleft,
  692.                         (int)(RECORDSIZE - count));
  693.             }
  694.             count = read(f, start->charptr, bufsize);
  695.             if (count < 0) {
  696.                 msg_perror("read error at byte %ld, reading\
  697.  %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);
  698.                 goto padit;
  699.             }
  700.             sizeleft -= count;
  701.  
  702.             /* This is nonportable (the type of userec's arg). */
  703.             userec(start+(count-1)/RECORDSIZE);
  704.  
  705.             if (count == bufsize) continue;
  706.             msg( "file %s shrunk by %d bytes, padding with zeros.", p, sizeleft);
  707.             goto padit;        /* Short read */
  708.         }
  709.  
  710.         if(f_multivol)
  711.             save_name = 0;
  712.  
  713.         if (f >= 0)
  714.             (void)close(f);
  715. #ifdef MSDOS
  716.         if (f_archive || f_reset_archive)
  717.               reset_archive(p);
  718. #endif
  719.  
  720.         break;
  721.  
  722.         /*
  723.          * File shrunk or gave error, pad out tape to match
  724.          * the size we specified in the header.
  725.          */
  726.     padit:
  727.         while(sizeleft>0) {
  728.             save_sizeleft=sizeleft;
  729.             start=findrec();
  730.             bzero(start->charptr,RECORDSIZE);
  731.             userec(start);
  732.             sizeleft-=RECORDSIZE;
  733.         }
  734.         if(f_multivol)
  735.             save_name=0;
  736.         if(f>=0)
  737.             (void)close(f);
  738.         break;
  739. /*        abort(); */
  740.     }
  741.  
  742. #ifdef S_IFLNK
  743.     case S_IFLNK:            /* Symbolic link */
  744.     {
  745.         int size;
  746.  
  747.         hstat.st_size = 0;        /* Force 0 size on symlink */
  748.         header = start_header(p, &hstat, 0);
  749.         if (header == NULL) goto badfile;
  750.         size = readlink(p, header->header.linkname, NAMSIZ);
  751.         if (size < 0) goto badperror;
  752.         if (size == NAMSIZ) {
  753.             char buf[MAXPATHLEN];
  754.  
  755.             readlink(p,buf,MAXPATHLEN);
  756.             /* next_mangle(header->header.linkname); */
  757.             add_symlink_mangle(buf,p,header->header.linkname);
  758.             msg("symbolic link %s too long: mangling to %s",p, header->header.linkname);
  759.             /* size=strlen(header->header.linkname); */
  760.         } else
  761.             header->header.linkname[size] = '\0';
  762.         header->header.linkflag = LF_SYMLINK;
  763.         finish_header(header);        /* Nothing more to do to it */
  764.     }
  765.         break;
  766. #endif
  767.  
  768.     case S_IFDIR:            /* Directory */
  769.     {
  770.         register DIR *dirp;
  771.         register struct direct *d;
  772.         char *namebuf;
  773.         int buflen;
  774.         register int len;
  775.         int our_device = hstat.st_dev;
  776.         extern char *ck_malloc(),*ck_realloc();
  777.  
  778.         /* Build new prototype name */
  779.         len = strlen(p);
  780.         buflen=len+NAMSIZ;
  781.         namebuf=ck_malloc(buflen+1);
  782.         strncpy(namebuf, p, buflen);
  783.         while (len >= 1 && '/' == namebuf[len-1]) 
  784.             len--;            /* Delete trailing slashes */
  785.         namebuf[len++] = '/';        /* Now add exactly one back */
  786.         namebuf[len] = '\0';        /* Make sure null-terminated */
  787.  
  788.         /*
  789.          * Output directory header record with permissions
  790.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  791.          * If old archive format, don't write record at all.
  792.          */
  793.         if (!f_oldarch) {
  794.             hstat.st_size = 0;    /* Force 0 size on dir */
  795.             /*
  796.              * If people could really read standard archives,
  797.              * this should be:        (FIXME)
  798.             header = start_header(f_standard? p: namebuf, &hstat, 0);
  799.              * but since they'd interpret LF_DIR records as
  800.              * regular files, we'd better put the / on the name.
  801.              */
  802.             header = start_header(namebuf, &hstat, 0);
  803.             if (header == NULL)
  804.                 goto badfile;    /* eg name too long */
  805.  
  806.             if (f_gnudump)
  807.                 header->header.linkflag = LF_DUMPDIR;
  808.             else if (f_standard)
  809.                 header->header.linkflag = LF_DIR;
  810.  
  811.             /* If we're gnudumping, we aren't done yet so don't close it. */
  812.             if (!(f_gnudump))
  813.                 finish_header(header);    /* Done with directory header */
  814.         }
  815.  
  816.         if(f_gnudump && gnu_list_name->dir_contents != NULL) {
  817.             int sizeleft;
  818.             int totsize;
  819.             int bufsize;
  820.             union record *start;
  821.             int count;
  822.             char *buf,*p_buf;
  823.  
  824.             buf=gnu_list_name->dir_contents; /* FOO */
  825.             totsize=0;
  826.             for(p_buf=buf;p_buf && *p_buf;) {
  827.                 int tmp;
  828.  
  829.                 tmp=strlen(p_buf)+1;
  830.                 totsize+=tmp;
  831.                 p_buf+=tmp;
  832.             }
  833.             totsize++;
  834.             to_oct((long)totsize,1+12,header->header.size);
  835.             finish_header(header);
  836.             p_buf=buf;
  837.             sizeleft=totsize;
  838.             while(sizeleft>0) {
  839.                 if(f_multivol) {
  840.                     /* PEC 7-29-91 */
  841.                     if (mange)
  842.                         save_name = mange_name;
  843.                     else
  844.                         save_name = p;
  845.                     /* end PEC 7-29-91 */
  846.                     save_sizeleft=sizeleft;
  847.                     save_totsize=totsize;
  848.                 }
  849.                 start=findrec();
  850.                 bufsize=endofrecs()->charptr - start->charptr;
  851.                 if(sizeleft<bufsize) {
  852.                     bufsize=sizeleft;
  853.                     count=bufsize%RECORDSIZE;
  854.                     if(count)
  855.                         bzero(start->charptr+sizeleft,RECORDSIZE-count);
  856.                 }
  857.                 bcopy(p_buf,start->charptr,bufsize);
  858.                 sizeleft-=bufsize;
  859.                 p_buf+=bufsize;
  860.                 userec(start+(bufsize-1)/RECORDSIZE);
  861.             }
  862.             if(f_multivol)
  863.                 save_name = 0;
  864. /*AK17.08.92 namebuf wird nicht freigegeben -> memory leak */
  865. /*AK17.08.92*/        free(namebuf);
  866.              break;
  867.         }
  868.  
  869.         /* Now output all the files in the directory */
  870.         /* if (f_dironly)
  871.             break;        /* Unless the cmdline said not to */
  872.         /*
  873.          * See if we are crossing from one file system to another,
  874.          * and avoid doing so if the user only wants to dump one file system.
  875.          */
  876.         if (f_local_filesys && !topLevelP && curdev != hstat.st_dev) {
  877.             if(f_verbose)
  878.                 msg("%s: is on a different filesystem; not dumped",p);
  879.             break;
  880.         }
  881.  
  882.         if (!f_no_recursion) {
  883.             errno = 0;
  884.             dirp = opendir(p);
  885.             if (!dirp) {
  886.                 if (errno) {
  887.                     msg_perror ("can't open directory %s",p);
  888.                 } else {
  889.                     msg("error opening directory %s",
  890.                         p);
  891.                 }
  892.                 break;
  893.             }
  894.  
  895.             /* Hack to remove "./" from the front of all the file names */
  896.             if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/')
  897.                 len = 0;
  898.  
  899.             /* Should speed this up by cd-ing into the dir, FIXME */
  900.             while (NULL != (d=readdir(dirp))) {
  901.                 /* Skip . and .. */
  902.                 if(is_dot_or_dotdot(d))
  903.                     continue;
  904.     
  905.                 if (DP_NAMELEN(d) + len >= buflen) {
  906.                     buflen=len+DP_NAMELEN(d);
  907.                     namebuf=ck_realloc(namebuf,buflen+1);
  908.                     /* namebuf[len]='\0';
  909.                     msg("file name %s%s too long", 
  910.                         namebuf, d->d_name);
  911.                     continue; */
  912.                 }
  913.                 strcpy(namebuf+len, d->d_name);
  914.                 if(f_exclude && check_exclude(namebuf))
  915.                     continue;
  916.                 dump_file(namebuf, our_device, 0);
  917.             }
  918.  
  919.             closedir(dirp);
  920.         }
  921.         free(namebuf);
  922.     }
  923.         break;
  924.  
  925. #ifdef S_IFCHR
  926.     case S_IFCHR:            /* Character special file */
  927.         type = LF_CHR;
  928.         goto easy;
  929. #endif
  930.  
  931. #ifdef S_IFBLK
  932.     case S_IFBLK:            /* Block     special file */
  933.         type = LF_BLK;
  934.         goto easy;
  935. #endif
  936.  
  937. /* Avoid screwy apollo lossage where S_IFIFO == S_IFSOCK */
  938. #if ((_ISP__M68K == 0) && (_ISP__A88K == 0))
  939. #ifdef S_IFIFO
  940.     case S_IFIFO:            /* Fifo      special file */
  941.         
  942.         type = LF_FIFO;
  943.         goto easy;
  944. #endif
  945. #endif
  946.  
  947. /*  This handling of sockets doesn't seem to achieve anything except
  948.     spurious errors on verify.  -Max Hailperin 8/2/91 */
  949. #if 0
  950. #ifdef S_IFSOCK
  951.     case S_IFSOCK:            /* Socket    pretend its a fifo? */
  952.         type = LF_FIFO;
  953.         goto easy;
  954. #endif
  955. #endif
  956.  
  957.     easy:
  958.         if (!f_standard) goto unknown;
  959.  
  960.         hstat.st_size = 0;        /* Force 0 size */
  961.         header = start_header(p, &hstat, 0);
  962.         if (header == NULL) goto badfile;    /* eg name too long */
  963.  
  964.         header->header.linkflag = type;
  965.         if (type != LF_FIFO) {
  966.             to_oct((long) major(hstat.st_rdev), 8,
  967.                 header->header.devmajor);
  968.             to_oct((long) minor(hstat.st_rdev), 8,
  969.                 header->header.devminor);
  970.         }
  971.  
  972.         finish_header(header);
  973.         break;
  974.  
  975.     default:
  976.     unknown:
  977.         msg("%s: Unknown file type; file ignored.", p);
  978.         break;
  979.     }
  980. }
  981.  
  982. int
  983. finish_sparse_file(fd, sizeleft, fullsize, name)
  984.     int    fd;
  985.     long     *sizeleft,
  986.         fullsize;
  987.     char    *name;
  988. {
  989.     union record    *start;
  990.     char        tempbuf[RECORDSIZE];
  991.     int        bufsize,
  992.             sparse_ind = 0,
  993.             count;
  994.     long        pos;
  995.     long        nwritten = 0;
  996.  
  997.  
  998.     while (*sizeleft > 0) {
  999.         start = findrec();
  1000.         bzero(start->charptr, RECORDSIZE);
  1001.         bufsize = sparsearray[sparse_ind].numbytes;
  1002.         if (!bufsize) {  /* we blew it, maybe */
  1003.                 msg("Wrote %ld of %ld bytes to file %s",
  1004.                        fullsize - *sizeleft, fullsize, name);
  1005.             break;
  1006.              }
  1007.         pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
  1008.         /* 
  1009.          * If the number of bytes to be written here exceeds
  1010.          * the size of the temporary buffer, do it in steps.
  1011.          */
  1012.         while (bufsize > RECORDSIZE) {
  1013. /*            if (amt_read) {
  1014.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  1015.                 bufsize -= RECORDSIZE - amt_read;
  1016.                 amt_read = 0;
  1017.                 userec(start);
  1018.                 start = findrec();
  1019.                 bzero(start->charptr, RECORDSIZE);
  1020.             }*/
  1021.             /* store the data */
  1022.             count = read(fd, start->charptr, RECORDSIZE);
  1023.             if (count < 0)     {
  1024.                 msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  1025.                         fullsize - *sizeleft, bufsize, name);
  1026.                 return 1;
  1027.             }            
  1028.             bufsize -= count;
  1029.             *sizeleft -= count;
  1030.             userec(start);
  1031.             nwritten += RECORDSIZE;    /* XXX */
  1032.             start = findrec();
  1033.             bzero(start->charptr, RECORDSIZE);
  1034.         }
  1035.  
  1036.  
  1037.         clear_buffer(tempbuf);
  1038.         count = read(fd, tempbuf, bufsize);
  1039.         bcopy(tempbuf, start->charptr, RECORDSIZE);
  1040.         if (count < 0)     {
  1041.             msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  1042.                     fullsize - *sizeleft, bufsize, name);
  1043.             return 1;
  1044.         }
  1045. /*        if (amt_read >= RECORDSIZE) {
  1046.             amt_read = 0;
  1047.             userec(start+(count-1)/RECORDSIZE);
  1048.             if (count != bufsize) {
  1049.                 msg("file %s shrunk by %d bytes, padding with zeros.", name, sizeleft);
  1050.                 return 1;
  1051.             }
  1052.             start = findrec();
  1053.         } else 
  1054.             amt_read += bufsize;*/
  1055.         nwritten += count; /* XXX */
  1056.         *sizeleft -= count;
  1057.         userec(start);
  1058.  
  1059.     }
  1060.     free(sparsearray);
  1061.     printf ("Amount actually written is (I hope) %d.\n", nwritten);
  1062. /*    userec(start+(count-1)/RECORDSIZE);*/
  1063.     return 0;
  1064.  
  1065. }
  1066.  
  1067. init_sparsearray()
  1068. {
  1069.     register int i;
  1070.  
  1071.     sp_array_size = 10;
  1072.     /* 
  1073.      * Make room for our scratch space -- initially is 10 elts long
  1074.      */
  1075.     sparsearray = (struct sp_array *) malloc(sp_array_size * sizeof(struct sp_array));
  1076.     for (i = 0; i < sp_array_size; i++) {
  1077.         sparsearray[i].offset = 0;
  1078.         sparsearray[i].numbytes = 0;
  1079.     }
  1080. }
  1081.  
  1082.  
  1083.  
  1084. /*
  1085.  * Okay, we've got a sparse file on our hands -- now, what we need to do is
  1086.  * make a pass through the file and carefully note where any data is, i.e.,
  1087.  * we want to find how far into the file each instance of data is, and how
  1088.  * many bytes are there.  We store this information in the sparsearray,
  1089.  * which will later be translated into header information.  For now, we use
  1090.  * the sparsearray as convenient storage.
  1091.  *
  1092.  * As a side note, this routine is a mess.  If I could have found a cleaner
  1093.  * way to do it, I would have.  If anyone wants to find a nicer way to do
  1094.  * this, feel free.
  1095.  */
  1096.  
  1097. /* There is little point in trimming small amounts of null data at the */
  1098.  /* head and tail of blocks -- it's ok if we only avoid dumping blocks */
  1099.  /* of complete null data */
  1100. int
  1101. deal_with_sparse(name, header, nulls_at_end)
  1102.     char        *name;
  1103.     union record     *header;
  1104.     
  1105. {
  1106.     long    numbytes = 0;
  1107.     long    offset = 0;
  1108.     long    save_offset;
  1109.     int    fd;
  1110.     int    current_size = hstat.st_size;
  1111.     int    sparse_ind = 0,
  1112.         cc;
  1113.     char    buf[RECORDSIZE];
  1114.     int    read_last_data = 0; /* did we just read the last record? */
  1115.     int     amidst_data = 0;
  1116.     
  1117.     header->header.isextended = 0;
  1118.     /* 
  1119.      * Can't open the file -- this problem will be caught later on,
  1120.      * so just return.
  1121.      */
  1122.     if ((fd = open(name, O_RDONLY|O_BINARY)) < 0)
  1123.         return 0;
  1124.         
  1125.     init_sparsearray();
  1126.     clear_buffer(buf);
  1127.  
  1128.     while ((cc = read(fd, buf, sizeof buf)) != 0) {
  1129.             
  1130.         if (sparse_ind > sp_array_size-1) {
  1131.         
  1132.         /*
  1133.          * realloc the scratch area, since we've run out of room --
  1134.          */
  1135.             sparsearray = (struct sp_array *) 
  1136.                     realloc(sparsearray,
  1137.                          2 * sp_array_size * (sizeof(struct sp_array)));
  1138.             sp_array_size *= 2;
  1139.         }
  1140.         if (cc == sizeof buf) {
  1141.             if (zero_record(buf)) {
  1142.                 if (amidst_data) {
  1143.                     sparsearray[sparse_ind++].numbytes
  1144.                         = numbytes;
  1145.                     amidst_data = 0;
  1146.                 }
  1147.             } else {  /* !zero_record(buf) */
  1148.                     if (amidst_data)
  1149.                         numbytes += cc;
  1150.                 else {
  1151.                         amidst_data = 1;
  1152.                     numbytes = cc;
  1153.                     sparsearray[sparse_ind].offset
  1154.                       = offset;
  1155.                 } 
  1156.             }
  1157.         } else if (cc < sizeof buf) {
  1158.           /* This has to be the last bit of the file, so this */
  1159.           /* is somewhat shorter than the above. */
  1160.                 if (!zero_record(buf)) {
  1161.                 if (!amidst_data) {
  1162.                         amidst_data = 1;
  1163.                     numbytes = cc;
  1164.                     sparsearray[sparse_ind].offset
  1165.                       = offset;
  1166.                 } else
  1167.                     numbytes += cc;
  1168.             } 
  1169.         }
  1170.         offset += cc;
  1171.         clear_buffer(buf);
  1172.     }
  1173.     if (amidst_data)
  1174.             sparsearray[sparse_ind++].numbytes = numbytes;
  1175.     close(fd);
  1176.  
  1177.     return sparse_ind - 1;
  1178. }
  1179.  
  1180. /* 
  1181.  * Just zeroes out the buffer so we don't confuse ourselves with leftover
  1182.  * data.
  1183.  */
  1184. clear_buffer(buf)
  1185.     char    *buf;
  1186. {
  1187.     register int     i;
  1188.  
  1189.     for (i = 0; i < RECORDSIZE; i++)
  1190.         buf[i] = '\0';
  1191. }
  1192.  
  1193. #if 0  /* I'm leaving this as a monument to Joy Kendall, who wrote it */
  1194. /* 
  1195.  * JK - 
  1196.  * This routine takes a character array, and tells where within that array
  1197.  * the data can be found.  It skips over any zeros, and sets the first
  1198.  * non-zero point in the array to be the "start", and continues until it
  1199.  * finds non-data again, which is marked as the "end."  This routine is 
  1200.  * mainly for 1) seeing how far into a file we must lseek to data, given
  1201.  * that we have a sparse file, and 2) determining the "real size" of the
  1202.  * file, i.e., the number of bytes in the sparse file that are data, as
  1203.  * opposed to the zeros we are trying to skip.
  1204.  */
  1205. where_is_data(from, to, buffer)
  1206.     int    *from,
  1207.         *to;
  1208.     char    *buffer;
  1209. {
  1210.     register int    i = 0;
  1211.     register int    save_to = *to;
  1212.     int    amidst_data = 0;
  1213.  
  1214.     
  1215.     while (!buffer[i])
  1216.         i++;
  1217.     *from = i;
  1218.  
  1219.     if (*from < 16)    /* don't bother */
  1220.         *from = 0;
  1221.     /* keep going to make sure there isn't more real
  1222.        data in this record */
  1223.     while (i < RECORDSIZE) {
  1224.         if (!buffer[i]) {
  1225.             if (amidst_data) {
  1226.                 save_to = i;
  1227.                 amidst_data = 0;
  1228.             }
  1229.             i++;
  1230.         }
  1231.         else if (buffer[i]) {
  1232.             if (!amidst_data)
  1233.                 amidst_data = 1;
  1234.             i++;
  1235.         }
  1236.     }
  1237.     if (i == RECORDSIZE)
  1238.         *to = i;
  1239.     else
  1240.         *to = save_to;
  1241.         
  1242. }
  1243. #endif
  1244.  
  1245. /* Note that this routine is only called if zero_record returned true */
  1246. #if 0 /* But we actually don't need it at all. */
  1247. where_is_data (from, to, buffer)
  1248.      int *from, *to;
  1249.      char *buffer;
  1250. {
  1251.   char *fp, *tp;
  1252.  
  1253.   for (fp = buffer; ! *fp; fp++)
  1254.     ;
  1255.   for (tp = buffer + RECORDSIZE - 1; ! *tp; tp--)
  1256.     ;
  1257.   *from = fp - buffer;
  1258.   *to = tp - buffer + 1;
  1259. }
  1260. #endif
  1261.  
  1262.  
  1263.  
  1264. /*
  1265.  * Takes a recordful of data and basically cruises through it to see if
  1266.  * it's made *entirely* of zeros, returning a 0 the instant it finds
  1267.  * something that is a non-zero, i.e., useful data.
  1268.  */
  1269. zero_record(buffer)
  1270.     char    *buffer;
  1271. {
  1272.     register int    i;
  1273.  
  1274.     for (i = 0; i < RECORDSIZE; i++)
  1275.         if (buffer[i] != '\000')
  1276.             return 0;
  1277.     return 1;
  1278. }
  1279.  
  1280. find_new_file_size(filesize, highest_index)
  1281.     int    *filesize;
  1282.     int    highest_index;
  1283. {
  1284.     register int     i;
  1285.  
  1286.     *filesize = 0;
  1287.     for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
  1288.         *filesize += sparsearray[i].numbytes;
  1289. }
  1290.     
  1291. /*
  1292.  * Make a header block for the file  name  whose stat info is  st .
  1293.  * Return header pointer for success, NULL if the name is too long.
  1294.  */
  1295. union record *
  1296. start_header(name, st, ea)
  1297.     char    *name;
  1298.     register struct stat *st;
  1299. {
  1300.     register union record *header;
  1301.  
  1302.     header = (union record *) findrec();
  1303.     bzero(header->charptr, sizeof(*header)); /* XXX speed up */
  1304.  
  1305.     /*
  1306.      * Check the file name and put it in the record.
  1307.      */
  1308.     if(!f_absolute_paths) {
  1309.         static int warned_once = 0;
  1310. #ifdef MSDOS
  1311.         if(name[1]==':') {
  1312.             name+=2;
  1313.             if(!warned_once++)
  1314.                 msg("Removing drive spec from names in the archive");
  1315.         }
  1316. #endif
  1317.         while ('/' == *name) {
  1318.             name++;                /* Force relative path */
  1319.             if (!warned_once++)
  1320.                 msg("Removing leading / from absolute path names in the archive.");
  1321.         }
  1322.     }
  1323.     strncpy(header->header.name, name, NAMSIZ);
  1324.     /* PEC 7-29-91 */
  1325.     mange = 0;
  1326.     /* end PEC 7-29-91 */
  1327.     if (header->header.name[NAMSIZ-1]) {
  1328.         char *mangled;
  1329.  
  1330.         /* next_mangle(header->header.name); */
  1331.         add_mangle(name,header->header.name);
  1332.         msg("%s: is too long: mangling to %s", name, header->header.name);
  1333.         /* PEC 7-29-91 */
  1334.         mange = 1;
  1335.         strncpy(mange_name, header->header.name, NAMSIZ);
  1336.         /* end PEC 7-29-91 */
  1337.     }
  1338.  
  1339.     to_oct((long) (st->st_mode & ~S_IFMT),
  1340.                     8,  header->header.mode);
  1341.     to_oct((long) st->st_uid,    8,  header->header.uid);
  1342.     to_oct((long) st->st_gid,    8,  header->header.gid);
  1343.     to_oct((long) st->st_size,    1+12, header->header.size);
  1344.     to_oct((long) st->st_mtime,    1+12, header->header.mtime);
  1345.     /* header->header.linkflag is left as null */
  1346. #ifdef OS2
  1347.     if(f_gnudump || f_all_timestamps) {
  1348. #else
  1349.     if(f_gnudump) {
  1350. #endif
  1351.         to_oct((long) st->st_atime, 1+12, header->header.atime);
  1352.         to_oct((long) st->st_ctime, 1+12, header->header.ctime);
  1353.     }
  1354.  
  1355. #ifdef OS2
  1356.     if (ea)
  1357.         to_oct((long)ealen, 1+8, header->header.size);
  1358. #endif
  1359.  
  1360. #ifndef NONAMES
  1361.     /* Fill in new Unix Standard fields if desired. */
  1362.     if (f_standard) {
  1363.         header->header.linkflag = LF_NORMAL;    /* New default */
  1364.         strcpy(header->header.magic, TMAGIC);    /* Mark as Unix Std */
  1365.         finduname(header->header.uname, st->st_uid);
  1366.         findgname(header->header.gname, st->st_gid);
  1367.     }
  1368. #endif
  1369.     return header;
  1370. }
  1371.  
  1372. /* 
  1373.  * Finish off a filled-in header block and write it out.
  1374.  * We also print the file name and/or full info if verbose is on.
  1375.  */
  1376. void
  1377. finish_header(header)
  1378.     register union record *header;
  1379. {
  1380.     register int    i, sum;
  1381.     register char    *p;
  1382.     void bcopy();
  1383.  
  1384.     bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  1385.  
  1386.     sum = 0;
  1387.     p = header->charptr;
  1388.     for (i = sizeof(*header); --i >= 0; ) {
  1389.         /*
  1390.          * We can't use unsigned char here because of old compilers,
  1391.          * e.g. V7.
  1392.          */
  1393.         sum += 0xFF & *p++;
  1394.     }
  1395.  
  1396.     /*
  1397.      * Fill in the checksum field.  It's formatted differently
  1398.      * from the other fields:  it has [6] digits, a null, then a
  1399.      * space -- rather than digits, a space, then a null.
  1400.      * We use to_oct then write the null in over to_oct's space.
  1401.      * The final space is already there, from checksumming, and
  1402.      * to_oct doesn't modify it.
  1403.      *
  1404.      * This is a fast way to do:
  1405.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1406.      */
  1407.     to_oct((long) sum,    8,  header->header.chksum);
  1408.     header->header.chksum[6] = '\0';    /* Zap the space */
  1409.  
  1410.     if (f_map_file) {
  1411.         extern union record *head;        /* Points to current tape header */
  1412.         extern int head_standard;        /* Tape header is in ANSI format */
  1413.         extern FILE *msg_file;
  1414.         extern FILE *map_file;
  1415.         extern long baserec;
  1416.         FILE *old_msg_file = msg_file;
  1417.         char buf[30];
  1418.         msg_file = map_file;
  1419.  
  1420. #ifdef TAPE_IO
  1421.         if (_isrmt(archive)) {
  1422.             /*
  1423.              * Get a new physical base address for every
  1424.              * 1MB of data. Calling tape_tell too often
  1425.              * slows down TAR. Make sure the treshold
  1426.              * is a multiple of blocksize.
  1427.              */
  1428.             static long prev_baserec;
  1429.             static long baseblk;
  1430.             static long treshold = 0;
  1431.             if (treshold == 0 || baserec == 0) {
  1432.                 treshold = ((1024L * 1024L) / blocksize) * blocking;
  1433.                 prev_baserec = 0;
  1434.                 baseblk = rmtlseek(archive, 0L, 4);
  1435.             } else if (baserec >= prev_baserec + treshold) {
  1436.                 prev_baserec = baserec;
  1437.                 baseblk = rmtlseek(archive, 0L, 4);
  1438.             }
  1439.             sprintf(buf, "blk %ld+%ld", baseblk,
  1440.                 (baserec - prev_baserec) + (ar_record - ar_block));
  1441.         } else
  1442. #endif
  1443.             sprintf(buf, "rec %ld+%d", baserec, ar_record - ar_block);
  1444.  
  1445.         fprintf(msg_file,"%-18s ", buf);
  1446.  
  1447.         /* These globals are parameters to print_header, sigh */
  1448.         head = header;
  1449.         /* hstat is already set up */
  1450.         head_standard = f_standard;
  1451.         f_verbose += 2;
  1452.         f_checkpoints--;
  1453.         print_header();
  1454.         f_checkpoints++;
  1455.         f_verbose -= 2;
  1456.  
  1457.         msg_file = old_msg_file;
  1458.     }
  1459.  
  1460.     userec(header);
  1461.  
  1462.     if (f_verbose) {
  1463.         extern union record *head;        /* Points to current tape header */
  1464.         extern int head_standard;        /* Tape header is in ANSI format */
  1465.  
  1466.         /* These globals are parameters to print_header, sigh */
  1467.         head = header;
  1468.         /* hstat is already set up */
  1469.         head_standard = f_standard;
  1470.         print_header();
  1471.     }
  1472.     return;
  1473. }
  1474.  
  1475.  
  1476. /*
  1477.  * Quick and dirty octal conversion.
  1478.  * Converts long "value" into a "digs"-digit field at "where",
  1479.  * including a trailing space and room for a null.  "digs"==3 means
  1480.  * 1 digit, a space, and room for a null.
  1481.  *
  1482.  * We assume the trailing null is already there and don't fill it in.
  1483.  * This fact is used by start_header and finish_header, so don't change it!
  1484.  *
  1485.  * This should be equivalent to:
  1486.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1487.  * except that sprintf fills in the trailing null and we don't.
  1488.  */
  1489. void
  1490. to_oct(value, digs, where)
  1491.     register unsigned long    value;
  1492.     register int    digs;
  1493.     register char    *where;
  1494. {
  1495.     
  1496.     --digs;                /* Trailing null slot is left alone */
  1497.     where[--digs] = ' ';        /* Put in the space, though */
  1498.  
  1499.     /* Produce the digits -- at least one */
  1500.     do {
  1501.         where[--digs] = '0' + (char)(value & 7); /* one octal digit */
  1502.         value >>= 3;
  1503.     } while (digs > 0 && value != 0);
  1504.  
  1505.     /* Leading spaces, if necessary */
  1506.     while (digs > 0)
  1507.         where[--digs] = ' ';
  1508.  
  1509. }
  1510.  
  1511.  
  1512. /*
  1513.  * Write the EOT record(s).
  1514.  * We actually zero at least one record, through the end of the block.
  1515.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1516.  */
  1517. write_eot()
  1518. {
  1519.     union record *p;
  1520.     int bufsize;
  1521.     void bzero();
  1522.  
  1523.     p = findrec();
  1524.     if (p)
  1525.       {
  1526.         bufsize = endofrecs()->charptr - p->charptr;
  1527.         bzero(p->charptr, bufsize);
  1528.         userec(p);
  1529.       }
  1530. }
  1531.