"Fossies" - the Fresh Open Source Software Archive

Member "afio-2.5.2/afio.c" (30 Nov 2018, 132555 Bytes) of package /linux/misc/afio-2.5.2.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "afio.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.5.1_vs_2.5.2.

    1 /*
    2  * afio.c
    3  *
    4  * Manipulate archives and files.
    5  *
    6  * This software was written by Mark Brukhartz at Lachman Associates,
    7  * Inc..  Additional code was written by a large cast of people.
    8  *
    9  * Licensing and (re)distribution
   10  * ------------------------------
   11  *
   12  * THE SUMMARY INFORMATION BELOW WAS WRITTEN FOR THE BENEFIT OF
   13  * SOFTWARE DISTRIBUTORS
   14  *
   15  * Because of historical reasons, different parts of this software
   16  * package are covered by different licenses.  As of 2012, my (Koen
   17  * Holtman's) intepretation of the license status is as follows.
   18  *
   19  * - The main authors and maintainers all intend afio to be free and
   20  *   freely distributable.  It has been distributed widely and for
   21  *   free since at least 1987, when it was posted to the
   22  *   comp.sources.unix newsgroup.
   23  *
   24  * - The legal risks to re-distributers, coming from the licence, are
   25  *   effectively zero.
   26  *
   27  * - The afio license is not a standard OSI/FSF approved free software
   28  *   license, it predates these license texts.  Unfortunately, the
   29  *   afio license includes wording that is considered to be
   30  *   problematic by several of todays open source licensing legal
   31  *   experts, because the wording leaves too much room for
   32  *   interpretation.  It is impossible to upgrade this problematic
   33  *   license text.
   34  *
   35  * - Therefore, if your software redistribution or package labeling
   36  *   policy implies a rejection of non-standard OSI/FSF approved free
   37  *   software licenses, you need to be careful about handling afio.
   38  *
   39  *   See the file afio_license_issues_v5.txt for more legal
   40  *   discussion.
   41  *
   42  * END OF SUMMARY INFORMATION
   43  *
   44  * ------------------------------------------------------------------
   45  *
   46  * License notice 1, covering part of this software package.
   47  *
   48  * [Covers the original 1985 afio code]
   49  *
   50  * Copyright (c) 1985 Lachman Associates, Inc..
   51  *
   52  * This software was written by Mark Brukhartz at Lachman Associates,
   53  * Inc.. It may be distributed within the following restrictions:
   54  *  (1) It may not be sold at a profit.
   55  *  (2) This credit and notice must remain intact.
   56  * This software may be distributed with other software by a commercial
   57  * vendor, provided that it is included at no additional charge.
   58  *
   59  *
   60  * [Note: it is believed that condition 5 of the Perl "Artistic
   61  * License" implies the intent of restriction (1) above.]
   62  *
   63  * --------
   64  *
   65  * ** License notice 2, covering part of this software package.
   66  *
   67  * [Covers the tempnam function]
   68  *
   69  * Copyright:   Copyright (c) 1989 by Monty Walls.
   70  *      Not derived from licensed software.
   71  *
   72  *      Permission to copy and/or distribute granted under the
   73  *      following conditions:
   74  *
   75  *      1). This notice must remain intact.
   76  *      2). The author is not responsible for the consequences of use
   77  *          this software, no matter how awful, even if they
   78  *          arise from defects in it.
   79  *      3). Altered version must not be represented as being the
   80  *          original software.
   81  *
   82  * --------
   83  *
   84  * ** License notice 3, covering part of this software package.
   85  *
   86  * [Covers the contents of the gnu.fnmatch.tar.gz file]
   87  *
   88  *  Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
   89  *
   90  *  This library is free software; you can redistribute it and/or
   91  *  modify it under the terms of the GNU Library General Public License as
   92  *  published by the Free Software Foundation; either version 2 of the
   93  *  License, or (at your option) any later version.
   94  *
   95  *  This library is distributed in the hope that it will be useful,
   96  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   97  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   98  *  Library General Public License for more details.
   99  *
  100  *  You should have received a copy of the GNU Library General Public
  101  *  License along with this library; see the file COPYING.LIB.  If
  102  *  not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  103  *  Cambridge, MA 02139, USA.
  104  *
  105  * --------
  106  *
  107  * ** License notice 4, covering part of this software package.
  108  *
  109  * [Covers the remainder of this software package]
  110  *
  111  * Additional code was written by a large cast of people.
  112  *
  113  * All additional code may be redistributed under the conditions of
  114  * license notice 1.
  115  *
  116  * Note that the authors of the additional code retain the right to
  117  * allow for the re-distribution of their code under weaker (and less
  118  * exotic) conditions.
  119  *
  120  * --------
  121  *
  122  * ** WARRANTY NOTICE
  123  *
  124  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  125  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  126  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  127  *
  128  *
  129  * [End of licensing and redistribution section]
  130  *
  131  * ---------------------------------------------------------------------
  132  *
  133  * Makefile options:
  134  *  o Define INDEX to use index() in place of strchr() (v7, BSD).
  135  *  o Define MEMCPY when an efficient memcpy() exists (SysV).
  136  *  o Define MKDIR when a mkdir() system call is present (4.2BSD, SysVr3).
  137  *  o Define NOVOID if your compiler doesn't like void casts.
  138  *  o Define SYSTIME to use <sys/time.h> rather than <time.h> (4.2BSD).
  139  *  o Define VOIDFIX to allow pointers to functions returning void (non-PCC).
  140  *  o Define CTC3B2 to support AT&T 3B2 streaming cartridge tape.
  141  *  o Define HAVEFCNTL if you have <fcntl.h>
  142  *  o Define MYTEMPNAM if you don't have tempnam()
  143  *  o Define UNIXPC if you are on a 3b1, 7300, etc.
  144  *  o Define HAVEMEMCMP if you have memcmp otherwise assumes bcmp
  145  *  o Define DEFFMTCMD to being how to format the media you use the most.
  146  *  o Define LONGZFILE if you want .Z to be tagged on the end of a 14 char
  147  *
  148  * BUGS:
  149  *  See the manpage.
  150  *
  151  * Added by Jeff Buhrt:
  152  *  Floppy Verify/format/restart output in the middle of a set,
  153  *  compress files on output, extended error messages and logging
  154  *
  155  * Added by Dave Gymer:
  156  *  Lotsa bugfixes, Linux support, recognition of .Z files in an archive
  157  *  that were compressed already (and shouldn't be uncompressed).
  158  *  Displays compression ratios.
  159  *
  160  * See the HISTORY file for more revision info.  */
  161 
  162 
  163 #include <stdio.h>
  164 #include <errno.h>
  165 
  166 #ifdef sun
  167 #include <sys/types.h>
  168 #include <utime.h>
  169 #include <signal.h>
  170 #include <strings.h>
  171 #include <sys/wait.h>
  172 #define linux_tstamp 1
  173 #if 0
  174 /* fix SunOS errno.h not declaring what the manpage says it declares
  175    bogosity. */
  176  extern int sys_nerr;
  177  extern char *sys_errlist[];
  178 #endif
  179 #endif
  180 
  181 #ifdef hpux
  182 #if 0
  183  /* Fix that HPUX dosent have sys_nerr or sys_errlist
  184     Added by Daniel Andersson, daniel.andersson@sto.sema.se
  185   */
  186 extern int sys_nerr;
  187 extern char *sys_errlist[];
  188 #endif
  189 #endif
  190 
  191 #include <unistd.h>
  192 #include <string.h>
  193 #include <stdlib.h>
  194 #ifdef __CYGWIN32__
  195 #include <signal.h>
  196 #else
  197 #include <sys/signal.h>
  198 #endif
  199 #include <sys/types.h>
  200 #include <sys/ioctl.h>
  201 #include <sys/stat.h>
  202 #include <pwd.h>
  203 #include <grp.h>
  204 #include "patchlevel.h"
  205 
  206 #ifdef linux
  207 
  208 #define linux_tstamp 1
  209 
  210 #include <utime.h>
  211 #include <sys/wait.h>
  212 
  213 /* for flushing floppy cache */
  214 #include <linux/fd.h>
  215 #endif
  216 
  217 /* compatibility fixes for IRIX native c compiler. */
  218 #ifdef irix_cc_compatibility
  219 #define linux_tstamp 1
  220 #include <strings.h>
  221 #endif
  222 
  223 #ifndef major
  224 #ifdef sun
  225 #include <sys/mkdev.h>
  226 #else
  227 #include <sys/sysmacros.h>
  228 #endif
  229 #endif /* major */
  230 
  231 #include "afio.h"
  232 
  233 
  234 /* define 1 to enable file descriptor leak debugging code */
  235 #define FDDEBUG 0
  236 
  237      /*
  238       * Static variables.
  239       */
  240      STATIC short Fflag;    /*
  241                  * floppy flag (write when buf full)
  242                  * set -sdisk_size as well
  243                  */
  244      STATIC short Zflag;    /* compress the files that we can */
  245      STATIC short verifyflag;   /* Verify (floppy) flag */
  246      STATIC short verifycnt;
  247 #ifdef  CTC3B2
  248      STATIC short Cflag;    /* Enable 3B2 CTC streaming (kludge) */
  249 #endif /* CTC3B2 */
  250      STATIC short aflag;    /* Preserve atime (while munging ctime) */
  251      STATIC short dflag;    /* Don't create missing directories */
  252      STATIC short fflag;    /* Fork before writing to archive */
  253      STATIC short gflag;    /* Change to input file directories */
  254             short hflag;    /* Follow symbolic links */
  255      STATIC short jflag;    /* Don't generate sparse filesystem blocks */
  256      STATIC short kflag;    /* Skip initial junk to find a header */
  257             short lflag;    /* Link rather than copying (when possible) */
  258      STATIC short mflag;    /* Ignore archived timestamps */
  259      STATIC short nflag;    /* Keep newer existing files */
  260      STATIC short uflag;    /* Report files with unseen links */
  261      STATIC short vflag;    /* Verbose */
  262      STATIC short xflag;    /* Retain file ownership */
  263      STATIC short zflag;    /* Print final statistics */
  264      STATIC short flag0;    /* Input names terminated with '\0' */
  265      STATIC short Jflag=0;  /* Keep going after archive write error */
  266      STATIC short hidequit; /* show the quit option? */
  267      STATIC short abspaths; /* allow absolute path names? */
  268      STATIC uint arbsize = BLOCK;   /* Archive block size */
  269      STATIC short areof;    /* End of input volume reached */
  270      STATIC int arfd = -1;  /* Archive file descriptor */
  271      STATIC ulonglong arleft;   /* Space remaining within current volume */
  272      STATIC char *arname;   /* Expanded archive name */
  273      STATIC uint arpad;     /* Final archive block padding boundary */
  274      STATIC char arspec[PATHSIZE];  /* Specified archive name */
  275      STATIC char proc_arname[PATHSIZE+10];/* %-processed archive name */
  276      STATIC ulonglong aruntil=0; /* Volume size limit */
  277      STATIC int sflagused=0;     /* flag if -s flag was used */
  278      STATIC int roundaruntil=1; /* Round aruntil to multiple of arbsize? */
  279      STATIC ulonglong maxsizetocompress=200L*1024L*1024L; /* ==0, then no max */
  280      STATIC int askfornext=0;   /* Ask for next disk on input eof? */
  281      STATIC uint arvolume = 1;  /* Volume number */
  282      STATIC off_t buflen;   /* Archive buffer length */
  283      STATIC char *buffer;   /* Archive buffer */
  284      STATIC char *bufidx;   /* Archive buffer index */
  285      STATIC char *bufend;   /* End of data within archive buffer */
  286      STATIC Child *children;    /* Child processes */
  287      STATIC char *formatcmd = DEFFMTCMD;    /* how to format */
  288      STATIC gid_t gid;      /* Group ID */
  289      STATIC Link *linkbase[1024];/* Unresolved link information */
  290      STATIC unsigned char ino16bitused[256*256/8];  /* bitmap of 16 bit inode numbers */
  291      STATIC ino_t freshino = 0; /* counter to make fresh inos */
  292      STATIC FILE *logfile = NULL;   /* log same errors as stderr would */
  293      STATIC ushort mask;    /* File creation mask */
  294      STATIC char *myname;   /* Arg0 */
  295      extern char *optarg;   /* Option argument */
  296      extern int optind;     /* Command line index */
  297      STATIC int outpid;     /* Process ID of outstanding outflush() */
  298      STATIC char pwd[PATHSIZE]; /* Working directory (with "-g") */
  299      STATIC int pipepid;    /* Pipeline process ID */
  300      STATIC time_t timenow; /* Current time */
  301      STATIC time_t timewait;    /* Time spent awaiting new media */
  302      STATIC ulonglong total;    /* Total number of bytes transferred */
  303      STATIC int ttyf = -1;  /* For interactive queries (yuk) */
  304      STATIC uid_t uid;      /* User ID */
  305      int uncompressrun = 0; /* is uncompress running? its pid if so */
  306      char uncompto[PATHSIZE];   /* name we uncompressed to */
  307      STATIC int anycorrupt = 0; /* if any data is corrupted */
  308      STATIC int warnings = 0; /* if any data is corrupted */
  309      int printbytepos = 0;      /* print position of each file in archive */
  310      ulonglong bytepos;            /* position of first byte of current file */
  311      STATIC char *controlscript=NULL;  /* script to pipe control files to */
  312      STATIC char *promptscript=NULL; /* name of disk-change script */
  313      STATIC ushort extfmt = 0;  /* Use extended ASCII format */
  314      STATIC ushort cpiocompat = 0;  /* Never use large ASCII format headers */
  315      STATIC ushort cpiowarned = 0;  /* warning given? */
  316      STATIC char *email=NULL;        /* email address to notify of volume change requests */
  317      STATIC int rewindfd = -1;  /* file descriptor to rewind before
  318                                    (un)compress invocations */
  319      STATIC char *ignorewarnings="mc"; /* data for -1 option */
  320      STATIC char *aruntil_string=NULL; /* -s option string given by user */
  321      STATIC int extcasesens=0; /* Case sensitive matching in -E option? */
  322      STATIC Dir *DirP=NULL; /* list of directories with their saved timestamps */
  323      STATIC char firstfilename[PATHSIZE]=""; /* for temp storage during -o */
  324      STATIC int useoutmodetoc=0; /* used in tocentry() */
  325      STATIC short noglob=0; /* disable globbing */
  326      STATIC int allowinsecurepaths=0;
  327      STATIC int allowinsecuresymlinks=0;
  328      STATIC int nosymlinks=0;
  329 
  330 int main (int ac, char **av)
  331 {
  332   reg int c;
  333   reg uint group = 1;
  334   VOIDFN (*fn)(char **) = NULL;
  335   time_t timedone;
  336   auto char remote[PATHSIZE];
  337   char *exitmsg;
  338   int status;
  339   Stat tmpstat;
  340 
  341 #if 0
  342   printf("sizeof off_t = %d\n",sizeof(off_t));
  343   printf("sizeof size_t = %d\n",sizeof(size_t));
  344 #endif
  345 
  346   if ((myname = strrchr (*av, '/')))
  347     ++myname;
  348   else
  349     myname = *av;
  350   mask = umask (0);
  351   uid = getuid ();
  352   gid = getgid ();
  353   if (uid == 0)
  354     xflag = 1;
  355 
  356   /* ignore SIGPIPE to deal with gzip -d exiting prematurely */
  357   VOID signal (SIGPIPE, SIG_IGN);
  358 
  359   /* All letters have been used as options, now eating into the numbers....
  360    */
  361 
  362   while ((c = options (ac, av,
  363          "aioprtIOVCb:c:de:fghjklmns:uvxXy:Y:zFKZL:R:qAE:G:M:w:W:T:SBD:P:Q:U4JH:0@:N:3:1:92:56:78:"))
  364         )
  365     {
  366       switch (c)
  367     {
  368     case 'r':
  369       if (fn)
  370         usage ();
  371       fn = readcheck;
  372       allowinsecurepaths=allowinsecuresymlinks=1;
  373       break;
  374     case 'i':
  375       if (fn)
  376         usage ();
  377       fn = in;
  378       break;
  379     case 'o':
  380       if (fn)
  381         usage ();
  382       fn = out;
  383       useoutmodetoc=1;
  384       break;
  385     case 'p':
  386       if (fn)
  387         usage ();
  388       fn = pass;
  389       break;
  390     case 't':
  391       if (fn)
  392         usage ();
  393       fn = toc;
  394       allowinsecurepaths=allowinsecuresymlinks=1;
  395       break;
  396     case 'I':
  397       if (fn)
  398         usage ();
  399       fn = copyin;
  400       break;
  401     case 'O':
  402       if (fn)
  403         usage ();
  404       fn = copyout;
  405       break;
  406     case 'V':
  407       VOID printf ("%s: Version %s dated %s\n",
  408                myname, VERSION, DATE);
  409       exit (0);
  410 #ifdef  CTC3B2
  411     case 'C':
  412       ++Cflag;
  413       arbsize = 31 * 512;
  414       group = 10;
  415       aruntil = 1469 * 31 * 512;
  416       break;
  417 #endif /* CTC3B2 */
  418     case 'a':
  419       ++aflag;
  420       break;
  421     case 'b':
  422       if ((arbsize = (uint) optsize (optarg)) == 0)
  423         fatal (optarg, "Bad block size");
  424       break;
  425     case 'c':
  426       if ((group = (uint) optsize (optarg)) == 0)
  427         fatal (optarg, "Bad buffer count");
  428       break;
  429     case 'd':
  430       ++dflag;
  431       break;
  432     case 'e':
  433       arpad = (uint) optsize (optarg);
  434       break;
  435     case 'f':
  436       ++fflag;
  437       break;
  438     case 'g':
  439       ++gflag;
  440       break;
  441     case 'h':
  442       ++hflag;
  443       break;
  444     case 'j':
  445       ++jflag;
  446       break;
  447     case 'k':
  448       ++kflag;
  449       break;
  450     case 'l':
  451       ++lflag;
  452       break;
  453     case 'm':
  454       ++mflag;
  455       break;
  456     case 'n':
  457       ++nflag;
  458       break;
  459     case 's':
  460       sflagused = 1;
  461       /* Do a 'dry run' to check all values for syntax errors */
  462       aruntil_string = strdup(optarg);
  463           while(aruntil_string) update_aruntil();
  464       /* Now the real initialisation */
  465           aruntil_string = optarg;
  466           update_aruntil();
  467       if (aruntil == 0)  askfornext = 1;
  468       break;
  469     case 'F':
  470       ++Fflag;
  471       break;
  472     case 'Z':
  473       ++Zflag;
  474       break;
  475     case 'K':
  476       ++verifyflag;
  477       break;
  478     case 'u':
  479       ++uflag;
  480       break;
  481     case 'v':
  482       ++vflag;
  483       break;
  484     case 'x':
  485       xflag = 1;
  486       break;
  487     case 'X':
  488       xflag = 0;
  489       break;
  490     case 'y':
  491       nameadd (optarg, PATTYPE_MATCH);
  492       break;
  493     case 'Y':
  494       nameadd (optarg, PATTYPE_NOMATCH);
  495       break;
  496     case 'z':
  497       ++zflag;
  498       break;
  499     case 'L':
  500       if ((logfile = fopen (optarg, "a")) == (FILE *) 0)
  501         {
  502           fprintf (stderr,
  503                "Can't open %s to append, get help\n",
  504                optarg);
  505           exit (1);
  506         }
  507       break;
  508     case 'R':
  509       formatcmd = optarg;
  510       break;
  511     case 'q':
  512       hidequit = TRUE;
  513       break;
  514     case 'A':
  515       abspaths = TRUE;
  516       break;
  517         case 'E':
  518       if(strcmp(optarg,"CS")==0) extcasesens=1;
  519       else if(strcmp(optarg,"CI")==0) extcasesens=0;
  520           else if(!readcompexts(optarg))
  521         {
  522           exit (1);
  523         }
  524           break;
  525         case 'G':
  526           gzipfactor=(uint) optsize(optarg);
  527           if((gzipfactor <1) || (gzipfactor >9))
  528         {
  529           fprintf (stderr,
  530                "%s: Illegal gzip speed factor (Must be 1--9)\n",
  531                optarg);
  532           exit (1);
  533         }
  534           break;
  535         case 'M':
  536           maxmem=(off_t) optsize(optarg);
  537           break;
  538         case 'T':
  539           compthreshold=(uint) optsize(optarg);
  540           break;
  541         case 'w':
  542           if(!nameaddfile(optarg,PATTYPE_MATCH,flag0))
  543         {
  544           fprintf (stderr,
  545                "Can't read configuration file %s\n",
  546                optarg);
  547           exit (1);
  548         }
  549           break;
  550         case 'W':
  551           if(!nameaddfile(optarg,PATTYPE_NOMATCH,flag0))
  552         {
  553           fprintf (stderr,
  554                "Can't read configuration file %s\n",
  555                optarg);
  556           exit (1);
  557         }
  558           break;
  559         case '6':
  560           if(!nameaddfile(optarg,PATTYPE_EXT,0))
  561         {
  562           fprintf (stderr,
  563                "Can't read configuration file %s\n",
  564                optarg);
  565           exit (1);
  566         }
  567           break;
  568         case 'S':
  569           ignoreslash=0;
  570           break;
  571         case 'B':
  572           printbytepos=1;
  573           break;
  574         case 'D':
  575           controlscript=optarg;
  576           break;
  577     case 'Q':
  578       compressargs=1;
  579       add_arg(optarg);
  580       break;
  581     case 'P':
  582       compressprog=optarg;
  583       break;
  584     case 'U':   /* compress All files */
  585       forceZflag=1;
  586       lflag=1; /* Due to internal limitations we need to set this */
  587       break;
  588     case '0':
  589       flag0 = 1-flag0;
  590       break;
  591     case '4':       /* Use extended ASCII format */
  592       extfmt = 1;
  593       break;
  594     case '5':
  595       cpiocompat = 1;
  596       break;
  597     case 'J':
  598       Jflag = 1;
  599       break;
  600        case 'H':
  601          promptscript=optarg;  /* name or definition of the promptscript */
  602          break;
  603        case '@':
  604          email=optarg;
  605          break;
  606        case '3':
  607          rewindfd=(int)optsize(optarg);
  608          break;
  609        case '1':
  610          ignorewarnings=optarg;
  611          break;
  612        case '9':
  613      roundaruntil=0;
  614          break;
  615        case '2':
  616      maxsizetocompress=optsize(optarg);
  617          break;
  618        case '7':
  619      noglob = 1-noglob;
  620      break;
  621        case '8':
  622      if (strcmp(optarg, "allowinsecurepaths") == 0) allowinsecurepaths=1;
  623      else if(strcmp(optarg, "allowinsecuresymlinks") == 0) allowinsecuresymlinks=1;
  624      else if (strcmp(optarg, "nosymlinks") == 0) nosymlinks=1;
  625      else fatal (optarg, "unknown value for -8 option");
  626      break;
  627 
  628     default:
  629       usage ();
  630     }
  631     }
  632   if (fn == NULL || av[optind] == NULL)
  633     usage ();
  634 
  635  if (extfmt && cpiocompat)
  636    {
  637      warn(av[0], "Options -4 and -5 cannot be specified at the same time.");
  638      usage ();
  639    }
  640 
  641   if(fflag && aruntil==0)
  642   {
  643       fprintf (stderr,"Fatal: must supply nonzero -s [volsize] to use -f\n");
  644       usage();
  645   }
  646 
  647   if(compressprog && (rewindfd==-1))
  648       if(strstr(compressprog,"pgp") || strstr(compressprog,"gpg"))
  649       {
  650       fatal(compressprog,"Must use -3 flag if -P program matches 'pgp' or 'gpg', see the afio manual page.");
  651       }
  652 
  653   if(!compressprog) compressprog = PRG_COMPRESS;
  654   compress_arg_list[0] = compressprog;
  655 
  656   if(maxmem/1024L/1024L > (1024+512))
  657     {
  658       /* afio uses uints and ints and size_t at several places that
  659      may make it (on architectures with 32 bit ints and size_t)
  660      fail to do the right calculations when the buffer size is
  661      >2GB.  This 1.5 GB limit is somewhat conservative, but better
  662      safe than sorry.
  663 
  664      If you have an os/compile environment witrh 64 bit size_t
  665      and int, things might be OK if you disable this test, but
  666      I have not tested it.
  667      If you disable here see also the code in memwrite().
  668       */
  669       fatal (arspec, "In-memory compression buffer size above 1.5GB not supported");
  670     }
  671 
  672   if (Fflag)
  673     {
  674       if ((buflen = (off_t) aruntil) == 0)
  675     usage ();
  676     }
  677   else
  678     buflen = (off_t)arbsize * (off_t)group;
  679 
  680   if( roundaruntil )
  681     {
  682       /* round aruntil down to a multiple of arbsize: some devices
  683          (like ftape) puke on a smaller-than-blocksize last write to
  684          the volume */
  685       aruntil = ( aruntil / (ulonglong) arbsize );
  686       aruntil = aruntil * arbsize;
  687     }
  688 
  689   if (aruntil && (aruntil < arbsize))
  690     {
  691 #ifdef hpux
  692       /* HPUX gcc dosent like the (ulong) fixed by Daniel Andersson
  693          daniel.andersson@sto.sema.se  */
  694       fprintf (stderr, "Media size %ld is less than block size %d\n",
  695                aruntil, arbsize);
  696 #else
  697       fprintf (stderr, "Media size %ld is less than block size %d\n",
  698            (unsigned long) aruntil, arbsize);
  699 #endif
  700    usage ();
  701     }
  702   if (arpad == 0)
  703     arpad = arbsize;
  704   if (fn != pass)
  705     {
  706       reg char *colon;
  707       reg char *perc;
  708       reg char *equal;
  709       char  *host;
  710       reg int isoutput = (fn == out || fn == copyout);
  711 
  712       arname = strcpy (arspec, av[optind++]);
  713       if ((colon = strchr (arspec, ':')))
  714     {
  715       *colon++ = '\0';
  716       if ((perc = strchr (arspec, '%')))
  717         *perc++ = '\0';
  718       if ((equal = strchr ((perc ? perc : arspec), '=')))
  719         *equal++ = '\0';
  720       if ((host=strchr(arspec,'@')))
  721           *host++ = 0;
  722       VOID sprintf (arname = remote,
  723             "!%s %s%s %s '%s -%c -b %u -c %u %s'",
  724             perc ? perc : "rsh",
  725             host ? "-l ":"",
  726             host ? arspec : "",
  727             host ? host : arspec,
  728             equal ? equal : myname,
  729             isoutput ? 'O' : 'I', arbsize,
  730             group, colon);
  731           if( host )
  732             *--host = '@';
  733       if (equal)
  734         *--equal = '=';
  735       if (perc)
  736         *--perc = '%';
  737       *--colon = ':';
  738     }
  739       if (gflag && *arname != '/' && *arname != '!')
  740     fatal (arspec, "Relative pathname");
  741       VOID signal (SIGINT, goodbye);
  742 
  743       if(buflen/1024L/1024L > (1024+512))
  744     {
  745       /* afio uses uints and ints at several places that make it
  746          (on architectures with 32 bit ints and size_t) fail to do
  747          the right calculations when the buffer size is >2GB.
  748          This 1.5GB limit is somewhat conservative, but better
  749          safe than sorry.
  750 
  751          If you have an os/compile environment witrh 64 bit size_t
  752          and int, things might be OK if you disable this test, but
  753          I have not tested it.
  754       */
  755       fatal (arspec, "In-memory I/O buffer size above 1.5GB not supported");
  756     }
  757 
  758       /*
  759        * +BLOCK is added to make sure we don't overrun buffer on a
  760        * read (internal read(1) length is thus met)
  761        */
  762 
  763       if ((buffer = bufidx = bufend = malloc ((size_t)buflen + BLOCK)) == NULL)
  764     fatal (arspec, "Cannot allocate enough memory for I/O buffer");
  765 
  766       /* if in -o mode, do a sanity check on the input now.  This
  767      should prevent deletion of the archive file contents in most
  768      cases when people who want to do afio -i accidentally type
  769          afio -o.  If not reading from a terminal, ignore check -- this
  770          allows backup scripts to create empty archives.
  771        */
  772       if((fn == out)&&isatty(STDIN))
  773     {
  774       while(1)
  775         {
  776           if (lineget (stdin, firstfilename, PATHSIZE) < 0)
  777         {
  778           fatal("-o (write archive) mode", "could not read any file names from stdin");
  779         }
  780           if(strncmp(firstfilename,"//--",4)==0) break;
  781           if (STAT (firstfilename, &tmpstat) < 0)
  782         {
  783           VOID warn (firstfilename, syserr ());
  784           VOID warn (firstfilename, "-o (write archive) mode needs file names on stdin");
  785         }
  786           else break;
  787         }
  788           /* OK, if there was a good file name, then
  789              now firstfilename[] has a non-NULL string, this indicates
  790          to the openin function that it needs to use that string, not
  791          read from stdin */
  792     }
  793 
  794       /*
  795        * open the archive file
  796        *
  797        * open a floppy at the last moment (if output), otherwise now
  798        * note we set arleft prematurely so we don't have to open the
  799        * disk now
  800        */
  801       if (!Fflag || !isoutput)
  802     {
  803       if (nextopen (isoutput ? O_WRONLY : O_RDONLY) < 0)
  804         goodbye (1);
  805     }
  806       else
  807     arleft = aruntil;
  808 
  809     }
  810   timenow = time ((time_t *) NULL);
  811   (*fn) (av + optind);
  812   timedone = time ((time_t *) NULL);
  813   if (uflag)
  814     linkleft ();
  815   if (vflag || (fn == toc))
  816     fflush(stdout);
  817 
  818   if(cpiowarned)
  819     {
  820       /* repeat warning message at end */
  821      VOID warn_nocount(arspec,"Warning: Created archive is not fully compatible with cpio or afio versions 2.4.7 and lower.");
  822      VOID warn_nocount(arspec,"See the ARCHIVE PORTABILITY section of the manpage.");
  823     }
  824 
  825   exitmsg="The operation was successful.";
  826   if(warnings)
  827   {
  828       exitmsg=malloc(80);
  829       if(exitmsg==NULL)
  830       exitmsg="The operation HAD WARNINGS ABOUT ERRORS.";
  831       else
  832       sprintf(exitmsg,"The operation HAD %d WARNING%s ABOUT ERRORS.",warnings,warnings==1?"":"S");
  833   }
  834   if(anycorrupt) exitmsg="The operation FAILED.";
  835 
  836 
  837   if (zflag)
  838     {
  839       reg FILE *stream;
  840 
  841       stream = fn == toc || fn == copyin || arfd == STDOUT ? stderr : stdout;
  842       VOID fprintf (stream, "%s: ", myname);
  843       prsize (stream, total);
  844       VOID fprintf (stream, " bytes %s in %lu seconds. %s\n",
  845                     fn == pass
  846                     ? "transferred"
  847                     : fn == out || fn == copyout
  848                     ? "written"
  849                     : "read",
  850                     timedone - timenow - timewait,
  851                     exitmsg);
  852     }
  853   if (logfile != (FILE *) 0)
  854     {
  855       VOID fprintf (logfile, "%s: Final count: ", myname);
  856       prsize (logfile, total);
  857       VOID fprintf (logfile,
  858             " bytes %s in %lu seconds (+waited %lu seconds for disk swapping (%u disks)) finished at %s",
  859             (fn == pass ? "transferred" : (fn == out
  860                            || fn == copyout ? "written" : "read")),
  861             timedone - timenow - timewait,
  862             timewait, arvolume, ctime (&timedone));
  863       VOID fprintf (logfile,"%s\n",exitmsg);
  864     }
  865   nextclos ();
  866 
  867   /* Added to lower chance of race condition (?) in rsh processing
  868      when reading remote files */
  869   if(fn==copyin) { fflush(stdout);  fclose(stdout); sleep(2);  }
  870   if (email) mail(email,-1,arspec);
  871 
  872   status=0;
  873   if(anycorrupt) status=1;
  874   if(warnings) if(index(ignorewarnings,(int)'a')==NULL) status=1;
  875 
  876   goodbye (status);
  877   /* NOTREACHED */
  878   return 0; /* silence gcc -Wall */
  879 }
  880 
  881 
  882 
  883 /*
  884  * update_aruntil()
  885  *
  886  * Sets the next aruntil-value out of the options-list
  887  */
  888 void update_aruntil()
  889 {
  890     char *next_aruntil_string = aruntil_string;
  891 
  892     if(aruntil_string)
  893       {
  894     aruntil_string = strchr (aruntil_string, ',');
  895     if(aruntil_string) *aruntil_string++='\0';
  896 
  897     aruntil = optsize (next_aruntil_string);
  898       }
  899 }
  900 
  901 /*
  902  * mail()
  903  *
  904  * Mail tape change message
  905  */
  906 void mail(char *who,int vol,char *archive)
  907 {
  908     FILE *fp;
  909     char cmd[1024];
  910     char hostname[256];
  911     gethostname(hostname,sizeof(hostname));
  912     sprintf(cmd,"sendmail %s",who);
  913     fp = popen(cmd,"w");
  914     if (fp == NULL ) {
  915         perror(cmd);
  916         return;
  917     }
  918     fprintf(fp,"From: Afio archiver\n");
  919     fprintf(fp,"Subject: %s %s: %s\n\n",hostname,archive,vol<0?"operation complete":"volume change needed");
  920     fprintf(fp,"Hostname: %s\n",hostname);
  921     fprintf(fp,"Archive : %s\n\n",archive);
  922     if(vol>=0)
  923         fprintf(fp,"Need change to volume #%d.\n\n",vol);
  924     else
  925         fprintf(fp,"Operation complete.\n\n");
  926     pclose(fp);
  927 }
  928 
  929 
  930 /*
  931  * copyin()
  932  *
  933  * Copy directly from the archive to the standard output.
  934  */
  935 STATIC VOIDFN
  936 copyin (char **av)
  937 {
  938   reg ssize_t got;
  939   reg ssize_t have;
  940 
  941   if (*av)
  942     fatal (*av, "Extraneous argument");
  943   while (!areof || askfornext)
  944   {
  945       VOID infill ();
  946       while ((have = bufend - bufidx))
  947       if ((got = writeall (STDOUT, bufidx, have)) < 0)
  948           fatal ("<stdout>", syserr ());
  949       else
  950       {
  951           total+=have;
  952           if (got > 0)
  953           bufidx += got;
  954           else
  955             return;
  956       }
  957   }
  958 }
  959 
  960 /*
  961  * copyout()
  962  *
  963  * Copy directly from the standard input to the archive.
  964  */
  965 STATIC VOIDFN
  966 copyout (char **av)
  967 {
  968   reg int got;
  969   reg uint want;
  970 
  971   if (*av)
  972     fatal (*av, "Extraneous argument");
  973   for (;;)
  974     {
  975       while ((want = bufend - bufidx) == 0)
  976     outflush (NOTDONE);
  977       if ((got = read (STDIN, bufidx, want)) < 0)
  978     fatal ("<stdin>", syserr ());
  979       else if (got == 0)
  980     break;
  981       else
  982       {
  983       bufidx += got;
  984       total += got; /* actually a bit too early for bytes written count */
  985       }
  986     }
  987   outflush (DONE);
  988   if (fflag)
  989     outwait ();
  990 }
  991 
  992 /*
  993  * dirchg()
  994  *
  995  * Change to the directory containing a given file.
  996  */
  997 STATIC int
  998 dirchg (char *name, char *local)
  999 {
 1000   reg char *last;
 1001   reg int len;
 1002   auto char dir[PATHSIZE];
 1003 
 1004   if (*name != '/')
 1005     return (warn (name, "Relative pathname"));
 1006   for (last = name + strlen (name); last[-1] != '/'; --last)
 1007     ;
 1008   len = last - name;
 1009   strncpy (dir, name, (size_t)len)[len] = '\0';
 1010   VOID strcpy (local, *last ? last : ".");
 1011   if (strcmp (dir, pwd) == 0)
 1012     return (0);
 1013   if (chdir (dir) < 0)
 1014     return (warn (name, syserr ()));
 1015   VOID strcpy (pwd, dir);
 1016   return (0);
 1017 }
 1018 
 1019 /*
 1020  * dirmake()
 1021  *
 1022  * Make a directory. Returns zero if successful, -1 otherwise.
 1023  */
 1024 STATIC int
 1025 dirmake (char *name, Stat *asb)
 1026 {
 1027   if (mkdir (name, asb->sb_mode & S_IPOPN) < 0)
 1028     return (-1);
 1029 /* First do the chown, then the chmod, because the chown may clear
 1030    the suid/sgid bits we want to set.
 1031 */
 1032   if (xflag)
 1033     VOID chown (name,
 1034         (uid == 0 ? asb->sb_uid : uid),
 1035         asb->sb_gid);
 1036   if (asb->sb_mode & S_IPEXE)
 1037     VOID chmod (name, asb->sb_mode & S_IPERM);
 1038   return (0);
 1039 }
 1040 
 1041 /*
 1042  * dirneed()
 1043  *
 1044  * Recursively create missing directories (with the same permissions
 1045  * as their first existing parent). Temporarily modifies the 'name'
 1046  * argument string. Returns zero if successful, -1 otherwise.
 1047  */
 1048 STATIC int
 1049 dirneed (char *name)
 1050 {
 1051   reg char *cp;
 1052   reg char *last;
 1053   reg int ok;
 1054   static Stat sb;
 1055 
 1056   last = NULL;
 1057   for (cp = name; *cp;)
 1058     if (*cp++ == '/')
 1059       last = cp;
 1060   if (last == NULL)
 1061     return (STAT (".", &sb));
 1062   *--last = '\0';
 1063   ok = STAT (*name ? name : "/", &sb) == 0
 1064     ? ((sb.sb_mode & S_IFMT) == S_IFDIR)
 1065     : (!dflag && dirneed (name) == 0 && dirmake (name, &sb) == 0);
 1066   *last = '/';
 1067   return (ok ? 0 : -1);
 1068 }
 1069 
 1070 /*
 1071  * fatal()
 1072  *
 1073  * Print fatal message and exit.
 1074  */
 1075 STATIC void
 1076 fatal (char *what, char *why)
 1077 {
 1078   /* print position in archive if some data was transferred */
 1079   if(total>0)
 1080     VOID warnarch ("Fatal error:",(off_t)0);
 1081   VOID warn (what, why);
 1082   goodbye (1);
 1083 }
 1084 
 1085 
 1086 
 1087 /*
 1088  * writeall()
 1089  *
 1090  * Write all bytes in buf or return -1.  Used to fix invalid assumptions
 1091  * about write() elsewhere.
 1092  */
 1093 STATIC
 1094 ssize_t writeall(int fd, const char *buf, size_t count)
 1095 {
 1096  ssize_t put;
 1097  size_t totalput;
 1098 
 1099  totalput=0;
 1100  while(totalput<count)
 1101  {
 1102      put=write(fd,buf+totalput,count-totalput);
 1103 
 1104      if(put<0) return put;
 1105      totalput+=put;
 1106  }
 1107 
 1108  return count;
 1109 }
 1110 
 1111 /*
 1112  * readall()
 1113  *
 1114  * Read, completely filling buf if we can, or return short size or -1.
 1115  * Used to fix invalid assumptions
 1116  * about read() elsewhere.
 1117  */
 1118 STATIC
 1119 ssize_t readall(int fd, char *buf, size_t count)
 1120 {
 1121  ssize_t got;
 1122  size_t totalgot;
 1123 
 1124  totalgot=0;
 1125  while(totalgot<count)
 1126  {
 1127      got=read(fd,buf+totalgot,count-totalgot);
 1128      /* if(got!=count) printf("got on %d = %d\n",fd,got); */
 1129      if(got<=0)
 1130        {
 1131      if(got==0) return totalgot;
 1132      if(got<0) return got;
 1133        }
 1134      totalgot+=got;
 1135  }
 1136 
 1137  return count;
 1138 }
 1139 
 1140 
 1141 /*
 1142  * mayberewind()
 1143  *
 1144  * implement -3 option
 1145  */
 1146 STATIC
 1147 void mayberewind()
 1148 {
 1149   if(rewindfd>=1)
 1150   {
 1151     if(lseek(rewindfd,(off_t)0,SEEK_SET)<0)
 1152     {
 1153     fatal("-3 option",syserr());
 1154     }
 1155   }
 1156 }
 1157 
 1158 
 1159  /*
 1160  * savedirstamp()
 1161  *
 1162  * Remember necessary timestamps for a directory,
 1163  * so they can be restored afterwards.
 1164  */
 1165 STATIC void
 1166 savedirstamp (char *name, time_t mtime)
 1167 {
 1168   Dir *dirp;
 1169 
 1170   /* Note that the cast below is necessary since memget() is pre-C89. */
 1171   if((dirp=(Dir *)memget(sizeof(Dir))) != NULL) {
 1172     if ((dirp->d_name=memstr(name)) == NULL) {
 1173       free(dirp);
 1174     } else {
 1175       dirp->d_mtime=mtime;
 1176       dirp->d_forw=DirP;
 1177       DirP=dirp;
 1178     }
 1179   }
 1180 }
 1181 
 1182 /*
 1183  * restoredirstamps()
 1184  *
 1185  * Restore timestamps for the saved list of directories.
 1186  */
 1187 STATIC void
 1188 restoredirstamps (void)
 1189 {
 1190 #ifdef linux_tstamp
 1191   auto struct utimbuf tstamp;
 1192 #else
 1193   auto time_t tstamp[2];
 1194 #endif
 1195   Dir *DirP_curr = DirP; /* keep DirP reachable */
 1196   Dir *DirP_forw;
 1197   while(DirP_curr!=NULL)
 1198   {
 1199 #ifdef linux_tstamp
 1200     tstamp.actime = DirP_curr->d_mtime;
 1201     tstamp.modtime = DirP_curr->d_mtime;
 1202     /* no error code checking on purpose */
 1203     VOID utime (DirP_curr->d_name, &tstamp);
 1204 #else
 1205     tstamp[0] = DirP_curr->d_mtime;
 1206     tstamp[1] = DirP_curr->d_mtime;
 1207     /* no error code checking on purpose */
 1208     VOID utime (DirP_curr->d_name, tstamp);
 1209 #endif
 1210     /* We don't call free because we are about to exit anyway.
 1211        Not calling free should make things a bit more robust if the
 1212        memory pool is corrupted due to a bug */
 1213     /* free(DirP_curr->d_name); */
 1214     DirP_forw=DirP_curr->d_forw;
 1215     /* free(DirP_curr); */
 1216     DirP_curr=DirP_forw;
 1217   }
 1218 }
 1219 
 1220 
 1221 /*
 1222  * in()
 1223  *
 1224  * Read an archive.
 1225  */
 1226 STATIC VOIDFN
 1227 in (av)
 1228      reg char **av;
 1229 {
 1230   auto Stat sb;
 1231   auto char name[PATHSIZE];
 1232   int sel,sel2,res;
 1233 
 1234   if (*av)
 1235     fatal (*av, "Extraneous argument");
 1236   name[0] = '\0';
 1237   while (inhead (name, &sb) == 0)
 1238     {
 1239       sel = (namecmp (name,&sb));
 1240       if (sel)
 1241     {
 1242       if (inskip (sb.sb_size) < 0)
 1243         VOID warn (name, "Skipped file data is corrupt");
 1244     }
 1245       else
 1246     {
 1247       if((sel2 = inentry (name, &sb)) != 0)
 1248         VOID warn (name, "unpacking error");
 1249       else
 1250         if (vflag)
 1251           {
 1252           /* we cast to double and print as floating point because
 1253              %Lu printing is buggy above 4G (at least with my C library). */
 1254           if(printbytepos) fprintf(stderr,"%.0f ",(double)bytepos);
 1255 
 1256           if (*uncompto)
 1257             res = fprintf (stderr, "%s -- uncompressed\n", uncompto);
 1258           else
 1259             res = fprintf (stderr, "%s -- okay\n", name);
 1260 
 1261           /* check for broken pipe on stderr */
 1262           if(res<0) {
 1263             if(errno == EPIPE)
 1264               fatal("<stderr>", syserr());
 1265           }
 1266           }
 1267     }
 1268     }
 1269   restoredirstamps();
 1270 }
 1271 
 1272 
 1273 /*
 1274  * readcheck()
 1275  *
 1276  * Read an archive and check contents against existing files
 1277  */
 1278 
 1279 Stat atime_sb;       /* set in openincheck */
 1280 int atime_sb_valid;  /* set in openincheck */
 1281 
 1282 STATIC VOIDFN
 1283 readcheck (av)
 1284      reg char **av;
 1285 {
 1286   auto Stat sb;
 1287   auto char name[PATHSIZE];
 1288   auto char local[PATHSIZE];
 1289   int sel, res;
 1290 #ifdef linux_tstamp
 1291   auto struct utimbuf tstamp;
 1292 #else
 1293   auto time_t tstamp[2];
 1294 #endif
 1295 
 1296   if (*av)
 1297     fatal (*av, "Extraneous argument");
 1298   name[0] = '\0';
 1299   while (inhead (name, &sb) == 0)
 1300     {
 1301       if ((sel = namecmp (name,&sb)) < 0) {
 1302     if (inskip (sb.sb_size) < 0)
 1303       VOID warn (name, "Skipped file data is corrupt");
 1304     continue;
 1305       }
 1306       if (vflag) {
 1307     strcpy(local, name);
 1308     tocentry (local, &sb);
 1309       }
 1310 
 1311       atime_sb_valid=0;
 1312       if ((res = incheckentry(name, &sb)) < 0)
 1313     inskip (sb.sb_size);
 1314 
 1315       if(aflag && atime_sb_valid && ((sb.sb_mode & S_IFMT)==S_IFREG))
 1316       {
 1317       /* reset access time, this distroys the ctime btw. */
 1318 #ifdef linux_tstamp
 1319       tstamp.actime = atime_sb.sb_atime;
 1320       tstamp.modtime = atime_sb.sb_mtime;
 1321       VOID utime (name, &tstamp);
 1322 #else
 1323       tstamp[0] = atime_sb.sb_atime;
 1324       tstamp[1] = atime_sb.sb_mtime;
 1325       VOID utime (name, tstamp);
 1326 #endif
 1327     }
 1328 
 1329 
 1330     }
 1331 }
 1332 
 1333 /*
 1334  * inalloc()
 1335  *
 1336  * Allocate input buffer space (which was previously indexed
 1337  * by inavail()).
 1338  */
 1339 STATIC void
 1340 inalloc (uint len)
 1341 {
 1342   bufidx += len;
 1343   total += len;
 1344 }
 1345 
 1346 /*
 1347  * inascii()
 1348  *
 1349  * Read an ASCII header. Returns zero if successful;
 1350  * -1 otherwise. Assumes that the entire magic number
 1351  * has been read.
 1352  */
 1353 
 1354 STATIC int
 1355 inascii (magic, name, asb)
 1356      reg char *magic;
 1357      reg char *name;
 1358      reg Stat *asb;
 1359 {
 1360   auto uint namelen;
 1361   auto char header[H_STRLEN + 1];
 1362   PStat pasb;
 1363 
 1364   if (strncmp (magic, M_ASCII, M_STRLEN) != 0)
 1365     return (-1);
 1366 
 1367   if (inread (header, H_STRLEN) < 0)
 1368     return (warnarch ("Corrupt ASCII header", (off_t) H_STRLEN));
 1369   header[H_STRLEN] = '\0';
 1370 
 1371   if (sscanf (header, PH_SCAN, &pasb.PSt_dev,
 1372              &pasb.PSt_ino, &pasb.PSt_mode, &pasb.PSt_uid,
 1373              &pasb.PSt_gid, &pasb.PSt_nlink, &pasb.PSt_rdev,
 1374              &pasb.PSt_mtime, &namelen, &pasb.PSt_size) != H_COUNT)
 1375     return (warnarch ("Bad ASCII header", (off_t) H_STRLEN));
 1376   /* now, we let the compiler cast the info to the right types (field sizes) */
 1377   asb->sb_dev = pasb.PSt_dev;
 1378   asb->sb_ino = pasb.PSt_ino;
 1379   asb->sb_mode = pasb.PSt_mode;
 1380   asb->sb_uid = pasb.PSt_uid;
 1381   asb->sb_gid = pasb.PSt_gid;
 1382   asb->sb_nlink = pasb.PSt_nlink;
 1383   asb->sb_rdev = pasb.PSt_rdev;
 1384   asb->sb_mtime = pasb.PSt_mtime;
 1385   asb->sb_size = pasb.PSt_size;
 1386   if (namelen == 0 || namelen >= PATHSIZE)
 1387     return (warnarch ("Bad ASCII pathname length", (off_t) H_STRLEN));
 1388   if (inread (name, namelen) < 0)
 1389     return (warnarch ("Corrupt ASCII pathname", (off_t) namelen));
 1390   if (name[namelen - 1] != '\0')
 1391     return (warnarch ("Bad ASCII pathname", (off_t) namelen));
 1392   return (0);
 1393 }
 1394 
 1395 
 1396 
 1397 /*
 1398  * inascii2()
 1399  *
 1400  * Read an ASCII header (new format). Returns zero if successful;
 1401  * -1 otherwise. Assumes that the entire magic number
 1402  * has been read.
 1403  */
 1404 
 1405 STATIC int
 1406 inascii2 (char *magic, char *name, Stat *asb)
 1407 {
 1408   auto uint namelen;
 1409   auto char header[H_STRLEN2 + 1];
 1410   PStat pasb;
 1411 
 1412   if (strncmp (magic, M_ASCII2, M_STRLEN) != 0)
 1413     return (-1);
 1414   if (inread (header, H_STRLEN2) < 0)
 1415     return (warnarch ("Corrupt extended ASCII header", (off_t) H_STRLEN2));
 1416   header[H_STRLEN2] = '\0';
 1417   if (sscanf (header, PH_SCAN2, &pasb.PSt_dev,
 1418              &pasb.PSt_ino, &pasb.PSt_mode, &pasb.PSt_uid,
 1419              &pasb.PSt_gid, &pasb.PSt_nlink, &pasb.PSt_rdev,
 1420              &pasb.PSt_mtime, &namelen, &pasb.PSt_size) != H_COUNT)
 1421     return (warnarch ("Bad extended ASCII header", (off_t) H_STRLEN));
 1422   /* now, we let the compiler cast the info to the right types (field sizes) */
 1423   asb->sb_dev = pasb.PSt_dev;
 1424   asb->sb_ino = pasb.PSt_ino;
 1425   asb->sb_mode = pasb.PSt_mode;
 1426   asb->sb_uid = pasb.PSt_uid;
 1427   asb->sb_gid = pasb.PSt_gid;
 1428   asb->sb_nlink = pasb.PSt_nlink;
 1429   asb->sb_rdev = pasb.PSt_rdev;
 1430   asb->sb_mtime = pasb.PSt_mtime;
 1431   asb->sb_size = pasb.PSt_size;
 1432 
 1433   if (namelen == 0 || namelen >= PATHSIZE)
 1434     return (warnarch ("Bad ASCII pathname length", (off_t) H_STRLEN));
 1435   if (inread (name, namelen) < 0)
 1436     return (warnarch ("Corrupt ASCII pathname", (off_t) namelen));
 1437   if (name[namelen - 1] != '\0')
 1438     return (warnarch ("Bad ASCII pathname", (off_t) namelen));
 1439   return (0);
 1440 }
 1441 
 1442 
 1443 /*
 1444  * inascii3()
 1445  *
 1446  * Read an ASCII header (large format). Returns zero if successful;
 1447  * -1 otherwise. Assumes that the entire magic number
 1448  * has been read.
 1449  */
 1450 
 1451 STATIC int
 1452 inascii3 (magic, name, asb)
 1453      reg char *magic;
 1454      reg char *name;
 1455      reg Stat *asb;
 1456 {
 1457   auto uint namelen;
 1458   auto char header[H_STRLEN3 + 1];
 1459   PHStat pasb;
 1460   uint specialflags;
 1461   uint extraheaderlen;
 1462 
 1463   if (strncmp (magic, M_ASCII3, M_STRLEN) != 0)
 1464     return (-1);
 1465   if (inread (header, H_STRLEN3) < 0)
 1466     return (warnarch ("Corrupt extended ASCII3 header", (off_t) H_STRLEN3));
 1467   header[H_STRLEN3] = '\0';
 1468   if (sscanf (header, PH_SCAN3, &pasb.PSt_dev,
 1469              &pasb.PSt_ino, &pasb.PSt_mode, &pasb.PSt_uid,
 1470              &pasb.PSt_gid, &pasb.PSt_nlink, &pasb.PSt_rdev,
 1471              &pasb.PSt_mtime, &namelen, &specialflags, &extraheaderlen, &pasb.PSt_size) != H_COUNT3)
 1472     return (warnarch ("Bad extended ASCII3 header", (off_t) H_STRLEN));
 1473   /* now, we let the compiler cast the info to the right types (field sizes) */
 1474   asb->sb_dev = pasb.PSt_dev;
 1475   asb->sb_ino = pasb.PSt_ino;
 1476   asb->sb_mode = pasb.PSt_mode;
 1477   asb->sb_uid = pasb.PSt_uid;
 1478   asb->sb_gid = pasb.PSt_gid;
 1479   asb->sb_nlink = pasb.PSt_nlink;
 1480   asb->sb_rdev = pasb.PSt_rdev;
 1481   asb->sb_mtime = pasb.PSt_mtime;
 1482   asb->sb_size = pasb.PSt_size;
 1483 
 1484   if (namelen == 0 || namelen >= PATHSIZE)
 1485     return (warnarch ("Bad ASCII pathname length", (off_t) H_STRLEN));
 1486   if (inread (name, namelen) < 0)
 1487     return (warnarch ("Corrupt ASCII pathname", (off_t) namelen));
 1488   if (name[namelen - 1] != '\0')
 1489     return (warnarch ("Bad ASCII pathname", (off_t) namelen));
 1490   if (inskip ((off_t)extraheaderlen) < 0)
 1491     return (warnarch ("Corrupt header", (off_t) 0));
 1492   return (0);
 1493 }
 1494 
 1495 
 1496 /*
 1497  * inavail()
 1498  *
 1499  * Index availible input data within the buffer. Stores a pointer
 1500  * to the data and its length in given locations. Returns zero with
 1501  * valid data, -1 if unreadable portions were replaced with nulls.
 1502  */
 1503 STATIC int
 1504 inavail (bufp, lenp)
 1505      reg char **bufp;
 1506      uint *lenp;
 1507 {
 1508   reg uint have;
 1509   reg int corrupt = 0;
 1510 
 1511   while ((have = bufend - bufidx) == 0)
 1512     corrupt |= infill ();
 1513   *bufp = bufidx;
 1514   *lenp = have;
 1515   return (corrupt);
 1516 }
 1517 
 1518 /*
 1519  * inbinary()
 1520  *
 1521  * Read a binary header. Returns the number of trailing alignment
 1522  * bytes to skip; -1 if unsuccessful.
 1523  */
 1524 STATIC int
 1525 inbinary (magic, name, asb)
 1526      reg char *magic;
 1527      reg char *name;
 1528      reg Stat *asb;
 1529 {
 1530   reg uint namefull;
 1531   auto Binary binary;
 1532 
 1533   if ((int) *((ushort *) magic) != M_BINARY)
 1534     return (-1);
 1535   memcpy ((char *) &binary,
 1536       magic + sizeof (ushort),
 1537       M_STRLEN - sizeof (ushort));
 1538   if (inread ((char *) &binary + M_STRLEN - sizeof (ushort),
 1539           sizeof (binary) - (M_STRLEN - sizeof (ushort))) < 0)
 1540     return (warnarch ("Corrupt binary header",
 1541            (off_t) sizeof (binary) - (M_STRLEN - sizeof (ushort))));
 1542   asb->sb_dev = binary.b_dev;
 1543   asb->sb_ino = binary.b_ino;
 1544   asb->sb_mode = binary.b_mode;
 1545   asb->sb_uid = binary.b_uid;
 1546   asb->sb_gid = binary.b_gid;
 1547   asb->sb_nlink = binary.b_nlink;
 1548   asb->sb_rdev = binary.b_rdev;
 1549   asb->sb_mtime = binary.b_mtime[0] << 16 | binary.b_mtime[1];
 1550   asb->sb_size = binary.b_size[0] << 16 | binary.b_size[1];
 1551   if (binary.b_name == 0 || binary.b_name >= PATHSIZE)
 1552     return (warnarch ("Bad binary pathname length",
 1553            (off_t) sizeof (binary) - (M_STRLEN - sizeof (ushort))));
 1554   if (inread (name, namefull = binary.b_name + binary.b_name % 2) < 0)
 1555     return (warnarch ("Corrupt binary pathname", (off_t) namefull));
 1556   if (name[binary.b_name - 1] != '\0')
 1557     return (warnarch ("Bad binary pathname", (off_t) namefull));
 1558   return (asb->sb_size % 2);
 1559 }
 1560 
 1561 /*
 1562  * indata()
 1563  *
 1564  * Install data from an archive. Returns given file descriptor.
 1565  */
 1566 STATIC int
 1567 indata (fd, size, name)
 1568      int fd;
 1569      reg off_t size;
 1570      char *name;
 1571 {
 1572   reg size_t chunk;
 1573   reg char *oops;
 1574   reg ssize_t sparse;
 1575   reg int corrupt;
 1576   auto char *buf;
 1577   auto uint avail;
 1578 
 1579   corrupt = sparse = 0;
 1580   oops = NULL;
 1581   while (size)
 1582     {
 1583       corrupt |= inavail (&buf, &avail);
 1584       size -= (chunk = size < (off_t)avail ? (uint) size : avail);
 1585       if (oops == NULL && (sparse = fswrite (fd, buf, chunk)) < 0)
 1586     oops = syserr ();
 1587       inalloc (chunk);
 1588     }
 1589   if (corrupt)
 1590     VOID warn (name, "Corrupt archive data");
 1591   if (oops)
 1592     VOID warn (name, oops);
 1593   else if (sparse > 0
 1594        && (lseek (fd, (off_t) - 1, 1) < 0
 1595            || write (fd, "", 1) != 1))
 1596     VOID warn (name, syserr ());
 1597   return (fd);
 1598 }
 1599 
 1600 /*
 1601  * incheckdata()
 1602  *
 1603  * Check data from an archive. Returns given file descriptor.
 1604  */
 1605 STATIC int
 1606 incheckdata (int fd, off_t size, char *name, Stat *asb, int comp)
 1607 {
 1608   reg uint chunk;
 1609   reg char *oops;
 1610   reg int corrupt, warned = 0;
 1611   auto char *buf;
 1612   auto uint avail;
 1613   auto int pfd[2], pfdc[2];
 1614   auto int pid, comppid;
 1615 
 1616   corrupt = 0;
 1617   oops = NULL;
 1618   if (comp) {
 1619       /* if compressed, we process data with the following setup:
 1620          - child 1 is the comparator
 1621          - child 2 is the gunzip (gzip -c -d)
 1622          - the main process reads data from the archive and writes it
 1623            to child 2 to be uncompressed
 1624          - child 2 writes the uncompressed data to child 1
 1625          - child 1 reads from the file in the filesystem and from child 2,
 1626            compares, and exits nonzero if is a discrepancy.
 1627       */
 1628 
 1629     if (pipe(pfd) < 0) {
 1630       perror("pipe"); exit(1);
 1631     }
 1632     switch ((pid = xfork("incheckdata, decompressing", NODIE))) {
 1633     case -1:
 1634       perror("fork");
 1635       exit(1);
 1636     /* child 1 start ======================== */
 1637     case 0: /* child */
 1638       VOID close (pfd[1]);
 1639       if (arfd != STDIN && arfd != STDOUT) VOID close (arfd);
 1640       if (pipe(pfdc) < 0) {
 1641     perror("pipe"); exit(1);
 1642       }
 1643       switch ((comppid = xfork ("incheckdata, decomp", NODIE))) {
 1644       case -1:
 1645     perror("fork");
 1646     exit(1);
 1647       /* child 2 start ======================== */
 1648       case 0: /* child */
 1649     VOID close (pfdc[0]);
 1650     VOID close (fileno (stdin));
 1651     VOID dup (pfd[0]);
 1652     VOID close (pfd[0]);
 1653     VOID close (fileno (stdout));
 1654     if (dup (pfdc[1]) < 0)
 1655       exit(1);
 1656     close(pfdc[1]);
 1657     mayberewind();
 1658     if(compressargs)
 1659         execvp (compressprog, compress_arg_list);
 1660     else
 1661         execlp (compressprog, compressprog, "-d", "-c", NULL);
 1662     fprintf (stderr, "Could not uncompress, errno %d\n", errno);
 1663     exit(1);
 1664     break;
 1665       /* child 2 end ======================== */
 1666       /* child 1 continued ======================== */
 1667       default:
 1668     {
 1669       char buff1[40960];
 1670       char buff2[40960];
 1671       size_t n;
 1672       ssize_t n1, n2;
 1673 
 1674       close(pfdc[1]);
 1675       n1 = n2 = 1;
 1676       while ((n1 > 0) && (n2 > 0)) {
 1677         n = sizeof(buff1);
 1678         n1 = readall(fd, buff1, n);
 1679         n2 = readall(pfdc[0], buff2, n);
 1680         size -= n1;
 1681         if (n1 < 0 || n2 < 0 || n1 != n2) {
 1682           VOID warn_nocount (name, "File in archive has different length than file on filesystem");
 1683           corrupt = 1;
 1684           break;
 1685         }
 1686         else {
 1687           if (memcmp(buff1, buff2, (size_t)n1) != 0) {
 1688         if (!warned++)
 1689           VOID warn_nocount (name, "File in archive has different data than file on filesystem");
 1690         corrupt = 1;
 1691           }
 1692         }
 1693       }
 1694       if (corrupt)
 1695         kill(comppid, SIGTERM);
 1696       close(pfdc[0]);
 1697       close(fd);
 1698       if (xwait (comppid, "incheckentry xwait() gunzip", FALSE) != 0) {
 1699         warn(name, "uncompressing failure");
 1700         corrupt = 1;
 1701       }
 1702       exit(corrupt ? 2 : 0);
 1703        }
 1704       }
 1705     /* child 2 end ======================== */
 1706     default:
 1707     /* main process continue ======================== */
 1708       close(pfd[0]);
 1709       uncompressrun = pid;
 1710       while (asb->sb_size) {
 1711     corrupt |= inavail (&buf, &avail);
 1712     if (corrupt) {
 1713       break;
 1714     }
 1715     asb->sb_size -= (chunk = asb->sb_size < (off_t)avail ? (uint) asb->sb_size : avail);
 1716     if (writeall (pfd[1], buf, chunk) < 0)
 1717       oops = syserr();
 1718     inalloc(chunk);
 1719       }
 1720       close(pfd[1]);
 1721       corrupt |= (xwait (pid, "incheckentry xwait()", FALSE) != 0);
 1722       break;
 1723     }
 1724   }
 1725   else { /* not compressed */
 1726     char buff1[40960];
 1727     ssize_t n1, n2;
 1728     ssize_t n;
 1729     while (asb->sb_size && !corrupt) {
 1730       if (!(corrupt |= inavail (&buf, &avail))) {
 1731     /* cast of asb->sb_size (which can be 8 byte) only happens when
 1732        the value fits in size_t (which is usually 4 byte) */
 1733     n2 = asb->sb_size < (off_t)avail ? (size_t) asb->sb_size : avail;
 1734     n = (n2 < (ssize_t)sizeof(buff1)) ? n2 : (ssize_t)sizeof(buff1);
 1735     n1 = readall(fd, buff1, n);
 1736     asb->sb_size -= n;
 1737     if (n1 < 0 || n2 < 0 || n1 != n)
 1738       {
 1739         if(n1!=n)
 1740           VOID warn_nocount (name, "File in archive has different length than file on filesystem");
 1741         corrupt = 1;
 1742       }
 1743     else
 1744       {
 1745         if( memcmp(buff1, buf, n) != 0 )
 1746           {
 1747         VOID warn_nocount (name, "File in archive has different data than file on filesystem");
 1748         corrupt = 1;
 1749           }
 1750       }
 1751     inalloc((uint)n);
 1752       }
 1753     }
 1754     /* See if the file is _longer_ then our backup. */
 1755     if (read(fd, buff1, 1) > 0)
 1756       {
 1757     VOID warn_nocount (name, "File in archive is shorter than file on filesystem");
 1758     corrupt = 1;
 1759       }
 1760   }
 1761   close(fd);
 1762   if (oops)
 1763     VOID warn (name, oops);
 1764   if (corrupt) {
 1765     /*
 1766         file    : Stat atime_sb
 1767         archive : Stat *asb
 1768     */
 1769     if ( (atime_sb.sb_mtime==asb->sb_mtime) &&
 1770      (atime_sb.sb_size==asb->sb_size))
 1771     {
 1772       /* file has same mod time and length --> should have verified OK,
 1773      so this is very probably a real error in the backup medium.
 1774       */
 1775       VOID warn (name, "File data in archive is corrupt");
 1776       anycorrupt=1;
 1777     }
 1778     else
 1779       {
 1780     VOID warn (name, "Archive headers indicate that file on filesystem was modified during or after archive was made");
 1781 
 1782     if(index(ignorewarnings,(int)'r'))
 1783       {
 1784         warn_nocount(name, "Not counting this as a verification error");
 1785         warnings--;
 1786       }
 1787     else
 1788       anycorrupt=1;
 1789 
 1790       }
 1791 
 1792     return -1;
 1793   }
 1794   return 0;
 1795 }
 1796 
 1797 /*
 1798  * inentry()
 1799  *
 1800  * Install a single archive entry. Returns zero if successful, -1 otherwise.
 1801  */
 1802 STATIC int
 1803 inentry (name, asb)
 1804      char *name;
 1805      reg Stat *asb;
 1806 {
 1807   reg Link *linkp;
 1808   reg int ifd;
 1809   reg int ofd;
 1810 #ifdef linux_tstamp
 1811   auto struct utimbuf tstamp;
 1812 #else
 1813   auto time_t tstamp[2];
 1814 #endif
 1815   int result;
 1816   result=0;
 1817 
 1818   if ((ofd = openotty (name, asb, linkp = linkfrom (asb,1), 0, Zflag)) > 0)
 1819     {
 1820       if (asb->sb_size || linkp == NULL || linkp->l_size == 0)
 1821     VOID close (indata (ofd, asb->sb_size, name));
 1822       else if ((ifd = open (linkp->l_path->p_name, O_RDONLY)) < 0)
 1823     VOID warn (linkp->l_path->p_name, syserr ());
 1824       else
 1825     {
 1826       passdata (linkp->l_path->p_name, ifd, name, ofd);
 1827       VOID close (ifd);
 1828       VOID close (ofd);
 1829     }
 1830       /* safety */
 1831       if (uncompressrun)
 1832     {
 1833       result = xwait (uncompressrun, "inentry xwait()", TRUE);
 1834       uncompressrun = 0;
 1835           if(result!=0) result=-1;
 1836     }
 1837     }
 1838   else if (ofd < 0)
 1839     return (-1);
 1840   else if (inskip (asb->sb_size) < 0)
 1841     VOID warn (name, "Redundant file data is corrupt");
 1842 
 1843   /* Cannot set utime on symlink (at least not under Linux) */
 1844   if((asb->sb_mode & S_IFMT) != S_IFLNK)
 1845   {
 1846 #ifdef linux_tstamp
 1847       tstamp.actime = tstamp.modtime = mflag ? timenow : asb->sb_mtime;
 1848       VOID utime (name, &tstamp);
 1849 #else
 1850       tstamp[0] = tstamp[1] = mflag ? timenow : asb->sb_mtime;
 1851       VOID utime (name, tstamp);
 1852 #endif
 1853   }
 1854 
 1855   return (result);
 1856 }
 1857 
 1858 /*
 1859  * incheckentry()
 1860  *
 1861  * Check a single archive entry. Returns zero if successful, -1 otherwise.
 1862  */
 1863 STATIC int
 1864 incheckentry (name, asb)
 1865      char *name;
 1866      reg Stat *asb;
 1867 {
 1868   reg int ifd;
 1869   auto int compression;
 1870 
 1871   if (ISCONTROL(asb))
 1872   {
 1873       /* process control file */
 1874       if(inentry (name, asb) < 0)
 1875       if (inskip (asb->sb_size) < 0)
 1876           VOID warn (name, "Skipped file data is corrupt");
 1877 
 1878       /* do not verify the control file, return success */
 1879       return(0);
 1880   }
 1881 
 1882   uncompressrun = 0;
 1883 
 1884   /* The exact logic below here, and inside openincheck and
 1885      incheckdata, is questionable -- it will not catch all faulty
 1886      situations as being a definate error.  It will work in 99.9% of
 1887      the error cases though, so I am not touching it...  -- KH */
 1888 
 1889   if ((ifd = openincheck (name, asb, &compression, Zflag)) > 0)
 1890     {
 1891       if (asb->sb_size)
 1892     return incheckdata(ifd, asb->sb_size, name, asb, compression);
 1893     }
 1894   else if (ifd < 0) /* some strangeness occured in in archive file */
 1895     {
 1896       anycorrupt = -1;
 1897       return (-1);
 1898     }
 1899   else if (inskip (asb->sb_size) < 0)
 1900     VOID warn (name, "Redundant file data is corrupt");
 1901   if (ifd > 0)
 1902     close(ifd);
 1903   return (0);
 1904 }
 1905 
 1906 /*
 1907  * infill()
 1908  *
 1909  * Fill the archive buffer. Remembers mid-buffer read failures and
 1910  * reports them the next time through. Replaces unreadable data with
 1911  * null characters. Returns zero with valid data, -1 otherwise.
 1912  */
 1913 STATIC int
 1914 infill ()
 1915 {
 1916   reg int got;
 1917   static int failed;
 1918   ulonglong ullreadsize;
 1919   size_t readsize;
 1920 
 1921   bufend = bufidx = buffer;
 1922   if (!failed)
 1923     {
 1924       if (areof)
 1925     {
 1926       if (total == 0)
 1927         {
 1928           fatal (arspec, "No input");
 1929         }
 1930       else
 1931         {
 1932           if((aruntil!=0) || askfornext)
 1933         {
 1934           next (O_RDONLY, "Input EOF");
 1935         }
 1936           else
 1937         {
 1938           fatal (arspec, "Premature input EOF");
 1939         }
 1940         }
 1941     }
 1942 #if 0
 1943     fprintf(stderr,"aruntil=%lld arleft=%lld arbsize=%d\n",aruntil,arleft,arbsize);
 1944 #endif
 1945       if (aruntil && (arleft == 0))
 1946     next (O_RDONLY, "Input limit reached");
 1947 
 1948       if(aruntil) ullreadsize=arleft; else ullreadsize=buffer + buflen - bufend;
 1949       if(ullreadsize>arbsize) ullreadsize=arbsize;
 1950 
 1951       readsize=(size_t)ullreadsize;
 1952 
 1953 
 1954       while (!failed
 1955          && !areof
 1956              && (aruntil == 0 || arleft >= (ulonglong)readsize)
 1957          && (off_t)(buffer - bufend) + buflen >= (off_t)readsize)
 1958     {
 1959       if ((got = read (arfd, bufend, readsize)) > 0)
 1960         {
 1961           bufend += got;
 1962           arleft -= got;
 1963         }
 1964       else if (got < 0)
 1965         failed = warnarch (syserr (),
 1966                    (off_t) 0 - (bufend - bufidx));
 1967       else
 1968         ++areof;
 1969     }
 1970     }
 1971   if (failed && bufend == buffer)
 1972     {
 1973       failed = 0;
 1974       for (got = 0; (uint)got < arbsize; ++got)
 1975     *bufend++ = '\0';
 1976       return (-1);
 1977     }
 1978   return (0);
 1979 }
 1980 
 1981 
 1982 /*
 1983  * fixinsecure()
 1984  *
 1985  * Rewrite .. subpath components in path names into XX,
 1986  * making them more secure for restoring.   For more info see the -8 option
 1987  * in the manpage.
 1988  */
 1989 STATIC int
 1990 fixinsecure (name)
 1991      char *name;
 1992 {
 1993   int changed=0;
 1994   int l=strlen(name);
 1995   int i;
 1996   if(strcmp("..",name)==0)
 1997     {
 1998       changed=1;
 1999       name[0]=name[1]='X';
 2000     }
 2001   if(strncmp("../",name,3)==0)
 2002     {
 2003       changed=1;
 2004       name[0]=name[1]='X';
 2005     }
 2006 
 2007   for(i=0; i<l-3; i++)
 2008     {
 2009       if(name[i]=='/')
 2010     {
 2011       if(strncmp("/../",name+i,4)==0)
 2012         {
 2013           changed=1;
 2014           name[i+1]=name[i+2]='X';
 2015         }
 2016     }
 2017     }
 2018 
 2019 
 2020   if(l>=3) if(strncmp("/..",name+l-3,3)==0)
 2021     {
 2022       changed=1;
 2023       name[l-2]=name[l-1]='X';
 2024     }
 2025 
 2026   return changed;
 2027 }
 2028 
 2029 /*
 2030  * inhead()
 2031  *
 2032  * Read a header. Quietly translates old-fashioned binary cpio headers
 2033  * (and arranges to skip the possible alignment byte). Returns zero if
 2034  * successful, -1 upon archive trailer.
 2035  */
 2036 STATIC int
 2037 inhead (name, asb)
 2038      reg char *name;
 2039      reg Stat *asb;
 2040 {
 2041   reg off_t skipped;
 2042   auto char magic[M_STRLEN];
 2043   static int align;
 2044   char *name2;
 2045   int rewritten;
 2046 
 2047 #if FDDEBUG
 2048 /* debug code added by KH.  Are we leaking file descriptors? */
 2049       { int i; i=dup(0); close(i); fprintf(stderr,"%d",i); }
 2050 #endif
 2051 
 2052   if (align > 0)
 2053     VOID inskip ((off_t) align);
 2054   align = 0;
 2055 
 2056   bytepos=total; /* position of current file */
 2057 
 2058   for (;;)
 2059     {
 2060       VOID inread (magic, M_STRLEN);
 2061       skipped = 0;
 2062 
 2063       while (   ((align = inascii (magic, name, asb)) < 0)
 2064          && ((align = inascii2 (magic, name, asb)) < 0)
 2065          && ((align = inascii3 (magic, name, asb)) < 0)
 2066          && ((align = inbinary (magic, name, asb)) < 0)
 2067          && ((align = inswab (magic, name, asb)) < 0))
 2068     {
 2069       if (++skipped == 1)
 2070         {
 2071           if (!kflag && total - sizeof (magic) == 0)
 2072         {
 2073           warn(arspec,"Input does not start with valid archive header.");
 2074           warn(arspec,"Use the -k option to start reading in the middle of an archive.");
 2075           fatal (arspec, "Unrecognizable archive");
 2076 
 2077         }
 2078           VOID warnarch ("Bad magic number",
 2079                    (off_t) sizeof (magic));
 2080           if (name[0])
 2081         VOID warn (name, "May be corrupt");
 2082         }
 2083       memcpy (magic, magic + 1, sizeof (magic) - 1);
 2084       VOID inread (magic + sizeof (magic) - 1, 1);
 2085     }
 2086       if (skipped)
 2087     {
 2088       VOID warnarch ("Apparently resynchronized",
 2089                (off_t) sizeof (magic));
 2090       VOID warn (name, "Continuing");
 2091     }
 2092       if (strcmp (name, TRAILER) == 0)
 2093     return (-1);
 2094       if (nameopt (name) >= 0)
 2095     break;
 2096       VOID inskip (asb->sb_size + align);
 2097     }
 2098 #ifdef  S_IFLNK
 2099   if ((asb->sb_mode & S_IFMT) == S_IFLNK)
 2100     {
 2101       /* buffer overflow protection */
 2102       if((uint) asb->sb_size > sizeof(asb->sb_link)-1)
 2103     {
 2104       VOID warn (name, "Corrupt symbolic link");
 2105       return (inhead (name, asb));
 2106     }
 2107       if (inread (asb->sb_link, (uint) asb->sb_size) < 0)
 2108     {
 2109       VOID warn (name, "Corrupt symbolic link");
 2110       return (inhead (name, asb));
 2111     }
 2112       asb->sb_link[asb->sb_size] = '\0';
 2113       asb->sb_size = 0;
 2114 
 2115       rewritten=0;
 2116       if(!allowinsecuresymlinks)
 2117     {
 2118       if(asb->sb_link[0]=='/')
 2119         {
 2120           asb->sb_link[0]='X';
 2121           rewritten=1;
 2122         }
 2123       if(fixinsecure (asb->sb_link)) rewritten=1;
 2124       if(rewritten)
 2125         {
 2126           VOID warn_nocount (name,"potentially insecure symlink destination path, rewriting:");;
 2127           VOID warn(asb->sb_link,"is the rewritten destination value used");
 2128           if(index(ignorewarnings,(int)'s')) warnings--;
 2129         }
 2130     }
 2131     }
 2132 #endif /* S_IFLNK */
 2133   if ((name[0] == '/') && !abspaths)
 2134     {
 2135       /* if there was more than 1 leading /, nameopt() has already
 2136      removed all leading / but one */
 2137       if (name[1])
 2138     {
 2139       name2=name;
 2140       while ((name2[0] = name2[1])) ++name2;
 2141     }
 2142       else
 2143     {
 2144       name[0] = '.';
 2145     }
 2146     }
 2147   if(!allowinsecurepaths)
 2148     {
 2149       if(fixinsecure(name))
 2150     {
 2151       VOID warn (name,"potentially insecure destination path rewritten");
 2152       if(index(ignorewarnings,(int)'s')) warnings--;
 2153     }
 2154     }
 2155 
 2156   asb->sb_atime = asb->sb_ctime = asb->sb_mtime;
 2157   return (0);
 2158 }
 2159 
 2160 /*
 2161  * inread()
 2162  *
 2163  * Read a given number of characters from the input archive. Returns
 2164  * zero with valid data, -1 if unreadable portions were replaced by
 2165  * null characters.
 2166  */
 2167 STATIC int
 2168 inread (dst, len)
 2169      reg char *dst;
 2170      uint len;
 2171 {
 2172   reg uint have;
 2173   reg uint want;
 2174   reg int corrupt = 0;
 2175   char *endx = dst + len;
 2176 
 2177   while ((want = endx - dst))
 2178     {
 2179       while ((have = bufend - bufidx) == 0)
 2180     corrupt |= infill ();
 2181       if (have > want)
 2182     have = want;
 2183       memcpy (dst, bufidx, have);
 2184       bufidx += have;
 2185       dst += have;
 2186       total += have;
 2187     }
 2188   return (corrupt);
 2189 }
 2190 
 2191 /*
 2192  * inskip()
 2193  *
 2194  * Skip input archive data. Returns zero under normal circumstances,
 2195  * -1 if unreadable data is encountered.
 2196  */
 2197 STATIC int
 2198 inskip (len)
 2199      reg off_t len;
 2200 {
 2201   reg uint chunk;
 2202   reg int corrupt = 0;
 2203 
 2204   while (len)
 2205     {
 2206       while ((chunk = bufend - bufidx) == 0)
 2207     corrupt |= infill ();
 2208       if ((off_t)chunk > len)
 2209     chunk = len;
 2210       bufidx += chunk;
 2211       len -= chunk;
 2212       total += chunk;
 2213     }
 2214   return (corrupt);
 2215 }
 2216 
 2217 /*
 2218  * inswab()
 2219  *
 2220  * Read a reversed byte order binary header. Returns the number
 2221  * of trailing alignment bytes to skip; -1 if unsuccessful.
 2222  */
 2223 STATIC int
 2224 inswab (magic, name, asb)
 2225      reg char *magic;
 2226      reg char *name;
 2227      reg Stat *asb;
 2228 {
 2229   reg ushort namesize;
 2230   reg uint namefull;
 2231   auto Binary binary;
 2232 
 2233   if ((int) *((ushort *) magic) != swab (M_BINARY))
 2234     return (-1);
 2235   memcpy ((char *) &binary,
 2236       magic + sizeof (ushort),
 2237       M_STRLEN - sizeof (ushort));
 2238   if (inread ((char *) &binary + M_STRLEN - sizeof (ushort),
 2239           sizeof (binary) - (M_STRLEN - sizeof (ushort))) < 0)
 2240     return (warnarch ("Corrupt swapped header",
 2241            (off_t) sizeof (binary) - (M_STRLEN - sizeof (ushort))));
 2242   asb->sb_dev = (dev_t) swab (binary.b_dev);
 2243   asb->sb_ino = (ino_t) swab (binary.b_ino);
 2244   asb->sb_mode = swab (binary.b_mode);
 2245   asb->sb_uid = swab (binary.b_uid);
 2246   asb->sb_gid = swab (binary.b_gid);
 2247   asb->sb_nlink = swab (binary.b_nlink);
 2248   asb->sb_rdev = (dev_t) swab (binary.b_rdev);
 2249   asb->sb_mtime = swab (binary.b_mtime[0]) << 16 | swab (binary.b_mtime[1]);
 2250   asb->sb_size = swab (binary.b_size[0]) << 16 | swab (binary.b_size[1]);
 2251   if ((namesize = swab (binary.b_name)) == 0 || namesize >= PATHSIZE)
 2252     return (warnarch ("Bad swapped pathname length",
 2253            (off_t) sizeof (binary) - (M_STRLEN - sizeof (ushort))));
 2254   if (inread (name, namefull = namesize + namesize % 2) < 0)
 2255     return (warnarch ("Corrupt swapped pathname", (off_t) namefull));
 2256   if (name[namesize - 1] != '\0')
 2257     return (warnarch ("Bad swapped pathname", (off_t) namefull));
 2258   return (asb->sb_size % 2);
 2259 }
 2260 
 2261 /*
 2262  * lineget()
 2263  *
 2264  * Get a line from a given stream. Returns 0 if successful, -1 at EOF.
 2265  */
 2266 STATIC int
 2267 lineget (stream, buf, bufsize)
 2268      reg FILE *stream;
 2269      reg char *buf;
 2270      int bufsize;
 2271 {
 2272   reg int c;
 2273   int size;
 2274   char *bufstart;
 2275 
 2276   size=0;
 2277   bufstart=buf;
 2278 
 2279   for (;;)
 2280     {
 2281       if ((c = getc (stream)) == EOF)
 2282     return (-1);
 2283       if ((!flag0 && c == '\n') || (flag0 && c == '\0'))
 2284     break;
 2285       if(size<bufsize-1)
 2286     *buf++ = c;
 2287       size++;
 2288 
 2289     }
 2290   *buf = '\0';
 2291 
 2292   if(size>bufsize-1)
 2293     warn(bufstart,"Path name too long, truncated");
 2294 
 2295   return (0);
 2296 }
 2297 
 2298 /*
 2299  * linkalso()
 2300  *
 2301  * Add a destination pathname to an existing chain. Assumes that
 2302  * at least one element is present.
 2303  */
 2304 STATIC void
 2305 linkalso (linkp, name)
 2306      reg Link *linkp;
 2307      char *name;
 2308 {
 2309   reg Path *path;
 2310 
 2311   if (((path = (Path *) memget (sizeof (Path))) == NULL)
 2312       || ((path->p_name = memstr (name)) == NULL))
 2313     return;
 2314   path->p_forw = NULL;
 2315   path->p_back = linkp->l_path->p_back;
 2316   path->p_back->p_forw = path;
 2317   linkp->l_path->p_back = path;
 2318 }
 2319 
 2320 /*
 2321  * linkfrom()
 2322  *
 2323  * Find a file to link from. Returns a pointer to a link
 2324  * structure, or NULL if unsuccessful.
 2325  */
 2326 /* In v2.4.4: added some checks which would be redundant if not
 2327    for the fact that the standard archive format only stores the
 2328    lower 16 bits of the inode number.
 2329    The checks reduce the chance of false matches when, reading archives
 2330    produced by older afio versions and by cpio in the old ascii
 2331    format.
 2332 */
 2333 STATIC Link *
 2334 linkfrom (asb, installing)
 2335      reg Stat *asb;
 2336      int installing;
 2337 {
 2338   reg Link *linkp;
 2339   reg Link *linknext;
 2340   reg Link **abase;
 2341 
 2342   /* check: could file be hard-linked at all? */
 2343   if(asb->sb_nlink<=1) return NULL;
 2344   /* check: if is a directory, then cannot be hard-linked to something */
 2345   if((asb->sb_mode & S_IFMT) == S_IFDIR) return NULL;
 2346   /* check: sb_size==0 for entry in archive which should produce hardlink */
 2347   if(installing && (asb->sb_size!=0)) return NULL;
 2348 
 2349   for (linkp = *(abase = linkhash (asb->sb_ino)); linkp; linkp = linknext)
 2350     {
 2351 
 2352       if (linkp->l_ino == asb->sb_ino
 2353       && linkp->l_dev == asb->sb_dev
 2354       /* check: do mtimes also match? */
 2355       && linkp->l_mtime == asb->sb_mtime
 2356       /* check: do modes also match? */
 2357       && linkp->l_mode == asb->sb_mode
 2358       )
 2359     {
 2360       --linkp->l_nlink; /* reference count for -u option */
 2361 
 2362       /* in older versions of afio, if l_nlink drops to 0, then the
 2363          link entry is removed from the hash table.
 2364              We don't do this anymore because that would break things
 2365          if the same hard linked directory entry was included
 2366          multiple times in the archive.  Also it allows us to call
 2367          linkfrom as often as we want for each file
 2368       */
 2369 
 2370       return (linkp);
 2371     }
 2372 
 2373       linknext = linkp->l_forw;
 2374     }
 2375 
 2376   return (NULL);
 2377 }
 2378 
 2379 
 2380 /*
 2381  * linkleft()
 2382  *
 2383  * Complain about files with unseen links.
 2384  */
 2385 STATIC void
 2386 linkleft ()
 2387 {
 2388   reg Link *lp;
 2389   reg Link **base;
 2390 
 2391   for (base = linkbase; base < linkbase + nel (linkbase); ++base)
 2392     for (lp = *base; lp; lp = lp->l_forw)
 2393       {
 2394     /* printf("%s ino=%ld nl=%d\n",lp->l_path->p_name,(long int)lp->l_ino,(int)lp->l_nlink); */
 2395       if (lp->l_nlink)
 2396     VOID warn (lp->l_path->p_name, "Unseen link(s)");
 2397 
 2398       }
 2399 }
 2400 
 2401 /*
 2402  * linkto()
 2403  *
 2404  * Remember a file with outstanding links. Returns a
 2405  * pointer to the associated link structure, or NULL
 2406  * when linking is not possible.
 2407  *
 2408  * except in extfmt mode,
 2409  * updates asb->sb_ino to create an (inode number,device number) pair that
 2410  * is unique for each set of hard linked files in the archive,
 2411  * while keeping the inode number <16bits as long as possible.
 2412  * before calling linkto, asb->sb_ino should contain the inode number
 2413  * from the filesystem, as obtained with a stat call.
 2414  */
 2415 STATIC Link *
 2416 linkto (name, asb)
 2417      char *name;
 2418      reg Stat *asb;
 2419 {
 2420   reg Link *linkp;
 2421   reg Path *path;
 2422   reg Link **abase;
 2423   ino_t ino;
 2424   int ino16;
 2425 
 2426   if ((asb->sb_mode & S_IFMT) == S_IFDIR)
 2427     return (NULL);
 2428 
 2429   if(!extfmt)
 2430   {
 2431     /* the old ASCII format only stores the least significant 16
 2432        bits of the inode.  We need to avoid duplicate ino numbers
 2433        for different files in the archive or else the restore can
 2434        have all kinds of horrible failure modes */
 2435 
 2436     /* first, try the inode that is the inode from the fs, truncated */
 2437     ino = asb->sb_ino & 0x0ffff;
 2438 
 2439     /* check if that has been used, if so choose other one */
 2440     while(1)
 2441       {
 2442     ino16=ino&0xffff;
 2443 
 2444     /* if the bit for ino16 is 0, then this value has not been used yet
 2445        in the archive, so we can break out of the loop and use it */
 2446     if((ino16bitused[ino16/8]&((unsigned char)(1)<<(ino16&0x7)))==0) break;
 2447 
 2448     /* choose other one */
 2449     ino=freshino++;
 2450 
 2451     if(freshino>0xffff)
 2452       {
 2453         /* break out of loop, no need to check if has been used */
 2454         break;
 2455       }
 2456       }
 2457 
 2458   }
 2459   else
 2460   {
 2461     ino = asb->sb_ino;
 2462   }
 2463 
 2464   /* add this number to the table of used 16-bit inode numbers */
 2465   /* this operation is unneccessary in some cases of the control
 2466      flow of the above if statements, but it is nice to put it here */
 2467   ino16=ino&0xffff;
 2468   ino16bitused[ino16/8]=ino16bitused[ino16/8]|((unsigned char)(1)<<(ino16&0x7));
 2469   /* add this inode to table of hard links (under filesystem inode number) */
 2470 
 2471   if(    ((linkp = (Link *) memget (sizeof (Link))) == NULL)
 2472       || ((path = (Path *) memget (sizeof (Path))) == NULL)
 2473       || ((path->p_name = memstr (name)) == NULL))
 2474     return (NULL);
 2475 
 2476   linkp->l_dev = asb->sb_dev;
 2477   linkp->l_ino = asb->sb_ino; /* original ino from fs */
 2478   linkp->l_nlink = asb->sb_nlink - 1;
 2479   linkp->l_size = asb->sb_size;
 2480   linkp->l_mtime = asb->sb_mtime;
 2481   linkp->l_mode = asb->sb_mode;
 2482   linkp->l_path = path;
 2483   path->p_forw = NULL;
 2484   path->p_back = path;
 2485 
 2486   linkp->l_ino_ar = asb->sb_ino = ino;
 2487 
 2488   if ((linkp->l_forw = *(abase = linkhash (linkp->l_ino))))
 2489     linkp->l_forw->l_back = linkp;
 2490   linkp->l_back = NULL;
 2491 
 2492   return (*abase = linkp);
 2493 }
 2494 
 2495 #ifndef MEMCPY
 2496 
 2497 /*
 2498  * memcpy()
 2499  *
 2500  * A simple block move.
 2501  */
 2502 STATIC char *
 2503 memcpy (to, from, len)
 2504      reg char *to;
 2505      reg char *from;
 2506      uint len;
 2507 {
 2508   reg char *toend;
 2509 
 2510   for (toend = to + len; to < toend; *to++ = *from++)
 2511     ;
 2512   return (to);
 2513 }
 2514 
 2515 #endif /* MEMCPY */
 2516 
 2517 /*
 2518  * memget()
 2519  *
 2520  * Allocate memory.
 2521  */
 2522 STATIC char *
 2523 memget (len)
 2524      uint len;
 2525 {
 2526   reg char *mem;
 2527   static short outofmem;
 2528 
 2529   if ((mem = malloc (len)) == NULL && !outofmem)
 2530     outofmem = warn ("memget()", "Out of memory");
 2531   return (mem);
 2532 }
 2533 
 2534 /*
 2535  * memstr()
 2536  *
 2537  * Duplicate a string into dynamic memory.
 2538  */
 2539 STATIC char *
 2540 memstr (str)
 2541      reg char *str;
 2542 {
 2543   reg char *mem;
 2544 
 2545   if ((mem = memget ((uint) strlen (str) + 1)))
 2546     VOID strcpy (mem, str);
 2547   return (mem);
 2548 }
 2549 
 2550 #ifndef MKDIR
 2551 
 2552 /*
 2553  * mkdir()
 2554  *
 2555  * Make a directory via "/bin/mkdir". Sets errno to a
 2556  * questionably sane value upon failure.
 2557  */
 2558 STATIC int
 2559 mkdir (name, mode)
 2560      reg char *name;
 2561      reg ushort mode;
 2562 {
 2563   reg int pid;
 2564 
 2565   if ((pid = xfork ("mkdir()", DIE)) == 0)
 2566     {
 2567       VOID close (fileno (stdin));
 2568       VOID close (fileno (stdout));
 2569       VOID close (fileno (stderr));
 2570       VOID open ("/dev/null", O_RDWR);
 2571       VOID dup (fileno (stdin));
 2572       VOID dup (fileno (stdin));
 2573       VOID umask (~mode);
 2574       VOID execl ("/bin/mkdir", "mkdir", name, (char *) NULL);
 2575       exit (1);
 2576     }
 2577   if (xwait (pid, "mkdir()", TRUE) == 0)
 2578     return (0);
 2579   errno = EACCES;
 2580   return (-1);
 2581 }
 2582 
 2583 #endif /* MKDIR */
 2584 
 2585 
 2586 /*
 2587  * nameopt()
 2588  *
 2589  * Used to optimize a pathname in a complicated way, trying to remove
 2590  * redundant ../ components, now just simplifies leading //// into one
 2591  * leading /.  Returns 1 always.
 2592  */
 2593 STATIC int
 2594 nameopt (name)
 2595      char *name;
 2596 {
 2597   char *name2;
 2598   while((name[0]=='/')&&(name[1]=='/'))
 2599     {
 2600       name2=name;
 2601       while ((name2[0] = name2[1])) ++name2;
 2602     }
 2603   return 1;
 2604 }
 2605 
 2606 /*
 2607  * next()
 2608  *
 2609  * Advance to the next archive volume.
 2610  *
 2611  */
 2612 STATIC void
 2613 next (mode, why)
 2614      reg int mode;
 2615      reg char *why;
 2616 {
 2617   reg time_t began;
 2618   char *msg;
 2619   int msgsize;
 2620   char answer[20];
 2621 
 2622   msgsize = 200 + strlen(myname) * 2 + strlen(arspec);
 2623   msg = memget (msgsize);
 2624 
 2625   began = time ((time_t *) NULL);
 2626   nextclos ();
 2627   if(!index(ignorewarnings,(int)'M'))
 2628   {
 2629     VOID warnarch (why, (off_t) 0);
 2630     warnings--; /* above warnach call is not an error condition */
 2631   }
 2632   if (arfd == STDIN || arfd == STDOUT)
 2633     goodbye (1);
 2634   ++arvolume;           /* change disk # here */
 2635 
 2636   if (email) mail(email,(int)arvolume,arspec);
 2637 
 2638   if(promptscript)
 2639   {
 2640       for (;;)
 2641       {
 2642       auto int result;
 2643 
 2644       result=runpromptscript(why);
 2645       if (result==1)
 2646           fatal(arspec,"Aborted");
 2647       if (result!=0)
 2648           fatal(arspec,"Promptscript failed");
 2649       if (nextopen(mode)==0)
 2650           break;
 2651       }
 2652   }
 2653   else
 2654   {
 2655       if(Fflag)
 2656       {
 2657       VOID sprintf (msg, "\
 2658 %s: Ready for disk %u on %s\n\
 2659 %s: \"quit\" to abort,\"f\" to format, anything else to proceed. > \07",
 2660             myname,
 2661             arvolume,
 2662             arspec,
 2663             myname);
 2664       }
 2665       else
 2666       {
 2667       VOID sprintf (msg, "\
 2668 %s: Ready for volume %u on %s\n\
 2669 %s: \"quit\" to abort, anything else to proceed. > \07",
 2670             myname,
 2671             arvolume,
 2672             arspec,
 2673             myname);
 2674       }
 2675 
 2676       for (;;)
 2677       {
 2678       nextask (msg, answer, sizeof (answer));
 2679       if (strcmp (answer, "quit") == 0)
 2680           fatal (arspec, "Aborted");
 2681       else
 2682       {
 2683           while (Fflag && strcmp(answer,"f") == 0) {
 2684           fprintf (stderr, "formatting using %s ...\n",formatcmd);
 2685           if (system (formatcmd) != 0)
 2686           {
 2687               strcpy(msg,"\n");
 2688               strcat(msg,myname);
 2689               strcat(msg,": Format failed! Try again (y/n)? > ");
 2690               nextask (msg, answer, sizeof (answer));
 2691               if (answer[0] == 'y') answer[0] = 'f';
 2692               else exit(1);
 2693           }
 2694           else break;
 2695           }
 2696 
 2697           if (nextopen (mode) == 0)
 2698           break;
 2699       }
 2700       }
 2701   }
 2702   if(!index(ignorewarnings,(int)'M'))
 2703     {
 2704       VOID warnarch ("Continuing", (off_t) 0);
 2705       warnings--; /* above warnach call is not an error condition */
 2706     }
 2707   timewait += time ((time_t *) NULL) - began;
 2708   free(msg);
 2709 }
 2710 
 2711 
 2712 /*
 2713  * runpromptscript()
 2714  *
 2715  * Utility function to run the promptscript
 2716  *
 2717  */
 2718 STATIC int
 2719 runpromptscript (why)
 2720      char *why;
 2721 {
 2722   int pid,result;
 2723   char vol[100];
 2724 
 2725   /* run info-script with volume number and archive spec,
 2726      and reason for calling it as arguments.
 2727      the script should return 0 for ok and 1 for abort, other
 2728      return codes will be treated as errors. */
 2729 
 2730   /* connect prompt script to /dev/tty if it can be opened, else
 2731      connect it to /dev/null (for crontab/at job use) */
 2732 
 2733   sprintf(vol,"%d",arvolume);
 2734 
 2735   if ((pid = xfork (promptscript, DIE)) == 0)
 2736     {
 2737       VOID close (fileno (stdin));
 2738       VOID close (fileno (stdout));
 2739       VOID close (fileno (stderr));
 2740 
 2741       if ((open (TTY, O_RDWR)) < 0)
 2742     {
 2743       VOID open ("/dev/null", O_RDWR);
 2744     }
 2745       VOID dup (fileno (stdin));
 2746       VOID dup (fileno (stdin));
 2747 
 2748       execlp(promptscript,promptscript,vol,arspec,why,(char *)NULL);
 2749       exit (1);
 2750     }
 2751   result=xwait (pid, "promptscript", TRUE);
 2752   return(result);
 2753 }
 2754 
 2755 
 2756 /*
 2757  * nextask()
 2758  *
 2759  * Ask a question and get a response. Ignores spaces and tabs.
 2760  */
 2761 STATIC void
 2762 nextask (msg, answer, limit)
 2763      reg char *msg;
 2764      reg char *answer;
 2765      reg int limit;
 2766 {
 2767   reg int idx;
 2768   reg int got;
 2769   auto char c;
 2770 
 2771   if (ttyf < 0)
 2772     ttyf = openqtty ();
 2773   if (ttyf < 0)
 2774     fatal (TTY, "Unavailable");
 2775   VOID writeall (ttyf, msg, (uint) strlen (msg));
 2776   idx = 0;
 2777   while ((got = read (ttyf, &c, 1)) == 1)
 2778     if (c == '\04' || c == '\n')
 2779       break;
 2780     else if (c == ' ' || c == '\t')
 2781       continue;
 2782     else if (idx < limit - 1)
 2783       answer[idx++] = c;
 2784   if (got < 0)
 2785     fatal (TTY, syserr ());
 2786   answer[idx] = '\0';
 2787 }
 2788 
 2789 /*
 2790  * nextclos()
 2791  *
 2792  * Close an archive.
 2793  */
 2794 STATIC void
 2795 nextclos ()
 2796 {
 2797   if (arfd != STDIN && arfd != STDOUT && !fflag)
 2798     {
 2799       VOID close (arfd);
 2800       arfd = -1;
 2801     }
 2802   areof = 0;
 2803   if (arname && *arname == '!')
 2804     pipewait ();
 2805 
 2806   /* the volume is complete, need to adjust the volume limit for the
 2807    * following volume.
 2808    */
 2809   if (aruntil != 0)
 2810     {
 2811       update_aruntil();
 2812       if (aruntil == 0)  askfornext = 1;
 2813 
 2814       if( roundaruntil )
 2815     {
 2816       /* round aruntil down to a multiple of arbsize: some devices
 2817          (like ftape) puke on a smaller-than-blocksize last write to
 2818          the volume */
 2819       aruntil = ( aruntil / (ulonglong) arbsize );
 2820       aruntil = aruntil * arbsize;
 2821     }
 2822 
 2823       /* error check... */
 2824       if (aruntil && (aruntil < arbsize))
 2825       {
 2826       fatal(arspec,"-s option value for this volume smaller than block (-b) size");
 2827       }
 2828 
 2829   }
 2830 }
 2831 
 2832 /*
 2833  * nextopen()
 2834  *
 2835  * Open an archive. Returns 0 if successful, -1 otherwise.
 2836  */
 2837 STATIC int
 2838 nextopen (mode)
 2839      int mode;
 2840 {
 2841 #if 1
 2842   if (arfd != -1)
 2843     close (arfd);
 2844 #endif
 2845   if (*arname == '!')
 2846     arfd = pipeopen (mode);
 2847   else if (strcmp (arname, "-") == 0)
 2848     arfd = mode ? STDOUT : STDIN;
 2849   else
 2850     {
 2851       process_arname(arname);
 2852 #ifdef  CTC3B2
 2853       if (Cflag)
 2854     {
 2855       reg int oops;
 2856       reg int fd;
 2857 
 2858       oops = ((fd = open (proc_arname, O_RDWR | O_CTSPECIAL)) < 0
 2859           || ioctl (fd, STREAMON) < 0);
 2860       VOID close (fd);
 2861       if (oops)
 2862         return (warnarch (syserr (), (off_t) 0));
 2863     }
 2864 #endif /* CTC3B2 */
 2865 
 2866 #ifdef linux
 2867       /* Do O_SYNC writing to the floppy drive */
 2868       if(Fflag && mode)
 2869         arfd = open (proc_arname, mode | O_CREAT | O_TRUNC | O_SYNC, 0666 & ~mask);
 2870       else
 2871         arfd = mode ? creat (proc_arname, (mode_t)(0666 & ~mask)) : open (proc_arname, mode);
 2872 #else
 2873       arfd = mode ? creat (proc_arname, (mode_t)(0666 & ~mask)) : open (proc_arname, mode);
 2874 #endif /* linux */
 2875 
 2876     }
 2877   if (arfd < 0)
 2878     return (warnarch (syserr (), (off_t) 0));
 2879   arleft = aruntil;
 2880   return (0);
 2881 }
 2882 
 2883 /*
 2884  * openin()
 2885  *
 2886  * Open the next input file. Returns a file descriptor, 0 if no data
 2887  * exists, or -1 at EOF. This kludge works because standard input is
 2888  * in use, preventing open() from returning zero.
 2889  *
 2890  * if fsname is non-NULL, copy filename on local filesystem into it,
 2891  * if not a control file, for later use by -a option.
 2892  */
 2893 STATIC int
 2894 openin (name, fsname, asb, cratio)
 2895      char *name,*fsname;
 2896      reg Stat *asb;
 2897      int *cratio;
 2898 {
 2899   int fd;
 2900   auto char local[PATHSIZE];
 2901   char *label;
 2902 
 2903   if(fsname) *fsname='\0';
 2904 
 2905   if (cratio)
 2906     *cratio = 100;
 2907   for (;;)
 2908     {
 2909       if(firstfilename[0]!=0)
 2910     {
 2911       /* special case to suport input sanity check code in main() */
 2912       strcpy(name,firstfilename);
 2913       firstfilename[0]=0;
 2914     }
 2915       else
 2916     {
 2917       if (lineget (stdin, name, PATHSIZE) < 0)
 2918         return (-1);
 2919     }
 2920 
 2921       /* control file syntax is //--SOURCEFILE[ LABEL] */
 2922       if(strncmp(name,"//--",4)==0)
 2923       {
 2924       strcpy(local,&name[4]);
 2925 
 2926       label=index(local,(int)' ');
 2927       if(label!=NULL)
 2928       {
 2929           *label='\000';    /* separate filename and label */
 2930           label++;
 2931       }
 2932       else
 2933           label=NOLABEL;
 2934       if(*label=='\000') label=NOLABEL;
 2935 
 2936       sprintf(name,"%s/%s",CONTROLNAME,label);
 2937 
 2938       /* Now, local is the filename, label is the label, and name is
 2939              the filename in the archive, with the label embedded.
 2940           */
 2941 
 2942       if (STAT (local, asb) < 0)
 2943       {
 2944           VOID warn (local, syserr ());
 2945           continue;
 2946       }
 2947 
 2948           /* Sun machines put trash in sb_rdev in stead of setting it to 0
 2949          for regular files.  Afio wants a 0 */
 2950           if(! (S_ISBLK(asb->sb_mode)||S_ISCHR(asb->sb_mode)) ) asb->sb_rdev=0;
 2951 
 2952       if ((asb->sb_mode & S_IFMT) != S_IFREG)
 2953       {
 2954           VOID warn (local, "Cannot read control file from this source.");
 2955           continue;
 2956       }
 2957 
 2958       /* Flag that this is a control file.
 2959          An archive entry is a control file if it is a regular file and
 2960              if the ISCONTROL flag is set.  The filename is not important.
 2961       */
 2962       asb->sb_rdev |= RDEV_ISCONTROL;
 2963 
 2964       if (asb->sb_size == 0)
 2965           return (0);
 2966       if ((fd = open (local, O_RDONLY)) >= 0)
 2967           return (fd);
 2968       VOID warn (local, syserr ());
 2969       continue;
 2970       }
 2971 
 2972       /* not a control file, make a normal archive entry */
 2973 
 2974       if (namecmp (name,NULL) < 0)
 2975       continue;
 2976       if (nameopt (name) < 0)
 2977       continue;
 2978       if (!gflag)
 2979       VOID strcpy (local, name);
 2980       else if (dirchg (name, local) < 0)
 2981       continue;
 2982 
 2983       if(fsname) strcpy(fsname,local); /* for use by utime() in -a option */
 2984 
 2985       if ((hflag ? STAT (local, asb) : LSTAT (local, asb)) < 0)
 2986     {
 2987       VOID warn (name, syserr ());
 2988       if(index(ignorewarnings,(int)'m')) warnings--;
 2989 #ifdef EOVERFLOW
 2990       /* try to catch (in a portable way we hope) the case of
 2991              statting a >2GB file with a regular 4-byte off_t stat
 2992              call, this gives an EOVERFLOW on Linux.  We do not want
 2993              to count this case as a missing file, so print extra
 2994              warning so that warnings counter gets increased properly.  */
 2995       if(errno==EOVERFLOW)
 2996           VOID warn (name, "Can't archive file with size >= 2GB");
 2997 #endif
 2998       continue;
 2999     }
 3000 
 3001       /* Sun machines put trash in sb_rdev in stead of setting it to 0
 3002      for regular files.  Afio wants a 0 */
 3003       if(! (S_ISBLK(asb->sb_mode)||S_ISCHR(asb->sb_mode)) ) asb->sb_rdev=0;
 3004 
 3005       switch (asb->sb_mode & S_IFMT)
 3006     {
 3007     case S_IFDIR:
 3008           asb->sb_nlink = 1;
 3009       asb->sb_size = 0;
 3010       return (0);
 3011 #ifdef  S_IFLNK
 3012     case S_IFLNK:
 3013       if ((asb->sb_size = readlink (local,
 3014                   asb->sb_link, sizeof (asb->sb_link) - 1)) < 0)
 3015         {
 3016           VOID warn (name, syserr ());
 3017           continue;
 3018         }
 3019       asb->sb_link[asb->sb_size] = '\0';
 3020       return (0);
 3021 #endif /* S_IFLNK */
 3022     case S_IFREG:
 3023       if (asb->sb_size == 0)
 3024             {
 3025               /* indicate that file is not suitable for compression */
 3026           asb->sb_rdev |= RDEV_NOTCOMPR;
 3027               return (0);
 3028         }
 3029 
 3030       if (cpiocompat && (asb->sb_size != (asb->sb_size&0x7fffffff)))
 3031         {
 3032           /* >=2GB file.  Can't handle this and remain cpio compatible */
 3033           VOID fatal (name, "Archiving file with size >= 2GB not allowed by -5 option");
 3034           continue;
 3035         }
 3036 
 3037       if ((fd = open (local, O_RDONLY)) >= 0)
 3038         {
 3039           if (Zflag)
 3040         compressfile (&fd, name, asb, cratio);
 3041 
 3042           return (fd);
 3043         }
 3044       VOID warn (name, syserr ());
 3045       break;
 3046     default:
 3047       asb->sb_size = 0;
 3048       return (0);
 3049     }
 3050     }
 3051 }
 3052 
 3053 /*
 3054  * openincheck()
 3055  *
 3056  * Open the input file. Returns a file descriptor, 0 if no data
 3057  * exists, or -1 at EOF. This kludge works because standard input is
 3058  * in use, preventing open() from returning zero.
 3059  */
 3060 STATIC int
 3061 openincheck (name, asb, comp, dozflag)
 3062      char *name;
 3063      reg Stat *asb;
 3064      int *comp;
 3065      int dozflag;
 3066 {
 3067   int fd;
 3068   auto char local[PATHSIZE];
 3069   auto char archlink[PATHSIZE];
 3070   char* namedot;
 3071 
 3072   *uncompto = '\0';
 3073   *comp = 0;
 3074   if (dozflag && ((asb->sb_mode & S_IFMT) == S_IFREG) &&
 3075       ((namedot = strrchr (name, '.')) != NULL) &&
 3076       (asb->sb_rdev & RDEV_NOTCOMPR) == 0 &&
 3077       (asb->sb_size > 0) &&
 3078       (strcmp (namedot, ".z") == 0))
 3079     {
 3080       *namedot = '\0';
 3081       strcpy(uncompto, name);
 3082       *comp = 1;
 3083     }
 3084   else
 3085     namedot = NULL;     /* not uncompressing */
 3086   if (nameopt (name) < 0)
 3087     return -1;
 3088   if (!gflag)
 3089     VOID strcpy (local, name);
 3090   else if (dirchg (name, local) < 0)
 3091     return 0;
 3092   switch (asb->sb_mode & S_IFMT)
 3093     {
 3094     case S_IFDIR:
 3095       asb->sb_nlink = 1;
 3096       asb->sb_size = 0;
 3097       /* do not check if directory exists */
 3098       /* do not check directory permissions and access times */
 3099       return (0);
 3100 #ifdef  S_IFLNK
 3101     case S_IFLNK:
 3102       /* if sb_size==0 then it is a hardlink to a symlink earlier
 3103          in the archive, so don't check. */
 3104       if (asb->sb_size == 0)
 3105     return (0);
 3106 
 3107       strcpy(archlink,asb->sb_link);
 3108 
 3109       if ((asb->sb_size =
 3110              readlink (local, asb->sb_link, sizeof (asb->sb_link) - 1)) < 0)
 3111     {
 3112       VOID warn (name, syserr ());
 3113       asb->sb_size = 0;
 3114       return 0;
 3115     }
 3116       asb->sb_link[asb->sb_size] = '\0';
 3117 
 3118       if(strcmp(archlink,asb->sb_link)!=0)
 3119       VOID warn (name, "Difference in symlink destination filename");
 3120 
 3121      asb->sb_size = 0;
 3122      return (0);
 3123 #endif /* S_IFLNK */
 3124     case S_IFREG:
 3125       /* does not check file permissions and access times */
 3126 
 3127       /* get last access time if we want to restore it */
 3128       if(aflag)
 3129       {
 3130       if (STAT (local, &atime_sb) < 0)
 3131       {
 3132           /* silently fail, the open below will report an error */
 3133       }
 3134       else
 3135       {
 3136           atime_sb_valid=1;
 3137       }
 3138       }
 3139 
 3140       if ((fd = open (local, O_RDONLY)) >= 0)
 3141     {
 3142       /* check for larger file on filesystem if file has 0 size */
 3143       /* special handling of hard links: non-first archive entries
 3144          for hardlinked files, which have 0 size, are not checked.
 3145          If the hardlinked file has 0 size originally, the first
 3146          archive entry for it also has 0 size, which means that
 3147          the code below does not then check if the file on the
 3148          filesystem grew larger.  Fixing this would be too much
 3149          work, we have to figure out correct coding of hard link
 3150          inode/file name administration (see e.g. code in
 3151          tocentry()) in order to detect whether the entry
 3152          represents a first entry. */
 3153       if ((asb->sb_size == 0)&&(asb->sb_nlink == 1))
 3154         {
 3155           if (STAT (local, &atime_sb) >= 0)
 3156         {
 3157           if (asb->sb_size != atime_sb.sb_size)
 3158             {
 3159               VOID warn (name, "File in archive has different length than file on filesystem");
 3160               if(index(ignorewarnings,(int)'r'))
 3161             {
 3162               warn_nocount(name, "Not counting this as a verification error");
 3163               warnings--;
 3164             }
 3165             }
 3166         }
 3167         }
 3168       return (fd);
 3169     }
 3170       VOID warn_nocount (name, syserr ());
 3171       VOID warn (name, "File on filesystem could not be opened for verify");
 3172       if(index(ignorewarnings,(int)'r'))
 3173     {
 3174       warn_nocount(name, "Not counting this as a verification error");
 3175       warnings--;
 3176     }
 3177 
 3178       return 0;
 3179     default:
 3180       asb->sb_size = 0;
 3181       return (0);
 3182     }
 3183 }
 3184 
 3185 /*
 3186  * opencontrolscript()
 3187  *
 3188  * Start a control script. Returns the stdin of the script,
 3189  * -1 if unsuccessful.
 3190  * If no control script option given, return file handle of /dev/null.
 3191  */
 3192 STATIC int
 3193 opencontrolscript (char *name)
 3194 {
 3195     auto int pfd[2];
 3196     int comppid;
 3197     char *label;
 3198 
 3199     *uncompto='\000';  /* for -v output on restore, verify */
 3200 
 3201     if(controlscript == NULL )
 3202     {
 3203     /* ignore data */
 3204     warnarch("No -D option given, ignoring control file.",(off_t)0);
 3205     return open("/dev/null",O_WRONLY);
 3206     }
 3207 
 3208     if(strcmp(controlscript,"")==0)
 3209     {
 3210     /* silently ignore data */
 3211     return open("/dev/null",O_WRONLY);
 3212     }
 3213 
 3214     label=index(name,(int)'/');
 3215     if(label==NULL) label=NOLABEL; else label++;
 3216 
 3217     if (pipe (pfd) < 0)
 3218     {
 3219     warn("Control script",syserr());
 3220     return -1;
 3221     }
 3222 
 3223     if ((comppid = xfork ("opencontrolscript(in), running control script", NODIE)) == 0)
 3224     {
 3225         /* Ignoring SIGPIPE may cause strange results in some shell scripts */
 3226     VOID signal (SIGPIPE, SIG_DFL);
 3227 
 3228     if (arfd != STDIN && arfd != STDOUT) VOID close (arfd);
 3229     VOID close (pfd[1]);    /* child */
 3230     VOID close (fileno (stdin));
 3231     VOID dup (pfd[0]);
 3232     VOID close (pfd[0]);
 3233 
 3234         execlp (controlscript, controlscript, label, NULL);
 3235 
 3236     warnarch("Problems running control script:",(off_t)0);
 3237     warn(controlscript,syserr());
 3238     exit (1);
 3239     }
 3240 
 3241     /*parent*/
 3242 
 3243     if (comppid < 0)
 3244     {
 3245     warn("Control script",syserr());
 3246     return -1;
 3247     }
 3248 
 3249     close (pfd[0]);
 3250 
 3251     /* this enables some safety checks */
 3252     uncompressrun = comppid;
 3253 
 3254     return pfd[1];
 3255 }
 3256 
 3257 /*
 3258  * openotty()
 3259  *
 3260  * Open an output file. Returns the output file descriptor,
 3261  * 0 if no data is required or -1 if unsuccessful. Note that
 3262  * UNIX open() will never return 0 because the standard input
 3263  * is in use.
 3264  */
 3265 STATIC int
 3266 openotty (name, asb, linkp, ispass, dozflag)
 3267      char *name;
 3268      reg Stat *asb;
 3269      Link *linkp;
 3270      reg int ispass;
 3271      int dozflag;
 3272 {
 3273   reg int exists;
 3274   reg int fd;
 3275   reg ushort perm;
 3276   ushort operm=0; /* this one and next two initialised to */
 3277   uid_t ouid=9999; /* suppress compiler warnings */
 3278   gid_t ogid=9999;
 3279   Path *path;
 3280   auto Stat osb;
 3281 #ifdef  S_IFLNK
 3282   reg int ssize;
 3283   auto char sname[PATHSIZE];
 3284 #endif /* S_IFLNK */
 3285   char *namedot;
 3286   auto int pfd[2];
 3287   int comppid;
 3288 
 3289   if(ISCONTROL(asb))
 3290       return opencontrolscript(name);
 3291 
 3292   *uncompto = '\0';
 3293   /*
 3294    * -iZ try to uncompress a compress'd regular file
 3295    */
 3296   if (dozflag && !linkp && ((asb->sb_mode & S_IFMT) == S_IFREG) &&
 3297       ((namedot = strrchr (name, '.')) != NULL) &&
 3298       (asb->sb_rdev & RDEV_NOTCOMPR) == 0 &&
 3299       (asb->sb_size > 0) &&
 3300       (strcmp (namedot, ".z") == 0))
 3301     {
 3302       *namedot = '\0';
 3303     }
 3304   else
 3305     namedot = NULL;     /* not uncompressing */
 3306   if ((exists = (LSTAT (name, &osb) == 0)))
 3307     {
 3308       /* The asb.sb_ino here has not been truncated to 16 bits, so the check is
 3309      safe and may even add some protection. */
 3310       if (ispass
 3311       && osb.sb_ino == asb->sb_ino
 3312       && osb.sb_dev == asb->sb_dev)
 3313     return (warn (name, "Same file"));
 3314       else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT))
 3315     operm = osb.sb_mode & (xflag ? S_IPERM : S_IPOPN);
 3316       else if (afremove (name, &osb) < 0)
 3317     return (warn (name, syserr ()));
 3318       else
 3319     exists = 0;
 3320     }
 3321   if (linkp)
 3322     {
 3323       if (exists)
 3324       {
 3325 #if 0
 3326  /* Bogus check commented out.
 3327     This check is bogus and dangerous because we only get the
 3328     least significant 16 bits of the ino of the archived file from
 3329     the archive header.  So the file this check would prevent
 3330     overwriting (replacing with a link) if true will probably be a different
 3331     file altogether, which we wanted overwritten, not preserved.
 3332     Also, the check is bogus anyway when installing the files on a
 3333     different computer system.  Ho hum.
 3334  */
 3335         printf("asb->sb_ino == osb.sb_ino %d %d\n",asb->sb_ino, osb.sb_ino);
 3336     if (asb->sb_ino == osb.sb_ino
 3337         && asb->sb_dev == osb.sb_dev)
 3338       return (0);
 3339     else
 3340 #endif
 3341         if (unlink (name) < 0)
 3342       return (warn (name, syserr ()));
 3343     else
 3344       exists = 0;
 3345       }
 3346       for (path = linkp->l_path; path; path = path->p_forw)
 3347     if (link (path->p_name, name) == 0
 3348         || (errno == ENOENT
 3349         && dirneed (name) == 0
 3350         && link (path->p_name, name) == 0))
 3351       return (0);
 3352     else if (errno != EXDEV)
 3353       return (warn (name, syserr ()));
 3354       VOID warn (name, "Link broken");
 3355       linkalso (linkp, name);
 3356     }
 3357   perm = asb->sb_mode & (xflag ? S_IPERM : S_IPOPN);
 3358   if (exists)
 3359     {
 3360       ouid = osb.sb_uid;
 3361       ogid = osb.sb_gid;
 3362     }
 3363   switch (asb->sb_mode & S_IFMT)
 3364     {
 3365     case S_IFBLK:
 3366     case S_IFCHR:
 3367       fd = 0;
 3368       /* rdev==0 means that dev_t value does not fit in 16 bits,
 3369      and is encoded in dev and ino instead
 3370      see out().
 3371       */
 3372       if(asb->sb_rdev==0) asb->sb_rdev=(asb->sb_dev << 16) + asb->sb_ino;
 3373 
 3374       if (exists)
 3375     {
 3376       if (asb->sb_rdev == osb.sb_rdev)
 3377         if (perm != operm && chmod (name, perm) < 0)
 3378           return (warn (name, syserr ()));
 3379         else
 3380           break;
 3381       else if (afremove (name, &osb) < 0)
 3382         return (warn (name, syserr ()));
 3383       else
 3384         exists = 0;
 3385     }
 3386 
 3387       if (mknod (name, asb->sb_mode, asb->sb_rdev) < 0
 3388       && (errno != ENOENT
 3389           || dirneed (name) < 0
 3390           || mknod (name, asb->sb_mode, asb->sb_rdev) < 0))
 3391     return (warn (name, syserr ()));
 3392       break;
 3393     case S_IFDIR:
 3394       if (exists)
 3395     {
 3396       if (xflag && (asb->sb_uid != ouid || asb->sb_gid != ogid) &&
 3397           chown (name, asb->sb_uid, asb->sb_gid) < 0)
 3398         return (warn (name, syserr ()));
 3399       else if (perm != operm && chmod (name, perm) < 0)
 3400         return (warn (name, syserr ()));
 3401       else { ; }
 3402       if(osb.sb_mtime <= (mflag ? timenow : asb->sb_mtime))
 3403         savedirstamp(name, mflag ? timenow : asb->sb_mtime);
 3404     }
 3405       else
 3406     {
 3407       savedirstamp(name, mflag ? timenow : asb->sb_mtime);
 3408       if (dirneed (name) < 0 || dirmake (name, asb) < 0)
 3409         return (warn (name, syserr ()));
 3410     }
 3411      return (0);
 3412 #ifdef  S_IFIFO
 3413     case S_IFIFO:
 3414       fd = 0;
 3415       if (exists)
 3416     if (perm != operm && chmod (name, perm) < 0)
 3417       return (warn (name, syserr ()));
 3418     else { ; }
 3419       else if (mkfifo (name, asb->sb_mode) < 0
 3420            && (errno != ENOENT
 3421            || dirneed (name) < 0
 3422            || mkfifo (name, asb->sb_mode) < 0))
 3423     return (warn (name, syserr ()));
 3424       break;
 3425 #endif /* S_IFIFO */
 3426 #ifdef  S_IFSOCK
 3427     case S_IFSOCK:
 3428       fd = 0;
 3429       if (exists)
 3430     if (perm != operm && chmod (name, perm) < 0)
 3431       return (warn (name, syserr ()));
 3432     else { ; }
 3433       else if (mknod (name, asb->sb_mode, (dev_t) 0) < 0
 3434            && (errno != ENOENT
 3435            || dirneed (name) < 0
 3436            || mknod (name, asb->sb_mode, (dev_t) 0) < 0))
 3437     return (warn (name, syserr ()));
 3438       break;
 3439 #endif /* S_IFSOCK */
 3440 #ifdef  S_IFLNK
 3441     case S_IFLNK:
 3442       fd = 0;
 3443       if (nosymlinks)
 3444     {
 3445       warn (name, "Not unpacking this symlink because of -8 nosymlinks");
 3446       if(index(ignorewarnings,(int)'l')) warnings--;
 3447       break;
 3448     }
 3449       if (exists)
 3450     {
 3451       if ((ssize = readlink (name, sname, sizeof (sname))) < 0)
 3452         return (warn (name, syserr ()));
 3453       else if (strncmp (sname, asb->sb_link, (size_t)ssize) == 0)
 3454         break;
 3455       else if (afremove (name, &osb) < 0)
 3456         return (warn (name, syserr ()));
 3457       else
 3458         exists = 0;
 3459     }
 3460       if (symlink (asb->sb_link, name) < 0
 3461       && (errno != ENOENT
 3462           || dirneed (name) < 0
 3463           || symlink (asb->sb_link, name) < 0))
 3464     return (warn (name, syserr ()));
 3465       break;
 3466 #endif /* S_IFLNK */
 3467     case S_IFREG:
 3468       if (exists)
 3469     {
 3470       if (nflag && osb.sb_mtime > asb->sb_mtime)
 3471         return (warn_nocount (name, "Newer file exists"));
 3472       else if (unlink (name) < 0)
 3473         return (warn (name, syserr ()));
 3474       else
 3475         exists = 0;
 3476     }
 3477 
 3478       if ((fd = creat (name, perm)) < 0
 3479       && (errno != ENOENT
 3480           || dirneed (name) < 0
 3481           || (fd = creat (name, perm)) < 0))
 3482     return (warn (name, syserr ()));
 3483       if (dozflag && !linkp && namedot)
 3484     {
 3485       if (pipe (pfd) >= 0)
 3486         {
 3487           if ((comppid = xfork ("openotty(in), compressing", NODIE)) == 0)
 3488         {
 3489           if (arfd != STDIN && arfd != STDOUT) VOID close (arfd);
 3490           VOID close (pfd[1]);  /* child */
 3491           VOID close (fileno (stdin));
 3492           VOID dup (pfd[0]);
 3493           VOID close (pfd[0]);
 3494 
 3495           VOID close (fileno (stdout));
 3496           if (dup (fd) < 0)
 3497             exit (1);
 3498           VOID close (fd);
 3499           mayberewind();
 3500           if(compressargs)
 3501               execvp (compressprog, compress_arg_list);
 3502           else
 3503               execlp (compressprog, compressprog, "-d", "-c", NULL);
 3504           fprintf (stderr, "Could not uncompress, errno %d\n", errno);
 3505           exit (1);
 3506           }
 3507           else
 3508           /* life seems ok */
 3509           if (comppid > 0)
 3510           {
 3511               close (fd);
 3512               fd = pfd[1];
 3513               close (pfd[0]);
 3514               uncompressrun = comppid;
 3515               strcpy (uncompto, name);
 3516 #if 0
 3517               *namedot = '.';
 3518 #endif
 3519               break;
 3520           }
 3521       }
 3522       /* we failed try again, not uncompressing the file */
 3523       unlink (name);
 3524       *namedot = '.';
 3525       return (openotty (name, asb, linkp, ispass, FALSE));
 3526     }
 3527 
 3528       break;
 3529     default:
 3530       return (warn (name, "Unknown filetype"));
 3531     }
 3532 
 3533   /* Can't chown()/chmod() a symbolic link, but for all others... */
 3534   if((asb->sb_mode & S_IFMT) != S_IFLNK)
 3535     {
 3536       if (xflag && (!exists || asb->sb_uid != osb.sb_uid
 3537             || asb->sb_gid != osb.sb_gid))
 3538     {
 3539       if (chown (name, (uid == 0 ? asb->sb_uid : uid),
 3540              asb->sb_gid))
 3541         perror (name);
 3542       else /* chown may have cleared suid/sgid flags; restore them */
 3543         if(perm&S_IPEXE)
 3544           if(chmod (name, perm) < 0)
 3545         return (warn (name, syserr ()));
 3546     }
 3547     }
 3548   else
 3549     {
 3550       /* but if we have an lchown call, we _can_ chown a symbolic link.. */
 3551       /* note: the lchown call is like chown, except that lchown does
 3552      not follow a symlink.  lchown is not present in all unix systems.
 3553      Therefore, an ifdef is used below, the symbol is defined in the
 3554      makefile */
 3555 #ifdef HAVE_LCHOWN
 3556       if (xflag && (!exists || asb->sb_uid != osb.sb_uid
 3557             || asb->sb_gid != osb.sb_gid))
 3558     {
 3559       if (lchown (name, (uid == 0 ? asb->sb_uid : uid),
 3560              asb->sb_gid))
 3561         perror (name);
 3562     }
 3563 #endif
 3564     }
 3565 
 3566   if (linkp == NULL && asb->sb_nlink > 1)
 3567     VOID linkto (name, asb);
 3568   return (fd);
 3569 }
 3570 
 3571 /*
 3572  * openqtty()
 3573  *
 3574  * Open the terminal for interactive queries (sigh). Assumes that
 3575  * background processes ignore interrupts and that the open() or
 3576  * the isatty() will fail for processes which are not attached to
 3577  * terminals. Returns a file descriptor (-1 if unsuccessful).
 3578  */
 3579 int
 3580 openqtty (void)
 3581 {
 3582   reg VOIDFN (*intr) (int);
 3583   int fd;
 3584 
 3585   fd = -1;
 3586   if (!Fflag)
 3587     {
 3588       if ((intr = signal (SIGINT, SIG_IGN)) == SIG_IGN)
 3589     return (fd);
 3590       VOID signal (SIGINT, intr);
 3591     }
 3592 
 3593   if ((fd = open (TTY, O_RDWR)) < 0)
 3594     {
 3595       VOID warn (TTY, syserr ());
 3596     }
 3597   else if (!isatty (fd))
 3598     VOID warn (TTY, "Is not a tty");
 3599   return (fd);
 3600 }
 3601 
 3602 /*
 3603  * options()
 3604  *
 3605  * Decode most reasonable forms of UNIX option syntax. Takes main()-
 3606  * style argument indices (argc/argv) and a string of valid option
 3607  * letters. Letters denoting options with arguments must be followed
 3608  * by colons. With valid options, returns the option letter and points
 3609  * "optarg" at the associated argument (if any). Returns '?' for bad
 3610  * options and missing arguments. Returns zero when no options remain,
 3611  * leaving "optind" indexing the first remaining argument.
 3612  */
 3613 STATIC int
 3614 options (ac, av, proto)
 3615      int ac;
 3616      register char **av;
 3617      char *proto;
 3618 {
 3619   register int c;
 3620   register char *idx;
 3621   static int optsub;
 3622 
 3623   if (optind == 0)
 3624     {
 3625       optind = 1;
 3626       optsub = 0;
 3627     }
 3628   optarg = NULL;
 3629   if (optind >= ac)
 3630     return (0);
 3631   if (optsub == 0 && (av[optind][0] != '-' || av[optind][1] == '\0'))
 3632     return (0);
 3633   switch (c = av[optind][++optsub])
 3634     {
 3635     case '\0':
 3636       ++optind;
 3637       optsub = 0;
 3638       return (options (ac, av, proto));
 3639     case '-':
 3640       ++optind;
 3641       optsub = 0;
 3642       return (0);
 3643     case ':':
 3644       return ('?');
 3645     }
 3646   if ((idx = strchr (proto, c)) == NULL)
 3647     return ('?');
 3648   if (idx[1] != ':')
 3649     return (c);
 3650   optarg = &av[optind][++optsub];
 3651   ++optind;
 3652   optsub = 0;
 3653   if (*optarg)
 3654     return (c);
 3655   if (optind >= ac)
 3656     return ('?');
 3657   optarg = av[optind++];
 3658   return (c);
 3659 }
 3660 
 3661 /*
 3662  * optsize()
 3663  *
 3664  * Interpret a "size" argument. Recognizes suffices for blocks
 3665  * (512-byte), kilobytes, megabytes, gigabytes and blocksize. Returns
 3666  * the size in bytes.
 3667  */
 3668 STATIC ulonglong
 3669 optsize (str)
 3670      char *str;
 3671 {
 3672   reg char *idx;
 3673   ulonglong number;
 3674   ulonglong result;
 3675 
 3676   result = 0;
 3677   idx = str;
 3678   for (;;)
 3679     {
 3680       number = 0;
 3681       while (*idx >= '0' && *idx <= '9')
 3682     number = number * 10 + *idx++ - '0';
 3683       switch (*idx++)
 3684     {
 3685     case 'b':
 3686       result += number * (ulonglong)512;
 3687       continue;
 3688     case 'k':
 3689       result += number * (ulonglong)1024;
 3690       continue;
 3691     case 'm':
 3692       result += number * (ulonglong)(1024L * 1024L);
 3693       continue;
 3694     case 'g':
 3695       result += number * (ulonglong)(1024L * 1024L * 1024L);
 3696       continue;
 3697     case 'x':
 3698       result += number * (ulonglong)arbsize;
 3699       continue;
 3700     case '+':
 3701       result += number;
 3702       continue;
 3703     case '\0':
 3704       result += number;
 3705       break;
 3706     default:
 3707       break;
 3708     }
 3709       break;
 3710     }
 3711   if (*--idx)
 3712     fatal (str, "Unrecognizable value");
 3713   return (result);
 3714 }
 3715 
 3716 /*
 3717  * out()
 3718  *
 3719  * Write an archive.
 3720  */
 3721 STATIC VOIDFN
 3722 out (av)
 3723      char **av;
 3724 {
 3725     reg int fd;
 3726     auto Stat sb;
 3727     auto char name[PATHSIZE];
 3728     auto char fsname[PATHSIZE];
 3729     auto int compression;
 3730 #ifdef linux_tstamp
 3731     auto struct utimbuf tstamp;
 3732 #else
 3733     auto time_t tstamp[2];
 3734 #endif
 3735     int wantlarge;
 3736     Link *linkp;
 3737 
 3738     if (*av)
 3739     fatal (*av, "Extraneous argument");
 3740 
 3741     while ((fd = openin (name, fsname, &sb, &compression)) >= 0)
 3742     {
 3743     bytepos=total; /* offset of this file in archive */
 3744 
 3745     sb.ino_orig=sb.sb_ino;
 3746     if (!lflag && sb.sb_nlink > 1)
 3747     {
 3748         if ((linkp = linkfrom (&sb,0)))
 3749             {
 3750              /* this file is a had link to a file we stored before */
 3751         sb.sb_size = 0;
 3752         sb.sb_ino=linkp->l_ino_ar;
 3753             }
 3754         else
 3755         {
 3756           /* linkto also updates sb.sb_ino to equal l_ino_ar */
 3757           VOID linkto (name, &sb);
 3758         }
 3759     }
 3760 
 3761     /* Some systems have a dev_t larger than 16 bits.  If the
 3762            dev_t value is larger, then encode it in the dev and ino fields
 3763        of the archive header, and set rdev to 0 to signify special
 3764        case. */
 3765     /* for symmetry, and to reduce the amount of conditional logic
 3766            needed in afio, this re-encoding measure is also used if we
 3767            produce an outhead3 large ascii header, even though the
 3768            outhead3 header has more room in its rdev field.  */
 3769 
 3770         if( (S_ISBLK(sb.sb_mode)||S_ISCHR(sb.sb_mode))&&
 3771        ( ((sb.sb_rdev|0xffff)!=0xffff) || (sb.sb_rdev==0)) )
 3772       {
 3773         sb.sb_dev=sb.sb_rdev>>16;
 3774         sb.sb_ino=sb.sb_rdev&0xffff;
 3775         sb.sb_rdev=(dev_t)0;
 3776       }
 3777 
 3778     /* calculate if we want to use a large ASCII header.
 3779      * Use them only when the data won't fit into the
 3780      * default header.
 3781      */
 3782     wantlarge=(sb.sb_size != (sb.sb_size&0x7FFFFFFF));
 3783 
 3784     /* also need large archive header to correctly store
 3785        hard linked files (if inode numbers assigned by linkto()
 3786        go above 16 bits) */
 3787 
 3788     if (!lflag && (sb.sb_nlink > 1) && !extfmt)
 3789       wantlarge = wantlarge || ((sb.sb_ino&0x0ffff)!=sb.sb_ino);
 3790 
 3791     /* also need it for big uid/gid values */
 3792     wantlarge=wantlarge || ((sb.sb_uid&0x0ffff)!=sb.sb_uid);
 3793     wantlarge=wantlarge || ((sb.sb_gid&0x0ffff)!=sb.sb_gid);
 3794 
 3795     /* When on a system with sizeof(time_t)>4bytes, and if the time
 3796        on the file is >2038, also use large archive header
 3797        (Linux right now has a 4-byte time_t, but we want to be
 3798        future-proof.)
 3799     */
 3800     wantlarge=wantlarge || ((sb.sb_mtime&0x7fffffff)!=sb.sb_mtime);
 3801 
 3802     if(cpiocompat && wantlarge)
 3803       {
 3804         /* if this was the >2GB case we already had a fatal elsewhere.. */
 3805         VOID fatal (name, "Cannot create cpio-compatible file header for this input, aborting because of -5 option");
 3806       }
 3807 
 3808     if(wantlarge && !cpiowarned && !index(ignorewarnings,(int)'C'))
 3809       {
 3810         VOID warn_nocount(name, "Cannot create cpio-compatible file header for this input");
 3811         VOID warnarch("Continuing, archive will not be fully compatible with cpio or afio versions 2.4.7 and lower",(off_t)0);
 3812         if(index(ignorewarnings,(int)'c')) warnings--;
 3813         cpiowarned=1;
 3814       }
 3815 
 3816 #ifdef  S_IFLNK
 3817     if ((sb.sb_mode & S_IFMT) == S_IFLNK)
 3818       if (nosymlinks)
 3819         {
 3820           warn (fsname, "Not including symlink because of -8 nosymlinks");
 3821           if(index(ignorewarnings,(int)'l')) warnings--;
 3822           continue;
 3823         }
 3824 #endif /* S_IFLNK */
 3825 
 3826     if(wantlarge)
 3827       {
 3828         outhead3 (name, &sb);
 3829       }
 3830     else
 3831       {
 3832         if(extfmt)
 3833           outhead2 (name, &sb);
 3834         else
 3835           outhead (name, &sb);
 3836       }
 3837 
 3838     if (fd)
 3839       {
 3840         if (fd==ZIPFD)
 3841           {
 3842         outdatazip(zipfdfd,name,sb.sb_size);
 3843         close(zipfdfd);
 3844           }
 3845         else if (fd==MEMFD)
 3846           {
 3847         outdatamem(name,sb.sb_size);
 3848           }
 3849         else
 3850           VOID close (outdata (fd, name, sb.sb_size));
 3851       }
 3852 
 3853     if ((vflag>1)&&((arfd!=STDOUT)))
 3854     {
 3855       /* You can use -vv for full ls-style listings on stdout. */
 3856       char toc_name[PATHSIZE];
 3857       Stat toc_sb;
 3858       /* Copy data structures first, because tocentry modifies them */
 3859       strncpy(toc_name,name,PATHSIZE);
 3860       memcpy(&toc_sb,&sb,sizeof(Stat));
 3861       tocentry (toc_name, &toc_sb);
 3862     }
 3863     else if (vflag)
 3864       {
 3865         if(printbytepos) fprintf(stderr,"%.0f ",(double)bytepos);
 3866 
 3867         if ((name[0] == '/') && !abspaths && (name[1]!=0))
 3868         fprintf (stderr, "%s -- ", &name[1]);
 3869         else
 3870         fprintf (stderr, "%s -- ", name);
 3871 
 3872         /* We do not check for a broken pipe on stderr, we wouldn't want
 3873            to stop making the archive if this happens.
 3874            */
 3875 
 3876         if ((fd==ZIPFD)||(fd==MEMFD))
 3877         VOID fprintf (stderr, "(%02d%%)\n", compression);
 3878         else
 3879         VOID fputs ("okay\n", stderr);
 3880     }
 3881 
 3882     /* ASX check if file changed between the begining
 3883        and end of the backup */
 3884         /* if *fsname==0, it was a control file, so do not check then */
 3885     if (*fsname!=0)
 3886     {
 3887         struct stat st;
 3888         /* I must check fsname !
 3889            but error must be reported as fsname or name ?????
 3890            I chosed to use fsname */
 3891         if ((hflag ? stat(fsname, &st) : lstat(fsname, &st))<0)
 3892         {
 3893             warn (fsname, syserr());
 3894         }
 3895         else
 3896         {
 3897             if (st.st_mtime!=sb.sb_mtime)
 3898             {
 3899                 warn (fsname, "File was modified during its backup");
 3900             if(index(ignorewarnings,(int)'d')) warnings--;
 3901             }
 3902         }
 3903     }
 3904 
 3905     if(aflag && *fsname && ((sb.sb_mode & S_IFMT)==S_IFREG))
 3906     {
 3907         /* reset access time, this distroys the ctime btw. */
 3908 #ifdef linux_tstamp
 3909         tstamp.actime = sb.sb_atime;
 3910         tstamp.modtime = sb.sb_mtime;
 3911         VOID utime (fsname, &tstamp);
 3912 #else
 3913         tstamp[0] = sb.sb_atime;
 3914         tstamp[1] = sb.sb_mtime;
 3915         VOID utime (fsname, tstamp);
 3916 #endif
 3917     }
 3918     }
 3919     outeof (TRAILER, TRAILZ);
 3920 }
 3921 
 3922 /*
 3923  * outalloc()
 3924  *
 3925  * Allocate buffer space previously referenced by outavail().
 3926  */
 3927 STATIC void
 3928 outalloc (len)
 3929      reg size_t len;
 3930 {
 3931   bufidx += len;
 3932   total += len;
 3933 }
 3934 
 3935 /*
 3936  * outavail()
 3937  *
 3938  * Index buffer space for archive output. Stores a buffer pointer
 3939  * at a given location. Returns the number of bytes available.
 3940  */
 3941 STATIC size_t
 3942 outavail (bufp)
 3943      reg char **bufp;
 3944 {
 3945   reg size_t have;
 3946 
 3947   while ((have = bufend - bufidx) == 0)
 3948     {
 3949       outflush (NOTDONE);
 3950     }
 3951 
 3952   *bufp = bufidx;
 3953   return (have);
 3954 }
 3955 
 3956 /*
 3957  * outdata()
 3958  *
 3959  * Write archive data. Continues after file read errors, padding with
 3960  * null characters if neccessary. Always returns the given input file
 3961  * descriptor.
 3962  */
 3963 STATIC int
 3964 outdata (fd, name, size)
 3965      int fd;
 3966      char *name;
 3967      reg off_t size;
 3968 {
 3969   reg size_t chunk;
 3970   reg ssize_t got;
 3971   reg int oops;
 3972   reg size_t avail;
 3973   auto char *buf;
 3974 
 3975   oops = got = 0;
 3976   while (size)
 3977     {
 3978       avail = outavail (&buf);
 3979       size -= (chunk = size < (off_t)avail ? size : avail);
 3980       if (oops == 0 && (got = readall (fd, buf, chunk)) < 0)
 3981     {
 3982       oops = warn (name, syserr ());
 3983       if(index(ignorewarnings,(int)'n')) warnings--;
 3984       got = 0;
 3985     }
 3986       if ((size_t)got < chunk)
 3987     {
 3988       if (oops == 0)
 3989         oops = warn (name, "Early EOF");
 3990       while ((size_t)got < chunk)
 3991         buf[got++] = '\0';
 3992     }
 3993       outalloc (chunk);
 3994     }
 3995   return (fd);
 3996 }
 3997 
 3998 /*
 3999  * outdatazip()
 4000  *
 4001  * Write archive data. Continues after file read errors, padding with
 4002  * null characters if neccessary.
 4003  *
 4004  * Special version for reading from gzip through a pipe.
 4005  */
 4006 void
 4007 outdatazip (fd, name, size)
 4008      int fd;
 4009      char *name;
 4010      reg off_t size;
 4011 {
 4012   reg size_t chunk;
 4013   reg ssize_t got;
 4014   reg size_t avail;
 4015   auto char *buf;
 4016   char localbuf[4096];
 4017   int overflow=0;
 4018 
 4019   while (size>0)
 4020     {
 4021       avail = outavail (&buf);
 4022       chunk = (size < (off_t)avail ? size : avail);
 4023 
 4024       got = read (fd, buf, chunk);
 4025       if(got<=0) break;
 4026 
 4027       outalloc (got);
 4028       size-=got;
 4029     }
 4030 
 4031   /* read the end of the stream, if the data changed on the second gzip */
 4032   overflow=0;
 4033   while (read (fd, localbuf, sizeof(localbuf))>0) overflow=1;
 4034 
 4035   waitforgzip(); /* wait for child to exit */
 4036 
 4037   if(size>0 || overflow)
 4038         warn (name, "Error zipping file, written damaged copy to archive.");
 4039 
 4040   /* pad with zeros, if necessary */
 4041   while (size>0)
 4042     {
 4043       avail = outavail (&buf);
 4044       size -= (chunk = size < (off_t)avail ? size : avail);
 4045       got=0;
 4046       while (got < chunk)
 4047           buf[got++] = '\0';
 4048       outalloc (chunk);
 4049     }
 4050 
 4051 }
 4052 
 4053 /*
 4054  * outdatamem()
 4055  *
 4056  * Write archive data.
 4057  *
 4058  * Special version for reading from internal memory buffer.
 4059  */
 4060 void
 4061 outdatamem (name, size)
 4062      char *name;
 4063      reg off_t size;
 4064 {
 4065   reg uint chunk;
 4066   reg uint got;
 4067   reg uint avail;
 4068   auto char *buf;
 4069 
 4070   /* read from memory */
 4071   memreset();
 4072 
 4073   while (size)
 4074     {
 4075       avail = outavail (&buf);
 4076       chunk = (size < (off_t)avail ? (uint) size : avail);
 4077 
 4078       got=memread (buf, (int)chunk);
 4079       if (got==0) break;
 4080 
 4081       outalloc (got);
 4082       size-=got;
 4083     }
 4084 
 4085   memfree();
 4086 }
 4087 
 4088 /*
 4089  * outeof()
 4090  *
 4091  * Write an archive trailer.
 4092  */
 4093 STATIC void
 4094 outeof (name, namelen)
 4095      char *name;
 4096      reg uint namelen;
 4097 {
 4098   ulonglong pad;
 4099   auto char header[M_STRLEN + H_STRLEN + 1];
 4100 
 4101   if ((pad = (total + M_STRLEN + H_STRLEN + namelen) % arpad))
 4102     pad = arpad - pad;
 4103   VOID strcpy (header, M_ASCII);
 4104   VOID sprintf (header + M_STRLEN, H_PRINT, 0, 0,
 4105         0, 0, 0, 1, 0, ulo(0) , namelen, (long unsigned int)pad);
 4106   outwrite (header, M_STRLEN + H_STRLEN);
 4107   outwrite (name, namelen);
 4108   outpad ((off_t)pad);
 4109   outflush (DONE);
 4110   if (fflag)
 4111     outwait ();
 4112 }
 4113 
 4114 /*
 4115  * outflush()
 4116  *
 4117  * Flush the output buffer. Optionally fork()s to allow the
 4118  * parent to refill the buffer while the child waits for the
 4119  * write() to complete.
 4120  */
 4121 STATIC void
 4122 outflush (done)
 4123      int done;
 4124 {
 4125   /*
 4126    * in this case we are a floppy and want to write the floppy from one
 4127    * buffer (to have a copy of the data to verify against)
 4128    */
 4129   bufend = buffer + ((aruntil!=0) ? min ((ulonglong)buflen, arleft) : (ulonglong)buflen);
 4130   if (Fflag && (done == NOTDONE) && ((bufend - bufidx) > 0))
 4131     {
 4132       return;
 4133     }
 4134 
 4135   /*
 4136    * Otherwise open up the next volume once we've run out of space
 4137    */
 4138   if ( !Fflag && aruntil && arleft == 0)
 4139      next (O_WRONLY, "Output limit reached");
 4140 
 4141   /* writedisk will report errors, no need to check return code */
 4142   VOID writedisk (1);
 4143   bufend = (bufidx = buffer) + ((aruntil!=0) ? min ((ulonglong)buflen, arleft) : (ulonglong)buflen);
 4144 }
 4145 
 4146 /*
 4147  * outhead()
 4148  *
 4149  * Write an archive header.
 4150  */
 4151 STATIC void
 4152 outhead (name, asb)
 4153      reg char *name;
 4154      reg Stat *asb;
 4155 {
 4156   reg uint namelen;
 4157   auto char header[M_STRLEN + H_STRLEN + 1];
 4158 
 4159   if ((name[0] == '/') && !abspaths)
 4160     {
 4161       if (name[1])
 4162     ++name;
 4163       else
 4164     name = ".";
 4165     }
 4166   namelen = (uint) strlen (name) + 1;
 4167   VOID strcpy (header, M_ASCII);
 4168   VOID sprintf (header + M_STRLEN, H_PRINT, ush (asb->sb_dev),
 4169         ush (asb->sb_ino), ush (asb->sb_mode), ush (asb->sb_uid),
 4170         ush (asb->sb_gid), ush (asb->sb_nlink), ush (asb->sb_rdev),
 4171         ulo(mflag ? timenow : asb->sb_mtime), namelen, (long unsigned int) asb->sb_size);
 4172   outwrite (header, M_STRLEN + H_STRLEN);
 4173   outwrite (name, namelen);
 4174 #ifdef  S_IFLNK
 4175   if ((asb->sb_mode & S_IFMT) == S_IFLNK)
 4176     outwrite (asb->sb_link, (uint) asb->sb_size);
 4177 #endif /* S_IFLNK */
 4178 }
 4179 
 4180 /*
 4181  * outhead2()
 4182  *
 4183  * Write an archive header.
 4184  */
 4185 STATIC void
 4186 outhead2 (name, asb)
 4187      reg char *name;
 4188      reg Stat *asb;
 4189 {
 4190   reg uint namelen;
 4191   auto char header[M_STRLEN + H_STRLEN2 + 1];
 4192 
 4193   if ((name[0] == '/') && !abspaths)
 4194     {
 4195       if (name[1])
 4196     ++name;
 4197       else
 4198     name = ".";
 4199     }
 4200   namelen = (uint) strlen (name) + 1;
 4201   VOID strcpy (header, M_ASCII2);
 4202   VOID sprintf (header + M_STRLEN, H_PRINT2, ush (asb->sb_dev),
 4203             (long unsigned int)(asb->sb_ino), ush (asb->sb_mode), ush (asb->sb_uid),
 4204         ush (asb->sb_gid), ush (asb->sb_nlink), ush (asb->sb_rdev),
 4205         ulo(mflag ? timenow : asb->sb_mtime), namelen, (long unsigned int)(asb->sb_size));
 4206   outwrite (header, M_STRLEN + H_STRLEN2);
 4207   outwrite (name, namelen);
 4208 #ifdef  S_IFLNK
 4209   if ((asb->sb_mode & S_IFMT) == S_IFLNK)
 4210     outwrite (asb->sb_link, (uint) asb->sb_size);
 4211 #endif /* S_IFLNK */
 4212 }
 4213 
 4214 /*
 4215  * outhead3()
 4216  *
 4217  * Write a large ASCII archive header.
 4218  */
 4219 STATIC void
 4220 outhead3 (name, asb)
 4221      reg char *name;
 4222      reg Stat *asb;
 4223 {
 4224   reg uint namelen;
 4225   auto char header[M_STRLEN + H_STRLEN3 + 1];
 4226 
 4227   if ((name[0] == '/') && !abspaths)
 4228     {
 4229       if (name[1])
 4230     ++name;
 4231       else
 4232     name = ".";
 4233     }
 4234   namelen = (uint) strlen (name) + 1;
 4235   VOID strcpy (header, M_ASCII3);
 4236 
 4237   VOID sprintf (header + M_STRLEN, H_PRINT3, ulo (asb->sb_dev),
 4238         ull (asb->sb_ino), ulo (asb->sb_mode), ulo (asb->sb_uid),
 4239         ulo (asb->sb_gid), ulo (asb->sb_nlink), ulo (asb->sb_rdev),
 4240         mflag ? ull (timenow) : ull (asb->sb_mtime), namelen, 0, 0,
 4241         ull (asb->sb_size));
 4242   outwrite (header, M_STRLEN + H_STRLEN3);
 4243   outwrite (name, namelen);
 4244 #ifdef  S_IFLNK
 4245   if ((asb->sb_mode & S_IFMT) == S_IFLNK)
 4246     outwrite (asb->sb_link, (uint) asb->sb_size);
 4247 #endif /* S_IFLNK */
 4248 }
 4249 
 4250 
 4251 /*
 4252  * outpad()
 4253  *
 4254  * Pad the archive.
 4255  */
 4256 STATIC void
 4257 outpad (pad)
 4258      reg off_t pad;
 4259 {
 4260   reg int idx;
 4261   reg int len;
 4262 
 4263   while (pad)
 4264     {
 4265       if ((len = bufend - bufidx) > pad)
 4266     len = pad;
 4267       for (idx = 0; idx < len; ++idx)
 4268     *bufidx++ = '\0';
 4269       total += len;
 4270       outflush (NOTDONE);
 4271       pad -= len;
 4272     }
 4273 }
 4274 
 4275 /*
 4276  * outwait()
 4277  *
 4278  * Wait for the last background outflush() process (if any). The child
 4279  * exit value is zero if successful, 255 if a write() returned zero or
 4280  * the value of errno if a write() was unsuccessful.
 4281  */
 4282 STATIC void
 4283 outwait ()
 4284 {
 4285   auto int status;
 4286 
 4287   if (outpid == 0)
 4288     return;
 4289   status = xwait (outpid, "outwait()", TRUE);
 4290   outpid = 0;
 4291   if (status)
 4292     fatal (arspec, "Child error");
 4293 }
 4294 
 4295 /*
 4296  * outwrite()
 4297  *
 4298  * Write archive data.
 4299  */
 4300 STATIC void
 4301 outwrite (idx, len)
 4302      reg char *idx;
 4303      uint len;
 4304 {
 4305   reg uint have;
 4306   reg uint want;
 4307   reg char *endx = idx + len;
 4308 
 4309   while ((want = endx - idx))
 4310     {
 4311       while ((have = bufend - bufidx) == 0)
 4312     outflush (NOTDONE);
 4313       if (have > want)
 4314     have = want;
 4315       memcpy (bufidx, idx, have);
 4316       bufidx += have;
 4317       idx += have;
 4318       total += have;
 4319     }
 4320 }
 4321 
 4322 /*
 4323  * pass()
 4324  *
 4325  * Copy within the filesystem.
 4326  */
 4327 STATIC VOIDFN
 4328 pass (av)
 4329      reg char **av;
 4330 {
 4331   reg int fd;
 4332   reg char **avx;
 4333   auto Stat sb;
 4334   auto char name[PATHSIZE];
 4335 
 4336   for (avx = av; *avx; ++avx)
 4337     {
 4338       if (gflag && **avx != '/')
 4339     fatal (*avx, "Relative pathname");
 4340       if (STAT (*avx, &sb) < 0)
 4341     fatal (*avx, syserr ());
 4342       if ((sb.sb_mode & S_IFMT) != S_IFDIR)
 4343     fatal (*avx, "Not a directory");
 4344     }
 4345   while ((fd = openin (name, NULL, &sb, (int *) 0)) >= 0)
 4346     {
 4347       if (passitem (name, &sb, fd, av))
 4348     VOID close (fd);
 4349       if (vflag)
 4350     {
 4351       if (*uncompto)
 4352         VOID fprintf (stderr, "%s -- uncompressed\n", uncompto);
 4353       else
 4354         VOID fprintf (stderr, "%s -- okay\n", name);
 4355     }
 4356     }
 4357 }
 4358 
 4359 /*
 4360  * passdata()
 4361  *
 4362  * Copy data to one file. Doesn't believe in input file
 4363  * descriptor zero (see description of kludge in openin()
 4364  * comments). Closes the provided output file descriptor.
 4365  */
 4366 STATIC void
 4367 passdata (from, ifd, to, ofd)
 4368      char *from;
 4369      reg int ifd;
 4370      char *to;
 4371      reg int ofd;
 4372 {
 4373   reg ssize_t got;
 4374   reg ssize_t sparse;
 4375   auto char block[FSBUF];
 4376 
 4377   if (ifd)
 4378     {
 4379       VOID lseek (ifd, (off_t) 0, 0);
 4380       sparse = 0;
 4381       while ((got = read (ifd, block, sizeof (block))) > 0
 4382          && (sparse = fswrite (ofd, block, (uint) got)) >= 0)
 4383     total += got;
 4384       if (got)
 4385     VOID warn (got < 0 ? from : to, syserr ());
 4386       else if (sparse > 0
 4387            && (lseek (ofd, (off_t) - sparse, 1) < 0
 4388            || writeall (ofd, block, sparse) != sparse))
 4389     VOID warn (to, syserr ());
 4390     }
 4391   VOID close (ofd);
 4392 }
 4393 
 4394 /*
 4395  * passitem()
 4396  *
 4397  * Copy one file. Returns given input file descriptor.
 4398  */
 4399 STATIC int
 4400 passitem (from, asb, ifd, dir)
 4401      char *from;
 4402      Stat *asb;
 4403      reg int ifd;
 4404      reg char **dir;
 4405 {
 4406   reg int ofd;
 4407 
 4408 #ifdef linux_tstamp
 4409   auto struct utimbuf tstamp;
 4410 #else
 4411   auto time_t tstamp[2];
 4412 #endif
 4413   auto char to[PATHSIZE];
 4414 
 4415   while (*dir)
 4416     {
 4417       if (nameopt (strcat (strcat (strcpy (to, *dir++), "/"), from)) < 0)
 4418     continue;
 4419       if ((ofd = openotty (to, asb,
 4420         lflag ? linkto (from, asb) : linkfrom (asb,0), 1, Zflag)) < 0)
 4421     continue;
 4422       if (ofd > 0)
 4423     passdata (from, ifd, to, ofd);
 4424 #ifdef linux_tstamp
 4425       tstamp.actime = tstamp.modtime = mflag ? timenow : asb->sb_mtime;
 4426       VOID utime (to, &tstamp);
 4427 #else
 4428       tstamp[0] = tstamp[1] = mflag ? timenow : asb->sb_mtime;
 4429       VOID utime (to, tstamp);
 4430 #endif
 4431       /* safety */
 4432       if (uncompressrun)
 4433     {
 4434       VOID xwait (uncompressrun, "passitem xwait()", TRUE);
 4435       uncompressrun = 0;
 4436     }
 4437     }
 4438   return (ifd);
 4439 }
 4440 
 4441 STATIC VOIDFN
 4442 process_arname (template)
 4443 char *template;
 4444 {
 4445     int remain, len;
 4446     char *sptr, *dptr;
 4447 
 4448     sptr=template;
 4449     dptr=proc_arname;
 4450 
 4451     if(!sflagused)
 4452       {
 4453         strcpy(dptr,sptr);
 4454         return;
 4455       }
 4456 
 4457     remain = sizeof(proc_arname)-10;
 4458 
 4459     for (; remain>=0; sptr++) {
 4460         *dptr = '\0';
 4461         if (*sptr == '%') {
 4462             switch (*++sptr) {
 4463             case 'V':       /* volume number */
 4464               if (remain < 40) break;
 4465               len = sprintf(dptr,"%u", arvolume);
 4466               dptr += len;
 4467               remain -= len;
 4468               break;
 4469             case 'S':       /* volume size */
 4470               if (remain < 40) break;
 4471               len = sprintf(dptr,"%llu", (unsigned long long) aruntil);
 4472               dptr += len;
 4473               remain -= len;
 4474               break;
 4475             default:
 4476               *dptr++ = *sptr;
 4477               remain--;
 4478               break;
 4479             }
 4480         }
 4481         else {
 4482             *dptr++ = *sptr;
 4483             remain--;
 4484         }
 4485         if (*sptr == '\0') break;
 4486     }
 4487 
 4488 }
 4489 
 4490 /*
 4491  * pipechld()
 4492  *
 4493  * Child portion of pipeline fork.
 4494  */
 4495 STATIC int
 4496 pipechld (mode, pfd)
 4497      int mode;
 4498      reg int *pfd;
 4499 {
 4500   reg char **av;
 4501   auto char *arg[32];
 4502 
 4503   av = arg;
 4504   if ((*av = getenv ("SHELL")) && **av)
 4505     ++av;
 4506   else
 4507     *av++ = "/bin/sh";
 4508   *av++ = "-c";
 4509   process_arname(arname + 1);
 4510   *av++ = proc_arname;
 4511   *av = NULL;
 4512   if (mode)
 4513     {
 4514       VOID close (pfd[1]);
 4515       VOID close (STDIN);
 4516       VOID dup (pfd[0]);
 4517       VOID close (pfd[0]);
 4518       VOID close (STDOUT);
 4519       VOID open ("/dev/null", O_WRONLY);
 4520     }
 4521   else
 4522     {
 4523       VOID close (STDIN);
 4524       VOID open ("/dev/null", O_RDONLY);
 4525       VOID close (pfd[0]);
 4526       VOID close (STDOUT);
 4527       VOID dup (pfd[1]);
 4528       VOID close (pfd[1]);
 4529     }
 4530   if (ttyf >= 0)
 4531     VOID close (ttyf);
 4532   VOID execvp (arg[0], arg);
 4533   VOID warn (arg[0], syserr ());
 4534   _exit (1);
 4535   return 0; /* to avoid compiler warning */
 4536 }
 4537 
 4538 /*
 4539  * pipeopen()
 4540  *
 4541  * Open an archive via a pipeline. Returns a file
 4542  * descriptor, or -1 if unsuccessful.
 4543  */
 4544 STATIC int
 4545 pipeopen (mode)
 4546      reg int mode;
 4547 {
 4548   auto int pfd[2];
 4549 
 4550   if (pipe (pfd) < 0)
 4551     return (-1);
 4552   if ((pipepid = xfork ("pipeopen()", DIE)) == 0)
 4553     pipechld (mode, pfd);
 4554   if (mode)
 4555     {
 4556       VOID close (pfd[0]);
 4557       return (pfd[1]);
 4558     }
 4559   else
 4560     {
 4561       VOID close (pfd[1]);
 4562       return (pfd[0]);
 4563     }
 4564 }
 4565 
 4566 /*
 4567  * pipewait()
 4568  *
 4569  * Await a pipeline.
 4570  */
 4571 STATIC void
 4572 pipewait ()
 4573 {
 4574   reg int status;
 4575 
 4576   if (pipepid == 0)
 4577     return;
 4578   status = xwait (pipepid, "pipewait()", TRUE);
 4579   pipepid = 0;
 4580   if (status)
 4581     fatal (arspec, "Pipeline error");
 4582 }
 4583 
 4584 /*
 4585  * prsize()
 4586  *
 4587  * Print a file offset.
 4588  */
 4589 STATIC void
 4590 prsize (stream, size)
 4591      FILE *stream;
 4592      reg ulonglong size;
 4593 {
 4594   reg ulonglong n;
 4595 
 4596   if ((n = (size / (1024L * 1024L))))
 4597     {
 4598       VOID fprintf (stream, "%lum+", (unsigned long)n);
 4599       size -= n * 1024 * 1024;
 4600     }
 4601   if ((n = (size / 1024)))
 4602     {
 4603       VOID fprintf (stream, "%luk+", (unsigned long)n);
 4604       size -= n * 1024;
 4605     }
 4606   VOID fprintf (stream, "%lu", (unsigned long) size);
 4607 }
 4608 
 4609 #ifndef MKDIR
 4610 
 4611 /*
 4612  * rmdir()
 4613  *
 4614  * Remove a directory via "/bin/rmdir". Sets errno to a
 4615  * questionably sane value upon failure.
 4616  */
 4617 STATIC int
 4618 rmdir (name)
 4619      reg char *name;
 4620 {
 4621   reg int pid;
 4622 
 4623   if ((pid = xfork ("rmdir()", DIE)) == 0)
 4624     {
 4625       VOID close (fileno (stdin));
 4626       VOID close (fileno (stdout));
 4627       VOID close (fileno (stderr));
 4628       VOID open ("/dev/null", O_RDWR);
 4629       VOID dup (fileno (stdin));
 4630       VOID dup (fileno (stdin));
 4631       VOID execl ("/bin/rmdir", "rmdir", name, (char *) NULL);
 4632       exit (1);
 4633     }
 4634   if (xwait (pid, "rmdir()", TRUE) == 0)
 4635     return (0);
 4636   errno = EACCES;
 4637   return (-1);
 4638 }
 4639 
 4640 #endif /* MKDIR */
 4641 
 4642 /*
 4643  * fswrite()
 4644  *
 4645  * Write a filesystem block. Seeks past sparse blocks. Returns
 4646  * 0 if the block was written, the given length for a sparse
 4647  * block or -1 if unsuccessful.
 4648  */
 4649 STATIC ssize_t
 4650 fswrite (fd, buf, len)
 4651      int fd;
 4652      char *buf;
 4653      size_t len;
 4654 {
 4655   reg char *bidx;
 4656   reg char *bend;
 4657 
 4658   /*
 4659    * if -j (no sparse blocks) or compressrun (piping to uncompress utility)
 4660    * then do not bother looking for empty buffers, just write the data.
 4661    */
 4662   if (jflag || uncompressrun)
 4663     return (writeall (fd, buf, len) == (int)len ? 0 : -1);
 4664   bend = (bidx = buf) + len;
 4665   while (bidx < bend)
 4666     if (*bidx++)
 4667       return (writeall (fd, buf, len) == (int)len ? 0 : -1);
 4668   return (lseek (fd, (off_t) len, 1) < 0 ? -1 : (int)len);
 4669 }
 4670 
 4671 /*
 4672  * syserr()
 4673  *
 4674  * Return pointer to appropriate system error message.
 4675  */
 4676 STATIC char *
 4677 syserr ()
 4678 {
 4679   static char msg[40];
 4680 #if 0
 4681   /* older version */
 4682   if (errno > 0 && errno < sys_nerr)
 4683     return ((char *) sys_errlist[errno]);
 4684   VOID sprintf (msg, "Unknown error (errno %d)", errno);
 4685   return (msg);
 4686 #else
 4687   /* newer version, should be posix compliant and eliminate
 4688      some compiler warnings
 4689   */
 4690   char *pTmp = NULL;
 4691   if (! (pTmp = strerror(errno)))
 4692   {
 4693     VOID sprintf (msg, "Unknown error (errno %d)", errno);
 4694     pTmp = msg;
 4695   }
 4696   return (pTmp);
 4697 #endif
 4698 }
 4699 
 4700 /*
 4701  * toc()
 4702  *
 4703  * Print archive table of contents.
 4704  */
 4705 STATIC VOIDFN
 4706 toc (av)
 4707      reg char **av;
 4708 {
 4709   auto Stat sb;
 4710   auto char name[PATHSIZE];
 4711 
 4712   if (*av)
 4713     fatal (*av, "Extraneous argument");
 4714   name[0] = '\0';
 4715   while (inhead (name, &sb) == 0)
 4716     {
 4717     if (ISCONTROL(&sb))
 4718     {
 4719         /* list it */
 4720         if (namecmp (name,&sb) == 0)
 4721         tocentry (name, &sb);
 4722 
 4723         /* process control file */
 4724         if(inentry (name, &sb) < 0)
 4725         if (inskip (sb.sb_size) < 0)
 4726             VOID warn (name, "Skipped file data is corrupt");
 4727 
 4728         continue;
 4729     }
 4730 
 4731     if (namecmp (name,&sb) == 0)
 4732         tocentry (name, &sb);
 4733     if (inskip (sb.sb_size) < 0)
 4734         VOID warn (name, "File data is corrupt");
 4735     }
 4736 }
 4737 
 4738 /*
 4739  * tocentry()
 4740  *
 4741  * Print a single table-of-contents entry.
 4742  */
 4743 STATIC void
 4744 tocentry (name, asb)
 4745      char *name;
 4746      reg Stat *asb;
 4747 {
 4748   reg Time *atm;
 4749   reg Link *from;
 4750   reg Passwd *pwp;
 4751   reg Group *grp;
 4752   static char *month[] =
 4753   {
 4754     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 4755     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 4756   };
 4757   int res;
 4758   Link *linkp;
 4759   Link *linknext;
 4760 
 4761   if(printbytepos) printf("%.0f ",(double)bytepos);
 4762 
 4763   if (vflag)
 4764     {
 4765       tocmode (asb->sb_mode);
 4766       VOID printf (" %2d", (int)asb->sb_nlink);
 4767       atm = localtime (&asb->sb_mtime);
 4768       if ((pwp = getpwuid (asb->sb_uid)))
 4769     VOID printf (" %-8s", pwp->pw_name);
 4770       else
 4771     VOID printf (" %-8u", (unsigned int)(asb->sb_uid));
 4772       if ((grp = getgrgid (asb->sb_gid)))
 4773     VOID printf (" %-8s", grp->gr_name);
 4774       else
 4775     VOID printf (" %-8u", (unsigned int)(asb->sb_gid));
 4776       switch (asb->sb_mode & S_IFMT)
 4777     {
 4778     case S_IFBLK:
 4779     case S_IFCHR:
 4780         /* rdev==0 means that rdev is encoded in dev and ino,
 4781            see out().
 4782            */
 4783       if(asb->sb_rdev==0) asb->sb_rdev=(asb->sb_dev<<16) + asb->sb_ino;
 4784       VOID printf (" %3d, %3d",
 4785                (int)major (asb->sb_rdev), (int)minor (asb->sb_rdev));
 4786       break;
 4787     case S_IFREG:
 4788       VOID printf (" %8lld", (long long int)(asb->sb_size));
 4789         /* VOID printf (" %8ld", (long unsigned int)(asb->sb_size)); */
 4790       break;
 4791     default:
 4792       VOID printf ("         ");
 4793     }
 4794       VOID printf (" %3s %2d %02d:%02d:%02d %4d ",
 4795            month[atm->tm_mon], atm->tm_mday, atm->tm_hour,
 4796            atm->tm_min, atm->tm_sec, atm->tm_year + 1900);
 4797     }
 4798 
 4799   {
 4800     char *namedot = strrchr (name, '.');
 4801 
 4802     if (Zflag && (asb->sb_mode & S_IFMT) == S_IFREG
 4803     && (asb->sb_rdev & RDEV_NOTCOMPR) == 0
 4804     && (asb->sb_size > 0)
 4805     && namedot && namedot[1] == 'z' && !namedot[2])
 4806       *namedot = '\0';
 4807     else
 4808       namedot = 0;
 4809 
 4810     if (ISCONTROL(asb)) res = printf("//--");
 4811 
 4812     if ((!useoutmodetoc) && flag0)
 4813       res = printf ("%s%c", name, 0);
 4814     else
 4815       res = printf ("%s", name);
 4816 
 4817     /* to find out about broken pipe as early as possible */
 4818     if(res > 0) res = fflush(stdout);
 4819     /* check for broken pipe on stdout, this ends the listing */
 4820     if(res<0) {
 4821     if(errno == EPIPE)
 4822         fatal("<stdout>", syserr());
 4823     }
 4824 
 4825 
 4826     if (vflag && namedot)
 4827       VOID printf (" -- compressed");
 4828    }
 4829 
 4830   if (!flag0 && (vflag || lflag))
 4831     {
 4832       from=NULL;
 4833       if (asb->sb_nlink > 1)
 4834     {
 4835 
 4836       if(!useoutmodetoc)
 4837         {
 4838           if ((from = linkfrom (asb,1)))
 4839         VOID printf (" -> %s", from->l_path->p_name);
 4840           else
 4841         VOID linkto (name, asb);
 4842         }
 4843       else
 4844         {
 4845           /* need special logic to resolve hard link info
 4846          when in -o mode: because
 4847          of side effects of linkfrom and linkto, which were
 4848          already called for the file entry, we cannot use
 4849          them here again */
 4850           if((asb->sb_mode & S_IFMT) != S_IFDIR)
 4851         {
 4852           for (linkp = *(linkhash (asb->ino_orig)); linkp; linkp = linknext)
 4853             {
 4854               if (linkp->l_ino == asb->ino_orig
 4855               && linkp->l_dev == asb->sb_dev
 4856               && strcmp(linkp->l_path->p_name,name)
 4857               )
 4858             {
 4859               VOID printf (" -> %s", linkp->l_path->p_name);
 4860               break;
 4861             }
 4862 
 4863               linknext = linkp->l_forw;
 4864             }
 4865         }
 4866         }
 4867 
 4868     }
 4869 
 4870 #ifdef  S_IFLNK
 4871       if (((asb->sb_mode & S_IFMT) == S_IFLNK)&&(from==NULL))
 4872     VOID printf (" S-> %s", asb->sb_link);
 4873 #endif /* S_IFLNK */
 4874     }
 4875 
 4876   if ((!flag0)||useoutmodetoc)
 4877     putchar ('\n');
 4878 }
 4879 
 4880 /*
 4881  * tocmode()
 4882  *
 4883  * Fancy file mode display.
 4884  */
 4885 STATIC void
 4886 tocmode (mode)
 4887      reg mode_t mode;
 4888 {
 4889   switch (mode & S_IFMT)
 4890     {
 4891     case S_IFREG:
 4892       putchar ('-');
 4893       break;
 4894     case S_IFDIR:
 4895       putchar ('d');
 4896       break;
 4897 #ifdef  S_IFLNK
 4898     case S_IFLNK:
 4899       putchar ('l');
 4900       break;
 4901 #endif /* S_IFLNK */
 4902 #ifdef  S_IFSOCK
 4903     case S_IFSOCK:
 4904       putchar ('s');
 4905       break;
 4906 #endif /* S_IFSOCK */
 4907     case S_IFBLK:
 4908       putchar ('b');
 4909       break;
 4910     case S_IFCHR:
 4911       putchar ('c');
 4912       break;
 4913 #ifdef  S_IFIFO
 4914     case S_IFIFO:
 4915       putchar ('p');
 4916       break;
 4917 #endif /* S_IFIFO */
 4918     default:
 4919       VOID printf ("[%o]", (uint)(mode >> S_IFSHF));
 4920     }
 4921   putchar (mode & 0400 ? 'r' : '-');
 4922   putchar (mode & 0200 ? 'w' : '-');
 4923   putchar (mode & 0100
 4924        ? mode & 04000 ? 's' : 'x'
 4925        : mode & 04000 ? 'S' : '-');
 4926   putchar (mode & 0040 ? 'r' : '-');
 4927   putchar (mode & 0020 ? 'w' : '-');
 4928   putchar (mode & 0010
 4929        ? mode & 02000 ? 's' : 'x'
 4930        : mode & 02000 ? 'S' : '-');
 4931   putchar (mode & 0004 ? 'r' : '-');
 4932   putchar (mode & 0002 ? 'w' : '-');
 4933   putchar (mode & 0001
 4934        ? mode & 01000 ? 't' : 'x'
 4935        : mode & 01000 ? 'T' : '-');
 4936 }
 4937 
 4938 /*
 4939  * usage()
 4940  *
 4941  * Print a helpful message and exit.
 4942  */
 4943 STATIC void
 4944 usage ()
 4945 {
 4946   VOID fprintf (stderr, "\n\
 4947 Usage:  [filename generator] | %s -o [options] archive  : write archive\n\
 4948         %s -i [options] archive  : install archive\n\
 4949         %s -t [options] archive  : list table-of-contents of archive\n\
 4950         %s -r [options] archive  : verify archive against filesystem\n\
 4951 Frequently used options:\n\
 4952  General: -v : verbose\n\
 4953           -Z : with -o: gzip files when writing them to the archive,\n\
 4954                with -i/t/r: handle archive written with -Z option\n\
 4955           -5 : abort instead of creating archive incompatible with cpio\n\
 4956  Tape:    -s [volsize]   : size of volume, can have suffix k or m or g\n\
 4957           -b [blocksize] : block size (default is 5120)\n\
 4958           -c [count]     : buffer count blocks between doing I/O\n\
 4959  Install: -n : protect newer files  -k : skip corrupt data at beginning\n\
 4960  Select:  -y [pattern] : only process files matching pattern\n\
 4961           -Y [pattern] : do not process files matching pattern\n",
 4962         myname, myname, myname, myname);
 4963   VOID fprintf (stderr,"Version %s dated %s\n", VERSION, DATE);
 4964   exit (1);
 4965 }
 4966 
 4967 /*
 4968  * warn()
 4969  *
 4970  * Print a warning message. Always returns -1.
 4971  */
 4972 STATIC int
 4973 warn (what, why)
 4974      char *what;
 4975      char *why;
 4976 {
 4977   time_t dietime;
 4978   warnings++;
 4979   dietime = time ((time_t *) NULL);
 4980 
 4981   VOID fprintf (stderr,
 4982         "%s: \"%s\": %s\n",
 4983         myname, what, why);
 4984   /* ctime() provides the \n for the fprintf. */
 4985   if (logfile != (FILE *) 0)
 4986     VOID fprintf (logfile, "%s: \"%s\": %s (disk %u) at %s",
 4987           myname, what, why, arvolume, ctime (&dietime));
 4988   return (-1);
 4989 }
 4990 
 4991 STATIC int warn_nocount (what, why)
 4992      char *what;
 4993      char *why;
 4994 {
 4995  warnings--;
 4996  return warn(what,why);
 4997 }
 4998 
 4999 /*
 5000  * warnarch()
 5001  *
 5002  * Print an archive-related warning message, including
 5003  * an adjusted file offset. Always returns -1.
 5004  */
 5005 STATIC int
 5006 warnarch (msg, adjust)
 5007      char *msg;
 5008      off_t adjust;
 5009 {
 5010   warnings++;
 5011   VOID fprintf (stderr, "%s: \"%s\" [offset ", myname, arspec);
 5012   prsize (stderr, total - adjust);
 5013   VOID fprintf (stderr, "]: %s\n", msg);
 5014   return (-1);
 5015 }
 5016 
 5017 /*
 5018  * xfork()
 5019  *
 5020  * Create a child.
 5021  */
 5022 STATIC int
 5023 xfork (what, die)
 5024      reg char *what;
 5025      int die;
 5026 {
 5027   reg int pid;
 5028   reg Child *cp;
 5029   reg int idx;
 5030   static uint delay[] =
 5031   {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144};
 5032 
 5033   /* flush error logfile before fork */
 5034   if(logfile != (FILE *)0) fflush(logfile);
 5035   /* also flush stdout and stderr */
 5036   fflush(stdout);
 5037   fflush(stderr);
 5038 
 5039 
 5040 #ifdef SIGCHLD
 5041    VOID signal (SIGCHLD, SIG_DFL);  /* SysV mostly... */
 5042 #else
 5043    VOID signal (SIGCLD, SIG_DFL);  /* some SysV's... */
 5044 #endif
 5045   for (idx = 0; (pid = fork ()) < 0; ++idx)
 5046     {
 5047       if (idx == sizeof (delay))
 5048     {
 5049       if (die)
 5050         fatal (arspec, syserr ());
 5051       else
 5052         return (-1);
 5053     }
 5054 
 5055       VOID warn_nocount (what, "Trouble forking...");
 5056       if (Fflag && !die)    /* give up and go on... */
 5057     return (-1);
 5058       sleep (delay[idx]);
 5059     }
 5060   if (idx)
 5061     VOID warn_nocount (what, "...successful fork");
 5062   cp = (Child *) memget (sizeof (*cp));
 5063   cp->c_pid = pid;
 5064   cp->c_flags = 0;
 5065   cp->c_status = 0;
 5066   cp->c_forw = children;
 5067   children = cp;
 5068   return (pid);
 5069 }
 5070 
 5071 /*
 5072  * xpause()
 5073  *
 5074  * Await a child.
 5075  */
 5076 STATIC void
 5077 xpause ()
 5078 {
 5079   reg Child *cp;
 5080   reg int pid;
 5081   auto int status;
 5082 
 5083   do
 5084     {
 5085       while ((pid = wait (&status)) < 0)
 5086     ;
 5087       for (cp = children; cp && cp->c_pid != pid; cp = cp->c_forw)
 5088     ;
 5089     }
 5090   while (cp == NULL);
 5091   cp->c_flags |= CF_EXIT;
 5092   cp->c_status = status;
 5093 }
 5094 
 5095 /*
 5096  * xwait()
 5097  *
 5098  * Find the status of a child.
 5099  */
 5100 STATIC int
 5101 xwait (pid, what, compstat2)
 5102      reg int pid;
 5103      char *what;
 5104      int compstat2;
 5105 {
 5106   reg int status;
 5107   reg Child *cp;
 5108   reg Child **acp;
 5109   auto char why[100];
 5110 
 5111   for (acp = &children; (cp = *acp); acp = &cp->c_forw)
 5112     if (cp->c_pid == pid)
 5113       break;
 5114   if (cp == NULL)
 5115     fatal (what, "Lost child");
 5116   while ((cp->c_flags & CF_EXIT) == 0)
 5117     xpause ();
 5118   status = cp->c_status;
 5119   *acp = cp->c_forw;
 5120   free ((char *) cp);
 5121   if (status == 0)
 5122     return (0);
 5123   if (status & 0377)
 5124     VOID sprintf (why, "Killed by signal %d%s",
 5125           status & 0177, status & 0200 ? " -- core dumped" : "");
 5126   else
 5127     VOID sprintf (why, "Exit %d", (status >> 8) & 0377);
 5128 
 5129   if ((!compstat2 && (((status >> 8) & 0377) != 2)) || compstat2)
 5130     return (warn (what, why));
 5131   else
 5132     return ((status >> 8) & 0377);
 5133 }
 5134 
 5135 
 5136 /* right now we verify the whole disk */
 5137 void
 5138 verify (error)
 5139      int error;
 5140 {
 5141   char *verbuf;
 5142   char *buf;
 5143   reg time_t began;
 5144   int got, len;
 5145   uint readamt;
 5146   auto char msg[200];
 5147   auto char answer[20];
 5148 
 5149   if (*arname == '!')
 5150     {
 5151       VOID warn ("Can't verify a piped command", "");
 5152       return;
 5153     }
 5154   if (!error)
 5155     {
 5156       if ((verbuf = malloc (arbsize)) == NULL)
 5157     fatal (arspec, "Cannot allocate Verify I/O buffer");
 5158 
 5159       /*
 5160        * close as O_WRONLY and reopen as O_RDONLY to verify (on a
 5161        * disk this is a good thing)
 5162        */
 5163       /* fprintf(stderr,"closing..\n"); */
 5164 
 5165       nextclos ();
 5166       verifycnt++;
 5167 
 5168       if (nextopen (O_RDONLY) < 0)
 5169     {
 5170       VOID warn ("re-open for verify failed", "");
 5171       error = 1;
 5172     }
 5173       else
 5174     {
 5175 #ifdef linux
 5176           /* flush the floppy cache. (added by KH) */
 5177           if(Fflag)
 5178         {   /*   fprintf(stderr,"flushing..\n"); */
 5179               if (ioctl(arfd,FDFLUSH,NULL) < 0)
 5180                   warn(arname,"can't flush device cache.");
 5181 
 5182             }
 5183 #endif
 5184       fprintf (stderr, "Verifying disk %u...\n", arvolume );
 5185       for (buf = buffer; (len = bufidx - buf);)
 5186         {
 5187           readamt = min ((uint)len, arbsize);
 5188           if ((uint)(got = read (arfd, verbuf, readamt)) == readamt)
 5189         {
 5190 #ifdef HAVEMEMCMP
 5191           if (memcmp (verbuf, buf, (size_t)got) != 0)
 5192 #else
 5193           if (bcmp (verbuf, buf, got) != 0)
 5194 #endif
 5195             {
 5196               VOID warn ("Verify failed", "");
 5197               error = 1;
 5198               break;
 5199             }
 5200           else
 5201             buf += got;
 5202         }
 5203           else
 5204         {
 5205           VOID warn ("Read returned short", "");
 5206           fprintf (stderr, "Read %d wanted %d bytes\n", got,
 5207                readamt);
 5208           error = 1;
 5209           break;
 5210         }
 5211         }
 5212     }
 5213       free (verbuf);
 5214     }
 5215   if (error)
 5216     {
 5217       int answernum = 0;
 5218       nextclos ();
 5219 
 5220       for (;;)
 5221     {
 5222         began = time ((time_t *) NULL);
 5223         VOID sprintf (msg, "\
 5224 %s: %s of disk %u has FAILED!\07\n\
 5225 \tEnter 1 to RETRY this disk\n\
 5226 \tEnter 2 to REFORMAT this disk before a RETRY\n\07\n%s",
 5227               myname,
 5228               ((error && (verifycnt == 0)) ? "Writing" :
 5229                "Verify"),
 5230               arvolume, hidequit ? "" :
 5231               "\tEnter \"quit\" to ABORT the backup\n\07");
 5232         nextask (msg, answer, sizeof (answer));
 5233         timewait += time ((time_t *) NULL) - began;
 5234         answernum = atoi (answer);
 5235 
 5236       if (answernum == 1)   /* note: recursive here... */
 5237         {
 5238           /* if we can't open, try again */
 5239           if (nextopen (O_WRONLY) < 0)
 5240         continue;
 5241         }
 5242       else if ((answernum == 2) )
 5243       {
 5244           if (system (formatcmd) != 0)
 5245           {
 5246           fprintf (stderr, "Format failed!\n");
 5247           answernum = 0;/* error, don't autowrite */
 5248           }
 5249           else
 5250           {
 5251           fprintf (stderr, "Format successful!\n");
 5252           /* if we can't open, try again */
 5253           if (nextopen (O_WRONLY) < 0)
 5254               continue;
 5255           return;
 5256           }
 5257       }
 5258       else if (strcmp (answer, "quit") == 0)
 5259           fatal (arspec, "Quitting during a verify");
 5260     }
 5261     }
 5262 }
 5263 
 5264 
 5265 int
 5266 writedisk (realwrite)
 5267      int realwrite;
 5268 {
 5269   reg char *buf;
 5270   reg int got;
 5271   reg uint len;
 5272   int wrstat;
 5273 static int firsttime = 1;
 5274   /*
 5275    * If we're double buffering wait for any pending writes to
 5276    * complete before starting next writing
 5277    */
 5278 
 5279   if (fflag)
 5280       outwait ();
 5281 
 5282   /*
 5283    * if we are a floppy open the disk at the last moment
 5284    * call verify w/ an error if the disk can't be opened
 5285    */
 5286   if (Fflag)
 5287   {
 5288     /* There's something funny in the program in that writedisk() gets
 5289        called when there is nothing in the buffer to write; it
 5290        apparently gets called twice for each buffer when using the -s
 5291        double buffer option.  I can't figure out the complex and
 5292        undocumented definitions of bufidx and bufend well enough to
 5293        stop this double calling, but the only harm done by the second
 5294        call is if we call for another disk to be loaded.  So we make
 5295        sure we only call for a disk if there's actually data to write
 5296        on it (i.e. bufidx > buffer).  - Bryan Henderson 98.08.12
 5297        */
 5298       if( ! firsttime && bufidx > buffer )
 5299           next( O_WRONLY, "Next disk needed");
 5300        else
 5301           while( nextopen (O_WRONLY) < 0)
 5302       {
 5303           verifycnt = 0;
 5304           verify (1);
 5305       }
 5306       firsttime = 0;
 5307   }
 5308 
 5309   /*
 5310    * If we're double buffering spawn a child to do the
 5311    * actual writing, and return immediately
 5312    */
 5313 
 5314   if( fflag )
 5315   {
 5316       outpid = xfork ("outflush()", DIE);
 5317       if( outpid != 0 )
 5318       {
 5319       /* what does this do? It seems to be needed to let -s -f work */
 5320       arleft -= bufidx - buffer;
 5321 
 5322           nextclos(); /* added by KH to make verify work */
 5323 
 5324       return(0);
 5325       }
 5326       else
 5327       VOID nice (-10);
 5328   }
 5329 
 5330   do
 5331   {
 5332       wrstat = 0 ;
 5333 
 5334       for (buf = buffer; (len = bufidx - buf);)
 5335       {
 5336       if ((got = write (arfd, buf,
 5337                 *arname == '!' ? len : min (len, arbsize))) > 0)
 5338          {
 5339          buf += got;
 5340          if (realwrite)
 5341              arleft -= got;
 5342          }
 5343       else if (fflag)
 5344          {
 5345          VOID warn (arspec, got < 0
 5346                 ? syserr ()
 5347                 : "Apparently full -- archive will be incomplete");
 5348          _exit (1);
 5349          }
 5350       else if (got < 0)
 5351          {
 5352          if(errno==EPIPE)
 5353              fatal(arspec, syserr());
 5354 
 5355                  if(errno==ENOSPC) {    /* For DAT/DDS -- RAM, 1998/05/19 */
 5356                      next (O_WRONLY, "No space left on device");
 5357                      continue;          /* Redo failed write on new volume */
 5358                  }
 5359 
 5360          if(!Jflag)
 5361            VOID fatal (arspec, syserr ());
 5362          else
 5363            {
 5364                VOID warn (arspec, syserr ());
 5365                anycorrupt=1;
 5366            }
 5367                  wrstat = 1;
 5368                  break;
 5369          }
 5370       else
 5371          {
 5372          if (Fflag && verifyflag)
 5373                  {
 5374              /* can't recover from this one, break out of loop
 5375                         and let verify detect the mess */
 5376              VOID warn (arspec,
 5377                 "Apparently full already");
 5378              wrstat = 1;
 5379              break;
 5380          }
 5381 
 5382          next (O_WRONLY, "Apparently full");
 5383                  /* added continue, this creates correct behavior
 5384                     (no unwritten data) when changing to next volume on
 5385                     write()=0 -- KH */
 5386          continue;
 5387          }
 5388          }
 5389       if (Fflag && verifyflag)
 5390        {
 5391            verifycnt = 0;
 5392            verify ( wrstat );
 5393        }
 5394 
 5395       /* Added KH: bug fix for double prompting bug if no -K and -f given */
 5396       /* It took me far too long to find this.  IMO it was a big mistake to
 5397          use arleft, which usually denotes the space left in the buffer, to
 5398          denote the space left on the device in this routine.
 5399          Talking about spaghetti variables.  I'd rather not think about what
 5400          will happen if the write/verify error handling stuff gets used.
 5401       */
 5402       if (Fflag && !verifyflag) arleft = aruntil;
 5403 
 5404 
 5405   } while( wrstat && Fflag && verifyflag );
 5406 
 5407   if( fflag )
 5408     _exit( wrstat );
 5409   else
 5410     return ( wrstat );
 5411 
 5412   return 0; /* to avoid compiler warning */
 5413 }
 5414 
 5415 void
 5416 goodbye (status)
 5417      int status;
 5418 {
 5419   /* log that we died */
 5420   if (status && (logfile != (FILE *) 0))
 5421     {
 5422       time_t dietime;
 5423       dietime = time ((time_t *) NULL);
 5424 
 5425       VOID fprintf (logfile, "%s: the backup has failed (status %d), died at %s",
 5426             myname, status, ctime (&dietime));
 5427 
 5428     }
 5429   exit (status);
 5430 }
 5431 
 5432 #ifdef MYTEMPNAM
 5433 /* author:  Monty Walls
 5434  * written: 4/17/89
 5435  * Copyright:   Copyright (c) 1989 by Monty Walls.
 5436  *      Not derived from licensed software.
 5437  *
 5438  *      Permission to copy and/or distribute granted under the
 5439  *      following conditions:
 5440  *
 5441  *      1). This notice must remain intact.
 5442  *      2). The author is not responsible for the consequences of use
 5443  *          this software, no matter how awful, even if they
 5444  *          arise from defects in it.
 5445  *      3). Altered version must not be represented as being the
 5446  *          original software.
 5447  */
 5448 
 5449 #define MAXPREFIX   5
 5450 #define TMPNAME     "tmp"
 5451 #ifndef P_tmpdir
 5452 #define P_tmpdir    "/tmp"
 5453 #define L_tmpnam    14
 5454 #endif
 5455 
 5456 extern char *mktemp ();
 5457 extern char *strcat ();
 5458 extern char *strcpy ();
 5459 extern char *getenv ();
 5460 
 5461 char *
 5462 tempnam (dir, name)
 5463      char *dir;
 5464      char *name;
 5465 {
 5466   char *buf, *tmpdir;
 5467 
 5468   /*
 5469    * This is kind of like the chicken & the egg.
 5470    * Do we use the users preference or the programmers?
 5471    */
 5472 #ifdef USE_ENV_VAR
 5473   if ((tmpdir = getenv ("TMPDIR")) == (char *) NULL)
 5474     {
 5475       if ((tmpdir = dir) == (char *) NULL)
 5476     tmpdir = P_tmpdir;
 5477     }
 5478 #else
 5479   if ((tmpdir = dir) == (char *) NULL)
 5480     {
 5481       if ((tmpdir = getenv ("TMPDIR")) == (char *) NULL)
 5482     tmpdir = P_tmpdir;
 5483     }
 5484 #endif
 5485   /* now lets check and see if we can work there */
 5486   if (access (tmpdir, R_OK + W_OK + X_OK) < 0)
 5487     return ((char *) NULL);
 5488 
 5489   if (name == (char *) NULL)
 5490     name = TMPNAME;
 5491   else if (strlen (name) > MAXPREFIX)
 5492     name[5] = '\0';     /* this is according to SYS5 */
 5493 
 5494   /* the magic value 2 is for '\0' & '/' */
 5495   if ((buf = (char *) malloc (L_tmpnam + strlen (tmpdir) + 2)) == (char *) NULL)
 5496     return ((char *) NULL);
 5497 
 5498   strcpy (buf, tmpdir);
 5499   strcat (buf, "/");
 5500   strcat (buf, name);
 5501   strcat (buf, ".XXXXXX");
 5502 
 5503   /* pass our completed pattern to mktemp */
 5504   return (mktemp (buf));
 5505 }
 5506 
 5507 #endif /* MYTEMPNAM */