11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1992 Keith Muller.
31556Srgrimes * Copyright (c) 1992, 1993
41556Srgrimes *	The Regents of the University of California.  All rights reserved.
51556Srgrimes *
61556Srgrimes * This code is derived from software contributed to Berkeley by
71556Srgrimes * Keith Muller of the University of California, San Diego.
81556Srgrimes *
91556Srgrimes * Redistribution and use in source and binary forms, with or without
101556Srgrimes * modification, are permitted provided that the following conditions
111556Srgrimes * are met:
121556Srgrimes * 1. Redistributions of source code must retain the above copyright
131556Srgrimes *    notice, this list of conditions and the following disclaimer.
141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151556Srgrimes *    notice, this list of conditions and the following disclaimer in the
161556Srgrimes *    documentation and/or other materials provided with the distribution.
171556Srgrimes * 4. Neither the name of the University nor the names of its contributors
181556Srgrimes *    may be used to endorse or promote products derived from this software
191556Srgrimes *    without specific prior written permission.
201556Srgrimes *
211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311556Srgrimes * SUCH DAMAGE.
321556Srgrimes */
331556Srgrimes
341556Srgrimes#ifndef lint
3536049Scharnier#if 0
3636049Scharnierstatic char sccsid[] = "@(#)buf_subs.c	8.2 (Berkeley) 4/18/94";
3736049Scharnier#endif
381556Srgrimes#endif /* not lint */
3999110Sobrien#include <sys/cdefs.h>
4099110Sobrien__FBSDID("$FreeBSD$");
411556Srgrimes
421556Srgrimes#include <sys/types.h>
431556Srgrimes#include <sys/stat.h>
441556Srgrimes#include <errno.h>
451556Srgrimes#include <unistd.h>
4676351Skris#include <stdio.h>
471556Srgrimes#include <stdlib.h>
481556Srgrimes#include <string.h>
491556Srgrimes#include "pax.h"
501556Srgrimes#include "extern.h"
511556Srgrimes
521556Srgrimes/*
531556Srgrimes * routines which implement archive and file buffering
541556Srgrimes */
551556Srgrimes
561556Srgrimes#define MINFBSZ		512		/* default block size for hole detect */
5776019Skris#define MAXFLT		10		/* default media read error limit */
581556Srgrimes
591556Srgrimes/*
601556Srgrimes * Need to change bufmem to dynamic allocation when the upper
611556Srgrimes * limit on blocking size is removed (though that will violate pax spec)
621556Srgrimes * MAXBLK define and tests will also need to be updated.
631556Srgrimes */
641556Srgrimesstatic char bufmem[MAXBLK+BLKMULT];	/* i/o buffer + pushback id space */
651556Srgrimesstatic char *buf;			/* normal start of i/o buffer */
661556Srgrimesstatic char *bufend;			/* end or last char in i/o buffer */
671556Srgrimesstatic char *bufpt;			/* read/write point in i/o buffer */
6876019Skrisint blksz = MAXBLK;			/* block input/output size in bytes */
6976019Skrisint wrblksz;				/* user spec output size in bytes */
701556Srgrimesint maxflt = MAXFLT;			/* MAX consecutive media errors */
711556Srgrimesint rdblksz;				/* first read blksize (tapes only) */
721556Srgrimesoff_t wrlimit;				/* # of bytes written per archive vol */
731556Srgrimesoff_t wrcnt;				/* # of bytes written on current vol */
741556Srgrimesoff_t rdcnt;				/* # of bytes read on current vol */
751556Srgrimes
761556Srgrimes/*
771556Srgrimes * wr_start()
781556Srgrimes *	set up the buffering system to operate in a write mode
791556Srgrimes * Return:
801556Srgrimes *	0 if ok, -1 if the user specified write block size violates pax spec
811556Srgrimes */
821556Srgrimes
831556Srgrimesint
841556Srgrimeswr_start(void)
851556Srgrimes{
861556Srgrimes	buf = &(bufmem[BLKMULT]);
871556Srgrimes	/*
881556Srgrimes	 * Check to make sure the write block size meets pax specs. If the user
891556Srgrimes	 * does not specify a blocksize, we use the format default blocksize.
901556Srgrimes	 * We must be picky on writes, so we do not allow the user to create an
911556Srgrimes	 * archive that might be hard to read elsewhere. If all ok, we then
921556Srgrimes	 * open the first archive volume
931556Srgrimes	 */
948855Srgrimes	if (!wrblksz)
951556Srgrimes		wrblksz = frmt->bsz;
961556Srgrimes	if (wrblksz > MAXBLK) {
9776017Skris		paxwarn(1, "Write block size of %d too large, maximum is: %d",
981556Srgrimes			wrblksz, MAXBLK);
991556Srgrimes		return(-1);
1001556Srgrimes	}
1011556Srgrimes	if (wrblksz % BLKMULT) {
10276017Skris		paxwarn(1, "Write block size of %d is not a %d byte multiple",
1031556Srgrimes		    wrblksz, BLKMULT);
1041556Srgrimes		return(-1);
1051556Srgrimes	}
10676351Skris	if (wrblksz > MAXBLK_POSIX) {
10776351Skris		paxwarn(0, "Write block size of %d larger than POSIX max %d, archive may not be portable",
10876351Skris			wrblksz, MAXBLK_POSIX);
10976351Skris		return(-1);
11076351Skris	}
1111556Srgrimes
1121556Srgrimes	/*
1138855Srgrimes	 * we only allow wrblksz to be used with all archive operations
1141556Srgrimes	 */
1151556Srgrimes	blksz = rdblksz = wrblksz;
1161556Srgrimes	if ((ar_open(arcname) < 0) && (ar_next() < 0))
1171556Srgrimes		return(-1);
1181556Srgrimes	wrcnt = 0;
1191556Srgrimes	bufend = buf + wrblksz;
1201556Srgrimes	bufpt = buf;
1211556Srgrimes	return(0);
1221556Srgrimes}
1231556Srgrimes
1241556Srgrimes/*
1251556Srgrimes * rd_start()
1261556Srgrimes *	set up buffering system to read an archive
1271556Srgrimes * Return:
1281556Srgrimes *	0 if ok, -1 otherwise
1291556Srgrimes */
1301556Srgrimes
1311556Srgrimesint
1321556Srgrimesrd_start(void)
1331556Srgrimes{
1341556Srgrimes	/*
1351556Srgrimes	 * leave space for the header pushback (see get_arc()). If we are
1361556Srgrimes	 * going to append and user specified a write block size, check it
1371556Srgrimes	 * right away
1381556Srgrimes	 */
1391556Srgrimes	buf = &(bufmem[BLKMULT]);
1401556Srgrimes	if ((act == APPND) && wrblksz) {
1411556Srgrimes		if (wrblksz > MAXBLK) {
14276017Skris			paxwarn(1,"Write block size %d too large, maximum is: %d",
1431556Srgrimes				wrblksz, MAXBLK);
1441556Srgrimes			return(-1);
1451556Srgrimes		}
1461556Srgrimes		if (wrblksz % BLKMULT) {
14776017Skris			paxwarn(1, "Write block size %d is not a %d byte multiple",
148222177Suqs			wrblksz, BLKMULT);
1491556Srgrimes			return(-1);
1501556Srgrimes		}
1511556Srgrimes	}
1521556Srgrimes
1531556Srgrimes	/*
1541556Srgrimes	 * open the archive
1551556Srgrimes	 */
1561556Srgrimes	if ((ar_open(arcname) < 0) && (ar_next() < 0))
1571556Srgrimes		return(-1);
1581556Srgrimes	bufend = buf + rdblksz;
1591556Srgrimes	bufpt = bufend;
1601556Srgrimes	rdcnt = 0;
1611556Srgrimes	return(0);
1621556Srgrimes}
1631556Srgrimes
1641556Srgrimes/*
1651556Srgrimes * cp_start()
166102230Strhodes *	set up buffer system for copying within the file system
1671556Srgrimes */
1681556Srgrimes
1691556Srgrimesvoid
1701556Srgrimescp_start(void)
1711556Srgrimes{
1721556Srgrimes	buf = &(bufmem[BLKMULT]);
1731556Srgrimes	rdblksz = blksz = MAXBLK;
1741556Srgrimes}
1751556Srgrimes
1761556Srgrimes/*
1771556Srgrimes * appnd_start()
1781556Srgrimes *	Set up the buffering system to append new members to an archive that
1791556Srgrimes *	was just read. The last block(s) of an archive may contain a format
1801556Srgrimes *	specific trailer. To append a new member, this trailer has to be
1811556Srgrimes *	removed from the archive. The first byte of the trailer is replaced by
1821556Srgrimes *	the start of the header of the first file added to the archive. The
1831556Srgrimes *	format specific end read function tells us how many bytes to move
1841556Srgrimes *	backwards in the archive to be positioned BEFORE the trailer. Two
185222177Suqs *	different positions have to be adjusted, the O.S. file offset (e.g. the
1861556Srgrimes *	position of the tape head) and the write point within the data we have
1871556Srgrimes *	stored in the read (soon to become write) buffer. We may have to move
1881556Srgrimes *	back several records (the number depends on the size of the archive
1891556Srgrimes *	record and the size of the format trailer) to read up the record where
1901556Srgrimes *	the first byte of the trailer is recorded. Trailers may span (and
191222177Suqs *	overlap) record boundaries.
1921556Srgrimes *	We first calculate which record has the first byte of the trailer. We
1931556Srgrimes *	move the OS file offset back to the start of this record and read it
1941556Srgrimes *	up. We set the buffer write pointer to be at this byte (the byte where
1951556Srgrimes *	the trailer starts). We then move the OS file pointer back to the
1961556Srgrimes *	start of this record so a flush of this buffer will replace the record
1971556Srgrimes *	in the archive.
1981556Srgrimes *	A major problem is rewriting this last record. For archives stored
199222177Suqs *	on disk files, this is trivial. However, many devices are really picky
2001556Srgrimes *	about the conditions under which they will allow a write to occur.
2011556Srgrimes *	Often devices restrict the conditions where writes can be made writes,
202222177Suqs *	so it may not be feasible to append archives stored on all types of
2038855Srgrimes *	devices.
2041556Srgrimes * Return:
2051556Srgrimes *	0 for success, -1 for failure
2061556Srgrimes */
2071556Srgrimes
2081556Srgrimesint
2091556Srgrimesappnd_start(off_t skcnt)
2101556Srgrimes{
21190113Simp	int res;
2121556Srgrimes	off_t cnt;
2131556Srgrimes
2141556Srgrimes	if (exit_val != 0) {
21576017Skris		paxwarn(0, "Cannot append to an archive that may have flaws.");
2161556Srgrimes		return(-1);
2171556Srgrimes	}
2181556Srgrimes	/*
2191556Srgrimes	 * if the user did not specify a write blocksize, inherit the size used
2201556Srgrimes	 * in the last archive volume read. (If a is set we still use rdblksz
2211556Srgrimes	 * until next volume, cannot shift sizes within a single volume).
2221556Srgrimes	 */
2231556Srgrimes	if (!wrblksz)
2241556Srgrimes		wrblksz = blksz = rdblksz;
2251556Srgrimes	else
2261556Srgrimes		blksz = rdblksz;
2271556Srgrimes
2281556Srgrimes	/*
2291556Srgrimes	 * make sure that this volume allows appends
2301556Srgrimes	 */
2311556Srgrimes	if (ar_app_ok() < 0)
2321556Srgrimes		return(-1);
2331556Srgrimes
2341556Srgrimes	/*
2351556Srgrimes	 * Calculate bytes to move back and move in front of record where we
2361556Srgrimes	 * need to start writing from. Remember we have to add in any padding
2371556Srgrimes	 * that might be in the buffer after the trailer in the last block. We
2381556Srgrimes	 * travel skcnt + padding ROUNDED UP to blksize.
2391556Srgrimes	 */
2401556Srgrimes	skcnt += bufend - bufpt;
2411556Srgrimes	if ((cnt = (skcnt/blksz) * blksz) < skcnt)
2421556Srgrimes		cnt += blksz;
2431556Srgrimes	if (ar_rev((off_t)cnt) < 0)
2441556Srgrimes		goto out;
2451556Srgrimes
2461556Srgrimes	/*
2471556Srgrimes	 * We may have gone too far if there is valid data in the block we are
2481556Srgrimes	 * now in front of, read up the block and position the pointer after
2491556Srgrimes	 * the valid data.
2501556Srgrimes	 */
2511556Srgrimes	if ((cnt -= skcnt) > 0) {
2521556Srgrimes		/*
2531556Srgrimes		 * watch out for stupid tape drives. ar_rev() will set rdblksz
2541556Srgrimes		 * to be real physical blocksize so we must loop until we get
2551556Srgrimes		 * the old rdblksz (now in blksz). If ar_rev() fouls up the
2561556Srgrimes		 * determination of the physical block size, we will fail.
2571556Srgrimes		 */
2581556Srgrimes		bufpt = buf;
2591556Srgrimes		bufend = buf + blksz;
2601556Srgrimes		while (bufpt < bufend) {
2611556Srgrimes			if ((res = ar_read(bufpt, rdblksz)) <= 0)
2621556Srgrimes				goto out;
2631556Srgrimes			bufpt += res;
2641556Srgrimes		}
2651556Srgrimes		if (ar_rev((off_t)(bufpt - buf)) < 0)
2661556Srgrimes			goto out;
2671556Srgrimes		bufpt = buf + cnt;
2681556Srgrimes		bufend = buf + blksz;
2691556Srgrimes	} else {
2701556Srgrimes		/*
2711556Srgrimes		 * buffer is empty
2721556Srgrimes		 */
2731556Srgrimes		bufend = buf + blksz;
2741556Srgrimes		bufpt = buf;
2751556Srgrimes	}
2761556Srgrimes	rdblksz = blksz;
2771556Srgrimes	rdcnt -= skcnt;
2781556Srgrimes	wrcnt = 0;
2791556Srgrimes
2801556Srgrimes	/*
2811556Srgrimes	 * At this point we are ready to write. If the device requires special
2821556Srgrimes	 * handling to write at a point were previously recorded data resides,
2831556Srgrimes	 * that is handled in ar_set_wr(). From now on we operate under normal
2841556Srgrimes	 * ARCHIVE mode (write) conditions
2851556Srgrimes	 */
2861556Srgrimes	if (ar_set_wr() < 0)
2871556Srgrimes		return(-1);
2881556Srgrimes	act = ARCHIVE;
2891556Srgrimes	return(0);
2901556Srgrimes
2911556Srgrimes    out:
29276017Skris	paxwarn(1, "Unable to rewrite archive trailer, cannot append.");
2931556Srgrimes	return(-1);
2941556Srgrimes}
29576019Skris
2961556Srgrimes/*
2971556Srgrimes * rd_sync()
2981556Srgrimes *	A read error occurred on this archive volume. Resync the buffer and
2991556Srgrimes *	try to reset the device (if possible) so we can continue to read. Keep
3001556Srgrimes *	trying to do this until we get a valid read, or we reach the limit on
3011556Srgrimes *	consecutive read faults (at which point we give up). The user can
3021556Srgrimes *	adjust the read error limit through a command line option.
3031556Srgrimes * Returns:
3041556Srgrimes *	0 on success, and -1 on failure
3051556Srgrimes */
3061556Srgrimes
3071556Srgrimesint
3081556Srgrimesrd_sync(void)
3091556Srgrimes{
31090113Simp	int errcnt = 0;
31190113Simp	int res;
3121556Srgrimes
3131556Srgrimes	/*
3141556Srgrimes	 * if the user says bail out on first fault, we are out of here...
3151556Srgrimes	 */
3161556Srgrimes	if (maxflt == 0)
3171556Srgrimes		return(-1);
3181556Srgrimes	if (act == APPND) {
31976017Skris		paxwarn(1, "Unable to append when there are archive read errors.");
3201556Srgrimes		return(-1);
3211556Srgrimes	}
3221556Srgrimes
3231556Srgrimes	/*
3241556Srgrimes	 * poke at device and try to get past media error
3251556Srgrimes	 */
3261556Srgrimes	if (ar_rdsync() < 0) {
3271556Srgrimes		if (ar_next() < 0)
3281556Srgrimes			return(-1);
3291556Srgrimes		else
3301556Srgrimes			rdcnt = 0;
3311556Srgrimes	}
3321556Srgrimes
3331556Srgrimes	for (;;) {
3341556Srgrimes		if ((res = ar_read(buf, blksz)) > 0) {
3351556Srgrimes			/*
3361556Srgrimes			 * All right! got some data, fill that buffer
3371556Srgrimes			 */
3381556Srgrimes			bufpt = buf;
3391556Srgrimes			bufend = buf + res;
3401556Srgrimes			rdcnt += res;
3411556Srgrimes			return(0);
3421556Srgrimes		}
3431556Srgrimes
3441556Srgrimes		/*
3451556Srgrimes		 * Oh well, yet another failed read...
3461556Srgrimes		 * if error limit reached, ditch. o.w. poke device to move past
3471556Srgrimes		 * bad media and try again. if media is badly damaged, we ask
3481556Srgrimes		 * the poor (and upset user at this point) for the next archive
3491556Srgrimes		 * volume. remember the goal on reads is to get the most we
3501556Srgrimes		 * can extract out of the archive.
3511556Srgrimes		 */
3521556Srgrimes		if ((maxflt > 0) && (++errcnt > maxflt))
35376017Skris			paxwarn(0,"Archive read error limit (%d) reached",maxflt);
3541556Srgrimes		else if (ar_rdsync() == 0)
3551556Srgrimes			continue;
3561556Srgrimes		if (ar_next() < 0)
3571556Srgrimes			break;
3581556Srgrimes		rdcnt = 0;
3591556Srgrimes		errcnt = 0;
3601556Srgrimes	}
3611556Srgrimes	return(-1);
3621556Srgrimes}
3631556Srgrimes
3641556Srgrimes/*
3651556Srgrimes * pback()
3661556Srgrimes *	push the data used during the archive id phase back into the I/O
3671556Srgrimes *	buffer. This is required as we cannot be sure that the header does NOT
368222177Suqs *	overlap a block boundary (as in the case we are trying to recover a
3691556Srgrimes *	flawed archived). This was not designed to be used for any other
3701556Srgrimes *	purpose. (What software engineering, HA!)
3711556Srgrimes *	WARNING: do not even THINK of pback greater than BLKMULT, unless the
3721556Srgrimes *	pback space is increased.
3731556Srgrimes */
3741556Srgrimes
3751556Srgrimesvoid
3761556Srgrimespback(char *pt, int cnt)
3771556Srgrimes{
3781556Srgrimes	bufpt -= cnt;
37976017Skris	memcpy(bufpt, pt, cnt);
3801556Srgrimes	return;
3811556Srgrimes}
3821556Srgrimes
3831556Srgrimes/*
3841556Srgrimes * rd_skip()
385222177Suqs *	skip forward in the archive during an archive read. Used to get quickly
3861556Srgrimes *	past file data and padding for files the user did NOT select.
3871556Srgrimes * Return:
3881556Srgrimes *	0 if ok, -1 failure, and 1 when EOF on the archive volume was detected.
3891556Srgrimes */
3901556Srgrimes
3911556Srgrimesint
3921556Srgrimesrd_skip(off_t skcnt)
3931556Srgrimes{
3941556Srgrimes	off_t res;
3951556Srgrimes	off_t cnt;
3961556Srgrimes	off_t skipped = 0;
3971556Srgrimes
3981556Srgrimes	/*
399222177Suqs	 * consume what data we have in the buffer. If we have to move forward
4001556Srgrimes	 * whole records, we call the low level skip function to see if we can
4011556Srgrimes	 * move within the archive without doing the expensive reads on data we
4021556Srgrimes	 * do not want.
4031556Srgrimes	 */
4041556Srgrimes	if (skcnt == 0)
4051556Srgrimes		return(0);
4061556Srgrimes	res = MIN((bufend - bufpt), skcnt);
4071556Srgrimes	bufpt += res;
4081556Srgrimes	skcnt -= res;
4091556Srgrimes
4101556Srgrimes	/*
4111556Srgrimes	 * if skcnt is now 0, then no additional i/o is needed
4121556Srgrimes	 */
4131556Srgrimes	if (skcnt == 0)
4141556Srgrimes		return(0);
4151556Srgrimes
4161556Srgrimes	/*
4171556Srgrimes	 * We have to read more, calculate complete and partial record reads
4181556Srgrimes	 * based on rdblksz. we skip over "cnt" complete records
4191556Srgrimes	 */
4201556Srgrimes	res = skcnt%rdblksz;
4211556Srgrimes	cnt = (skcnt/rdblksz) * rdblksz;
4221556Srgrimes
4231556Srgrimes	/*
4241556Srgrimes	 * if the skip fails, we will have to resync. ar_fow will tell us
4251556Srgrimes	 * how much it can skip over. We will have to read the rest.
4261556Srgrimes	 */
4271556Srgrimes	if (ar_fow(cnt, &skipped) < 0)
4281556Srgrimes		return(-1);
4291556Srgrimes	res += cnt - skipped;
4301556Srgrimes	rdcnt += skipped;
4311556Srgrimes
4321556Srgrimes	/*
4331556Srgrimes	 * what is left we have to read (which may be the whole thing if
4341556Srgrimes	 * ar_fow() told us the device can only read to skip records);
4351556Srgrimes	 */
4361556Srgrimes	while (res > 0L) {
4371556Srgrimes		cnt = bufend - bufpt;
4381556Srgrimes		/*
4391556Srgrimes		 * if the read fails, we will have to resync
4401556Srgrimes		 */
4411556Srgrimes		if ((cnt <= 0) && ((cnt = buf_fill()) < 0))
4421556Srgrimes			return(-1);
4431556Srgrimes		if (cnt == 0)
4441556Srgrimes			return(1);
4451556Srgrimes		cnt = MIN(cnt, res);
4461556Srgrimes		bufpt += cnt;
4471556Srgrimes		res -= cnt;
4481556Srgrimes	}
4491556Srgrimes	return(0);
4501556Srgrimes}
4511556Srgrimes
4528855Srgrimes/*
4531556Srgrimes * wr_fin()
4541556Srgrimes *	flush out any data (and pad if required) the last block. We always pad
4551556Srgrimes *	with zero (even though we do not have to). Padding with 0 makes it a
456222177Suqs *	lot easier to recover if the archive is damaged. zero padding SHOULD
4571556Srgrimes *	BE a requirement....
4581556Srgrimes */
4591556Srgrimes
4601556Srgrimesvoid
4611556Srgrimeswr_fin(void)
4621556Srgrimes{
4631556Srgrimes	if (bufpt > buf) {
46476017Skris		memset(bufpt, 0, bufend - bufpt);
4651556Srgrimes		bufpt = bufend;
4661556Srgrimes		(void)buf_flush(blksz);
4671556Srgrimes	}
4681556Srgrimes}
4691556Srgrimes
4701556Srgrimes/*
4711556Srgrimes * wr_rdbuf()
4721556Srgrimes *	fill the write buffer from data passed to it in a buffer (usually used
4731556Srgrimes *	by format specific write routines to pass a file header). On failure we
4741556Srgrimes *	punt. We do not allow the user to continue to write flawed archives.
4751556Srgrimes *	We assume these headers are not very large (the memory copy we use is
4768855Srgrimes *	a bit expensive).
4771556Srgrimes * Return:
4781556Srgrimes *	0 if buffer was filled ok, -1 o.w. (buffer flush failure)
4791556Srgrimes */
4801556Srgrimes
4811556Srgrimesint
48290113Simpwr_rdbuf(char *out, int outcnt)
4831556Srgrimes{
48490113Simp	int cnt;
4851556Srgrimes
4861556Srgrimes	/*
4871556Srgrimes	 * while there is data to copy copy into the write buffer. when the
4881556Srgrimes	 * write buffer fills, flush it to the archive and continue
4891556Srgrimes	 */
4901556Srgrimes	while (outcnt > 0) {
4911556Srgrimes		cnt = bufend - bufpt;
4921556Srgrimes		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0))
4931556Srgrimes			return(-1);
4941556Srgrimes		/*
4951556Srgrimes		 * only move what we have space for
4961556Srgrimes		 */
4971556Srgrimes		cnt = MIN(cnt, outcnt);
49876017Skris		memcpy(bufpt, out, cnt);
4991556Srgrimes		bufpt += cnt;
5001556Srgrimes		out += cnt;
5011556Srgrimes		outcnt -= cnt;
5021556Srgrimes	}
5031556Srgrimes	return(0);
5041556Srgrimes}
5051556Srgrimes
5061556Srgrimes/*
5071556Srgrimes * rd_wrbuf()
5081556Srgrimes *	copy from the read buffer into a supplied buffer a specified number of
5091556Srgrimes *	bytes. If the read buffer is empty fill it and continue to copy.
5101556Srgrimes *	usually used to obtain a file header for processing by a format
5111556Srgrimes *	specific read routine.
5121556Srgrimes * Return
5131556Srgrimes *	number of bytes copied to the buffer, 0 indicates EOF on archive volume,
5141556Srgrimes *	-1 is a read error
5151556Srgrimes */
5161556Srgrimes
5171556Srgrimesint
51890113Simprd_wrbuf(char *in, int cpcnt)
5191556Srgrimes{
52090113Simp	int res;
52190113Simp	int cnt;
52290113Simp	int incnt = cpcnt;
5231556Srgrimes
5241556Srgrimes	/*
5251556Srgrimes	 * loop until we fill the buffer with the requested number of bytes
5261556Srgrimes	 */
5271556Srgrimes	while (incnt > 0) {
5281556Srgrimes		cnt = bufend - bufpt;
5291556Srgrimes		if ((cnt <= 0) && ((cnt = buf_fill()) <= 0)) {
5301556Srgrimes			/*
5311556Srgrimes			 * read error, return what we got (or the error if
5321556Srgrimes			 * no data was copied). The caller must know that an
533222177Suqs			 * error occurred and has the best knowledge what to
5341556Srgrimes			 * do with it
5351556Srgrimes			 */
5361556Srgrimes			if ((res = cpcnt - incnt) > 0)
5371556Srgrimes				return(res);
5381556Srgrimes			return(cnt);
5391556Srgrimes		}
5401556Srgrimes
5411556Srgrimes		/*
5421556Srgrimes		 * calculate how much data to copy based on whats left and
5431556Srgrimes		 * state of buffer
5441556Srgrimes		 */
5451556Srgrimes		cnt = MIN(cnt, incnt);
54676017Skris		memcpy(in, bufpt, cnt);
5471556Srgrimes		bufpt += cnt;
5481556Srgrimes		incnt -= cnt;
5491556Srgrimes		in += cnt;
5501556Srgrimes	}
5511556Srgrimes	return(cpcnt);
5521556Srgrimes}
5531556Srgrimes
5541556Srgrimes/*
5551556Srgrimes * wr_skip()
55646684Skris *	skip forward during a write. In other words add padding to the file.
5571556Srgrimes *	we add zero filled padding as it makes flawed archives much easier to
5581556Srgrimes *	recover from. the caller tells us how many bytes of padding to add
5591556Srgrimes *	This routine was not designed to add HUGE amount of padding, just small
5601556Srgrimes *	amounts (a few 512 byte blocks at most)
5611556Srgrimes * Return:
5621556Srgrimes *	0 if ok, -1 if there was a buf_flush failure
5631556Srgrimes */
5641556Srgrimes
5651556Srgrimesint
5661556Srgrimeswr_skip(off_t skcnt)
5671556Srgrimes{
56890113Simp	int cnt;
5691556Srgrimes
5701556Srgrimes	/*
5711556Srgrimes	 * loop while there is more padding to add
5721556Srgrimes	 */
5731556Srgrimes	while (skcnt > 0L) {
5741556Srgrimes		cnt = bufend - bufpt;
5751556Srgrimes		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0))
5761556Srgrimes			return(-1);
5771556Srgrimes		cnt = MIN(cnt, skcnt);
57876017Skris		memset(bufpt, 0, cnt);
5791556Srgrimes		bufpt += cnt;
5801556Srgrimes		skcnt -= cnt;
5811556Srgrimes	}
5821556Srgrimes	return(0);
5831556Srgrimes}
5841556Srgrimes
5851556Srgrimes/*
5861556Srgrimes * wr_rdfile()
587222177Suqs *	fill write buffer with the contents of a file. We are passed an open
588100012Skeramida *	file descriptor to the file and the archive structure that describes the
5891556Srgrimes *	file we are storing. The variable "left" is modified to contain the
5901556Srgrimes *	number of bytes of the file we were NOT able to write to the archive.
5911556Srgrimes *	it is important that we always write EXACTLY the number of bytes that
5921556Srgrimes *	the format specific write routine told us to. The file can also get
5931556Srgrimes *	bigger, so reading to the end of file would create an improper archive,
59476017Skris *	we just detect this case and warn the user. We never create a bad
5951556Srgrimes *	archive if we can avoid it. Of course trying to archive files that are
5961556Srgrimes *	active is asking for trouble. It we fail, we pass back how much we
5971556Srgrimes *	could NOT copy and let the caller deal with it.
5981556Srgrimes * Return:
5991556Srgrimes *	0 ok, -1 if archive write failure. a short read of the file returns a
6001556Srgrimes *	0, but "left" is set to be greater than zero.
6011556Srgrimes */
6021556Srgrimes
6031556Srgrimesint
6041556Srgrimeswr_rdfile(ARCHD *arcn, int ifd, off_t *left)
6051556Srgrimes{
60690113Simp	int cnt;
60790113Simp	int res = 0;
60890113Simp	off_t size = arcn->sb.st_size;
6091556Srgrimes	struct stat sb;
6101556Srgrimes
6111556Srgrimes	/*
6121556Srgrimes	 * while there are more bytes to write
6131556Srgrimes	 */
6141556Srgrimes	while (size > 0L) {
6151556Srgrimes		cnt = bufend - bufpt;
6161556Srgrimes		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) {
6171556Srgrimes			*left = size;
6181556Srgrimes			return(-1);
6191556Srgrimes		}
6201556Srgrimes		cnt = MIN(cnt, size);
6211556Srgrimes		if ((res = read(ifd, bufpt, cnt)) <= 0)
6221556Srgrimes			break;
6231556Srgrimes		size -= res;
6241556Srgrimes		bufpt += res;
6251556Srgrimes	}
6261556Srgrimes
6271556Srgrimes	/*
6281556Srgrimes	 * better check the file did not change during this operation
6291556Srgrimes	 * or the file read failed.
6301556Srgrimes	 */
6311556Srgrimes	if (res < 0)
63276017Skris		syswarn(1, errno, "Read fault on %s", arcn->org_name);
6331556Srgrimes	else if (size != 0L)
63476017Skris		paxwarn(1, "File changed size during read %s", arcn->org_name);
6351556Srgrimes	else if (fstat(ifd, &sb) < 0)
63676017Skris		syswarn(1, errno, "Failed stat on %s", arcn->org_name);
6371556Srgrimes	else if (arcn->sb.st_mtime != sb.st_mtime)
63876017Skris		paxwarn(1, "File %s was modified during copy to archive",
6391556Srgrimes			arcn->org_name);
6401556Srgrimes	*left = size;
6411556Srgrimes	return(0);
6421556Srgrimes}
6431556Srgrimes
6441556Srgrimes/*
6451556Srgrimes * rd_wrfile()
6461556Srgrimes *	extract the contents of a file from the archive. If we are unable to
6471556Srgrimes *	extract the entire file (due to failure to write the file) we return
6481556Srgrimes *	the numbers of bytes we did NOT process. This way the caller knows how
6491556Srgrimes *	many bytes to skip past to find the next archive header. If the failure
6501556Srgrimes *	was due to an archive read, we will catch that when we try to skip. If
6511556Srgrimes *	the format supplies a file data crc value, we calculate the actual crc
6521556Srgrimes *	so that it can be compared to the value stored in the header
6531556Srgrimes * NOTE:
6541556Srgrimes *	We call a special function to write the file. This function attempts to
6551556Srgrimes *	restore file holes (blocks of zeros) into the file. When files are
6561556Srgrimes *	sparse this saves space, and is a LOT faster. For non sparse files
6571556Srgrimes *	the performance hit is small. As of this writing, no archive supports
6581556Srgrimes *	information on where the file holes are.
6591556Srgrimes * Return:
6601556Srgrimes *	0 ok, -1 if archive read failure. if we cannot write the entire file,
6611556Srgrimes *	we return a 0 but "left" is set to be the amount unwritten
6621556Srgrimes */
6631556Srgrimes
6641556Srgrimesint
6651556Srgrimesrd_wrfile(ARCHD *arcn, int ofd, off_t *left)
6661556Srgrimes{
66790113Simp	int cnt = 0;
66890113Simp	off_t size = arcn->sb.st_size;
66990113Simp	int res = 0;
67090113Simp	char *fnm = arcn->name;
6711556Srgrimes	int isem = 1;
6721556Srgrimes	int rem;
6731556Srgrimes	int sz = MINFBSZ;
674222177Suqs	struct stat sb;
6751556Srgrimes	u_long crc = 0L;
6761556Srgrimes
6771556Srgrimes	/*
6781556Srgrimes	 * pass the blocksize of the file being written to the write routine,
6791556Srgrimes	 * if the size is zero, use the default MINFBSZ
6801556Srgrimes	 */
68176019Skris	if (fstat(ofd, &sb) == 0) {
6821556Srgrimes		if (sb.st_blksize > 0)
6831556Srgrimes			sz = (int)sb.st_blksize;
68476019Skris	} else
68576019Skris		syswarn(0,errno,"Unable to obtain block size for file %s",fnm);
6861556Srgrimes	rem = sz;
6871556Srgrimes	*left = 0L;
6881556Srgrimes
6891556Srgrimes	/*
6901556Srgrimes	 * Copy the archive to the file the number of bytes specified. We have
6911556Srgrimes	 * to assume that we want to recover file holes as none of the archive
6921556Srgrimes	 * formats can record the location of file holes.
6931556Srgrimes	 */
6941556Srgrimes	while (size > 0L) {
6951556Srgrimes		cnt = bufend - bufpt;
6961556Srgrimes		/*
6971556Srgrimes		 * if we get a read error, we do not want to skip, as we may
6981556Srgrimes		 * miss a header, so we do not set left, but if we get a write
6991556Srgrimes		 * error, we do want to skip over the unprocessed data.
7001556Srgrimes		 */
7011556Srgrimes		if ((cnt <= 0) && ((cnt = buf_fill()) <= 0))
7021556Srgrimes			break;
7031556Srgrimes		cnt = MIN(cnt, size);
7041556Srgrimes		if ((res = file_write(ofd,bufpt,cnt,&rem,&isem,sz,fnm)) <= 0) {
7051556Srgrimes			*left = size;
7061556Srgrimes			break;
7071556Srgrimes		}
7081556Srgrimes
7091556Srgrimes		if (docrc) {
7101556Srgrimes			/*
7111556Srgrimes			 * update the actual crc value
7121556Srgrimes			 */
7131556Srgrimes			cnt = res;
7141556Srgrimes			while (--cnt >= 0)
7151556Srgrimes				crc += *bufpt++ & 0xff;
7161556Srgrimes		} else
7171556Srgrimes			bufpt += res;
7181556Srgrimes		size -= res;
7191556Srgrimes	}
7201556Srgrimes
7211556Srgrimes	/*
7221556Srgrimes	 * if the last block has a file hole (all zero), we must make sure this
7231556Srgrimes	 * gets updated in the file. We force the last block of zeros to be
72446684Skris	 * written. just closing with the file offset moved forward may not put
7251556Srgrimes	 * a hole at the end of the file.
7261556Srgrimes	 */
7271556Srgrimes	if (isem && (arcn->sb.st_size > 0L))
7281556Srgrimes		file_flush(ofd, fnm, isem);
7291556Srgrimes
7301556Srgrimes	/*
7311556Srgrimes	 * if we failed from archive read, we do not want to skip
7321556Srgrimes	 */
7338855Srgrimes	if ((size > 0L) && (*left == 0L))
7341556Srgrimes		return(-1);
7351556Srgrimes
7361556Srgrimes	/*
7371556Srgrimes	 * some formats record a crc on file data. If so, then we compare the
7381556Srgrimes	 * calculated crc to the crc stored in the archive
7391556Srgrimes	 */
7401556Srgrimes	if (docrc && (size == 0L) && (arcn->crc != crc))
74176017Skris		paxwarn(1,"Actual crc does not match expected crc %s",arcn->name);
7421556Srgrimes	return(0);
7431556Srgrimes}
7441556Srgrimes
7451556Srgrimes/*
7461556Srgrimes * cp_file()
7471556Srgrimes *	copy the contents of one file to another. used during -rw phase of pax
7481556Srgrimes *	just as in rd_wrfile() we use a special write function to write the
7491556Srgrimes *	destination file so we can properly copy files with holes.
7501556Srgrimes */
7511556Srgrimes
7521556Srgrimesvoid
7531556Srgrimescp_file(ARCHD *arcn, int fd1, int fd2)
7541556Srgrimes{
75590113Simp	int cnt;
75690113Simp	off_t cpcnt = 0L;
75790113Simp	int res = 0;
75890113Simp	char *fnm = arcn->name;
75990113Simp	int no_hole = 0;
7601556Srgrimes	int isem = 1;
7611556Srgrimes	int rem;
7621556Srgrimes	int sz = MINFBSZ;
7631556Srgrimes	struct stat sb;
7641556Srgrimes
7651556Srgrimes	/*
7661556Srgrimes	 * check for holes in the source file. If none, we will use regular
7671556Srgrimes	 * write instead of file write.
7681556Srgrimes	 */
7691556Srgrimes	 if (((off_t)(arcn->sb.st_blocks * BLKMULT)) >= arcn->sb.st_size)
7701556Srgrimes		++no_hole;
7711556Srgrimes
7721556Srgrimes	/*
7731556Srgrimes	 * pass the blocksize of the file being written to the write routine,
7741556Srgrimes	 * if the size is zero, use the default MINFBSZ
7751556Srgrimes	 */
77676019Skris	if (fstat(fd2, &sb) == 0) {
7771556Srgrimes		if (sb.st_blksize > 0)
7781556Srgrimes			sz = sb.st_blksize;
77976019Skris	} else
78076019Skris		syswarn(0,errno,"Unable to obtain block size for file %s",fnm);
7811556Srgrimes	rem = sz;
7821556Srgrimes
7831556Srgrimes	/*
7841556Srgrimes	 * read the source file and copy to destination file until EOF
7851556Srgrimes	 */
7861556Srgrimes	for(;;) {
7871556Srgrimes		if ((cnt = read(fd1, buf, blksz)) <= 0)
7881556Srgrimes			break;
7891556Srgrimes		if (no_hole)
7901556Srgrimes			res = write(fd2, buf, cnt);
7911556Srgrimes		else
7921556Srgrimes			res = file_write(fd2, buf, cnt, &rem, &isem, sz, fnm);
7931556Srgrimes		if (res != cnt)
7941556Srgrimes			break;
7951556Srgrimes		cpcnt += cnt;
7961556Srgrimes	}
7971556Srgrimes
7981556Srgrimes	/*
7991556Srgrimes	 * check to make sure the copy is valid.
8001556Srgrimes	 */
8011556Srgrimes	if (res < 0)
80276017Skris		syswarn(1, errno, "Failed write during copy of %s to %s",
8031556Srgrimes			arcn->org_name, arcn->name);
8041556Srgrimes	else if (cpcnt != arcn->sb.st_size)
80576017Skris		paxwarn(1, "File %s changed size during copy to %s",
8061556Srgrimes			arcn->org_name, arcn->name);
8071556Srgrimes	else if (fstat(fd1, &sb) < 0)
80876017Skris		syswarn(1, errno, "Failed stat of %s", arcn->org_name);
8091556Srgrimes	else if (arcn->sb.st_mtime != sb.st_mtime)
81076017Skris		paxwarn(1, "File %s was modified during copy to %s",
8111556Srgrimes			arcn->org_name, arcn->name);
8121556Srgrimes
8131556Srgrimes	/*
8141556Srgrimes	 * if the last block has a file hole (all zero), we must make sure this
8151556Srgrimes	 * gets updated in the file. We force the last block of zeros to be
81646684Skris	 * written. just closing with the file offset moved forward may not put
8171556Srgrimes	 * a hole at the end of the file.
8181556Srgrimes	 */
8191556Srgrimes	if (!no_hole && isem && (arcn->sb.st_size > 0L))
8201556Srgrimes		file_flush(fd2, fnm, isem);
8211556Srgrimes	return;
8221556Srgrimes}
8231556Srgrimes
8241556Srgrimes/*
8251556Srgrimes * buf_fill()
8261556Srgrimes *	fill the read buffer with the next record (or what we can get) from
8271556Srgrimes *	the archive volume.
8281556Srgrimes * Return:
8291556Srgrimes *	Number of bytes of data in the read buffer, -1 for read error, and
8301556Srgrimes *	0 when finished (user specified termination in ar_next()).
8311556Srgrimes */
8321556Srgrimes
8331556Srgrimesint
8341556Srgrimesbuf_fill(void)
8351556Srgrimes{
83690113Simp	int cnt;
8371556Srgrimes	static int fini = 0;
8381556Srgrimes
8391556Srgrimes	if (fini)
8401556Srgrimes		return(0);
8411556Srgrimes
8421556Srgrimes	for(;;) {
8431556Srgrimes		/*
8441556Srgrimes		 * try to fill the buffer. on error the next archive volume is
8451556Srgrimes		 * opened and we try again.
8461556Srgrimes		 */
8471556Srgrimes		if ((cnt = ar_read(buf, blksz)) > 0) {
8481556Srgrimes			bufpt = buf;
8491556Srgrimes			bufend = buf + cnt;
8501556Srgrimes			rdcnt += cnt;
8511556Srgrimes			return(cnt);
8521556Srgrimes		}
8531556Srgrimes
8541556Srgrimes		/*
8551556Srgrimes		 * errors require resync, EOF goes to next archive
8561556Srgrimes		 */
8571556Srgrimes		if (cnt < 0)
8581556Srgrimes			break;
8591556Srgrimes		if (ar_next() < 0) {
8601556Srgrimes			fini = 1;
8611556Srgrimes			return(0);
8621556Srgrimes		}
8631556Srgrimes		rdcnt = 0;
8641556Srgrimes	}
8651556Srgrimes	exit_val = 1;
8661556Srgrimes	return(-1);
8671556Srgrimes}
8681556Srgrimes
8691556Srgrimes/*
8701556Srgrimes * buf_flush()
8711556Srgrimes *	force the write buffer to the archive. We are passed the number of
8721556Srgrimes *	bytes in the buffer at the point of the flush. When we change archives
8731556Srgrimes *	the record size might change. (either larger or smaller).
8741556Srgrimes * Return:
8751556Srgrimes *	0 if all is ok, -1 when a write error occurs.
8761556Srgrimes */
8771556Srgrimes
8781556Srgrimesint
87990113Simpbuf_flush(int bufcnt)
8801556Srgrimes{
88190113Simp	int cnt;
88290113Simp	int push = 0;
88390113Simp	int totcnt = 0;
8841556Srgrimes
8851556Srgrimes	/*
8861556Srgrimes	 * if we have reached the user specified byte count for each archive
887222177Suqs	 * volume, prompt for the next volume. (The non-standard -R flag).
8881556Srgrimes	 * NOTE: If the wrlimit is smaller than wrcnt, we will always write
8891556Srgrimes	 * at least one record. We always round limit UP to next blocksize.
8901556Srgrimes	 */
8911556Srgrimes	if ((wrlimit > 0) && (wrcnt > wrlimit)) {
89276017Skris		paxwarn(0, "User specified archive volume byte limit reached.");
8931556Srgrimes		if (ar_next() < 0) {
8941556Srgrimes			wrcnt = 0;
8951556Srgrimes			exit_val = 1;
8961556Srgrimes			return(-1);
8971556Srgrimes		}
8981556Srgrimes		wrcnt = 0;
8991556Srgrimes
9001556Srgrimes		/*
9011556Srgrimes		 * The new archive volume might have changed the size of the
9021556Srgrimes		 * write blocksize. if so we figure out if we need to write
9031556Srgrimes		 * (one or more times), or if there is now free space left in
9041556Srgrimes		 * the buffer (it is no longer full). bufcnt has the number of
9051556Srgrimes		 * bytes in the buffer, (the blocksize, at the point we were
9061556Srgrimes		 * CALLED). Push has the amount of "extra" data in the buffer
9071556Srgrimes		 * if the block size has shrunk from a volume change.
9081556Srgrimes		 */
9091556Srgrimes		bufend = buf + blksz;
9101556Srgrimes		if (blksz > bufcnt)
9111556Srgrimes			return(0);
9121556Srgrimes		if (blksz < bufcnt)
9131556Srgrimes			push = bufcnt - blksz;
9141556Srgrimes	}
9151556Srgrimes
9161556Srgrimes	/*
9171556Srgrimes	 * We have enough data to write at least one archive block
9181556Srgrimes	 */
9191556Srgrimes	for (;;) {
9201556Srgrimes		/*
9211556Srgrimes		 * write a block and check if it all went out ok
9221556Srgrimes		 */
9238855Srgrimes		cnt = ar_write(buf, blksz);
9241556Srgrimes		if (cnt == blksz) {
9251556Srgrimes			/*
9261556Srgrimes			 * the write went ok
9271556Srgrimes			 */
9281556Srgrimes			wrcnt += cnt;
9291556Srgrimes			totcnt += cnt;
9301556Srgrimes			if (push > 0) {
9311556Srgrimes				/* we have extra data to push to the front.
9321556Srgrimes				 * check for more than 1 block of push, and if
9331556Srgrimes				 * so we loop back to write again
9341556Srgrimes				 */
93576017Skris				memcpy(buf, bufend, push);
9361556Srgrimes				bufpt = buf + push;
9371556Srgrimes				if (push >= blksz) {
9381556Srgrimes					push -= blksz;
9391556Srgrimes					continue;
9401556Srgrimes				}
9411556Srgrimes			} else
9421556Srgrimes				bufpt = buf;
9431556Srgrimes			return(totcnt);
9441556Srgrimes		} else if (cnt > 0) {
9451556Srgrimes			/*
9461556Srgrimes			 * Oh drat we got a partial write!
947222177Suqs			 * if format doesn't care about alignment let it go,
94876017Skris			 * we warned the user in ar_write().... but this means
9491556Srgrimes			 * the last record on this volume violates pax spec....
9501556Srgrimes			 */
9511556Srgrimes			totcnt += cnt;
9521556Srgrimes			wrcnt += cnt;
9531556Srgrimes			bufpt = buf + cnt;
9541556Srgrimes			cnt = bufcnt - cnt;
95576017Skris			memcpy(buf, bufpt, cnt);
9561556Srgrimes			bufpt = buf + cnt;
9571556Srgrimes			if (!frmt->blkalgn || ((cnt % frmt->blkalgn) == 0))
9581556Srgrimes				return(totcnt);
9591556Srgrimes			break;
9601556Srgrimes		}
9611556Srgrimes
9621556Srgrimes		/*
9631556Srgrimes		 * All done, go to next archive
9641556Srgrimes		 */
9651556Srgrimes		wrcnt = 0;
9661556Srgrimes		if (ar_next() < 0)
9671556Srgrimes			break;
9681556Srgrimes
9691556Srgrimes		/*
9701556Srgrimes		 * The new archive volume might also have changed the block
9711556Srgrimes		 * size. if so, figure out if we have too much or too little
9721556Srgrimes		 * data for using the new block size
9731556Srgrimes		 */
9741556Srgrimes		bufend = buf + blksz;
9751556Srgrimes		if (blksz > bufcnt)
9761556Srgrimes			return(0);
9771556Srgrimes		if (blksz < bufcnt)
9781556Srgrimes			push = bufcnt - blksz;
9791556Srgrimes	}
9801556Srgrimes
9811556Srgrimes	/*
9821556Srgrimes	 * write failed, stop pax. we must not create a bad archive!
9831556Srgrimes	 */
9841556Srgrimes	exit_val = 1;
9851556Srgrimes	return(-1);
9861556Srgrimes}
987