"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "afio.c" between
afio-2.5.1.tgz and afio-2.5.2.tgz

About: Afio is an archiver & backup program with builtin compression (generates cpio-format archives).

afio.c  (afio-2.5.1.tgz):afio.c  (afio-2.5.2.tgz)
skipping to change at line 22 skipping to change at line 22
* THE SUMMARY INFORMATION BELOW WAS WRITTEN FOR THE BENEFIT OF * THE SUMMARY INFORMATION BELOW WAS WRITTEN FOR THE BENEFIT OF
* SOFTWARE DISTRIBUTORS * SOFTWARE DISTRIBUTORS
* *
* Because of historical reasons, different parts of this software * Because of historical reasons, different parts of this software
* package are covered by different licenses. As of 2012, my (Koen * package are covered by different licenses. As of 2012, my (Koen
* Holtman's) intepretation of the license status is as follows. * Holtman's) intepretation of the license status is as follows.
* *
* - The main authors and maintainers all intend afio to be free and * - The main authors and maintainers all intend afio to be free and
* freely distributable. It has been distributed widely and for * freely distributable. It has been distributed widely and for
* free since at least 1987, when it was posted to the * free since at least 1987, when it was posted to the
* comp.sources.linux newsgroup. * comp.sources.unix newsgroup.
* *
* - The legal risks to re-distributers, coming from the licence, are * - The legal risks to re-distributers, coming from the licence, are
* effectively zero. * effectively zero.
* *
* - The afio license is not a standard OSI/FSF approved free software * - The afio license is not a standard OSI/FSF approved free software
* license, it predates these license texts. Unfortunately, the * license, it predates these license texts. Unfortunately, the
* afio license includes wording that is considered to be * afio license includes wording that is considered to be
* problematic by several of todays open source licensing legal * problematic by several of todays open source licensing legal
* experts, because the wording leaves too much room for * experts, because the wording leaves too much room for
* interpretation. It is impossible to upgrade this problematic * interpretation. It is impossible to upgrade this problematic
skipping to change at line 162 skipping to change at line 162
* Floppy Verify/format/restart output in the middle of a set, * Floppy Verify/format/restart output in the middle of a set,
* compress files on output, extended error messages and logging * compress files on output, extended error messages and logging
* *
* Added by Dave Gymer: * Added by Dave Gymer:
* Lotsa bugfixes, Linux support, recognition of .Z files in an archive * Lotsa bugfixes, Linux support, recognition of .Z files in an archive
* that were compressed already (and shouldn't be uncompressed). * that were compressed already (and shouldn't be uncompressed).
* Displays compression ratios. * Displays compression ratios.
* *
* See the HISTORY file for more revision info. */ * See the HISTORY file for more revision info. */
#ifdef LINT
static char *ident = "$Header: /u/buhrt/src/afio/RCS/afio.c,v 2.3 1991/09/25 20:
08:33 buhrt Exp $";
#endif
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#ifdef sun #ifdef sun
#include <sys/types.h> #include <sys/types.h>
#include <utime.h> #include <utime.h>
#include <signal.h> #include <signal.h>
#include <strings.h> #include <strings.h>
#include <sys/wait.h> #include <sys/wait.h>
#define linux_tstamp 1 #define linux_tstamp 1
skipping to change at line 277 skipping to change at line 273
STATIC short Jflag=0; /* Keep going after archive write error */ STATIC short Jflag=0; /* Keep going after archive write error */
STATIC short hidequit; /* show the quit option? */ STATIC short hidequit; /* show the quit option? */
STATIC short abspaths; /* allow absolute path names? */ STATIC short abspaths; /* allow absolute path names? */
STATIC uint arbsize = BLOCK; /* Archive block size */ STATIC uint arbsize = BLOCK; /* Archive block size */
STATIC short areof; /* End of input volume reached */ STATIC short areof; /* End of input volume reached */
STATIC int arfd = -1; /* Archive file descriptor */ STATIC int arfd = -1; /* Archive file descriptor */
STATIC ulonglong arleft; /* Space remaining within current volume */ STATIC ulonglong arleft; /* Space remaining within current volume */
STATIC char *arname; /* Expanded archive name */ STATIC char *arname; /* Expanded archive name */
STATIC uint arpad; /* Final archive block padding boundary * / STATIC uint arpad; /* Final archive block padding boundary * /
STATIC char arspec[PATHSIZE]; /* Specified archive name */ STATIC char arspec[PATHSIZE]; /* Specified archive name */
STATIC ulonglong aruntil; /* Volume size limit */ STATIC char proc_arname[PATHSIZE+10];/* %-processed archive name */
STATIC ulonglong aruntil=0; /* Volume size limit */
STATIC int sflagused=0; /* flag if -s flag was used */
STATIC int roundaruntil=1; /* Round aruntil to multiple of arbsize? */ STATIC int roundaruntil=1; /* Round aruntil to multiple of arbsize? */
STATIC ulonglong maxsizetocompress=200L*1024L*1024L; /* ==0, then no max */ STATIC ulonglong maxsizetocompress=200L*1024L*1024L; /* ==0, then no max */
STATIC int askfornext=0; /* Ask for next disk on input eof? */ STATIC int askfornext=0; /* Ask for next disk on input eof? */
STATIC uint arvolume = 1; /* Volume number */ STATIC uint arvolume = 1; /* Volume number */
STATIC off_t buflen; /* Archive buffer length */ STATIC off_t buflen; /* Archive buffer length */
STATIC char *buffer; /* Archive buffer */ STATIC char *buffer; /* Archive buffer */
STATIC char *bufidx; /* Archive buffer index */ STATIC char *bufidx; /* Archive buffer index */
STATIC char *bufend; /* End of data within archive buffer */ STATIC char *bufend; /* End of data within archive buffer */
STATIC Child *children; /* Child processes */ STATIC Child *children; /* Child processes */
STATIC char *formatcmd = DEFFMTCMD; /* how to format */ STATIC char *formatcmd = DEFFMTCMD; /* how to format */
skipping to change at line 320 skipping to change at line 318
ulonglong bytepos; /* position of first byte of current file */ ulonglong bytepos; /* position of first byte of current file */
STATIC char *controlscript=NULL; /* script to pipe control files to */ STATIC char *controlscript=NULL; /* script to pipe control files to */
STATIC char *promptscript=NULL; /* name of disk-change script */ STATIC char *promptscript=NULL; /* name of disk-change script */
STATIC ushort extfmt = 0; /* Use extended ASCII format */ STATIC ushort extfmt = 0; /* Use extended ASCII format */
STATIC ushort cpiocompat = 0; /* Never use large ASCII format headers */ STATIC ushort cpiocompat = 0; /* Never use large ASCII format headers */
STATIC ushort cpiowarned = 0; /* warning given? */ STATIC ushort cpiowarned = 0; /* warning given? */
STATIC char *email=NULL; /* email address to notify of volume change requests */ STATIC char *email=NULL; /* email address to notify of volume change requests */
STATIC int rewindfd = -1; /* file descriptor to rewind before STATIC int rewindfd = -1; /* file descriptor to rewind before
(un)compress invocations */ (un)compress invocations */
STATIC char *ignorewarnings="mc"; /* data for -1 option */ STATIC char *ignorewarnings="mc"; /* data for -1 option */
STATIC char *aruntil_string; /* -s option string given by user */ STATIC char *aruntil_string=NULL; /* -s option string given by user */
STATIC int extcasesens=0; /* Case sensitive matching in -E option? */ STATIC int extcasesens=0; /* Case sensitive matching in -E option? */
STATIC Dir *DirP=NULL; /* list of directories with their saved timestamps * / STATIC Dir *DirP=NULL; /* list of directories with their saved timestamps * /
STATIC char firstfilename[PATHSIZE]=""; /* for temp storage during -o */ STATIC char firstfilename[PATHSIZE]=""; /* for temp storage during -o */
STATIC int useoutmodetoc=0; /* used in tocentry() */ STATIC int useoutmodetoc=0; /* used in tocentry() */
STATIC short noglob=0; /* disable globbing */ STATIC short noglob=0; /* disable globbing */
STATIC int allowinsecurepaths=0;
STATIC int allowinsecuresymlinks=0;
STATIC int nosymlinks=0;
int main (int ac, char **av) int main (int ac, char **av)
{ {
reg int c; reg int c;
reg uint group = 1; reg uint group = 1;
VOIDFN (*fn)(char **) = NULL; VOIDFN (*fn)(char **) = NULL;
time_t timedone; time_t timedone;
auto char remote[PATHSIZE]; auto char remote[PATHSIZE];
char *exitmsg; char *exitmsg;
int status; int status;
skipping to change at line 360 skipping to change at line 361
if (uid == 0) if (uid == 0)
xflag = 1; xflag = 1;
/* ignore SIGPIPE to deal with gzip -d exiting prematurely */ /* ignore SIGPIPE to deal with gzip -d exiting prematurely */
VOID signal (SIGPIPE, SIG_IGN); VOID signal (SIGPIPE, SIG_IGN);
/* All letters have been used as options, now eating into the numbers.... /* All letters have been used as options, now eating into the numbers....
*/ */
while ((c = options (ac, av, while ((c = options (ac, av,
"aioprtIOVCb:c:de:fghjklmns:uvxXy:Y:zFKZL:R:qAE:G:M:w:W:T:SBD:P:Q:U4JH: 0@:N:3:1:92:56:7")) "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:"))
) )
{ {
switch (c) switch (c)
{ {
case 'r': case 'r':
if (fn) if (fn)
usage (); usage ();
fn = readcheck; fn = readcheck;
allowinsecurepaths=allowinsecuresymlinks=1;
break; break;
case 'i': case 'i':
if (fn) if (fn)
usage (); usage ();
fn = in; fn = in;
break; break;
case 'o': case 'o':
if (fn) if (fn)
usage (); usage ();
fn = out; fn = out;
skipping to change at line 390 skipping to change at line 392
break; break;
case 'p': case 'p':
if (fn) if (fn)
usage (); usage ();
fn = pass; fn = pass;
break; break;
case 't': case 't':
if (fn) if (fn)
usage (); usage ();
fn = toc; fn = toc;
allowinsecurepaths=allowinsecuresymlinks=1;
break; break;
case 'I': case 'I':
if (fn) if (fn)
usage (); usage ();
fn = copyin; fn = copyin;
break; break;
case 'O': case 'O':
if (fn) if (fn)
usage (); usage ();
fn = copyout; fn = copyout;
skipping to change at line 455 skipping to change at line 458
case 'l': case 'l':
++lflag; ++lflag;
break; break;
case 'm': case 'm':
++mflag; ++mflag;
break; break;
case 'n': case 'n':
++nflag; ++nflag;
break; break;
case 's': case 's':
sflagused = 1;
/* Do a 'dry run' to check all values for syntax errors */ /* Do a 'dry run' to check all values for syntax errors */
aruntil_string = strdup(optarg); aruntil_string = strdup(optarg);
while(aruntil_string) update_aruntil(); while(aruntil_string) update_aruntil();
/* Now the real initialisation */ /* Now the real initialisation */
aruntil_string = optarg; aruntil_string = optarg;
update_aruntil(); update_aruntil();
if (aruntil == 0) askfornext = 1; if (aruntil == 0) askfornext = 1;
break; break;
case 'F': case 'F':
++Fflag; ++Fflag;
skipping to change at line 615 skipping to change at line 619
break; break;
case '9': case '9':
roundaruntil=0; roundaruntil=0;
break; break;
case '2': case '2':
maxsizetocompress=optsize(optarg); maxsizetocompress=optsize(optarg);
break; break;
case '7': case '7':
noglob = 1-noglob; noglob = 1-noglob;
break; break;
case '8':
if (strcmp(optarg, "allowinsecurepaths") == 0) allowinsecurepaths=1;
else if(strcmp(optarg, "allowinsecuresymlinks") == 0) allowinsecuresymli
nks=1;
else if (strcmp(optarg, "nosymlinks") == 0) nosymlinks=1;
else fatal (optarg, "unknown value for -8 option");
break;
default: default:
usage (); usage ();
} }
} }
if (fn == NULL || av[optind] == NULL) if (fn == NULL || av[optind] == NULL)
usage (); usage ();
if (extfmt && cpiocompat) if (extfmt && cpiocompat)
{ {
skipping to change at line 644 skipping to change at line 654
if(compressprog && (rewindfd==-1)) if(compressprog && (rewindfd==-1))
if(strstr(compressprog,"pgp") || strstr(compressprog,"gpg")) if(strstr(compressprog,"pgp") || strstr(compressprog,"gpg"))
{ {
fatal(compressprog,"Must use -3 flag if -P program matches 'pgp' or 'gp g', see the afio manual page."); fatal(compressprog,"Must use -3 flag if -P program matches 'pgp' or 'gp g', see the afio manual page.");
} }
if(!compressprog) compressprog = PRG_COMPRESS; if(!compressprog) compressprog = PRG_COMPRESS;
compress_arg_list[0] = compressprog; compress_arg_list[0] = compressprog;
if(maxmem/1024L/1024L > (1024+512))
{
/* afio uses uints and ints and size_t at several places that
may make it (on architectures with 32 bit ints and size_t)
fail to do the right calculations when the buffer size is
>2GB. This 1.5 GB limit is somewhat conservative, but better
safe than sorry.
If you have an os/compile environment witrh 64 bit size_t
and int, things might be OK if you disable this test, but
I have not tested it.
If you disable here see also the code in memwrite().
*/
fatal (arspec, "In-memory compression buffer size above 1.5GB not supporte
d");
}
if (Fflag) if (Fflag)
{ {
if ((buflen = (off_t) aruntil) == 0) if ((buflen = (off_t) aruntil) == 0)
usage (); usage ();
} }
else else
buflen = arbsize * group; buflen = (off_t)arbsize * (off_t)group;
if( roundaruntil ) if( roundaruntil )
{ {
/* round aruntil down to a multiple of arbsize: some devices /* round aruntil down to a multiple of arbsize: some devices
(like ftape) puke on a smaller-than-blocksize last write to (like ftape) puke on a smaller-than-blocksize last write to
the volume */ the volume */
aruntil = ( aruntil / (ulonglong) arbsize ); aruntil = ( aruntil / (ulonglong) arbsize );
aruntil = aruntil * arbsize; aruntil = aruntil * arbsize;
} }
skipping to change at line 714 skipping to change at line 740
*--host = '@'; *--host = '@';
if (equal) if (equal)
*--equal = '='; *--equal = '=';
if (perc) if (perc)
*--perc = '%'; *--perc = '%';
*--colon = ':'; *--colon = ':';
} }
if (gflag && *arname != '/' && *arname != '!') if (gflag && *arname != '/' && *arname != '!')
fatal (arspec, "Relative pathname"); fatal (arspec, "Relative pathname");
VOID signal (SIGINT, goodbye); VOID signal (SIGINT, goodbye);
if(buflen/1024L/1024L > (1024+512))
{
/* afio uses uints and ints at several places that make it
(on architectures with 32 bit ints and size_t) fail to do
the right calculations when the buffer size is >2GB.
This 1.5GB limit is somewhat conservative, but better
safe than sorry.
If you have an os/compile environment witrh 64 bit size_t
and int, things might be OK if you disable this test, but
I have not tested it.
*/
fatal (arspec, "In-memory I/O buffer size above 1.5GB not supported");
}
/* /*
* +BLOCK is added to make sure we don't overrun buffer on a * +BLOCK is added to make sure we don't overrun buffer on a
* read (internal read(1) length is thus met) * read (internal read(1) length is thus met)
*/ */
if ((buffer = bufidx = bufend = malloc ((size_t)buflen + BLOCK)) == NULL) if ((buffer = bufidx = bufend = malloc ((size_t)buflen + BLOCK)) == NULL)
fatal (arspec, "Cannot allocate enough memory for I/O buffer"); fatal (arspec, "Cannot allocate enough memory for I/O buffer");
/* if in -o mode, do a sanity check on the input now. This /* if in -o mode, do a sanity check on the input now. This
should prevent deletion of the archive file contents in most should prevent deletion of the archive file contents in most
skipping to change at line 890 skipping to change at line 932
} }
/* /*
* copyin() * copyin()
* *
* Copy directly from the archive to the standard output. * Copy directly from the archive to the standard output.
*/ */
STATIC VOIDFN STATIC VOIDFN
copyin (char **av) copyin (char **av)
{ {
reg int got; reg ssize_t got;
reg uint have; reg ssize_t have;
if (*av) if (*av)
fatal (*av, "Extraneous argument"); fatal (*av, "Extraneous argument");
while (!areof || askfornext) while (!areof || askfornext)
{ {
VOID infill (); VOID infill ();
while ((have = bufend - bufidx)) while ((have = bufend - bufidx))
if ((got = writeall (STDOUT, bufidx, have)) < 0) if ((got = writeall (STDOUT, bufidx, have)) < 0)
fatal ("<stdout>", syserr ()); fatal ("<stdout>", syserr ());
else else
skipping to change at line 1040 skipping to change at line 1082
/* print position in archive if some data was transferred */ /* print position in archive if some data was transferred */
if(total>0) if(total>0)
VOID warnarch ("Fatal error:",(off_t)0); VOID warnarch ("Fatal error:",(off_t)0);
VOID warn (what, why); VOID warn (what, why);
goodbye (1); goodbye (1);
} }
/* /*
* writeall() * writeall()
* *
* Write all bytes in buf or return -1. Used to fix invalud assumptions * Write all bytes in buf or return -1. Used to fix invalid assumptions
* about write() elsewhere. * about write() elsewhere.
*/ */
STATIC STATIC
int writeall(int fd, const char *buf, unsigned int count) ssize_t writeall(int fd, const char *buf, size_t count)
{ {
ssize_t put; ssize_t put;
unsigned int totalput; size_t totalput;
totalput=0; totalput=0;
while(totalput<count) while(totalput<count)
{ {
put=write(fd,buf+totalput,count-totalput); put=write(fd,buf+totalput,count-totalput);
if(put<0) return put; if(put<0) return put;
totalput+=put; totalput+=put;
} }
return count; return count;
} }
/* /*
* readall() * readall()
* *
* Read, completely filling buf if we can, or return short size or -1. * Read, completely filling buf if we can, or return short size or -1.
* Used to fix invalud assumptions * Used to fix invalid assumptions
* about read() elsewhere. * about read() elsewhere.
*/ */
STATIC STATIC
int readall(int fd, char *buf, unsigned int count) ssize_t readall(int fd, char *buf, size_t count)
{ {
ssize_t got; ssize_t got;
unsigned int totalgot; size_t totalgot;
totalgot=0; totalgot=0;
while(totalgot<count) while(totalgot<count)
{ {
got=read(fd,buf+totalgot,count-totalgot); got=read(fd,buf+totalgot,count-totalgot);
/* if(got!=count) printf("got on %d = %d\n",fd,got); */ /* if(got!=count) printf("got on %d = %d\n",fd,got); */
if(got<=0) if(got<=0)
{ {
if(got==0) return totalgot; if(got==0) return totalgot;
if(got<0) return got; if(got<0) return got;
skipping to change at line 1118 skipping to change at line 1160
* savedirstamp() * savedirstamp()
* *
* Remember necessary timestamps for a directory, * Remember necessary timestamps for a directory,
* so they can be restored afterwards. * so they can be restored afterwards.
*/ */
STATIC void STATIC void
savedirstamp (char *name, time_t mtime) savedirstamp (char *name, time_t mtime)
{ {
Dir *dirp; Dir *dirp;
if( (dirp=(Dir *)memget(sizeof(Dir))) != NULL && (dirp->d_name=memstr(name)) ! /* Note that the cast below is necessary since memget() is pre-C89. */
= NULL ) if((dirp=(Dir *)memget(sizeof(Dir))) != NULL) {
{ if ((dirp->d_name=memstr(name)) == NULL) {
dirp->d_mtime=mtime; free(dirp);
dirp->d_forw=DirP; } else {
DirP=dirp; dirp->d_mtime=mtime;
dirp->d_forw=DirP;
DirP=dirp;
}
} }
} }
/* /*
* restoredirstamps() * restoredirstamps()
* *
* Restore timestamps for the saved list of directories. * Restore timestamps for the saved list of directories.
*/ */
STATIC void STATIC void
restoredirstamps (void) restoredirstamps (void)
{ {
#ifdef linux_tstamp #ifdef linux_tstamp
auto struct utimbuf tstamp; auto struct utimbuf tstamp;
#else #else
auto time_t tstamp[2]; auto time_t tstamp[2];
#endif #endif
Dir *DirP_curr = DirP; /* keep DirP reachable */
Dir *DirP_forw; Dir *DirP_forw;
while(DirP!=NULL) while(DirP_curr!=NULL)
{ {
#ifdef linux_tstamp #ifdef linux_tstamp
tstamp.actime = DirP->d_mtime; tstamp.actime = DirP_curr->d_mtime;
tstamp.modtime = DirP->d_mtime; tstamp.modtime = DirP_curr->d_mtime;
/* no error code checking on purpose */ /* no error code checking on purpose */
VOID utime (DirP->d_name, &tstamp); VOID utime (DirP_curr->d_name, &tstamp);
#else #else
tstamp[0] = DirP->d_mtime; tstamp[0] = DirP_curr->d_mtime;
tstamp[1] = DirP->d_mtime; tstamp[1] = DirP_curr->d_mtime;
/* no error code checking on purpose */ /* no error code checking on purpose */
VOID utime (DirP->d_name, tstamp); VOID utime (DirP_curr->d_name, tstamp);
#endif #endif
/* We don't call free because we are about to exit anyway. /* We don't call free because we are about to exit anyway.
Not calling free should make things a bit more robust if the Not calling free should make things a bit more robust if the
memory pool is corrupted due to a bug */ memory pool is corrupted due to a bug */
/* free(DirP->d_name); */ /* free(DirP_curr->d_name); */
DirP_forw=DirP->d_forw; DirP_forw=DirP_curr->d_forw;
/* free(DirP); */ /* free(DirP_curr); */
DirP=DirP_forw; DirP_curr=DirP_forw;
} }
} }
/* /*
* in() * in()
* *
* Read an archive. * Read an archive.
*/ */
STATIC VOIDFN STATIC VOIDFN
in (av) in (av)
skipping to change at line 1508 skipping to change at line 1555
* indata() * indata()
* *
* Install data from an archive. Returns given file descriptor. * Install data from an archive. Returns given file descriptor.
*/ */
STATIC int STATIC int
indata (fd, size, name) indata (fd, size, name)
int fd; int fd;
reg off_t size; reg off_t size;
char *name; char *name;
{ {
reg uint chunk; reg size_t chunk;
reg char *oops; reg char *oops;
reg int sparse; reg ssize_t sparse;
reg int corrupt; reg int corrupt;
auto char *buf; auto char *buf;
auto uint avail; auto uint avail;
corrupt = sparse = 0; corrupt = sparse = 0;
oops = NULL; oops = NULL;
while (size) while (size)
{ {
corrupt |= inavail (&buf, &avail); corrupt |= inavail (&buf, &avail);
size -= (chunk = size < (off_t)avail ? (uint) size : avail); size -= (chunk = size < (off_t)avail ? (uint) size : avail);
skipping to change at line 1546 skipping to change at line 1593
/* /*
* incheckdata() * incheckdata()
* *
* Check data from an archive. Returns given file descriptor. * Check data from an archive. Returns given file descriptor.
*/ */
STATIC int STATIC int
incheckdata (int fd, off_t size, char *name, Stat *asb, int comp) incheckdata (int fd, off_t size, char *name, Stat *asb, int comp)
{ {
reg uint chunk; reg uint chunk;
reg char *oops; reg char *oops;
reg int sparse;
reg int corrupt, warned = 0; reg int corrupt, warned = 0;
auto char *buf; auto char *buf;
auto uint avail; auto uint avail;
auto int pfd[2], pfdc[2]; auto int pfd[2], pfdc[2];
auto int pid, comppid; auto int pid, comppid;
corrupt = sparse = 0; corrupt = 0;
oops = NULL; oops = NULL;
if (comp) { if (comp) {
/* if compressed, we process data with the following setup: /* if compressed, we process data with the following setup:
- child 1 is the comparator - child 1 is the comparator
- child 2 is the gunzip (gzip -c -d) - child 2 is the gunzip (gzip -c -d)
- the main process reads data from the archive and writes it - the main process reads data from the archive and writes it
to child 2 to be uncompressed to child 2 to be uncompressed
- child 2 writes the uncompressed data to child 1 - child 2 writes the uncompressed data to child 1
- child 1 reads from the file in the filesystem and from child 2, - child 1 reads from the file in the filesystem and from child 2,
compares, and exits nonzero if is a discrepancy. compares, and exits nonzero if is a discrepancy.
skipping to change at line 1653 skipping to change at line 1699
default: default:
/* main process continue ======================== */ /* main process continue ======================== */
close(pfd[0]); close(pfd[0]);
uncompressrun = pid; uncompressrun = pid;
while (asb->sb_size) { while (asb->sb_size) {
corrupt |= inavail (&buf, &avail); corrupt |= inavail (&buf, &avail);
if (corrupt) { if (corrupt) {
break; break;
} }
asb->sb_size -= (chunk = asb->sb_size < (off_t)avail ? (uint) asb->sb_siz e : avail); asb->sb_size -= (chunk = asb->sb_size < (off_t)avail ? (uint) asb->sb_siz e : avail);
if ((sparse = write (pfd[1], buf, chunk)) < 0) if (writeall (pfd[1], buf, chunk) < 0)
oops = syserr(); oops = syserr();
inalloc(chunk); inalloc(chunk);
} }
close(pfd[1]); close(pfd[1]);
corrupt |= (xwait (pid, "incheckentry xwait()", FALSE) != 0); corrupt |= (xwait (pid, "incheckentry xwait()", FALSE) != 0);
break; break;
} }
} }
else { /* not compressed */ else { /* not compressed */
char buff1[40960]; char buff1[40960];
skipping to change at line 1699 skipping to change at line 1745
} }
} }
/* See if the file is _longer_ then our backup. */ /* See if the file is _longer_ then our backup. */
if (read(fd, buff1, 1) > 0) if (read(fd, buff1, 1) > 0)
{ {
VOID warn_nocount (name, "File in archive is shorter than file on filesys tem"); VOID warn_nocount (name, "File in archive is shorter than file on filesys tem");
corrupt = 1; corrupt = 1;
} }
} }
close(fd); close(fd);
if (oops)
VOID warn (name, oops);
if (corrupt) { if (corrupt) {
/* /*
file : Stat atime_sb file : Stat atime_sb
archive : Stat *asb archive : Stat *asb
*/ */
if ( (atime_sb.sb_mtime==asb->sb_mtime) && if ( (atime_sb.sb_mtime==asb->sb_mtime) &&
(atime_sb.sb_size==asb->sb_size)) (atime_sb.sb_size==asb->sb_size))
{ {
/* file has same mod time and length --> should have verified OK, /* file has same mod time and length --> should have verified OK,
so this is very probably a real error in the backup medium. so this is very probably a real error in the backup medium.
skipping to change at line 1916 skipping to change at line 1964
{ {
failed = 0; failed = 0;
for (got = 0; (uint)got < arbsize; ++got) for (got = 0; (uint)got < arbsize; ++got)
*bufend++ = '\0'; *bufend++ = '\0';
return (-1); return (-1);
} }
return (0); return (0);
} }
/* /*
* fixinsecure()
*
* Rewrite .. subpath components in path names into XX,
* making them more secure for restoring. For more info see the -8 option
* in the manpage.
*/
STATIC int
fixinsecure (name)
char *name;
{
int changed=0;
int l=strlen(name);
int i;
if(strcmp("..",name)==0)
{
changed=1;
name[0]=name[1]='X';
}
if(strncmp("../",name,3)==0)
{
changed=1;
name[0]=name[1]='X';
}
for(i=0; i<l-3; i++)
{
if(name[i]=='/')
{
if(strncmp("/../",name+i,4)==0)
{
changed=1;
name[i+1]=name[i+2]='X';
}
}
}
if(l>=3) if(strncmp("/..",name+l-3,3)==0)
{
changed=1;
name[l-2]=name[l-1]='X';
}
return changed;
}
/*
* inhead() * inhead()
* *
* Read a header. Quietly translates old-fashioned binary cpio headers * Read a header. Quietly translates old-fashioned binary cpio headers
* (and arranges to skip the possible alignment byte). Returns zero if * (and arranges to skip the possible alignment byte). Returns zero if
* successful, -1 upon archive trailer. * successful, -1 upon archive trailer.
*/ */
STATIC int STATIC int
inhead (name, asb) inhead (name, asb)
reg char *name; reg char *name;
reg Stat *asb; reg Stat *asb;
{ {
reg off_t skipped; reg off_t skipped;
auto char magic[M_STRLEN]; auto char magic[M_STRLEN];
static int align; static int align;
char *name2;
int rewritten;
#if FDDEBUG #if FDDEBUG
/* debug code added by KH. Are we leaking file descriptors? */ /* debug code added by KH. Are we leaking file descriptors? */
{ int i; i=dup(0); close(i); fprintf(stderr,"%d",i); } { int i; i=dup(0); close(i); fprintf(stderr,"%d",i); }
#endif #endif
if (align > 0) if (align > 0)
VOID inskip ((off_t) align); VOID inskip ((off_t) align);
align = 0; align = 0;
skipping to change at line 1985 skipping to change at line 2081
} }
if (strcmp (name, TRAILER) == 0) if (strcmp (name, TRAILER) == 0)
return (-1); return (-1);
if (nameopt (name) >= 0) if (nameopt (name) >= 0)
break; break;
VOID inskip (asb->sb_size + align); VOID inskip (asb->sb_size + align);
} }
#ifdef S_IFLNK #ifdef S_IFLNK
if ((asb->sb_mode & S_IFMT) == S_IFLNK) if ((asb->sb_mode & S_IFMT) == S_IFLNK)
{ {
/* buffer overflow protection */
if((uint) asb->sb_size > sizeof(asb->sb_link)-1)
{
VOID warn (name, "Corrupt symbolic link");
return (inhead (name, asb));
}
if (inread (asb->sb_link, (uint) asb->sb_size) < 0) if (inread (asb->sb_link, (uint) asb->sb_size) < 0)
{ {
VOID warn (name, "Corrupt symbolic link"); VOID warn (name, "Corrupt symbolic link");
return (inhead (name, asb)); return (inhead (name, asb));
} }
asb->sb_link[asb->sb_size] = '\0'; asb->sb_link[asb->sb_size] = '\0';
asb->sb_size = 0; asb->sb_size = 0;
rewritten=0;
if(!allowinsecuresymlinks)
{
if(asb->sb_link[0]=='/')
{
asb->sb_link[0]='X';
rewritten=1;
}
if(fixinsecure (asb->sb_link)) rewritten=1;
if(rewritten)
{
VOID warn_nocount (name,"potentially insecure symlink destination p
ath, rewriting:");;
VOID warn(asb->sb_link,"is the rewritten destination value used");
if(index(ignorewarnings,(int)'s')) warnings--;
}
}
} }
#endif /* S_IFLNK */ #endif /* S_IFLNK */
if ((name[0] == '/') && !abspaths) if ((name[0] == '/') && !abspaths)
{ {
/* if there was more than 1 leading /, nameopt() has already
removed all leading / but one */
if (name[1]) if (name[1])
{ {
while ((name[0] = name[1])) name2=name;
++name; while ((name2[0] = name2[1])) ++name2;
} }
else else
{ {
name[0] = '.'; name[0] = '.';
} }
} }
if(!allowinsecurepaths)
{
if(fixinsecure(name))
{
VOID warn (name,"potentially insecure destination path rewritten");
if(index(ignorewarnings,(int)'s')) warnings--;
}
}
asb->sb_atime = asb->sb_ctime = asb->sb_mtime; asb->sb_atime = asb->sb_ctime = asb->sb_mtime;
return (0); return (0);
} }
/* /*
* inread() * inread()
* *
* Read a given number of characters from the input archive. Returns * Read a given number of characters from the input archive. Returns
* zero with valid data, -1 if unreadable portions were replaced by * zero with valid data, -1 if unreadable portions were replaced by
skipping to change at line 2438 skipping to change at line 2567
return (0); return (0);
errno = EACCES; errno = EACCES;
return (-1); return (-1);
} }
#endif /* MKDIR */ #endif /* MKDIR */
/* /*
* nameopt() * nameopt()
* *
* Optimize a pathname. Confused by "<symlink>/.." twistiness. * Used to optimize a pathname in a complicated way, trying to remove
* Returns the number of final pathname elements (zero for "/" * redundant ../ components, now just simplifies leading //// into one
* or ".") or -1 if unsuccessful. * leading /. Returns 1 always.
*/ */
STATIC int STATIC int
nameopt (begin) nameopt (name)
char *begin; char *name;
{ {
reg char *name; char *name2;
reg char *item; while((name[0]=='/')&&(name[1]=='/'))
reg int idx;
int absolute;
auto char *element[PATHELEM];
absolute = (*(name = begin) == '/');
idx = 0;
for (;;)
{ {
if (idx == PATHELEM) name2=name;
return (warn (begin, "Too many elements")); while ((name2[0] = name2[1])) ++name2;
while (*name == '/') }
++name; return 1;
if (*name == '\0')
break;
element[idx] = item = name;
while (*name && *name != '/')
++name;
if (*name)
*name++ = '\0';
if (strcmp (item, "..") == 0)
if (idx == 0)
if (absolute)
;
else
++idx;
else if (strcmp (element[idx - 1], "..") == 0)
++idx;
else
--idx;
else if (strcmp (item, ".") != 0)
++idx;
}
if (idx == 0)
element[idx++] = absolute ? "" : ".";
element[idx] = NULL;
name = begin;
if (absolute)
*name++ = '/';
for (idx = 0; (item = element[idx]); ++idx, *name++ = '/')
while (*item)
*name++ = *item++;
*--name = '\0';
return (idx);
} }
/* /*
* next() * next()
* *
* Advance to the next archive volume. * Advance to the next archive volume.
* *
*/ */
STATIC void STATIC void
next (mode, why) next (mode, why)
reg int mode; reg int mode;
reg char *why; reg char *why;
{ {
reg time_t began; reg time_t began;
char *msg; char *msg;
int msgsize; int msgsize;
char answer[20]; char answer[20];
int ttyfd;
char *ttystr;
msgsize = 200 + strlen(myname) * 2 + strlen(arspec); msgsize = 200 + strlen(myname) * 2 + strlen(arspec);
if(promptscript) msgsize += strlen(promptscript);
msg = memget (msgsize); msg = memget (msgsize);
began = time ((time_t *) NULL); began = time ((time_t *) NULL);
nextclos (); nextclos ();
if(!index(ignorewarnings,(int)'M')) if(!index(ignorewarnings,(int)'M'))
{ {
VOID warnarch (why, (off_t) 0); VOID warnarch (why, (off_t) 0);
warnings--; /* above warnach call is not an error condition */ warnings--; /* above warnach call is not an error condition */
} }
if (arfd == STDIN || arfd == STDOUT) if (arfd == STDIN || arfd == STDOUT)
goodbye (1); goodbye (1);
++arvolume; /* change disk # here */ ++arvolume; /* change disk # here */
if (email) mail(email,(int)arvolume,arspec); if (email) mail(email,(int)arvolume,arspec);
if(promptscript) if(promptscript)
{ {
/* run info-script with volume number and archive spec,
and reason for calling it as arguments.
the script should return 0 for ok and 1 for abort, other
return codes will be treated as errors. */
/* connect prompt script to /dev/tty if it can be opened, else
connect it to /dev/null (for crontab/at job use) */
if ((ttyfd = open (TTY, O_RDWR)) < 0)
{
ttystr="/dev/null";
}
else
{
close(ttyfd);
ttystr=TTY;
}
VOID sprintf(msg,"%s %u %s '%s' <%s",promptscript,arvolume,arspec,why,ttys
tr);
for (;;) for (;;)
{ {
auto int result; auto int result;
result=system(msg); result=runpromptscript(why);
if (result==1) if (result==1)
fatal(arspec,"Aborted"); fatal(arspec,"Aborted");
if (result!=0) if (result!=0)
fatal(arspec,"Promptscript failed"); fatal(arspec,"Promptscript failed");
if (nextopen(mode)==0) if (nextopen(mode)==0)
break; break;
} }
} }
else else
{ {
if(Fflag) if(Fflag)
{ {
VOID sprintf (msg, "\ VOID sprintf (msg, "\
%s: Ready for disk %u on %s\n\ %s: Ready for disk %u on %s\n\
%s: \"quit\" to abort,\"f\" to format, anything else to proceed. > \07", %s: \"quit\" to abort,\"f\" to format, anything else to proceed. > \07",
myname, myname,
arvolume, arvolume,
skipping to change at line 2594 skipping to change at line 2662
} }
for (;;) for (;;)
{ {
nextask (msg, answer, sizeof (answer)); nextask (msg, answer, sizeof (answer));
if (strcmp (answer, "quit") == 0) if (strcmp (answer, "quit") == 0)
fatal (arspec, "Aborted"); fatal (arspec, "Aborted");
else else
{ {
while (Fflag && strcmp(answer,"f") == 0) { while (Fflag && strcmp(answer,"f") == 0) {
fprintf (stderr, "formating using %s ...\n",formatcmd); fprintf (stderr, "formatting using %s ...\n",formatcmd);
if (system (formatcmd) != 0) if (system (formatcmd) != 0)
{ {
strcpy(msg,"\n"); strcpy(msg,"\n");
strcat(msg,myname); strcat(msg,myname);
strcat(msg,": Format failed! Try again (y/n)? > "); strcat(msg,": Format failed! Try again (y/n)? > ");
nextask (msg, answer, sizeof (answer)); nextask (msg, answer, sizeof (answer));
if (answer[0] == 'y') answer[0] = 'f'; if (answer[0] == 'y') answer[0] = 'f';
else exit(1); else exit(1);
} }
else break; else break;
skipping to change at line 2622 skipping to change at line 2690
if(!index(ignorewarnings,(int)'M')) if(!index(ignorewarnings,(int)'M'))
{ {
VOID warnarch ("Continuing", (off_t) 0); VOID warnarch ("Continuing", (off_t) 0);
warnings--; /* above warnach call is not an error condition */ warnings--; /* above warnach call is not an error condition */
} }
timewait += time ((time_t *) NULL) - began; timewait += time ((time_t *) NULL) - began;
free(msg); free(msg);
} }
/* /*
* runpromptscript()
*
* Utility function to run the promptscript
*
*/
STATIC int
runpromptscript (why)
char *why;
{
int pid,result;
char vol[100];
/* run info-script with volume number and archive spec,
and reason for calling it as arguments.
the script should return 0 for ok and 1 for abort, other
return codes will be treated as errors. */
/* connect prompt script to /dev/tty if it can be opened, else
connect it to /dev/null (for crontab/at job use) */
sprintf(vol,"%d",arvolume);
if ((pid = xfork (promptscript, DIE)) == 0)
{
VOID close (fileno (stdin));
VOID close (fileno (stdout));
VOID close (fileno (stderr));
if ((open (TTY, O_RDWR)) < 0)
{
VOID open ("/dev/null", O_RDWR);
}
VOID dup (fileno (stdin));
VOID dup (fileno (stdin));
execlp(promptscript,promptscript,vol,arspec,why,(char *)NULL);
exit (1);
}
result=xwait (pid, "promptscript", TRUE);
return(result);
}
/*
* nextask() * nextask()
* *
* Ask a question and get a response. Ignores spaces and tabs. * Ask a question and get a response. Ignores spaces and tabs.
*/ */
STATIC void STATIC void
nextask (msg, answer, limit) nextask (msg, answer, limit)
reg char *msg; reg char *msg;
reg char *answer; reg char *answer;
reg int limit; reg int limit;
{ {
skipping to change at line 2716 skipping to change at line 2827
#if 1 #if 1
if (arfd != -1) if (arfd != -1)
close (arfd); close (arfd);
#endif #endif
if (*arname == '!') if (*arname == '!')
arfd = pipeopen (mode); arfd = pipeopen (mode);
else if (strcmp (arname, "-") == 0) else if (strcmp (arname, "-") == 0)
arfd = mode ? STDOUT : STDIN; arfd = mode ? STDOUT : STDIN;
else else
{ {
process_arname(arname);
#ifdef CTC3B2 #ifdef CTC3B2
if (Cflag) if (Cflag)
{ {
reg int oops; reg int oops;
reg int fd; reg int fd;
oops = ((fd = open (arname, O_RDWR | O_CTSPECIAL)) < 0 oops = ((fd = open (proc_arname, O_RDWR | O_CTSPECIAL)) < 0
|| ioctl (fd, STREAMON) < 0); || ioctl (fd, STREAMON) < 0);
VOID close (fd); VOID close (fd);
if (oops) if (oops)
return (warnarch (syserr (), (off_t) 0)); return (warnarch (syserr (), (off_t) 0));
} }
#endif /* CTC3B2 */ #endif /* CTC3B2 */
#ifdef linux #ifdef linux
/* Do O_SYNC writing to the floppy drive */ /* Do O_SYNC writing to the floppy drive */
if(Fflag && mode) if(Fflag && mode)
arfd = open (arname, mode | O_CREAT | O_TRUNC | O_SYNC, 0666 & ~mask); arfd = open (proc_arname, mode | O_CREAT | O_TRUNC | O_SYNC, 0666 & ~mas k);
else else
arfd = mode ? creat (arname, (mode_t)(0666 & ~mask)) : open (arname, mod e); arfd = mode ? creat (proc_arname, (mode_t)(0666 & ~mask)) : open (proc_a rname, mode);
#else #else
arfd = mode ? creat (arname, (mode_t)(0666 & ~mask)) : open (arname, mode) ; arfd = mode ? creat (proc_arname, (mode_t)(0666 & ~mask)) : open (proc_arn ame, mode);
#endif /* linux */ #endif /* linux */
} }
if (arfd < 0) if (arfd < 0)
return (warnarch (syserr (), (off_t) 0)); return (warnarch (syserr (), (off_t) 0));
arleft = aruntil; arleft = aruntil;
return (0); return (0);
} }
/* /*
skipping to change at line 2990 skipping to change at line 3102
asb->sb_link[asb->sb_size] = '\0'; asb->sb_link[asb->sb_size] = '\0';
if(strcmp(archlink,asb->sb_link)!=0) if(strcmp(archlink,asb->sb_link)!=0)
VOID warn (name, "Difference in symlink destination filename"); VOID warn (name, "Difference in symlink destination filename");
asb->sb_size = 0; asb->sb_size = 0;
return (0); return (0);
#endif /* S_IFLNK */ #endif /* S_IFLNK */
case S_IFREG: case S_IFREG:
/* does not check file permissions and access times */ /* does not check file permissions and access times */
if (asb->sb_size == 0)
return (0);
/* get last access time if we want to restore it */ /* get last access time if we want to restore it */
if(aflag) if(aflag)
{ {
if (STAT (local, &atime_sb) < 0) if (STAT (local, &atime_sb) < 0)
{ {
/* silently fail, the open below will report an error */ /* silently fail, the open below will report an error */
} }
else else
{ {
atime_sb_valid=1; atime_sb_valid=1;
} }
} }
if ((fd = open (local, O_RDONLY)) >= 0) if ((fd = open (local, O_RDONLY)) >= 0)
{ {
/* check for larger file on filesystem if file has 0 size */
/* special handling of hard links: non-first archive entries
for hardlinked files, which have 0 size, are not checked.
If the hardlinked file has 0 size originally, the first
archive entry for it also has 0 size, which means that
the code below does not then check if the file on the
filesystem grew larger. Fixing this would be too much
work, we have to figure out correct coding of hard link
inode/file name administration (see e.g. code in
tocentry()) in order to detect whether the entry
represents a first entry. */
if ((asb->sb_size == 0)&&(asb->sb_nlink == 1))
{
if (STAT (local, &atime_sb) >= 0)
{
if (asb->sb_size != atime_sb.sb_size)
{
VOID warn (name, "File in archive has different length than
file on filesystem");
if(index(ignorewarnings,(int)'r'))
{
warn_nocount(name, "Not counting this as a verification
error");
warnings--;
}
}
}
}
return (fd); return (fd);
} }
VOID warn_nocount (name, syserr ()); VOID warn_nocount (name, syserr ());
VOID warn (name, "File on filesystem could not be opened for verify"); VOID warn (name, "File on filesystem could not be opened for verify");
if(index(ignorewarnings,(int)'r')) if(index(ignorewarnings,(int)'r'))
{ {
warn_nocount(name, "Not counting this as a verification error"); warn_nocount(name, "Not counting this as a verification error");
warnings--; warnings--;
} }
skipping to change at line 3283 skipping to change at line 3419
else if (mknod (name, asb->sb_mode, (dev_t) 0) < 0 else if (mknod (name, asb->sb_mode, (dev_t) 0) < 0
&& (errno != ENOENT && (errno != ENOENT
|| dirneed (name) < 0 || dirneed (name) < 0
|| mknod (name, asb->sb_mode, (dev_t) 0) < 0)) || mknod (name, asb->sb_mode, (dev_t) 0) < 0))
return (warn (name, syserr ())); return (warn (name, syserr ()));
break; break;
#endif /* S_IFSOCK */ #endif /* S_IFSOCK */
#ifdef S_IFLNK #ifdef S_IFLNK
case S_IFLNK: case S_IFLNK:
fd = 0; fd = 0;
if (nosymlinks)
{
warn (name, "Not unpacking this symlink because of -8 nosymlinks");
if(index(ignorewarnings,(int)'l')) warnings--;
break;
}
if (exists) if (exists)
{ {
if ((ssize = readlink (name, sname, sizeof (sname))) < 0) if ((ssize = readlink (name, sname, sizeof (sname))) < 0)
return (warn (name, syserr ())); return (warn (name, syserr ()));
else if (strncmp (sname, asb->sb_link, (size_t)ssize) == 0) else if (strncmp (sname, asb->sb_link, (size_t)ssize) == 0)
break; break;
else if (afremove (name, &osb) < 0) else if (afremove (name, &osb) < 0)
return (warn (name, syserr ())); return (warn (name, syserr ()));
else else
exists = 0; exists = 0;
skipping to change at line 3650 skipping to change at line 3792
} }
if(wantlarge && !cpiowarned && !index(ignorewarnings,(int)'C')) if(wantlarge && !cpiowarned && !index(ignorewarnings,(int)'C'))
{ {
VOID warn_nocount(name, "Cannot create cpio-compatible file header fo r this input"); VOID warn_nocount(name, "Cannot create cpio-compatible file header fo r this input");
VOID warnarch("Continuing, archive will not be fully compatible with cpio or afio versions 2.4.7 and lower",(off_t)0); VOID warnarch("Continuing, archive will not be fully compatible with cpio or afio versions 2.4.7 and lower",(off_t)0);
if(index(ignorewarnings,(int)'c')) warnings--; if(index(ignorewarnings,(int)'c')) warnings--;
cpiowarned=1; cpiowarned=1;
} }
#ifdef S_IFLNK
if ((sb.sb_mode & S_IFMT) == S_IFLNK)
if (nosymlinks)
{
warn (fsname, "Not including symlink because of -8 nosymlinks");
if(index(ignorewarnings,(int)'l')) warnings--;
continue;
}
#endif /* S_IFLNK */
if(wantlarge) if(wantlarge)
{ {
outhead3 (name, &sb); outhead3 (name, &sb);
} }
else else
{ {
if(extfmt) if(extfmt)
outhead2 (name, &sb); outhead2 (name, &sb);
else else
outhead (name, &sb); outhead (name, &sb);
skipping to change at line 3708 skipping to change at line 3860
*/ */
if ((fd==ZIPFD)||(fd==MEMFD)) if ((fd==ZIPFD)||(fd==MEMFD))
VOID fprintf (stderr, "(%02d%%)\n", compression); VOID fprintf (stderr, "(%02d%%)\n", compression);
else else
VOID fputs ("okay\n", stderr); VOID fputs ("okay\n", stderr);
} }
/* ASX check if file changed between the begining /* ASX check if file changed between the begining
and end of the backup */ and end of the backup */
if (*fsname) /* if *fsname==0, it was a control file, so do not check then */
if (*fsname!=0)
{ {
struct stat st; struct stat st;
/* I must check fsname ! /* I must check fsname !
but error must be reported as fsname or name ????? but error must be reported as fsname or name ?????
I chosed to use fsname */ I chosed to use fsname */
if ((hflag ? stat(fsname, &st) : lstat(fsname, &st))<0) if ((hflag ? stat(fsname, &st) : lstat(fsname, &st))<0)
{ {
warn (fsname, syserr()); warn (fsname, syserr());
} }
else else
{ {
if (st.st_mtime!=sb.sb_mtime) if (st.st_mtime!=sb.sb_mtime)
{ {
warn (fsname, "File was modified during its backup"); warn (fsname, "File was modified during its backup");
if(index(ignorewarnings,(int)'d')) warnings--;
} }
} }
} }
else
{
warn (name, "ASX no fsname for this name ??");
}
if(aflag && *fsname && ((sb.sb_mode & S_IFMT)==S_IFREG)) if(aflag && *fsname && ((sb.sb_mode & S_IFMT)==S_IFREG))
{ {
/* reset access time, this distroys the ctime btw. */ /* reset access time, this distroys the ctime btw. */
#ifdef linux_tstamp #ifdef linux_tstamp
tstamp.actime = sb.sb_atime; tstamp.actime = sb.sb_atime;
tstamp.modtime = sb.sb_mtime; tstamp.modtime = sb.sb_mtime;
VOID utime (fsname, &tstamp); VOID utime (fsname, &tstamp);
#else #else
tstamp[0] = sb.sb_atime; tstamp[0] = sb.sb_atime;
skipping to change at line 3755 skipping to change at line 3905
outeof (TRAILER, TRAILZ); outeof (TRAILER, TRAILZ);
} }
/* /*
* outalloc() * outalloc()
* *
* Allocate buffer space previously referenced by outavail(). * Allocate buffer space previously referenced by outavail().
*/ */
STATIC void STATIC void
outalloc (len) outalloc (len)
reg uint len; reg size_t len;
{ {
bufidx += len; bufidx += len;
total += len; total += len;
} }
/* /*
* outavail() * outavail()
* *
* Index buffer space for archive output. Stores a buffer pointer * Index buffer space for archive output. Stores a buffer pointer
* at a given location. Returns the number of bytes available. * at a given location. Returns the number of bytes available.
*/ */
STATIC uint STATIC size_t
outavail (bufp) outavail (bufp)
reg char **bufp; reg char **bufp;
{ {
reg uint have; reg size_t have;
while ((have = bufend - bufidx) == 0) while ((have = bufend - bufidx) == 0)
{ {
outflush (NOTDONE); outflush (NOTDONE);
} }
*bufp = bufidx; *bufp = bufidx;
return (have); return (have);
} }
skipping to change at line 3795 skipping to change at line 3945
* Write archive data. Continues after file read errors, padding with * Write archive data. Continues after file read errors, padding with
* null characters if neccessary. Always returns the given input file * null characters if neccessary. Always returns the given input file
* descriptor. * descriptor.
*/ */
STATIC int STATIC int
outdata (fd, name, size) outdata (fd, name, size)
int fd; int fd;
char *name; char *name;
reg off_t size; reg off_t size;
{ {
reg uint chunk; reg size_t chunk;
reg int got; reg ssize_t got;
reg int oops; reg int oops;
reg uint avail; reg size_t avail;
auto char *buf; auto char *buf;
oops = got = 0; oops = got = 0;
while (size) while (size)
{ {
avail = outavail (&buf); avail = outavail (&buf);
size -= (chunk = size < (off_t)avail ? (uint) size : avail); size -= (chunk = size < (off_t)avail ? size : avail);
if (oops == 0 && (got = readall (fd, buf, chunk)) < 0) if (oops == 0 && (got = readall (fd, buf, chunk)) < 0)
{ {
oops = warn (name, syserr ()); oops = warn (name, syserr ());
if(index(ignorewarnings,(int)'n')) warnings--; if(index(ignorewarnings,(int)'n')) warnings--;
got = 0; got = 0;
} }
if ((uint)got < chunk) if ((size_t)got < chunk)
{ {
if (oops == 0) if (oops == 0)
oops = warn (name, "Early EOF"); oops = warn (name, "Early EOF");
while ((uint)got < chunk) while ((size_t)got < chunk)
buf[got++] = '\0'; buf[got++] = '\0';
} }
outalloc (chunk); outalloc (chunk);
} }
return (fd); return (fd);
} }
/* /*
* outdatazip() * outdatazip()
* *
skipping to change at line 3838 skipping to change at line 3988
* null characters if neccessary. * null characters if neccessary.
* *
* Special version for reading from gzip through a pipe. * Special version for reading from gzip through a pipe.
*/ */
void void
outdatazip (fd, name, size) outdatazip (fd, name, size)
int fd; int fd;
char *name; char *name;
reg off_t size; reg off_t size;
{ {
reg uint chunk; reg size_t chunk;
reg int got; reg ssize_t got;
reg uint avail; reg size_t avail;
auto char *buf; auto char *buf;
char localbuf[4096]; char localbuf[4096];
int overflow=0; int overflow=0;
while (size>0) while (size>0)
{ {
avail = outavail (&buf); avail = outavail (&buf);
chunk = (size < (off_t)avail ? (uint) size : avail); chunk = (size < (off_t)avail ? size : avail);
got = read (fd, buf, chunk); got = read (fd, buf, chunk);
if(got<=0) break; if(got<=0) break;
outalloc ((uint)got); outalloc (got);
size-=got; size-=got;
} }
/* read the end of the stream, if the data changed on the second gzip */ /* read the end of the stream, if the data changed on the second gzip */
overflow=0; overflow=0;
while (read (fd, localbuf, sizeof(localbuf))>0) overflow=1; while (read (fd, localbuf, sizeof(localbuf))>0) overflow=1;
waitforgzip(); /* wait for child to exit */ waitforgzip(); /* wait for child to exit */
if(size>0 || overflow) if(size>0 || overflow)
warn (name, "Error zipping file, written damaged copy to archive."); warn (name, "Error zipping file, written damaged copy to archive.");
/* pad with zeros, if necessary */ /* pad with zeros, if necessary */
while (size>0) while (size>0)
{ {
avail = outavail (&buf); avail = outavail (&buf);
size -= (chunk = size < (off_t)avail ? (uint) size : avail); size -= (chunk = size < (off_t)avail ? size : avail);
got=0; got=0;
while ((uint)got < chunk) while (got < chunk)
buf[got++] = '\0'; buf[got++] = '\0';
outalloc (chunk); outalloc (chunk);
} }
} }
/* /*
* outdatamem() * outdatamem()
* *
* Write archive data. * Write archive data.
skipping to change at line 3951 skipping to change at line 4101
* outflush() * outflush()
* *
* Flush the output buffer. Optionally fork()s to allow the * Flush the output buffer. Optionally fork()s to allow the
* parent to refill the buffer while the child waits for the * parent to refill the buffer while the child waits for the
* write() to complete. * write() to complete.
*/ */
STATIC void STATIC void
outflush (done) outflush (done)
int done; int done;
{ {
int wrstat;
/* /*
* in this case we are a floppy and want to write the floppy from one * in this case we are a floppy and want to write the floppy from one
* buffer (to have a copy of the data to verify against) * buffer (to have a copy of the data to verify against)
*/ */
bufend = buffer + ((aruntil!=0) ? min ((ulonglong)buflen, arleft) : (ulonglong )buflen); bufend = buffer + ((aruntil!=0) ? min ((ulonglong)buflen, arleft) : (ulonglong )buflen);
if (Fflag && (done == NOTDONE) && ((bufend - bufidx) > 0)) if (Fflag && (done == NOTDONE) && ((bufend - bufidx) > 0))
{ {
return; return;
} }
/* /*
* Otherwise open up the next volume once we've run out of space * Otherwise open up the next volume once we've run out of space
*/ */
if ( !Fflag && aruntil && arleft == 0) if ( !Fflag && aruntil && arleft == 0)
next (O_WRONLY, "Output limit reached"); next (O_WRONLY, "Output limit reached");
wrstat = writedisk (1); /* writedisk will report errors, no need to check return code */
VOID writedisk (1);
bufend = (bufidx = buffer) + ((aruntil!=0) ? min ((ulonglong)buflen, arleft) : (ulonglong)buflen); bufend = (bufidx = buffer) + ((aruntil!=0) ? min ((ulonglong)buflen, arleft) : (ulonglong)buflen);
} }
/* /*
* outhead() * outhead()
* *
* Write an archive header. * Write an archive header.
*/ */
STATIC void STATIC void
outhead (name, asb) outhead (name, asb)
skipping to change at line 4199 skipping to change at line 4348
* descriptor zero (see description of kludge in openin() * descriptor zero (see description of kludge in openin()
* comments). Closes the provided output file descriptor. * comments). Closes the provided output file descriptor.
*/ */
STATIC void STATIC void
passdata (from, ifd, to, ofd) passdata (from, ifd, to, ofd)
char *from; char *from;
reg int ifd; reg int ifd;
char *to; char *to;
reg int ofd; reg int ofd;
{ {
reg int got; reg ssize_t got;
reg int sparse; reg ssize_t sparse;
auto char block[FSBUF]; auto char block[FSBUF];
if (ifd) if (ifd)
{ {
VOID lseek (ifd, (off_t) 0, 0); VOID lseek (ifd, (off_t) 0, 0);
sparse = 0; sparse = 0;
while ((got = read (ifd, block, sizeof (block))) > 0 while ((got = read (ifd, block, sizeof (block))) > 0
&& (sparse = fswrite (ofd, block, (uint) got)) >= 0) && (sparse = fswrite (ofd, block, (uint) got)) >= 0)
total += got; total += got;
if (got) if (got)
VOID warn (got < 0 ? from : to, syserr ()); VOID warn (got < 0 ? from : to, syserr ());
else if (sparse > 0 else if (sparse > 0
&& (lseek (ofd, (off_t) - sparse, 1) < 0 && (lseek (ofd, (off_t) - sparse, 1) < 0
|| writeall (ofd, block, (uint) sparse) != sparse)) || writeall (ofd, block, sparse) != sparse))
VOID warn (to, syserr ()); VOID warn (to, syserr ());
} }
VOID close (ofd); VOID close (ofd);
} }
/* /*
* passitem() * passitem()
* *
* Copy one file. Returns given input file descriptor. * Copy one file. Returns given input file descriptor.
*/ */
skipping to change at line 4267 skipping to change at line 4416
/* safety */ /* safety */
if (uncompressrun) if (uncompressrun)
{ {
VOID xwait (uncompressrun, "passitem xwait()", TRUE); VOID xwait (uncompressrun, "passitem xwait()", TRUE);
uncompressrun = 0; uncompressrun = 0;
} }
} }
return (ifd); return (ifd);
} }
STATIC VOIDFN
process_arname (template)
char *template;
{
int remain, len;
char *sptr, *dptr;
sptr=template;
dptr=proc_arname;
if(!sflagused)
{
strcpy(dptr,sptr);
return;
}
remain = sizeof(proc_arname)-10;
for (; remain>=0; sptr++) {
*dptr = '\0';
if (*sptr == '%') {
switch (*++sptr) {
case 'V': /* volume number */
if (remain < 40) break;
len = sprintf(dptr,"%u", arvolume);
dptr += len;
remain -= len;
break;
case 'S': /* volume size */
if (remain < 40) break;
len = sprintf(dptr,"%llu", (unsigned long long) aruntil
);
dptr += len;
remain -= len;
break;
default:
*dptr++ = *sptr;
remain--;
break;
}
}
else {
*dptr++ = *sptr;
remain--;
}
if (*sptr == '\0') break;
}
}
/* /*
* pipechld() * pipechld()
* *
* Child portion of pipeline fork. * Child portion of pipeline fork.
*/ */
STATIC int STATIC int
pipechld (mode, pfd) pipechld (mode, pfd)
int mode; int mode;
reg int *pfd; reg int *pfd;
{ {
reg char **av; reg char **av;
auto char *arg[32]; auto char *arg[32];
av = arg; av = arg;
if ((*av = getenv ("SHELL")) && **av) if ((*av = getenv ("SHELL")) && **av)
++av; ++av;
else else
*av++ = "/bin/sh"; *av++ = "/bin/sh";
*av++ = "-c"; *av++ = "-c";
*av++ = arname + 1; process_arname(arname + 1);
*av++ = proc_arname;
*av = NULL; *av = NULL;
if (mode) if (mode)
{ {
VOID close (pfd[1]); VOID close (pfd[1]);
VOID close (STDIN); VOID close (STDIN);
VOID dup (pfd[0]); VOID dup (pfd[0]);
VOID close (pfd[0]); VOID close (pfd[0]);
VOID close (STDOUT); VOID close (STDOUT);
VOID open ("/dev/null", O_WRONLY); VOID open ("/dev/null", O_WRONLY);
} }
skipping to change at line 4425 skipping to change at line 4624
#endif /* MKDIR */ #endif /* MKDIR */
/* /*
* fswrite() * fswrite()
* *
* Write a filesystem block. Seeks past sparse blocks. Returns * Write a filesystem block. Seeks past sparse blocks. Returns
* 0 if the block was written, the given length for a sparse * 0 if the block was written, the given length for a sparse
* block or -1 if unsuccessful. * block or -1 if unsuccessful.
*/ */
STATIC int STATIC ssize_t
fswrite (fd, buf, len) fswrite (fd, buf, len)
int fd; int fd;
char *buf; char *buf;
uint len; size_t len;
{ {
reg char *bidx; reg char *bidx;
reg char *bend; reg char *bend;
/* /*
* if -j (no sparse blocks) or compressrun (piping to uncompress utility) * if -j (no sparse blocks) or compressrun (piping to uncompress utility)
* then do not bother looking for empty buffers, just write the data. * then do not bother looking for empty buffers, just write the data.
*/ */
if (jflag || uncompressrun) if (jflag || uncompressrun)
return (writeall (fd, buf, len) == (int)len ? 0 : -1); return (writeall (fd, buf, len) == (int)len ? 0 : -1);
skipping to change at line 4586 skipping to change at line 4785
char *namedot = strrchr (name, '.'); char *namedot = strrchr (name, '.');
if (Zflag && (asb->sb_mode & S_IFMT) == S_IFREG if (Zflag && (asb->sb_mode & S_IFMT) == S_IFREG
&& (asb->sb_rdev & RDEV_NOTCOMPR) == 0 && (asb->sb_rdev & RDEV_NOTCOMPR) == 0
&& (asb->sb_size > 0) && (asb->sb_size > 0)
&& namedot && namedot[1] == 'z' && !namedot[2]) && namedot && namedot[1] == 'z' && !namedot[2])
*namedot = '\0'; *namedot = '\0';
else else
namedot = 0; namedot = 0;
if (ISCONTROL(asb)) if (ISCONTROL(asb)) res = printf("//--");
res = printf("//--%s",name);
if ((!useoutmodetoc) && flag0)
res = printf ("%s%c", name, 0);
else else
{ res = printf ("%s", name);
if (flag0)
res = printf ("%s%c", name, 0);
else
res = printf ("%s", name);
}
/* to find out about broken pipe as early as possible */ /* to find out about broken pipe as early as possible */
if(res > 0) res = fflush(stdout); if(res > 0) res = fflush(stdout);
/* check for broken pipe on stdout, this ends the listing */ /* check for broken pipe on stdout, this ends the listing */
if(res<0) { if(res<0) {
if(errno == EPIPE) if(errno == EPIPE)
fatal("<stdout>", syserr()); fatal("<stdout>", syserr());
} }
if (vflag && namedot) if (vflag && namedot)
VOID printf (" -- compressed"); VOID printf (" -- compressed");
skipping to change at line 4653 skipping to change at line 4850
} }
} }
#ifdef S_IFLNK #ifdef S_IFLNK
if (((asb->sb_mode & S_IFMT) == S_IFLNK)&&(from==NULL)) if (((asb->sb_mode & S_IFMT) == S_IFLNK)&&(from==NULL))
VOID printf (" S-> %s", asb->sb_link); VOID printf (" S-> %s", asb->sb_link);
#endif /* S_IFLNK */ #endif /* S_IFLNK */
} }
if (!flag0) if ((!flag0)||useoutmodetoc)
putchar ('\n'); putchar ('\n');
} }
/* /*
* tocmode() * tocmode()
* *
* Fancy file mode display. * Fancy file mode display.
*/ */
STATIC void STATIC void
tocmode (mode) tocmode (mode)
skipping to change at line 4761 skipping to change at line 4958
char *what; char *what;
char *why; char *why;
{ {
time_t dietime; time_t dietime;
warnings++; warnings++;
dietime = time ((time_t *) NULL); dietime = time ((time_t *) NULL);
VOID fprintf (stderr, VOID fprintf (stderr,
"%s: \"%s\": %s\n", "%s: \"%s\": %s\n",
myname, what, why); myname, what, why);
/* ctime() prodives the \n for the fprintf. */ /* ctime() provides the \n for the fprintf. */
if (logfile != (FILE *) 0) if (logfile != (FILE *) 0)
VOID fprintf (logfile, "%s: \"%s\": %s (disk %u) at %s", VOID fprintf (logfile, "%s: \"%s\": %s (disk %u) at %s",
myname, what, why, arvolume, ctime (&dietime)); myname, what, why, arvolume, ctime (&dietime));
return (-1); return (-1);
} }
STATIC int warn_nocount (what, why) STATIC int warn_nocount (what, why)
char *what; char *what;
char *why; char *why;
{ {
skipping to change at line 5034 skipping to change at line 5231
else else
{ {
fprintf (stderr, "Format successful!\n"); fprintf (stderr, "Format successful!\n");
/* if we can't open, try again */ /* if we can't open, try again */
if (nextopen (O_WRONLY) < 0) if (nextopen (O_WRONLY) < 0)
continue; continue;
return; return;
} }
} }
else if (strcmp (answer, "quit") == 0) else if (strcmp (answer, "quit") == 0)
fatal (arspec, "Quiting during a verify"); fatal (arspec, "Quitting during a verify");
} }
} }
} }
int int
writedisk (realwrite) writedisk (realwrite)
int realwrite; int realwrite;
{ {
reg char *buf; reg char *buf;
reg int got; reg int got;
 End of changes. 90 change blocks. 
164 lines changed or deleted 364 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)