home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Workbench / Archivers / AmiGNUtar.lha / AmiGNUtar / src.lha / src / create.c < prev    next >
C/C++ Source or Header  |  1996-04-19  |  34KB  |  1,477 lines

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