home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / mach / amiga / tools / gtar10.lha / create.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-10  |  30.6 KB  |  1,360 lines

  1. /* Create a tar archive.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Create a tar archive.
  22.  *
  23.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  24.  *
  25.  * @(#)create.c 1.36 11/6/87 - gnu
  26.  */
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <stdio.h>
  30.  
  31. #ifndef V7
  32. #include <fcntl.h>
  33. #endif
  34.  
  35. #ifndef    __MSDOS__
  36. #include <sys/file.h>
  37. #include <sys/param.h>        /* for MAXPATHLEN */
  38. #include <pwd.h>
  39. #include <grp.h>
  40. #endif
  41.  
  42. #ifdef BSD42
  43. #include <sys/dir.h>
  44. #else
  45. #ifdef __MSDOS__
  46. #include "msd_dir.h"
  47. #else
  48. #ifdef USG
  49. #ifdef NDIR
  50. #include <ndir.h>
  51. #else
  52. #include <dirent.h>
  53. #endif
  54. #ifndef DIRECT
  55. #define direct dirent
  56. #endif
  57. #define DP_NAMELEN(x) strlen((x)->d_name)
  58. #else
  59. /*
  60.  * FIXME: On other systems there is no standard place for the header file
  61.  * for the portable directory access routines.  Change the #include line
  62.  * below to bring it in from wherever it is.
  63.  */
  64. #include "ndir.h"
  65. #endif
  66. #endif
  67. #endif
  68.  
  69. #ifndef DP_NAMELEN
  70. #define DP_NAMELEN(x)    (x)->d_namlen
  71. #endif
  72.  
  73. #ifdef USG
  74. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  75. #endif
  76.  
  77. /*
  78.  * V7 doesn't have a #define for this.
  79.  */
  80. #ifndef O_RDONLY
  81. #define    O_RDONLY    0
  82. #endif
  83.  
  84. /*
  85.  * Most people don't have a #define for this.
  86.  */
  87. #ifndef    O_BINARY
  88. #define    O_BINARY    0
  89. #endif
  90.  
  91. #ifndef MAXPATHLEN
  92. #define MAXPATHLEN 1024
  93. #endif
  94.  
  95. #include "tar.h"
  96. #include "port.h"
  97.  
  98. extern struct stat hstat;        /* Stat struct corresponding */
  99.  
  100. #ifndef __MSDOS__
  101. extern dev_t ar_dev;
  102. extern ino_t ar_ino;
  103. #endif
  104.  
  105. /* JF */
  106. extern struct name *gnu_list_name;
  107.  
  108. /*
  109.  * If there are no symbolic links, there is no lstat().  Use stat().
  110.  */
  111. #ifndef S_IFLNK
  112. #define lstat stat
  113. #endif
  114.  
  115. #ifndef __STDC__
  116. extern char    *malloc();
  117. extern char    *strcpy();
  118. extern char    *strncpy();
  119. extern void    bzero();
  120. extern void    bcopy();
  121. #endif
  122. extern int    errno;
  123.  
  124. extern void print_header();
  125.  
  126. union record *start_header();
  127. void finish_header();
  128. void finduname();
  129. void findgname();
  130. char *name_next();
  131. void to_oct();
  132. void dump_file();
  133.  
  134.  
  135. /* This code moved from tar.h since create.c is the only file that cares
  136.    about 'struct link's.  This means that other files might not have to
  137.    include sys/types.h any more.
  138.  */
  139.  
  140. struct link {
  141.     struct link    *next;
  142.     dev_t        dev;
  143.     ino_t        ino;
  144.     short        linkcount;
  145.     char        name[1];
  146. };
  147.  
  148. struct link    *linklist;    /* Points to first link in list */
  149.  
  150. static nolinks;            /* Gets set if we run out of RAM */
  151.  
  152. /*
  153.  * "Scratch" space to store the information about a sparse file before
  154.  * writing the info into the header or extended header
  155.  */
  156. /* struct sp_array     *sparsearray;*/
  157.  
  158. /* number of elts storable in the sparsearray */
  159. /*int     sparse_array_size = 10;*/
  160.  
  161. void
  162. create_archive()
  163. {
  164.     register char    *p;
  165.     char *name_from_list();
  166.  
  167.     open_archive(0);        /* Open for writing */
  168.  
  169.     if(f_gnudump) {
  170.         char buf[MAXNAMLEN],*q,*bufp;
  171.  
  172.         collect_and_sort_names();
  173.  
  174.         while(p=name_from_list())
  175.             dump_file(p,-1);
  176.         /* if(!f_dironly) { */
  177.             blank_name_list();
  178.             while(p=name_from_list()) {
  179.                 strcpy(buf,p);
  180.                 if(p[strlen(p)-1]!='/')
  181.                     strcat(buf,"/");
  182.                 bufp=buf+strlen(buf);
  183.                 for(q=gnu_list_name->dir_contents;q && *q;q+=strlen(q)+1) {
  184.                     if(*q=='Y') {
  185.                         strcpy(bufp,q+1);
  186.                         dump_file(buf,-1);
  187.                     }
  188.                 }
  189.             }
  190.         /* } */
  191.     
  192.     } else {
  193.         p = name_next(1);
  194.         if(!p)
  195.             dump_file(".", -1);
  196.         else {
  197.             do dump_file(p, -1);
  198.             while (p = name_next(1));
  199.         }
  200.     }
  201.  
  202.     write_mangled();
  203.     write_eot();
  204.     close_archive();
  205.     if(f_gnudump)
  206.         write_dir_file();
  207.     name_close();
  208. }
  209.  
  210. /*
  211.  * Dump a single file.  If it's a directory, recurse.
  212.  * Result is 1 for success, 0 for failure.
  213.  * Sets global "hstat" to stat() output for this file.
  214.  */
  215. void
  216. dump_file (p, curdev)
  217.     char    *p;            /* File name to dump */
  218.     int    curdev;            /* Device our parent dir was on */
  219. {
  220.     union record    *header;
  221.     char type;
  222.     extern char *save_name;        /* JF for multi-volume support */
  223.     extern long save_totsize;
  224.     extern long save_sizeleft;
  225.     union record    *exhdr;
  226.     char save_linkflag;
  227.     extern time_t new_time;
  228.     int sparse_ind = 0;
  229.  
  230.  
  231.     if(f_confirm && !confirm("add",p))
  232.         return;
  233.  
  234.     /*
  235.      * Use stat if following (rather than dumping) 4.2BSD's
  236.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  237.      * systems, is #define'd to stat anyway.
  238.      */
  239. #ifdef AIX
  240.     if (0 != f_follow_links ?
  241.         statx (p, &hstat, STATSIZE, STX_HIDDEN):
  242.         statx (p, &hstat, STATSIZE, STX_HIDDEN|STX_LINK))
  243. #else
  244.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  245. #endif /* AIX */
  246.     {
  247. badperror:
  248.         msg_perror("can't add file %s",p);
  249. badfile:
  250.         errors++;
  251.         return;
  252.     }
  253.  
  254. #ifdef AIX
  255.     if (S_ISHIDDEN (hstat.st_mode)) {
  256.         char *new = (char *)allocate (strlen (p) + 2);
  257.         if (new) {
  258.             strcpy (new, p);
  259.             strcat (new, "@");
  260.             p = new;
  261.         }
  262.     }
  263. #endif /* AIX */
  264.  
  265.     /* See if we only want new files, and check if this one is too old to
  266.        put in the archive. */
  267.     if(   f_new_files
  268.        && !f_gnudump
  269.         && new_time>hstat.st_mtime
  270.         && (hstat.st_mode&S_IFMT)!=S_IFDIR
  271.         && (f_new_files>1 || new_time>hstat.st_ctime)) {
  272.         if(curdev<0) {
  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.         msg("%s is the archive; not dumped",p);
  282.         return;
  283.     }
  284. #endif
  285.     /*
  286.      * Check for multiple links.
  287.      *
  288.      * We maintain a list of all such files that we've written so
  289.      * far.  Any time we see another, we check the list and
  290.      * avoid dumping the data again if we've done it once already.
  291.      */
  292.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  293.         register struct link    *lp;
  294.  
  295.     case S_IFREG:            /* Regular file */
  296. #ifdef S_IFCTG
  297.     case S_IFCTG:            /* Contigous file */
  298. #endif
  299. #ifdef S_IFCHR
  300.     case S_IFCHR:            /* Character special file */
  301. #endif
  302.  
  303. #ifdef S_IFBLK
  304.     case S_IFBLK:            /* Block     special file */
  305. #endif
  306.  
  307. #ifdef S_IFIFO
  308.     case S_IFIFO:            /* Fifo      special file */
  309. #endif
  310.  
  311.         /* First quick and dirty.  Hashing, etc later FIXME */
  312.         for (lp = linklist; lp; lp = lp->next) {
  313.             if (lp->ino == hstat.st_ino &&
  314.                 lp->dev == hstat.st_dev) {
  315.                 char *link_name = lp->name;
  316.  
  317.                 /* We found a link. */
  318.                 hstat.st_size = 0;
  319.                 header = start_header(p, &hstat);
  320.                 if (header == NULL) goto badfile;
  321.                 while(!f_absolute_paths && *link_name == '/') {
  322.                     static int link_warn = 0;
  323.  
  324.                     if (!link_warn) {
  325.                         msg("Removing leading / from absolute links");
  326.                         link_warn++;
  327.                     }
  328.                     link_name++;
  329.                 }
  330.                   strncpy(header->header.linkname,
  331.                     link_name,NAMSIZ);
  332.                 if(header->header.linkname[NAMSIZ-1]) {
  333.                     char *mangled;
  334.                     extern char *find_mangled();
  335.  
  336.                     mangled=find_mangled(link_name);
  337.                     msg("%s: link name too long: mangled to %s",link_name,mangled);
  338.                     strncpy(header->header.linkname,mangled,NAMSIZ);
  339.                 }
  340.                 header->header.linkflag = LF_LINK;
  341.                 finish_header(header);
  342.         /* FIXME: Maybe remove from list after all links found? */
  343.                 return;        /* We dumped it */
  344.             }
  345.         }
  346.  
  347.         /* Not found.  Add it to the list of possible links. */
  348.         lp = (struct link *)malloc((unsigned)(sizeof(struct link)+strlen(p)));
  349.         if (!lp) {
  350.             if (!nolinks) {
  351.                 msg(
  352.     "no memory for links, they will be dumped as separate files");
  353.                 nolinks++;
  354.             }
  355.         }
  356.         lp->ino = hstat.st_ino;
  357.         lp->dev = hstat.st_dev;
  358.         strcpy(lp->name, p);
  359.         lp->next = linklist;
  360.         linklist = lp;
  361.     }
  362.  
  363.     /*
  364.      * This is not a link to a previously dumped file, so dump it.
  365.      */
  366.     switch (hstat.st_mode & S_IFMT) {
  367.  
  368.     case S_IFREG:            /* Regular file */
  369. #ifdef S_IFCTG
  370.     case S_IFCTG:            /* Contiguous file */
  371. #endif
  372.     {
  373.         int    f;        /* File descriptor */
  374.         long    bufsize, count;
  375.         long    sizeleft;
  376.         register union record     *start;
  377.         int     header_moved;
  378.         char    isextended = 0;
  379.         int     upperbound;
  380.         int    end_nulls = 0;
  381.         
  382.         header_moved = 0;
  383.  
  384. #ifdef BSD42
  385.         if (f_sparse_files) {
  386.         /*
  387.           * JK - This is the test for sparseness: whether the
  388.          * "size" of the file matches the number of blocks
  389.          * allocated for it.  If there is a smaller number
  390.          * of blocks that would be necessary to accommodate
  391.          * a file of this size, we have a sparse file, i.e.,
  392.          * at least one of those records in the file is just
  393.          * a useless hole.
  394.          */
  395. #ifdef hpux    /* Nice of HPUX to gratuitiously change it, huh?  - mib */
  396.                 if (hstat.st_size - (hstat.st_blocks * 1024) > 1024 ) {
  397. #else
  398.             if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE) {
  399. #endif
  400.                 int    filesize = hstat.st_size;
  401.                 register int i;
  402.                 
  403.                 header = start_header(p, &hstat);
  404.                 if (header == NULL)
  405.                     goto badfile;
  406.                 header->header.linkflag = LF_SPARSE;
  407.                 header_moved++;
  408.                 
  409.             /*
  410.              * Call the routine that figures out the
  411.              * layout of the sparse file in question.
  412.              * UPPERBOUND is the index of the last
  413.              * element of the "sparsearray," i.e.,
  414.              * the number of elements it needed to
  415.              * describe the file.
  416.              */
  417.                  
  418.                 upperbound = deal_with_sparse(p, header);
  419.                          
  420.             /* 
  421.              * See if we'll need an extended header
  422.              * later
  423.              */
  424.                 if (upperbound > SPARSE_IN_HDR-1)
  425.                      header->header.isextended++;
  426.             /*
  427.              * We store the "real" file size so
  428.              * we can show that in case someone wants
  429.              * to list the archive, i.e., tar tvf <file>.
  430.              * It might be kind of disconcerting if the
  431.              * shrunken file size was the one that showed
  432.              * up.
  433.              */
  434.                  to_oct((long) hstat.st_size, 1+12, 
  435.                          header->header.realsize);
  436.                     
  437.             /*
  438.              * This will be the new "size" of the
  439.              * file, i.e., the size of the file
  440.              * minus the records of holes that we're
  441.              * skipping over. 
  442.              */
  443.                  
  444.                 find_new_file_size(&filesize, upperbound);
  445.                 hstat.st_size = filesize;
  446.                 to_oct((long) filesize, 1+12,
  447.                          header->header.size);
  448. /*                to_oct((long) end_nulls, 1+12, 
  449.                         header->header.ending_blanks);*/
  450.                         
  451.                 for (i = 0; i < SPARSE_IN_HDR; i++) {
  452.                     if (!sparsearray[i].numbytes)
  453.                         break;
  454.                     to_oct(sparsearray[i].offset, 1+12,
  455.                         header->header.sp[i].offset);
  456.                     to_oct(sparsearray[i].numbytes, 1+12,
  457.                         header->header.sp[i].numbytes);
  458.                 }
  459.                     
  460.             }
  461.         }
  462. #else
  463.         upperbound=SPARSE_IN_HDR-1;
  464. #endif
  465.         
  466.         sizeleft = hstat.st_size;
  467.         /* Don't bother opening empty, world readable files. */
  468.         if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
  469.             f = open(p, O_RDONLY|O_BINARY);
  470.             if (f < 0) goto badperror;
  471.         } else {
  472.             f = -1;
  473.         }
  474.         
  475.         /* If the file is sparse, we've already taken care of this */
  476.         if (!header_moved) {
  477.             header = start_header(p, &hstat);
  478.             if (header == NULL) {
  479.                 if(f>=0)
  480.                     (void)close(f);
  481.                 goto badfile;
  482.             }
  483.         }
  484. #ifdef S_IFCTG
  485.         /* Mark contiguous files, if we support them */
  486.         if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
  487.             header->header.linkflag = LF_CONTIG;
  488.         }
  489. #endif
  490.         isextended = header->header.isextended;
  491.         save_linkflag = header->header.linkflag;
  492.         finish_header(header);
  493.         if (isextended) {
  494.             int     sum = 0;
  495.             register int i;
  496. /*            register union record *exhdr;*/
  497.             int     arraybound = SPARSE_EXT_HDR;
  498.             /* static */ int index_offset = SPARSE_IN_HDR;
  499.             
  500.     extend:        exhdr = findrec();
  501.             
  502.             if (exhdr == NULL) goto badfile;
  503.             bzero(exhdr->charptr, RECORDSIZE);
  504.             for (i = 0; i < SPARSE_EXT_HDR; i++) {
  505.                 if (i+index_offset > upperbound)
  506.                     break;
  507.                 to_oct((long) sparsearray[i+index_offset].numbytes,
  508.                      1+12,
  509.                     exhdr->ext_hdr.sp[i].numbytes);
  510.                 to_oct((long) sparsearray[i+index_offset].offset,
  511.                      1+12,
  512.                     exhdr->ext_hdr.sp[i].offset);
  513.             }
  514.             userec(exhdr);
  515. /*            sum += i;
  516.             if (sum < upperbound)
  517.                 goto extend;*/
  518.             if (index_offset+i < upperbound) {
  519.                 index_offset += i;
  520.                 exhdr->ext_hdr.isextended++;
  521.                 goto extend;
  522.             }
  523.                 
  524.         }
  525.         if (save_linkflag == LF_SPARSE) {
  526.             if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
  527.                 goto padit;
  528.         }
  529.         else
  530.           while (sizeleft > 0) {
  531.             
  532.             if(f_multivol) {   
  533.                 save_name = p;
  534.                 save_sizeleft = sizeleft;
  535.                 save_totsize = hstat.st_size;
  536.             }
  537.             start = findrec();
  538.  
  539.             bufsize = endofrecs()->charptr - start->charptr;
  540.                 
  541.             if (sizeleft < bufsize) {
  542.                 /* Last read -- zero out area beyond */
  543.                 bufsize = (int)sizeleft;
  544.                 count = bufsize % RECORDSIZE;
  545.                 if (count) 
  546.                     bzero(start->charptr + sizeleft,
  547.                         (int)(RECORDSIZE - count));
  548.             }
  549.             count = read(f, start->charptr, bufsize);
  550.             if (count < 0) {
  551.                 msg_perror("read error at byte %ld, reading\
  552.  %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);
  553.                 goto padit;
  554.             }
  555.             sizeleft -= count;
  556.  
  557.             /* This is nonportable (the type of userec's arg). */
  558.             userec(start+(count-1)/RECORDSIZE);
  559.  
  560.             if (count == bufsize) continue;
  561.             msg( "file %s shrunk by %d bytes, padding with zeros.", p, sizeleft);
  562.             goto padit;        /* Short read */
  563.         }
  564.  
  565.         if(f_multivol)
  566.             save_name = 0;
  567.  
  568.         if (f >= 0)
  569.             (void)close(f);
  570.  
  571.         break;
  572.  
  573.         /*
  574.          * File shrunk or gave error, pad out tape to match
  575.          * the size we specified in the header.
  576.          */
  577.     padit:
  578.         while(sizeleft>0) {
  579.             save_sizeleft=sizeleft;
  580.             start=findrec();
  581.             bzero(start->charptr,RECORDSIZE);
  582.             userec(start);
  583.             sizeleft-=RECORDSIZE;
  584.         }
  585.         if(f_multivol)
  586.             save_name=0;
  587.         if(f>=0)
  588.             (void)close(f);
  589.         break;
  590. /*        abort(); */
  591.     }
  592.  
  593. #ifdef S_IFLNK
  594.     case S_IFLNK:            /* Symbolic link */
  595.     {
  596.         int size;
  597.  
  598.         hstat.st_size = 0;        /* Force 0 size on symlink */
  599.         header = start_header(p, &hstat);
  600.         if (header == NULL) goto badfile;
  601.         size = readlink(p, header->header.linkname, NAMSIZ);
  602.         if (size < 0) goto badperror;
  603.         if (size == NAMSIZ) {
  604.             char buf[MAXPATHLEN];
  605.  
  606.             readlink(p,buf,MAXPATHLEN);
  607.             /* next_mangle(header->header.linkname); */
  608.             add_symlink_mangle(buf,p,header->header.linkname);
  609.             msg("symbolic link %s too long: mangling to %s",p, header->header.linkname);
  610.             /* size=strlen(header->header.linkname); */
  611.         } else
  612.             header->header.linkname[size] = '\0';
  613.         header->header.linkflag = LF_SYMLINK;
  614.         finish_header(header);        /* Nothing more to do to it */
  615.     }
  616.         break;
  617. #endif
  618.  
  619.     case S_IFDIR:            /* Directory */
  620.     {
  621.         register DIR *dirp;
  622.         register struct direct *d;
  623.         char *namebuf;
  624.         int buflen;
  625.         register int len;
  626.         int our_device = hstat.st_dev;
  627.         extern char *ck_malloc(),*ck_realloc();
  628.  
  629.         /* Build new prototype name */
  630.         len = strlen(p);
  631.         buflen=len+NAMSIZ;
  632.         namebuf=ck_malloc(buflen+1);
  633.         strncpy(namebuf, p, buflen);
  634.         while (len >= 1 && '/' == namebuf[len-1]) 
  635.             len--;            /* Delete trailing slashes */
  636.         namebuf[len++] = '/';        /* Now add exactly one back */
  637.         namebuf[len] = '\0';        /* Make sure null-terminated */
  638.  
  639.         /*
  640.          * Output directory header record with permissions
  641.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  642.          * If old archive format, don't write record at all.
  643.          */
  644.         if (!f_oldarch) {
  645.             hstat.st_size = 0;    /* Force 0 size on dir */
  646.             /*
  647.              * If people could really read standard archives,
  648.              * this should be:        (FIXME)
  649.             header = start_header(f_standard? p: namebuf, &hstat);
  650.              * but since they'd interpret LF_DIR records as
  651.              * regular files, we'd better put the / on the name.
  652.              */
  653.             header = start_header(namebuf, &hstat);
  654.             if (header == NULL)
  655.                 goto badfile;    /* eg name too long */
  656.  
  657.             if (f_gnudump)
  658.                 header->header.linkflag = LF_DUMPDIR;
  659.             else if (f_standard)
  660.                 header->header.linkflag = LF_DIR;
  661.  
  662.             /* If we're gnudumping, we aren't done yet so don't close it. */
  663.             if(!f_gnudump)
  664.                 finish_header(header);    /* Done with directory header */
  665.         }
  666.  
  667.         if(f_gnudump) {
  668.             int sizeleft;
  669.             int totsize;
  670.             int bufsize;
  671.             union record *start;
  672.             int count;
  673.             char *buf,*p_buf;
  674.  
  675.             buf=gnu_list_name->dir_contents; /* FOO */
  676.             totsize=0;
  677.             for(p_buf=buf;p_buf && *p_buf;) {
  678.                 int tmp;
  679.  
  680.                 tmp=strlen(p_buf)+1;
  681.                 totsize+=tmp;
  682.                 p_buf+=tmp;
  683.             }
  684.             totsize++;
  685.             to_oct((long)totsize,1+12,header->header.size);
  686.             finish_header(header);
  687.             p_buf=buf;
  688.             sizeleft=totsize;
  689.             while(sizeleft>0) {
  690.                 if(f_multivol) {
  691.                     save_name=p;
  692.                     save_sizeleft=sizeleft;
  693.                     save_totsize=totsize;
  694.                 }
  695.                 start=findrec();
  696.                 bufsize=endofrecs()->charptr - start->charptr;
  697.                 if(sizeleft<bufsize) {
  698.                     bufsize=sizeleft;
  699.                     count=bufsize%RECORDSIZE;
  700.                     if(count)
  701.                         bzero(start->charptr+sizeleft,RECORDSIZE-count);
  702.                 }
  703.                 bcopy(p_buf,start->charptr,bufsize);
  704.                 sizeleft-=bufsize;
  705.                 p_buf+=bufsize;
  706.                 userec(start+(bufsize-1)/RECORDSIZE);
  707.             }
  708.             if(f_multivol)
  709.                 save_name = 0;
  710.              break;
  711.         }
  712.  
  713.         /* Now output all the files in the directory */
  714.         /* if (f_dironly)
  715.             break;        /* Unless the cmdline said not to */
  716.         /*
  717.          * See if we are crossing from one file system to another,
  718.          * and avoid doing so if the user only wants to dump one file system.
  719.          */
  720.         if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
  721.             if(f_verbose)
  722.                 msg("%s: is on a different filesystem; not dumped",p);
  723.             break;
  724.         }
  725.  
  726.  
  727.         errno = 0;
  728.         dirp = opendir(p);
  729.         if (!dirp) {
  730.             if (errno) {
  731.                 msg_perror ("can't open directory %s",p);
  732.             } else {
  733.                 msg("error opening directory %s",
  734.                     p);
  735.             }
  736.             break;
  737.         }
  738.  
  739.         /* Hack to remove "./" from the front of all the file names */
  740.         if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/')
  741.             len = 0;
  742.  
  743.         /* Should speed this up by cd-ing into the dir, FIXME */
  744.         while (NULL != (d=readdir(dirp))) {
  745.             /* Skip . and .. */
  746.             if(is_dot_or_dotdot(d->d_name))
  747.                 continue;
  748.  
  749.             if (DP_NAMELEN(d) + len >= buflen) {
  750.                 buflen=len+DP_NAMELEN(d);
  751.                 namebuf=ck_realloc(namebuf,buflen+1);
  752.                 /* namebuf[len]='\0';
  753.                 msg("file name %s%s too long", 
  754.                     namebuf, d->d_name);
  755.                 continue; */
  756.             }
  757.             strcpy(namebuf+len, d->d_name);
  758.             if(f_exclude && check_exclude(namebuf))
  759.                 continue;
  760.             dump_file(namebuf, our_device);
  761.         }
  762.  
  763.         closedir(dirp);
  764.         free(namebuf);
  765.     }
  766.         break;
  767.  
  768. #ifdef S_IFCHR
  769.     case S_IFCHR:            /* Character special file */
  770.         type = LF_CHR;
  771.         goto easy;
  772. #endif
  773.  
  774. #ifdef S_IFBLK
  775.     case S_IFBLK:            /* Block     special file */
  776.         type = LF_BLK;
  777.         goto easy;
  778. #endif
  779.  
  780. /* Avoid screwy apollo lossage where S_IFIFO == S_IFSOCK */
  781. #if ((_ISP__M68K == 0) && (_ISP__A88K == 0))
  782. #ifdef S_IFIFO
  783.     case S_IFIFO:            /* Fifo      special file */
  784.         
  785.         type = LF_FIFO;
  786.         goto easy;
  787. #endif
  788. #endif
  789.  
  790. #ifdef S_IFSOCK
  791.     case S_IFSOCK:            /* Socket    pretend its a fifo? */
  792.         type = LF_FIFO;
  793.         goto easy;
  794. #endif
  795.  
  796.     easy:
  797.         if (!f_standard) goto unknown;
  798.  
  799.         hstat.st_size = 0;        /* Force 0 size */
  800.         header = start_header(p, &hstat);
  801.         if (header == NULL) goto badfile;    /* eg name too long */
  802.  
  803.         header->header.linkflag = type;
  804.         if (type != LF_FIFO) {
  805.             to_oct((long) major(hstat.st_rdev), 8,
  806.                 header->header.devmajor);
  807.             to_oct((long) minor(hstat.st_rdev), 8,
  808.                 header->header.devminor);
  809.         }
  810.  
  811.         finish_header(header);
  812.         break;
  813.  
  814.     default:
  815.     unknown:
  816.         msg("%s: Unknown file type; file ignored.", p);
  817.         break;
  818.     }
  819. }
  820.  
  821. int
  822. finish_sparse_file(fd, sizeleft, fullsize, name)
  823.     int    fd;
  824.     long     *sizeleft,
  825.         fullsize;
  826.     char    *name;
  827. {
  828.     union record    *start;
  829.     char        tempbuf[RECORDSIZE];
  830.     int        bufsize,
  831.             sparse_ind = 0,
  832.             count;
  833.     long        pos;
  834.     long        nwritten = 0;
  835.  
  836.  
  837.     while (*sizeleft > 0) {
  838.         start = findrec();
  839.         bzero(start->charptr, RECORDSIZE);
  840.         bufsize = sparsearray[sparse_ind].numbytes;
  841.         if (!bufsize) {  /* we blew it, maybe */
  842.                 msg("Wrote %ld of %ld bytes to file %s",
  843.                        fullsize - *sizeleft, fullsize, name);
  844.             break;
  845.              }
  846.         pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
  847.         /* 
  848.          * If the number of bytes to be written here exceeds
  849.          * the size of the temporary buffer, do it in steps.
  850.          */
  851.         while (bufsize > RECORDSIZE) {
  852. /*            if (amt_read) {
  853.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  854.                 bufsize -= RECORDSIZE - amt_read;
  855.                 amt_read = 0;
  856.                 userec(start);
  857.                 start = findrec();
  858.                 bzero(start->charptr, RECORDSIZE);
  859.             }*/
  860.             /* store the data */
  861.             count = read(fd, start->charptr, RECORDSIZE);
  862.             if (count < 0)     {
  863.                 msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  864.                         fullsize - *sizeleft, bufsize, name);
  865.                 return 1;
  866.             }            
  867.             bufsize -= count;
  868.             *sizeleft -= count;
  869.             userec(start);
  870.             nwritten += RECORDSIZE;    /* XXX */
  871.             start = findrec();
  872.             bzero(start->charptr, RECORDSIZE);
  873.         }
  874.  
  875.  
  876.         clear_buffer(tempbuf);
  877.         count = read(fd, tempbuf, bufsize);
  878.         bcopy(tempbuf, start->charptr, RECORDSIZE);
  879.         if (count < 0)     {
  880.             msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  881.                     fullsize - *sizeleft, bufsize, name);
  882.             return 1;
  883.         }
  884. /*        if (amt_read >= RECORDSIZE) {
  885.             amt_read = 0;
  886.             userec(start+(count-1)/RECORDSIZE);
  887.             if (count != bufsize) {
  888.                 msg("file %s shrunk by %d bytes, padding with zeros.", name, sizeleft);
  889.                 return 1;
  890.             }
  891.             start = findrec();
  892.         } else 
  893.             amt_read += bufsize;*/
  894.         nwritten += count; /* XXX */
  895.         *sizeleft -= count;
  896.         userec(start);
  897.  
  898.     }
  899.     free(sparsearray);
  900.     printf ("Amount actually written is (I hope)buff     * nnametten is)*        abrec(start+(count-1)/RECORDSIZE);
  901.                 *surn 1;
  902.  
  903.  
  904.     wint
  905. fit_rsearray);
  906. ()    uniister int leni    }
  907.     sp_ay);
  908. ze = 0;    1            u
  909.          * ake surrothefopenurrewyh
  910.         arse0 s-- 
  911. fitiy wri(I 10se a fg        n
  912. /
  913.         whrsearray);
  914. 0;    (uct dirsp_ay);
  915.  *ajorc(namsp_ay);
  916. ze = 0ize=stof(uct dirsp_ay);
  917. )    prifope(i0;
  918.          i0) sp_ay);
  919. ze =      i++
  920.         starsearray[spaiffset, 00;
  921.             usrsearray[spaiffbytes;
  922.     0;
  923.             u
  924.  
  925. int* Av
  926. Outpkaye'd b"./o bfifrsearrle %s"recnurrhardss-- n fe'dhbytblen thiso to is
  927. Outm suraddithe croughe file nam .. c crlsizyt duhere S_Ianyta */
  928. iin f.e.,
  929. Outblets t file .. houtfarto the dire namea        ainndarcf thea */
  930. iin a.. hou
  931. Outm nytes;
  932.     0athe dare.  Weore the din thmat, d recthe dirrsearray[sp,
  933. Outbhi        awithela intbrailinsld */
  934. o theder == thmat, d re.  ce  n fe'dser o
  935. the sizesearray);
  936. 0asuntnvng  filre t wh.
  937. th
  938. theA fifsi&&  duh,e din rout saii fif */s.  theIuld reahaformauavoi ar_bner
  939. Outb;
  940. 0so to ibufI wd reahafo.  the ny withs to dume .. a n);
  941. rtb;
  942. 0so to
  943. this shulleeile(sp.
  944. th/* AvoTe S_Ii flen nampo lenihe rimm so iorc(t_rt-1)s thel-teea */
  945. ahe / oh/* XXXder  a.. ting bytek   ss-- it's tk we arey wanid doining, wtek   ssh/* XXXbytcompe tral-teea */
  946. h/*
  947. findloc_h ze_rsearr(e, sizder ==,al-tes_at_if
  948. )har        temme;
  949. {
  950.     ion record *st    *der ==
  951.     i    unig        nwbytes;
  952.     0;
  953.             ug        nwset, 00;
  954.             ug        nwe_namset, 0;nt    fd;
  955.     lon    fd;devt fize = 0;    at.st_size = lon    fd;rse_ind = 0,
  956.             coccchar        te[RECORDSIZE];
  957.     int        bud +=_hesev) */
  958. ;
  959.          XXXddoiarejustad sta / ohesecord *s/
  960.         ty lent_ridsev) */
  961. ;
  962.             i    ader->header.devisern nde 0;
  963.             u
  964.          * akCt open dir dire nam--  din blems?
  965. awithebracaughtela inton, * akif justad n 1;.
  966. /
  967.         wh((_ISfdopendir(e, sizO_RDONLY{
  968.     )     {
  969.     surn 1;
  970.  
  971.  
  972.                 b
  973. fit_rsearray);
  974. ()charr_buffer(tem);
  975.         chile (*si(ccread(fd, tem, star=stof ))
  976.          buf{
  977.                 ifif (course_ind = 0> sp_ay);
  978. ze = /RE                i/*
  979.          * Seelloc(nae sizewyh
  980.         aatha,nce thed b"./k btputXbytrothe-- */
  981.         whihrsearray);
  982. 0;    (uct dirsp_ay);
  983.  *aj            fullloc(namrsearray[sp,
  984. O            ful2 akip_ay);
  985. ze = 0iz(e=stof(uct dirsp_ay);
  986. )                    reip_ay);
  987. ze = 0i &&    }
  988. /*    f (counc NULr=stof ))
  989.                 if (erros."_ord *s())
  990.                      if(f_mt_ridsev) */
  991.                     savesearray[sparse_ind++].offbytes;
  992.                     ful= bytes;
  993.         if amt_ridsev) */
  994. ;
  995.             i}
  996.             stalse {
  997.         * we !os."_ord *s())
  998.     
  999.         whih     }
  1000.     f_mt_ridsev) */
  1001.     i}
  1002.          }
  1003.     bytes;
  1004.     0counc        i}
  1005.     e {
  1006.                 msg     }
  1007.     _ridsev) */
  1008. ;
  1009.                 totwbytes;
  1010.     0;
  1011. nc        i}
  1012.         rsearray[sparse_ind].numset, 0    i}
  1013.          openet, 0;ntstals    }
  1014.             stlse {
  1015.     (counc <Lr=stof ))
  1016.                 if* we Tdin hao be wri / ohesecbit the teme na,kif  din              if (hruomedhbytshor intthare temabofo.                 msg(!bufos."_ord *s())
  1017.                      if(f_mt!_ridsev) */
  1018.                     sa     }
  1019.     _ridsev) */
  1020. ;
  1021.                 totwbytes;
  1022.     0;
  1023. nc        i}
  1024.         rsearray[sparse_ind].numset, 0    i}
  1025.          openet, 0;ntstalse {
  1026.         totwbytes;
  1027.     0counc        i}
  1028. ls    }
  1029.         stset, 00counc        i}rr_buffer(tem);
  1030.         c
  1031.         sf_mt_ridsev) */
  1032.     i     }
  1033.     esearray[sparse_ind++].offbytes;
  1034.      = bytes;
  1035.         ifsedir, t        chiurn 1;
  1036. rse_ind = 0-
  1037.             }* Avo
  1038. thiJustaos."
  1039.      putX temfer(tekif aredo opentnfr ocnurselv
  1040.      h zert -=ofor
  1041. Out) */.
  1042. th/*rr_buffer(tem);
  1043.     har    *nam;
  1044.             uniister int len    i    }
  1045.     fope(i0;
  1046.          i0) ORDSIZE;    /* i++
  1047. bufsizaif0;
  1048. ';
  1049.             }ifdefsiz if I'mrt av, wt din a fif obyte t filJoy K ndoc(e'dhf ae %ldit h/*Avo
  1050. thiJK0-
  1051.  
  1052. thiTdin rout sait su fifcacter speay[sp, a.. tetesere S_Ih zethe dbytay[sp
  1053. the siz) */
  1054. 't  wrimauav.  tyts .      pvspeanytos.",, a.. , 0se teme rst
  1055. thenon-os."mpo lenihe temay);
  1056.  be wri / o"rt+(c", a.. tinue;
  1057.     p bnueldit
  1058. thee ..senon-a */
  1059. again,tbhi        ain marke 0ase tem" nd." iTdin rout saiin 
  1060. Outm i wanfopeRE    k(f, wthoutfarto theare namaremustaek(fd0so t */, givng
  1061. the sbytblehaforifrsearrle %s, a.. 2) d trrm s, wt dem"llocLr=st" the te
  1062. thee %s, f.e.,e number of bytes to the dirrsearrle typedbytaye t */, as
  1063. Outoppdir( the diros.", are crotry, wt ots . .
  1064. th/*re S__dot_ */(m th,e o,mfer(teint    fd;*m th,*sizto;har    *nam;
  1065.     f==
  1066.     uniister int le    i
  1067. ;
  1068.             iister int le    e_namt 0;
  1069. zto;ha le    _ridsev) */
  1070. ;
  1071.                 i    ale (*si!;
  1072.     f==aif
  1073. bufi++;ha*m th
  1074. ;
  1075. i    }
  1076.     f_mt*m th
  1077. < 16)u
  1078.         do opeber,
  1079.     
  1080.         *sizm th
  1081. ;
  1082.             u
  1083.         keep/o , wt otm sursuthe dareiin opem thelloc    i   a */
  1084. ine din rrd *st        *sle (*sii0) ORDSIZE;    /
  1085.                     (!bufsizf==aif
  1086.             if (err_ridsev) */
  1087.                     sae_namt 0;
  1088. i            amt_ridsev) */
  1089. ;
  1090.             i}
  1091.         stai++;ha
  1092.         ste {
  1093.     (cousizf==aif
  1094.             if (err!_ridsev) */
  1095.     i}
  1096.     _ridsev) */
  1097. ;
  1098.                 toi++;ha
  1099.         s        sf_mti NULORDSIZE;    /
  1100. *sizto0;
  1101. i            e {
  1102.         tzto0;
  1103. e_namt 
  1104.                 }ndif
  1105.  
  1106. /* AvoN %ldedbyt din rout saii fy wancoc(*/
  1107. of os."_ord *sad n 1;r( true
  1108. #if ((_0 if Buytbleually wrido open thiit bytall.th/*re S__dot_ */ (m th,e o,mfer(tein  msg(len*m th,
  1109. zto;h  msgr    *n m;
  1110.     f==
  1111.     unsgr    *n mfp,
  1112. ztp    }
  1113.  nfope(fp =mfer(te; ! mfpilep++
  1114. b msg;
  1115.  nfope(tp =mfer(telenORDSIZE - amt1; ! mtp     tp--
  1116. b msg;
  1117.  nzm th
  1118. ;
  1119. fp -mfer(te;
  1120.  nzto0;
  1121. tp -mfer(telen            }*dif
  1122.  
  1123. /* * Av
  1124. OutT su fiford *slsi thea */
  1125. a.. basicy wricruisehe crougheit filk(f
  1126. of
  1127. Outit's mr.d *e tirelyXXbytos.",, d n 1;, wta_0  dirinndarteit e ..s
  1128.  akifmezethgdedbyti fifnon-os.", f.e.,er olsi ) */.
  1129. th/*os."_ord *s())
  1130. (teintr    *nam;
  1131.     f==
  1132.     uniister int le    i    }
  1133.     fope(i0;
  1134.          i0) ORDSIZE;    /* i++
  1135. buf(cousizf==aif buf';
  1136. 00')    return 1;
  1137.             iisn 1;
  1138.             }ife .._newle(fdze = (e(fde, namhighesev ..exint    fd;*m(fde, n;ha le    highesev ..ex        uniister int len    i    }
  1139.     *m(fde, n
  1140. ;
  1141.             ifope(i0;
  1142.          rsearray[spaiffbytes;
  1143.     0(_Ii0)=mhighesev ..ex* i++
  1144. buf*m(fde, n
  1145. += rsearray[spaiffbytes;
  1146.             }i     Av
  1147. OutM suradder == ek   nfope dire namme too'dhfseorebytihmati fore .
  1148. th Rsn 1;
  1149. der == po le== fopesucc*/s,LL) g
  1150. of  numb tooiso long */.
  1151. th/*on record *st*
  1152. rt_header(p, e, sizet)har    *name;
  1153. {
  1154.     iister intuct dirsebytart        uniister inton record *st*der ==
  1155.     
  1156. ader = sta(on record *st*)ndrec();
  1157.         } ro(stader->hearptr, RECe=stof(*der ==             XXX */
  1158. sp thiup
  1159.  
  1160.         he         * akChe  n dire namb tooa.. put in ste dirord *s.
  1161. /
  1162.         wh(((!f_absolute_paths
  1163.         start tict lenwa1;r(_o the;
  1164.              ((aul __MSDOS__buf(c e, s[1]==':'
  1165.             if e, s+=2        if (c(!wa1;r(_o th++
  1166. bufsg("filRemov, wtdrivn
  1167. sp c m th
  1168. e, ssnihe temaychivn"        }
  1169.  
  1170.  
  1171.     dif
  1172.  
  1173. /* ((aul _rigadosbuf(c  ..ex  e, siz':'
  1174.  
  1175.             if e, s0;
  1176. i..ex  e, siz':'
  1177. +1        if (c(!wa1;r(_o th++
  1178. bufsg("filRemov, wtvolumn
  1179. sp c m th
  1180. e, ssnihe temaychivn"        }
  1181.  
  1182.  
  1183.     dif
  1184.  
  1185. /*hile (buf'/' NULme;
  1186. {
  1187.             if e, s++;    /* stoce cirorla ivn
  1188. path
  1189.         whih(err!wa1;r(_o th++
  1190. bufsg("filRemov, wtling %d / m th
  1191. absolute
  1192. path
  1193. e, ssnihe temaychivn."        }
  1194.  
  1195.  
  1196.     
  1197.  
  1198.     
  1199. uctnctemder->header.deve, size, sizNAME;            }
  1200. (errder->header.deve, s[NAME;    -1f
  1201.             ifr    *n mm ng(*/
  1202.     
  1203. a stonern_m ng(*rder->header.deve, s                 whiing_m ng(*re, sider->header.deve, s        
  1204. sg("fil%s:oiso long */: m ng(, wt ot, 
  1205.         e, sizder ==eader.deve, s        
  1206. s}if    to_oct((g */)    (uc->sevmo.d & ~S_IFMT),        totw8, zder ==eader.devmo.d);* ((aul _rigadosbu(err_rigarrorms
  1207. bufto_oct ((g */)uc->sevamo.d, 1+12izder ==eader.devdevmajor);* if
  1208.  
  1209. /*hto_oct((g */)    uc->sevuid,w8, zder ==eader.devuid        
  1210. sto_oct((g */)    uc->sevgid,w8, zder ==eader.devgid        
  1211. sto_oct((g */)    uc->seve, na    1+12izder ==eader.deve);
  1212.         bcto_oct((g */)    uc->sevmtimna    1+12izder ==eader.devmtimn)        u
  1213.         der ==eader.dev(, kflagIi fl -= asel-tee        wh(((f_gnuning
  1214.             ifto_oct((g */)    uc->sevatimna 1+12izder ==eader.devatimn)        ufto_oct((g */)    uc->sevctimna 1+12izder ==eader.devctimn)        u}ifdefnaul NONAMES    u
  1215.         Fitheihenew Unix Sdarda*stfiel.se(erdde,red.
  1216.         wh((_If_sdarda*s
  1217.             ifder ==eader.dev(, kflagI= LF_NORMAL* XXXNew aulault         whiuctctemder->header.devmagic, TMAGIC)* XXXMark aseUnix Sdst        *s    drecue, smder->header.devue, sizet->sevuid)        ufdrecge, smder->header.devge, sizet->sevgid        
  1218. s
  1219.     dif
  1220.  
  1221. /*hrsn 1;
  1222. der ==        }* Avo
  1223. thiF s,sheneteare n(*/-indder == ek   na.. ttenldit out.
  1224. th Weoalif ntf (n dire namb tooa../opelsiztihmatif vspbfseoi fy .
  1225. th/*d dofe .,shader(p, der ==    niister inton record *st*der ==
  1226.     uniister int le    iizeum
  1227.     iister intr    *namp    }    d doibcop
  1228. ()ch} rcop
  1229. (CHKBLANKSizder ==eader.devchkeumECe=stof(der ==eader.devchkeum))ch} eum
  1230. ;
  1231.             ip =mder->hearptr, R        ifope(i0;
  1232. e=stof(*der ==    ;e--i REC         
  1233.             if         * SeeWraca oper ocunsig;r( r    *n dareibecausf theoldtcomp nars, * Seee.g. V7. */
  1234.         whieum
  1235. += 0xFF & *p++;ha}    he         * akFitheihe dirche  eum
  1236. fiel..  ty's mat, d */
  1237.  
  1238.  
  1239. /f==e tly * akm th
  1240.  direr,
  1241.     
  1242. fiel.s: dit hao [6]
  1243.  
  1244.  
  1245. git,, ael-te,e nun a * akise0 s-- yh
  1246. hintthare
  1247.  
  1248. git,, aeise0 ,e nun ael-te.
  1249. /
  1250.     eWrausf to_oct  nun ttenld numbetheihepvspeto_oct's ise0 .
  1251. /
  1252.     eTdire nocLrse0 si fild(fdye dare,km th
  1253. che  eumm so, a..
  1254. /
  1255.     eto_oct d"
  1256.      opem 
  1257.  
  1258. /ri(t.
  1259. /
  1260.     
  1261. /
  1262.     eTdin t fiffesecb;
  1263. 0so to:
  1264. /
  1265.     e(d do)    untf (f(der ==eader.devchkeum, "%6o"izeum        
  1266. s
  1267.         whto_oct((g */)    uum,w8, zder ==eader.devchkeum);    ader->header.devchkeum[6]
  1268. ;
  1269. ';
  1270.          XXXZape dirrsece
  1271.  
  1272.         heusf();
  1273. der ==    ;
  1274. wh((_If_vspbfse
  1275.             ifern 1;
  1276. on record *st*der ;a stoPo leo be devt fiit pedder ==         whiern 1;
  1277. f (nder _sdarda*s;a stoT pedder == in th ANSI mat, d
  1278.  
  1279.         he    AvoTe sf globalie crosea ton 1o be ntf (_der ==,asigh
  1280.         whider  =
  1281. der ==        e    Avohrebyti fild(fdye, 00up
  1282.  
  1283.         hider _sdarda*s
  1284. ;
  1285. f_sdarda*s;    hintf (_der ==(        
  1286. s}if    rsn 1;        }*  Av
  1287. OutQui  na.. dirty octocLntnvnrsiy .
  1288. th Ctnvnreo g */ "valut" o thear"
  1289.  
  1290. gs"-
  1291.  
  1292. git
  1293. fiel. byt"re S_",
  1294. Oute tlud, wta_ilii(, wtrsece
  1295. a.. rothefopeael-te. r"
  1296.  
  1297. gs"==3f *ans
  1298.  ak1e
  1299.  
  1300. git, aeise0 ,ea.. rothefopeael-te.
  1301. th
  1302. theWeoassumn
  1303.  dirilii(, wtbethei fild(fdye darena.. do opefithein st.
  1304. thiTdin fualei fuir( by rt_header(p,na.. e .,shader(p,,kif do openhargldit!
  1305. th
  1306. theTdin shoul. wriequivale t fi:
  1307. th    (d do)    untf (f(wdare,k"%*lo "iz
  1308.  
  1309. gs-2izvalut        
  1310. Seeexceptdedbytuntf (fefithsnihe temilii(, wtbethea.. tredo op.
  1311. th/*d dofto_oct(valutiz
  1312.  
  1313. gs,ere S_    niister intg        nwvalut        iister int le    
  1314.  
  1315. gs
  1316.     iister intr    *namre S_
  1317.     uni
  1318.     --
  1319.  
  1320. gs
  1321.     /* stoTlii(, wtbetheslotIi fl -= ag        et        *sle S_[--
  1322.  
  1323. gs]
  1324. ;
  1325. ' ';a stoPut the dirrse0 ,e noughe
  1326.         he         Producn
  1327.  dir
  1328.  
  1329. git,s-- bytlinsec        et        *sdo            ifle S_[--
  1330.  
  1331. gs]
  1332. ;
  1333. '0'len(r    *n)(valut & 7         XXX        etoctocL
  1334.  
  1335. git
  1336.  
  1337.         hivalut >REC3    
  1338. s} le (buf
  1339.  
  1340. gs0> 00(_Ivalut buf{
  1341. ;    he         Ling %d rse0 s,e((_nec*/saryt        *sle (*si
  1342.  
  1343. gs0> 0)    ifle S_[--
  1344.  
  1345. gs]
  1346. ;
  1347. ' ';
  1348.     }*  Av
  1349. OutWtenld numEOTcord *s(s).
  1350. th Weoaally wrios."mbytlinsec        etord *s,e croughe numif
  1351.  the temek   .
  1352. th Ol. t_h ttenls garbagldaf inttwoaos."
  1353. dtord *s,s-- bf
  1354.  PDt_h uir( th.
  1355. th/*rtenl_eot()    union record *st*p;ha lemfere, n;had doibo(sta
  1356. ;    hep =mdrec();
  1357.         } ((_Ip
  1358.     i  {    i    fere, n =mif
  1359. of();s()earptr, R -mpearptr, R        i    fo(stapearptr, RECfere, n)        i    usf();
  1360. p)        i  }