diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-12-09 12:00:17 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-12-09 12:00:17 +0000 |
commit | d5046aac533bf79016f48a1264cf6ce6094a5240 (patch) | |
tree | 2b37708a0c3b0f87e3b4e21013ccd5b2050f68e2 /bin/pax/ar_io.c | |
parent | f31bd15fdb85439b411810a414f1ac5f5df3ed5c (diff) |
revert to spawning compress-ing program. normally we want extracts using
'z' to also work on .Z files, but libz does not deal with compressed
data. Hacking the code to deal well with pipes has proven very hard.
Diffstat (limited to 'bin/pax/ar_io.c')
-rw-r--r-- | bin/pax/ar_io.c | 419 |
1 files changed, 189 insertions, 230 deletions
diff --git a/bin/pax/ar_io.c b/bin/pax/ar_io.c index 3573f7c021b..aff14dcfe10 100644 --- a/bin/pax/ar_io.c +++ b/bin/pax/ar_io.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar_io.c,v 1.7 1996/11/24 18:15:59 millert Exp $ */ +/* $OpenBSD: ar_io.c,v 1.8 1996/12/09 12:00:13 deraadt Exp $ */ /* $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $ */ /*- @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94"; #else -static char rcsid[] = "$OpenBSD: ar_io.c,v 1.7 1996/11/24 18:15:59 millert Exp $"; +static char rcsid[] = "$OpenBSD: ar_io.c,v 1.8 1996/12/09 12:00:13 deraadt Exp $"; #endif #endif /* not lint */ @@ -60,7 +60,6 @@ static char rcsid[] = "$OpenBSD: ar_io.c,v 1.7 1996/11/24 18:15:59 millert Exp $ #include <errno.h> #include <stdlib.h> #include <err.h> -#include <zlib.h> #include "pax.h" #include "extern.h" @@ -85,13 +84,12 @@ static struct stat arsb; /* stat of archive device at open */ static int invld_rec; /* tape has out of spec record size */ static int wr_trail = 1; /* trailer was rewritten in append */ static int can_unlnk = 0; /* do we unlink null archives? */ -static gzFile gzf; /* file pointer for gzip archives */ -static FILE *cfp; /* file pointer for compress archives */ char *arcname; /* printable name of archive */ +char *gzip_program; /* name of gzip program */ -FILE *zdopen __P((int, const char *)); static int get_phys __P((void)); extern sigset_t s_mask; +static void ar_start_gzip __P((int)); /* * ar_open() @@ -113,14 +111,8 @@ ar_open(name) { struct mtget mb; - if (arfd != -1) { - if (zflag == GZIP_CMP) - (void)gzclose(gzf); - else if (zflag == COMPRESS_CMP) - (void)fclose(cfp); - else - (void)close(arfd); - } + if (arfd != -1) + (void)close(arfd); arfd = -1; can_unlnk = did_io = io_ok = invld_rec = 0; artyp = ISREG; @@ -137,15 +129,8 @@ ar_open(name) arcname = STDN; } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0) syswarn(0, errno, "Failed open to read on %s", name); - if (zflag == GZIP_CMP) { - gzf = gzdopen(arfd, "r"); - if (gzf && !gz_iszipped(gzf)) { - (void)lseek(arfd, 0, SEEK_SET); - zflag = COMPRESS_CMP; - } - } - if (zflag == COMPRESS_CMP) - cfp = zdopen(arfd, "r"); + if (zflag) + ar_start_gzip(arfd); break; case ARCHIVE: if (name == NULL) { @@ -155,14 +140,12 @@ ar_open(name) syswarn(0, errno, "Failed open to write on %s", name); else can_unlnk = 1; - if (zflag == GZIP_CMP) - gzf = gzdopen(arfd, "w"); - else if (zflag == COMPRESS_CMP) - cfp = zdopen(arfd, "w"); + if (zflag) + ar_start_gzip(arfd); break; case APPND: if (zflag) - err(1, "can not compress while appending"); + err(1, "can not gzip while appending"); if (name == NULL) { arfd = STDOUT_FILENO; arcname = STDO; @@ -186,12 +169,7 @@ ar_open(name) */ if (fstat(arfd, &arsb) < 0) { syswarn(0, errno, "Failed stat on %s", arcname); - if (zflag == GZIP_CMP) - (void)gzclose(gzf); - else if (zflag == COMPRESS_CMP) - (void)fclose(cfp); - else - (void)close(arfd); + (void)close(arfd); arfd = -1; can_unlnk = 0; return(-1); @@ -199,12 +177,7 @@ ar_open(name) if (S_ISDIR(arsb.st_mode)) { paxwarn(0, "Cannot write an archive on top of a directory %s", arcname); - if (zflag == GZIP_CMP) - (void)gzclose(gzf); - else if (zflag == COMPRESS_CMP) - (void)fclose(cfp); - else - (void)close(arfd); + (void)close(arfd); arfd = -1; can_unlnk = 0; return(-1); @@ -376,12 +349,7 @@ ar_close() can_unlnk = 0; } - if (zflag == GZIP_CMP) - (void)gzclose(gzf); - else if (zflag == COMPRESS_CMP) - (void)fclose(cfp); - else - (void)close(arfd); + (void)close(arfd); if (vflag && (artyp == ISTAPE)) { (void)fputs("done.\n", outf); @@ -473,18 +441,8 @@ ar_drain() /* * keep reading until pipe is drained */ - if (zflag == GZIP_CMP) { - while ((res = gzread(gzf, drbuf, sizeof(drbuf))) > 0) - ; - } - else if (zflag == COMPRESS_CMP) { - while ((res = fread(drbuf, 1, sizeof(drbuf), cfp)) > 0) - ; - } - else { - while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0) - ; - } + while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0) + ; lstrval = res; } @@ -554,11 +512,6 @@ ar_app_ok() return(-1); } - if (zflag) { - paxwarn(1, "Cannot append to a compressed archive."); - return(-1); - } - if (!invld_rec) return(0); paxwarn(1,"Cannot append, device record size %d does not support %s spec", @@ -598,34 +551,32 @@ ar_read(buf, cnt) */ switch (artyp) { case ISTAPE: - if (!zflag) { - if ((res = read(arfd, buf, cnt)) > 0) { + if ((res = read(arfd, buf, cnt)) > 0) { + /* + * CAUTION: tape systems may not always return the same + * sized records so we leave blksz == MAXBLK. The + * physical record size that a tape drive supports is + * very hard to determine in a uniform and portable + * manner. + */ + io_ok = 1; + if (res != rdblksz) { /* - * CAUTION: tape systems may not always return the same - * sized records so we leave blksz == MAXBLK. The - * physical record size that a tape drive supports is - * very hard to determine in a uniform and portable - * manner. + * Record size changed. If this is happens on + * any record after the first, we probably have + * a tape drive which has a fixed record size + * we are getting multiple records in a single + * read). Watch out for record blocking that + * violates pax spec (must be a multiple of + * BLKMULT). */ - io_ok = 1; - if (res != rdblksz) { - /* - * Record size changed. If this is happens on - * any record after the first, we probably have - * a tape drive which has a fixed record size - * we are getting multiple records in a single - * read). Watch out for record blocking that - * violates pax spec (must be a multiple of - * BLKMULT). - */ - rdblksz = res; - if (rdblksz % BLKMULT) - invld_rec = 1; - } - return(res); + rdblksz = res; + if (rdblksz % BLKMULT) + invld_rec = 1; } - break; + return(res); } + break; case ISREG: case ISBLK: case ISCHR: @@ -638,23 +589,9 @@ ar_read(buf, cnt) * and return. Trying to do anything else with them runs the * risk of failure. */ - if (zflag == GZIP_CMP) { - if ((res = gzread(gzf, buf, cnt)) > 0) { - io_ok = 1; - return(res); - } - } - else if (zflag == COMPRESS_CMP) { - if ((res = fread(buf, 1, cnt, cfp)) > 0) { - io_ok = 1; - return(res); - } - } - else { - if ((res = read(arfd, buf, cnt)) > 0) { - io_ok = 1; - return(res); - } + if ((res = read(arfd, buf, cnt)) > 0) { + io_ok = 1; + return(res); } break; } @@ -701,26 +638,10 @@ ar_write(buf, bsz) if (lstrval <= 0) return(lstrval); - if (zflag == GZIP_CMP) { - if ((res = gzwrite(gzf, buf, bsz)) == bsz) { - wr_trail = 1; - io_ok = 1; - return(bsz); - } - } - else if (zflag == COMPRESS_CMP) { - if ((res = fwrite(buf, 1, bsz, cfp)) == bsz) { - wr_trail = 1; - io_ok = 1; - return(bsz); - } - } - else { - if ((res = write(arfd, buf, bsz)) == bsz) { - wr_trail = 1; - io_ok = 1; - return(bsz); - } + if ((res = write(arfd, buf, bsz)) == bsz) { + wr_trail = 1; + io_ok = 1; + return(bsz); } /* * write broke, see what we can do with it. We try to send any partial @@ -731,55 +652,53 @@ ar_write(buf, bsz) else lstrval = 0; - if (!zflag) { - switch (artyp) { - case ISREG: - if ((res > 0) && (res % BLKMULT)) { - /* - * try to fix up partial writes which are not BLKMULT - * in size by forcing the runt record to next archive - * volume - */ - if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) - break; - cpos -= (off_t)res; - if (ftruncate(arfd, cpos) < 0) - break; - res = lstrval = 0; + switch (artyp) { + case ISREG: + if ((res > 0) && (res % BLKMULT)) { + /* + * try to fix up partial writes which are not BLKMULT + * in size by forcing the runt record to next archive + * volume + */ + if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) break; - } - if (res >= 0) + cpos -= (off_t)res; + if (ftruncate(arfd, cpos) < 0) break; - /* - * if file is out of space, handle it like a return of 0 - */ - if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT)) - res = lstrval = 0; + res = lstrval = 0; break; - case ISTAPE: - case ISCHR: - case ISBLK: - if (res >= 0) - break; - if (errno == EACCES) { - paxwarn(0, "Write failed, archive is write protected."); - res = lstrval = 0; - return(0); - } - /* - * see if we reached the end of media, if so force a change to - * the next volume - */ - if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO)) - res = lstrval = 0; + } + if (res >= 0) break; - case ISPIPE: - default: - /* - * we cannot fix errors to these devices - */ + /* + * if file is out of space, handle it like a return of 0 + */ + if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT)) + res = lstrval = 0; + break; + case ISTAPE: + case ISCHR: + case ISBLK: + if (res >= 0) break; + if (errno == EACCES) { + paxwarn(0, "Write failed, archive is write protected."); + res = lstrval = 0; + return(0); } + /* + * see if we reached the end of media, if so force a change to + * the next volume + */ + if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO)) + res = lstrval = 0; + break; + case ISPIPE: + default: + /* + * we cannot fix errors to these devices + */ + break; } /* @@ -852,54 +771,50 @@ ar_rdsync() if (io_ok) did_io = 1; - if (zflag) - io_ok = 0; - else { - switch(artyp) { - case ISTAPE: - /* - * if the last i/o was a successful data transfer, we assume - * the fault is just a bad record on the tape that we are now - * past. If we did not get any data since the last resync try - * to move the tape foward one PHYSICAL record past any - * damaged tape section. Some tape drives are stubborn and need - * to be pushed. - */ - if (io_ok) { - io_ok = 0; - lstrval = 1; - break; - } - mb.mt_op = MTFSR; - mb.mt_count = 1; - if (ioctl(arfd, MTIOCTOP, &mb) < 0) - break; - lstrval = 1; - break; - case ISREG: - case ISCHR: - case ISBLK: - /* - * try to step over the bad part of the device. - */ + switch(artyp) { + case ISTAPE: + /* + * if the last i/o was a successful data transfer, we assume + * the fault is just a bad record on the tape that we are now + * past. If we did not get any data since the last resync try + * to move the tape foward one PHYSICAL record past any + * damaged tape section. Some tape drives are stubborn and need + * to be pushed. + */ + if (io_ok) { io_ok = 0; - if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG)) - fsbz = BLKMULT; - if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) - break; - mpos = fsbz - (cpos % (off_t)fsbz); - if (lseek(arfd, mpos, SEEK_CUR) < 0) - break; lstrval = 1; break; - case ISPIPE: - default: - /* - * cannot recover on these archive device types - */ - io_ok = 0; - break; } + mb.mt_op = MTFSR; + mb.mt_count = 1; + if (ioctl(arfd, MTIOCTOP, &mb) < 0) + break; + lstrval = 1; + break; + case ISREG: + case ISCHR: + case ISBLK: + /* + * try to step over the bad part of the device. + */ + io_ok = 0; + if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG)) + fsbz = BLKMULT; + if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) + break; + mpos = fsbz - (cpos % (off_t)fsbz); + if (lseek(arfd, mpos, SEEK_CUR) < 0) + break; + lstrval = 1; + break; + case ISPIPE: + default: + /* + * cannot recover on these archive device types + */ + io_ok = 0; + break; } if (lstrval <= 0) { paxwarn(1, "Unable to recover from an archive read failure."); @@ -933,7 +848,7 @@ ar_fow(sksz, skipped) off_t mpos; *skipped = 0; - if (zflag || sksz <= 0) + if (sksz <= 0) return(0); /* @@ -1004,19 +919,6 @@ ar_rev(sksz) if (lstrval < 0) return(lstrval); - if (zflag) { - if (sksz <= 0) { - lstrval = 1; - return 0; - } - /* - * cannot go backwards on these critters - */ - paxwarn(1, "Reverse positioning on pipes is not supported."); - lstrval = -1; - return(-1); - } - switch(artyp) { case ISPIPE: if (sksz <= 0) @@ -1150,11 +1052,6 @@ get_phys() struct mtop mb; char scbuf[MAXBLK]; - if (zflag) { - syswarn(1, errno, "Cannot determine archive tape blocksize."); - return(-1); - } - /* * move to the file mark, and then back up one record and read it. * this should tell us the physical record size the tape is using. @@ -1404,3 +1301,65 @@ ar_next() } return(0); } + +/* + * ar_start_gzip() + * starts the gzip compression/decompression process as a child, using magic + * to keep the fd the same in the calling function (parent). + */ +void +#ifdef __STDC__ +ar_start_gzip(int fd) +#else +ar_start_gzip(fd) + int fd; +#endif +{ + pid_t pid; + int fds[2]; + char *gzip_flags; + + if (pipe(fds) < 0) + err(1, "could not pipe"); + pid = fork(); + if (pid < 0) + err(1, "could not fork"); + + /* parent */ + if (pid) { + switch (act) { + case ARCHIVE: + dup2(fds[1], fd); + break; + case LIST: + case EXTRACT: + dup2(fds[0], fd); + break; + default: + errx(1, "ar_start_gzip: impossible"); + } + close(fds[0]); + close(fds[1]); + } else { + switch (act) { + case ARCHIVE: + dup2(fds[0], STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + gzip_flags = "-c"; + break; + case LIST: + case EXTRACT: + dup2(fds[1], STDOUT_FILENO); + dup2(fd, STDIN_FILENO); + gzip_flags = "-dc"; + break; + default: + errx(1, "ar_start_gzip: impossible"); + } + close(fds[0]); + close(fds[1]); + if (execlp(gzip_program, gzip_program, gzip_flags, NULL) < 0) + err(1, "could not exec"); + /* NOTREACHED */ + } +} |