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 |