buf_subs.c revision 46684
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 * 3. All advertising materials mentioning features or use of this software
181556Srgrimes *    must display the following acknowledgement:
191556Srgrimes *	This product includes software developed by the University of
201556Srgrimes *	California, Berkeley and its contributors.
211556Srgrimes * 4. Neither the name of the University nor the names of its contributors
221556Srgrimes *    may be used to endorse or promote products derived from this software
231556Srgrimes *    without specific prior written permission.
241556Srgrimes *
251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
351556Srgrimes * SUCH DAMAGE.
361556Srgrimes */
371556Srgrimes
381556Srgrimes#ifndef lint
3936049Scharnier#if 0
4036049Scharnierstatic char sccsid[] = "@(#)buf_subs.c	8.2 (Berkeley) 4/18/94";
4136049Scharnier#endif
4236049Scharnierstatic const char rcsid[] =
4346684Skris	"$Id: buf_subs.c,v 1.10 1998/05/15 06:27:37 charnier Exp $";
441556Srgrimes#endif /* not lint */
451556Srgrimes
461556Srgrimes#include <sys/types.h>
471556Srgrimes#include <sys/stat.h>
481556Srgrimes#include <errno.h>
491556Srgrimes#include <unistd.h>
501556Srgrimes#include <stdlib.h>
511556Srgrimes#include <string.h>
521556Srgrimes#include "pax.h"
531556Srgrimes#include "extern.h"
541556Srgrimes
551556Srgrimes/*
561556Srgrimes * routines which implement archive and file buffering
571556Srgrimes */
581556Srgrimes
591556Srgrimes#define MINFBSZ		512		/* default block size for hole detect */
601556Srgrimes#define MAXFLT          10              /* default media read error limit */
611556Srgrimes
621556Srgrimes/*
631556Srgrimes * Need to change bufmem to dynamic allocation when the upper
641556Srgrimes * limit on blocking size is removed (though that will violate pax spec)
651556Srgrimes * MAXBLK define and tests will also need to be updated.
661556Srgrimes */
671556Srgrimesstatic char bufmem[MAXBLK+BLKMULT];	/* i/o buffer + pushback id space */
681556Srgrimesstatic char *buf;			/* normal start of i/o buffer */
691556Srgrimesstatic char *bufend;			/* end or last char in i/o buffer */
701556Srgrimesstatic char *bufpt;			/* read/write point in i/o buffer */
711556Srgrimesint blksz = MAXBLK;                    	/* block input/output size in bytes */
721556Srgrimesint wrblksz;                      	/* user spec output size in bytes */
731556Srgrimesint maxflt = MAXFLT;			/* MAX consecutive media errors */
741556Srgrimesint rdblksz;				/* first read blksize (tapes only) */
751556Srgrimesoff_t wrlimit;				/* # of bytes written per archive vol */
761556Srgrimesoff_t wrcnt;				/* # of bytes written on current vol */
771556Srgrimesoff_t rdcnt;				/* # of bytes read on current vol */
781556Srgrimes
791556Srgrimes/*
801556Srgrimes * wr_start()
811556Srgrimes *	set up the buffering system to operate in a write mode
821556Srgrimes * Return:
831556Srgrimes *	0 if ok, -1 if the user specified write block size violates pax spec
841556Srgrimes */
851556Srgrimes
861556Srgrimes#if __STDC__
871556Srgrimesint
881556Srgrimeswr_start(void)
891556Srgrimes#else
901556Srgrimesint
911556Srgrimeswr_start()
921556Srgrimes#endif
931556Srgrimes{
941556Srgrimes	buf = &(bufmem[BLKMULT]);
951556Srgrimes	/*
961556Srgrimes	 * Check to make sure the write block size meets pax specs. If the user
971556Srgrimes	 * does not specify a blocksize, we use the format default blocksize.
981556Srgrimes	 * We must be picky on writes, so we do not allow the user to create an
991556Srgrimes	 * archive that might be hard to read elsewhere. If all ok, we then
1001556Srgrimes	 * open the first archive volume
1011556Srgrimes	 */
1028855Srgrimes	if (!wrblksz)
1031556Srgrimes		wrblksz = frmt->bsz;
1041556Srgrimes	if (wrblksz > MAXBLK) {
10546684Skris		pax_warn(1, "Write block size of %d too large, maximum is: %d",
1061556Srgrimes			wrblksz, MAXBLK);
1071556Srgrimes		return(-1);
1081556Srgrimes	}
1091556Srgrimes	if (wrblksz % BLKMULT) {
11028904Ssos		pax_warn(1, "Write block size of %d is not a %d byte multiple",
1111556Srgrimes		    wrblksz, BLKMULT);
1121556Srgrimes		return(-1);
1131556Srgrimes	}
1141556Srgrimes
1151556Srgrimes	/*
1168855Srgrimes	 * we only allow wrblksz to be used with all archive operations
1171556Srgrimes	 */
1181556Srgrimes	blksz = rdblksz = wrblksz;
1191556Srgrimes	if ((ar_open(arcname) < 0) && (ar_next() < 0))
1201556Srgrimes		return(-1);
1211556Srgrimes	wrcnt = 0;
1221556Srgrimes	bufend = buf + wrblksz;
1231556Srgrimes	bufpt = buf;
1241556Srgrimes	return(0);
1251556Srgrimes}
1261556Srgrimes
1271556Srgrimes/*
1281556Srgrimes * rd_start()
1291556Srgrimes *	set up buffering system to read an archive
1301556Srgrimes * Return:
1311556Srgrimes *	0 if ok, -1 otherwise
1321556Srgrimes */
1331556Srgrimes
1341556Srgrimes#if __STDC__
1351556Srgrimesint
1361556Srgrimesrd_start(void)
1371556Srgrimes#else
1381556Srgrimesint
1391556Srgrimesrd_start()
1401556Srgrimes#endif
1411556Srgrimes{
1421556Srgrimes	/*
1431556Srgrimes	 * leave space for the header pushback (see get_arc()). If we are
1441556Srgrimes	 * going to append and user specified a write block size, check it
1451556Srgrimes	 * right away
1461556Srgrimes	 */
1471556Srgrimes	buf = &(bufmem[BLKMULT]);
1481556Srgrimes	if ((act == APPND) && wrblksz) {
1491556Srgrimes		if (wrblksz > MAXBLK) {
15046684Skris			pax_warn(1,"Write block size %d too large, maximum is: %d",
1511556Srgrimes				wrblksz, MAXBLK);
1521556Srgrimes			return(-1);
1531556Srgrimes		}
1541556Srgrimes		if (wrblksz % BLKMULT) {
15528904Ssos			pax_warn(1, "Write block size %d is not a %d byte multiple",
1561556Srgrimes		    	wrblksz, BLKMULT);
1571556Srgrimes			return(-1);
1581556Srgrimes		}
1591556Srgrimes	}
1601556Srgrimes
1611556Srgrimes	/*
1621556Srgrimes	 * open the archive
1631556Srgrimes	 */
1641556Srgrimes	if ((ar_open(arcname) < 0) && (ar_next() < 0))
1651556Srgrimes		return(-1);
1661556Srgrimes	bufend = buf + rdblksz;
1671556Srgrimes	bufpt = bufend;
1681556Srgrimes	rdcnt = 0;
1691556Srgrimes	return(0);
1701556Srgrimes}
1711556Srgrimes
1721556Srgrimes/*
1731556Srgrimes * cp_start()
1741556Srgrimes *	set up buffer system for copying within the file system
1751556Srgrimes */
1761556Srgrimes
1771556Srgrimes#if __STDC__
1781556Srgrimesvoid
1791556Srgrimescp_start(void)
1801556Srgrimes#else
1811556Srgrimesvoid
1821556Srgrimescp_start()
1831556Srgrimes#endif
1841556Srgrimes{
1851556Srgrimes	buf = &(bufmem[BLKMULT]);
1861556Srgrimes	rdblksz = blksz = MAXBLK;
1871556Srgrimes}
1881556Srgrimes
1891556Srgrimes/*
1901556Srgrimes * appnd_start()
1911556Srgrimes *	Set up the buffering system to append new members to an archive that
1921556Srgrimes *	was just read. The last block(s) of an archive may contain a format
1931556Srgrimes *	specific trailer. To append a new member, this trailer has to be
1941556Srgrimes *	removed from the archive. The first byte of the trailer is replaced by
1951556Srgrimes *	the start of the header of the first file added to the archive. The
1961556Srgrimes *	format specific end read function tells us how many bytes to move
1971556Srgrimes *	backwards in the archive to be positioned BEFORE the trailer. Two
1981556Srgrimes *	different postions have to be adjusted, the O.S. file offset (e.g. the
1991556Srgrimes *	position of the tape head) and the write point within the data we have
2001556Srgrimes *	stored in the read (soon to become write) buffer. We may have to move
2011556Srgrimes *	back several records (the number depends on the size of the archive
2021556Srgrimes *	record and the size of the format trailer) to read up the record where
2031556Srgrimes *	the first byte of the trailer is recorded. Trailers may span (and
2041556Srgrimes *	overlap) record boundries.
2051556Srgrimes *	We first calculate which record has the first byte of the trailer. We
2061556Srgrimes *	move the OS file offset back to the start of this record and read it
2071556Srgrimes *	up. We set the buffer write pointer to be at this byte (the byte where
2081556Srgrimes *	the trailer starts). We then move the OS file pointer back to the
2091556Srgrimes *	start of this record so a flush of this buffer will replace the record
2101556Srgrimes *	in the archive.
2111556Srgrimes *	A major problem is rewriting this last record. For archives stored
2121556Srgrimes *	on disk files, this is trival. However, many devices are really picky
2131556Srgrimes *	about the conditions under which they will allow a write to occur.
2141556Srgrimes *	Often devices restrict the conditions where writes can be made writes,
2151556Srgrimes *	so it may not be feasable to append archives stored on all types of
2168855Srgrimes *	devices.
2171556Srgrimes * Return:
2181556Srgrimes *	0 for success, -1 for failure
2191556Srgrimes */
2201556Srgrimes
2211556Srgrimes#if __STDC__
2221556Srgrimesint
2231556Srgrimesappnd_start(off_t skcnt)
2241556Srgrimes#else
2251556Srgrimesint
2261556Srgrimesappnd_start(skcnt)
2271556Srgrimes	off_t skcnt;
2281556Srgrimes#endif
2291556Srgrimes{
2301556Srgrimes	register int res;
2311556Srgrimes	off_t cnt;
2321556Srgrimes
2331556Srgrimes	if (exit_val != 0) {
23428904Ssos		pax_warn(0, "Cannot append to an archive that may have flaws.");
2351556Srgrimes		return(-1);
2361556Srgrimes	}
2371556Srgrimes	/*
2381556Srgrimes	 * if the user did not specify a write blocksize, inherit the size used
2391556Srgrimes	 * in the last archive volume read. (If a is set we still use rdblksz
2401556Srgrimes	 * until next volume, cannot shift sizes within a single volume).
2411556Srgrimes	 */
2421556Srgrimes	if (!wrblksz)
2431556Srgrimes		wrblksz = blksz = rdblksz;
2441556Srgrimes	else
2451556Srgrimes		blksz = rdblksz;
2461556Srgrimes
2471556Srgrimes	/*
2481556Srgrimes	 * make sure that this volume allows appends
2491556Srgrimes	 */
2501556Srgrimes	if (ar_app_ok() < 0)
2511556Srgrimes		return(-1);
2521556Srgrimes
2531556Srgrimes	/*
2541556Srgrimes	 * Calculate bytes to move back and move in front of record where we
2551556Srgrimes	 * need to start writing from. Remember we have to add in any padding
2561556Srgrimes	 * that might be in the buffer after the trailer in the last block. We
2571556Srgrimes	 * travel skcnt + padding ROUNDED UP to blksize.
2581556Srgrimes	 */
2591556Srgrimes	skcnt += bufend - bufpt;
2601556Srgrimes	if ((cnt = (skcnt/blksz) * blksz) < skcnt)
2611556Srgrimes		cnt += blksz;
2621556Srgrimes	if (ar_rev((off_t)cnt) < 0)
2631556Srgrimes		goto out;
2641556Srgrimes
2651556Srgrimes	/*
2661556Srgrimes	 * We may have gone too far if there is valid data in the block we are
2671556Srgrimes	 * now in front of, read up the block and position the pointer after
2681556Srgrimes	 * the valid data.
2691556Srgrimes	 */
2701556Srgrimes	if ((cnt -= skcnt) > 0) {
2711556Srgrimes		/*
2721556Srgrimes		 * watch out for stupid tape drives. ar_rev() will set rdblksz
2731556Srgrimes		 * to be real physical blocksize so we must loop until we get
2741556Srgrimes		 * the old rdblksz (now in blksz). If ar_rev() fouls up the
2751556Srgrimes		 * determination of the physical block size, we will fail.
2761556Srgrimes		 */
2771556Srgrimes		bufpt = buf;
2781556Srgrimes		bufend = buf + blksz;
2791556Srgrimes		while (bufpt < bufend) {
2801556Srgrimes			if ((res = ar_read(bufpt, rdblksz)) <= 0)
2811556Srgrimes				goto out;
2821556Srgrimes			bufpt += res;
2831556Srgrimes		}
2841556Srgrimes		if (ar_rev((off_t)(bufpt - buf)) < 0)
2851556Srgrimes			goto out;
2861556Srgrimes		bufpt = buf + cnt;
2871556Srgrimes		bufend = buf + blksz;
2881556Srgrimes	} else {
2891556Srgrimes		/*
2901556Srgrimes		 * buffer is empty
2911556Srgrimes		 */
2921556Srgrimes		bufend = buf + blksz;
2931556Srgrimes		bufpt = buf;
2941556Srgrimes	}
2951556Srgrimes	rdblksz = blksz;
2961556Srgrimes	rdcnt -= skcnt;
2971556Srgrimes	wrcnt = 0;
2981556Srgrimes
2991556Srgrimes	/*
3001556Srgrimes	 * At this point we are ready to write. If the device requires special
3011556Srgrimes	 * handling to write at a point were previously recorded data resides,
3021556Srgrimes	 * that is handled in ar_set_wr(). From now on we operate under normal
3031556Srgrimes	 * ARCHIVE mode (write) conditions
3041556Srgrimes	 */
3051556Srgrimes	if (ar_set_wr() < 0)
3061556Srgrimes		return(-1);
3071556Srgrimes	act = ARCHIVE;
3081556Srgrimes	return(0);
3091556Srgrimes
3101556Srgrimes    out:
31128904Ssos	pax_warn(1, "Unable to rewrite archive trailer, cannot append.");
3121556Srgrimes	return(-1);
3131556Srgrimes}
3148855Srgrimes
3151556Srgrimes/*
3161556Srgrimes * rd_sync()
3171556Srgrimes *	A read error occurred on this archive volume. Resync the buffer and
3181556Srgrimes *	try to reset the device (if possible) so we can continue to read. Keep
3191556Srgrimes *	trying to do this until we get a valid read, or we reach the limit on
3201556Srgrimes *	consecutive read faults (at which point we give up). The user can
3211556Srgrimes *	adjust the read error limit through a command line option.
3221556Srgrimes * Returns:
3231556Srgrimes *	0 on success, and -1 on failure
3241556Srgrimes */
3251556Srgrimes
3261556Srgrimes#if __STDC__
3271556Srgrimesint
3281556Srgrimesrd_sync(void)
3291556Srgrimes#else
3301556Srgrimesint
3311556Srgrimesrd_sync()
3321556Srgrimes#endif
3331556Srgrimes{
3341556Srgrimes	register int errcnt = 0;
3351556Srgrimes	register int res;
3361556Srgrimes
3371556Srgrimes	/*
3381556Srgrimes	 * if the user says bail out on first fault, we are out of here...
3391556Srgrimes	 */
3401556Srgrimes	if (maxflt == 0)
3411556Srgrimes		return(-1);
3421556Srgrimes	if (act == APPND) {
34328904Ssos		pax_warn(1, "Unable to append when there are archive read errors.");
3441556Srgrimes		return(-1);
3451556Srgrimes	}
3461556Srgrimes
3471556Srgrimes	/*
3481556Srgrimes	 * poke at device and try to get past media error
3491556Srgrimes	 */
3501556Srgrimes	if (ar_rdsync() < 0) {
3511556Srgrimes		if (ar_next() < 0)
3521556Srgrimes			return(-1);
3531556Srgrimes		else
3541556Srgrimes			rdcnt = 0;
3551556Srgrimes	}
3561556Srgrimes
3571556Srgrimes	for (;;) {
3581556Srgrimes		if ((res = ar_read(buf, blksz)) > 0) {
3591556Srgrimes			/*
3601556Srgrimes			 * All right! got some data, fill that buffer
3611556Srgrimes			 */
3621556Srgrimes			bufpt = buf;
3631556Srgrimes			bufend = buf + res;
3641556Srgrimes			rdcnt += res;
3651556Srgrimes			return(0);
3661556Srgrimes		}
3671556Srgrimes
3681556Srgrimes		/*
3691556Srgrimes		 * Oh well, yet another failed read...
3701556Srgrimes		 * if error limit reached, ditch. o.w. poke device to move past
3711556Srgrimes		 * bad media and try again. if media is badly damaged, we ask
3721556Srgrimes		 * the poor (and upset user at this point) for the next archive
3731556Srgrimes		 * volume. remember the goal on reads is to get the most we
3741556Srgrimes		 * can extract out of the archive.
3751556Srgrimes		 */
3761556Srgrimes		if ((maxflt > 0) && (++errcnt > maxflt))
37728904Ssos			pax_warn(0,"Archive read error limit (%d) reached",maxflt);
3781556Srgrimes		else if (ar_rdsync() == 0)
3791556Srgrimes			continue;
3801556Srgrimes		if (ar_next() < 0)
3811556Srgrimes			break;
3821556Srgrimes		rdcnt = 0;
3831556Srgrimes		errcnt = 0;
3841556Srgrimes	}
3851556Srgrimes	return(-1);
3861556Srgrimes}
3871556Srgrimes
3881556Srgrimes/*
3891556Srgrimes * pback()
3901556Srgrimes *	push the data used during the archive id phase back into the I/O
3911556Srgrimes *	buffer. This is required as we cannot be sure that the header does NOT
3921556Srgrimes *	overlap a block boundry (as in the case we are trying to recover a
3931556Srgrimes *	flawed archived). This was not designed to be used for any other
3941556Srgrimes *	purpose. (What software engineering, HA!)
3951556Srgrimes *	WARNING: do not even THINK of pback greater than BLKMULT, unless the
3961556Srgrimes *	pback space is increased.
3971556Srgrimes */
3981556Srgrimes
3991556Srgrimes#if __STDC__
4001556Srgrimesvoid
4011556Srgrimespback(char *pt, int cnt)
4021556Srgrimes#else
4031556Srgrimesvoid
4041556Srgrimespback(pt, cnt)
4051556Srgrimes	char *pt;
4061556Srgrimes	int cnt;
4071556Srgrimes#endif
4081556Srgrimes{
4091556Srgrimes	bufpt -= cnt;
4101556Srgrimes	bcopy(pt, bufpt, cnt);
4111556Srgrimes	return;
4121556Srgrimes}
4131556Srgrimes
4141556Srgrimes/*
4151556Srgrimes * rd_skip()
4161556Srgrimes *	skip foward in the archive during a archive read. Used to get quickly
4171556Srgrimes *	past file data and padding for files the user did NOT select.
4181556Srgrimes * Return:
4191556Srgrimes *	0 if ok, -1 failure, and 1 when EOF on the archive volume was detected.
4201556Srgrimes */
4211556Srgrimes
4221556Srgrimes#if __STDC__
4231556Srgrimesint
4241556Srgrimesrd_skip(off_t skcnt)
4251556Srgrimes#else
4261556Srgrimesint
4271556Srgrimesrd_skip(skcnt)
4281556Srgrimes	off_t skcnt;
4291556Srgrimes#endif
4301556Srgrimes{
4311556Srgrimes	off_t res;
4321556Srgrimes	off_t cnt;
4331556Srgrimes	off_t skipped = 0;
4341556Srgrimes
4351556Srgrimes	/*
4361556Srgrimes	 * consume what data we have in the buffer. If we have to move foward
4371556Srgrimes	 * whole records, we call the low level skip function to see if we can
4381556Srgrimes	 * move within the archive without doing the expensive reads on data we
4391556Srgrimes	 * do not want.
4401556Srgrimes	 */
4411556Srgrimes	if (skcnt == 0)
4421556Srgrimes		return(0);
4431556Srgrimes	res = MIN((bufend - bufpt), skcnt);
4441556Srgrimes	bufpt += res;
4451556Srgrimes	skcnt -= res;
4461556Srgrimes
4471556Srgrimes	/*
4481556Srgrimes	 * if skcnt is now 0, then no additional i/o is needed
4491556Srgrimes	 */
4501556Srgrimes	if (skcnt == 0)
4511556Srgrimes		return(0);
4521556Srgrimes
4531556Srgrimes	/*
4541556Srgrimes	 * We have to read more, calculate complete and partial record reads
4551556Srgrimes	 * based on rdblksz. we skip over "cnt" complete records
4561556Srgrimes	 */
4571556Srgrimes	res = skcnt%rdblksz;
4581556Srgrimes	cnt = (skcnt/rdblksz) * rdblksz;
4591556Srgrimes
4601556Srgrimes	/*
4611556Srgrimes	 * if the skip fails, we will have to resync. ar_fow will tell us
4621556Srgrimes	 * how much it can skip over. We will have to read the rest.
4631556Srgrimes	 */
4641556Srgrimes	if (ar_fow(cnt, &skipped) < 0)
4651556Srgrimes		return(-1);
4661556Srgrimes	res += cnt - skipped;
4671556Srgrimes	rdcnt += skipped;
4681556Srgrimes
4691556Srgrimes	/*
4701556Srgrimes	 * what is left we have to read (which may be the whole thing if
4711556Srgrimes	 * ar_fow() told us the device can only read to skip records);
4721556Srgrimes	 */
4731556Srgrimes	while (res > 0L) {
4741556Srgrimes		cnt = bufend - bufpt;
4751556Srgrimes		/*
4761556Srgrimes		 * if the read fails, we will have to resync
4771556Srgrimes		 */
4781556Srgrimes		if ((cnt <= 0) && ((cnt = buf_fill()) < 0))
4791556Srgrimes			return(-1);
4801556Srgrimes		if (cnt == 0)
4811556Srgrimes			return(1);
4821556Srgrimes		cnt = MIN(cnt, res);
4831556Srgrimes		bufpt += cnt;
4841556Srgrimes		res -= cnt;
4851556Srgrimes	}
4861556Srgrimes	return(0);
4871556Srgrimes}
4881556Srgrimes
4898855Srgrimes/*
4901556Srgrimes * wr_fin()
4911556Srgrimes *	flush out any data (and pad if required) the last block. We always pad
4921556Srgrimes *	with zero (even though we do not have to). Padding with 0 makes it a
4931556Srgrimes *	lot easier to recover if the archive is damaged. zero paddding SHOULD
4941556Srgrimes *	BE a requirement....
4951556Srgrimes */
4961556Srgrimes
4971556Srgrimes#if __STDC__
4981556Srgrimesvoid
4991556Srgrimeswr_fin(void)
5001556Srgrimes#else
5011556Srgrimesvoid
5021556Srgrimeswr_fin()
5031556Srgrimes#endif
5041556Srgrimes{
5051556Srgrimes	if (bufpt > buf) {
5061556Srgrimes		bzero(bufpt, bufend - bufpt);
5071556Srgrimes		bufpt = bufend;
5081556Srgrimes		(void)buf_flush(blksz);
5091556Srgrimes	}
5101556Srgrimes}
5111556Srgrimes
5121556Srgrimes/*
5131556Srgrimes * wr_rdbuf()
5141556Srgrimes *	fill the write buffer from data passed to it in a buffer (usually used
5151556Srgrimes *	by format specific write routines to pass a file header). On failure we
5161556Srgrimes *	punt. We do not allow the user to continue to write flawed archives.
5171556Srgrimes *	We assume these headers are not very large (the memory copy we use is
5188855Srgrimes *	a bit expensive).
5191556Srgrimes * Return:
5201556Srgrimes *	0 if buffer was filled ok, -1 o.w. (buffer flush failure)
5211556Srgrimes */
5221556Srgrimes
5231556Srgrimes#if __STDC__
5241556Srgrimesint
5251556Srgrimeswr_rdbuf(register char *out, register int outcnt)
5261556Srgrimes#else
5271556Srgrimesint
5281556Srgrimeswr_rdbuf(out, outcnt)
5291556Srgrimes	register char *out;
5301556Srgrimes	register int outcnt;
5311556Srgrimes#endif
5321556Srgrimes{
5331556Srgrimes	register int cnt;
5341556Srgrimes
5351556Srgrimes	/*
5361556Srgrimes	 * while there is data to copy copy into the write buffer. when the
5371556Srgrimes	 * write buffer fills, flush it to the archive and continue
5381556Srgrimes	 */
5391556Srgrimes	while (outcnt > 0) {
5401556Srgrimes		cnt = bufend - bufpt;
5411556Srgrimes		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0))
5421556Srgrimes			return(-1);
5431556Srgrimes		/*
5441556Srgrimes		 * only move what we have space for
5451556Srgrimes		 */
5461556Srgrimes		cnt = MIN(cnt, outcnt);
5471556Srgrimes		bcopy(out, bufpt, cnt);
5481556Srgrimes		bufpt += cnt;
5491556Srgrimes		out += cnt;
5501556Srgrimes		outcnt -= cnt;
5511556Srgrimes	}
5521556Srgrimes	return(0);
5531556Srgrimes}
5541556Srgrimes
5551556Srgrimes/*
5561556Srgrimes * rd_wrbuf()
5571556Srgrimes *	copy from the read buffer into a supplied buffer a specified number of
5581556Srgrimes *	bytes. If the read buffer is empty fill it and continue to copy.
5591556Srgrimes *	usually used to obtain a file header for processing by a format
5601556Srgrimes *	specific read routine.
5611556Srgrimes * Return
5621556Srgrimes *	number of bytes copied to the buffer, 0 indicates EOF on archive volume,
5631556Srgrimes *	-1 is a read error
5641556Srgrimes */
5651556Srgrimes
5661556Srgrimes#if __STDC__
5671556Srgrimesint
5681556Srgrimesrd_wrbuf(register char *in, register int cpcnt)
5691556Srgrimes#else
5701556Srgrimesint
5711556Srgrimesrd_wrbuf(in, cpcnt)
5721556Srgrimes	register char *in;
5731556Srgrimes	register int cpcnt;
5741556Srgrimes#endif
5751556Srgrimes{
5761556Srgrimes	register int res;
5771556Srgrimes	register int cnt;
5781556Srgrimes	register int incnt = cpcnt;
5791556Srgrimes
5801556Srgrimes	/*
5811556Srgrimes	 * loop until we fill the buffer with the requested number of bytes
5821556Srgrimes	 */
5831556Srgrimes	while (incnt > 0) {
5841556Srgrimes		cnt = bufend - bufpt;
5851556Srgrimes		if ((cnt <= 0) && ((cnt = buf_fill()) <= 0)) {
5861556Srgrimes			/*
5871556Srgrimes			 * read error, return what we got (or the error if
5881556Srgrimes			 * no data was copied). The caller must know that an
5891556Srgrimes			 * error occured and has the best knowledge what to
5901556Srgrimes			 * do with it
5911556Srgrimes			 */
5921556Srgrimes			if ((res = cpcnt - incnt) > 0)
5931556Srgrimes				return(res);
5941556Srgrimes			return(cnt);
5951556Srgrimes		}
5961556Srgrimes
5971556Srgrimes		/*
5981556Srgrimes		 * calculate how much data to copy based on whats left and
5991556Srgrimes		 * state of buffer
6001556Srgrimes		 */
6011556Srgrimes		cnt = MIN(cnt, incnt);
6021556Srgrimes		bcopy(bufpt, in, cnt);
6031556Srgrimes		bufpt += cnt;
6041556Srgrimes		incnt -= cnt;
6051556Srgrimes		in += cnt;
6061556Srgrimes	}
6071556Srgrimes	return(cpcnt);
6081556Srgrimes}
6091556Srgrimes
6101556Srgrimes/*
6111556Srgrimes * wr_skip()
61246684Skris *	skip forward during a write. In other words add padding to the file.
6131556Srgrimes *	we add zero filled padding as it makes flawed archives much easier to
6141556Srgrimes *	recover from. the caller tells us how many bytes of padding to add
6151556Srgrimes *	This routine was not designed to add HUGE amount of padding, just small
6161556Srgrimes *	amounts (a few 512 byte blocks at most)
6171556Srgrimes * Return:
6181556Srgrimes *	0 if ok, -1 if there was a buf_flush failure
6191556Srgrimes */
6201556Srgrimes
6211556Srgrimes#if __STDC__
6221556Srgrimesint
6231556Srgrimeswr_skip(off_t skcnt)
6241556Srgrimes#else
6251556Srgrimesint
6261556Srgrimeswr_skip(skcnt)
6271556Srgrimes	off_t skcnt;
6281556Srgrimes#endif
6291556Srgrimes{
6301556Srgrimes	register int cnt;
6311556Srgrimes
6321556Srgrimes	/*
6331556Srgrimes	 * loop while there is more padding to add
6341556Srgrimes	 */
6351556Srgrimes	while (skcnt > 0L) {
6361556Srgrimes		cnt = bufend - bufpt;
6371556Srgrimes		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0))
6381556Srgrimes			return(-1);
6391556Srgrimes		cnt = MIN(cnt, skcnt);
6401556Srgrimes		bzero(bufpt, cnt);
6411556Srgrimes		bufpt += cnt;
6421556Srgrimes		skcnt -= cnt;
6431556Srgrimes	}
6441556Srgrimes	return(0);
6451556Srgrimes}
6461556Srgrimes
6471556Srgrimes/*
6481556Srgrimes * wr_rdfile()
6491556Srgrimes *	fill write buffer with the contents of a file. We are passed an	open
6501556Srgrimes *	file descriptor to the file an the archive structure that describes the
6511556Srgrimes *	file we are storing. The variable "left" is modified to contain the
6521556Srgrimes *	number of bytes of the file we were NOT able to write to the archive.
6531556Srgrimes *	it is important that we always write EXACTLY the number of bytes that
6541556Srgrimes *	the format specific write routine told us to. The file can also get
6551556Srgrimes *	bigger, so reading to the end of file would create an improper archive,
65628904Ssos *	we just detect this case and pax_warn the user. We never create a bad
6571556Srgrimes *	archive if we can avoid it. Of course trying to archive files that are
6581556Srgrimes *	active is asking for trouble. It we fail, we pass back how much we
6591556Srgrimes *	could NOT copy and let the caller deal with it.
6601556Srgrimes * Return:
6611556Srgrimes *	0 ok, -1 if archive write failure. a short read of the file returns a
6621556Srgrimes *	0, but "left" is set to be greater than zero.
6631556Srgrimes */
6641556Srgrimes
6651556Srgrimes#if __STDC__
6661556Srgrimesint
6671556Srgrimeswr_rdfile(ARCHD *arcn, int ifd, off_t *left)
6681556Srgrimes#else
6691556Srgrimesint
6701556Srgrimeswr_rdfile(arcn, ifd, left)
6711556Srgrimes	ARCHD *arcn;
6721556Srgrimes	int ifd;
6731556Srgrimes	off_t *left;
6741556Srgrimes#endif
6751556Srgrimes{
6761556Srgrimes	register int cnt;
6771556Srgrimes	register int res = 0;
6781556Srgrimes	register off_t size = arcn->sb.st_size;
6791556Srgrimes	struct stat sb;
6801556Srgrimes
6811556Srgrimes	/*
6821556Srgrimes	 * while there are more bytes to write
6831556Srgrimes	 */
6841556Srgrimes	while (size > 0L) {
6851556Srgrimes		cnt = bufend - bufpt;
6861556Srgrimes		if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) {
6871556Srgrimes			*left = size;
6881556Srgrimes			return(-1);
6891556Srgrimes		}
6901556Srgrimes		cnt = MIN(cnt, size);
6911556Srgrimes		if ((res = read(ifd, bufpt, cnt)) <= 0)
6921556Srgrimes			break;
6931556Srgrimes		size -= res;
6941556Srgrimes		bufpt += res;
6951556Srgrimes	}
6961556Srgrimes
6971556Srgrimes	/*
6981556Srgrimes	 * better check the file did not change during this operation
6991556Srgrimes	 * or the file read failed.
7001556Srgrimes	 */
7011556Srgrimes	if (res < 0)
70228904Ssos		sys_warn(1, errno, "Read fault on %s", arcn->org_name);
7031556Srgrimes	else if (size != 0L)
70428904Ssos		pax_warn(1, "File changed size during read %s", arcn->org_name);
7051556Srgrimes	else if (fstat(ifd, &sb) < 0)
70628904Ssos		sys_warn(1, errno, "Failed stat on %s", arcn->org_name);
7071556Srgrimes	else if (arcn->sb.st_mtime != sb.st_mtime)
70828904Ssos		pax_warn(1, "File %s was modified during copy to archive",
7091556Srgrimes			arcn->org_name);
7101556Srgrimes	*left = size;
7111556Srgrimes	return(0);
7121556Srgrimes}
7131556Srgrimes
7141556Srgrimes/*
7151556Srgrimes * rd_wrfile()
7161556Srgrimes *	extract the contents of a file from the archive. If we are unable to
7171556Srgrimes *	extract the entire file (due to failure to write the file) we return
7181556Srgrimes *	the numbers of bytes we did NOT process. This way the caller knows how
7191556Srgrimes *	many bytes to skip past to find the next archive header. If the failure
7201556Srgrimes *	was due to an archive read, we will catch that when we try to skip. If
7211556Srgrimes *	the format supplies a file data crc value, we calculate the actual crc
7221556Srgrimes *	so that it can be compared to the value stored in the header
7231556Srgrimes * NOTE:
7241556Srgrimes *	We call a special function to write the file. This function attempts to
7251556Srgrimes *	restore file holes (blocks of zeros) into the file. When files are
7261556Srgrimes *	sparse this saves space, and is a LOT faster. For non sparse files
7271556Srgrimes *	the performance hit is small. As of this writing, no archive supports
7281556Srgrimes *	information on where the file holes are.
7291556Srgrimes * Return:
7301556Srgrimes *	0 ok, -1 if archive read failure. if we cannot write the entire file,
7311556Srgrimes *	we return a 0 but "left" is set to be the amount unwritten
7321556Srgrimes */
7331556Srgrimes
7341556Srgrimes#if __STDC__
7351556Srgrimesint
7361556Srgrimesrd_wrfile(ARCHD *arcn, int ofd, off_t *left)
7371556Srgrimes#else
7381556Srgrimesint
7391556Srgrimesrd_wrfile(arcn, ofd, left)
7401556Srgrimes	ARCHD *arcn;
7411556Srgrimes	int ofd;
7421556Srgrimes	off_t *left;
7431556Srgrimes#endif
7441556Srgrimes{
7451556Srgrimes	register int cnt = 0;
7461556Srgrimes	register off_t size = arcn->sb.st_size;
7471556Srgrimes	register int res = 0;
7481556Srgrimes	register char *fnm = arcn->name;
7491556Srgrimes	int isem = 1;
7501556Srgrimes	int rem;
7511556Srgrimes	int sz = MINFBSZ;
7521556Srgrimes 	struct stat sb;
7531556Srgrimes	u_long crc = 0L;
7541556Srgrimes
7551556Srgrimes	/*
7561556Srgrimes	 * pass the blocksize of the file being written to the write routine,
7571556Srgrimes	 * if the size is zero, use the default MINFBSZ
7581556Srgrimes	 */
7591556Srgrimes        if (fstat(ofd, &sb) == 0) {
7601556Srgrimes		if (sb.st_blksize > 0)
7611556Srgrimes			sz = (int)sb.st_blksize;
7621556Srgrimes        } else
76328904Ssos                sys_warn(0,errno,"Unable to obtain block size for file %s",fnm);
7641556Srgrimes	rem = sz;
7651556Srgrimes	*left = 0L;
7661556Srgrimes
7671556Srgrimes	/*
7681556Srgrimes	 * Copy the archive to the file the number of bytes specified. We have
7691556Srgrimes	 * to assume that we want to recover file holes as none of the archive
7701556Srgrimes	 * formats can record the location of file holes.
7711556Srgrimes	 */
7721556Srgrimes	while (size > 0L) {
7731556Srgrimes		cnt = bufend - bufpt;
7741556Srgrimes		/*
7751556Srgrimes		 * if we get a read error, we do not want to skip, as we may
7761556Srgrimes		 * miss a header, so we do not set left, but if we get a write
7771556Srgrimes		 * error, we do want to skip over the unprocessed data.
7781556Srgrimes		 */
7791556Srgrimes		if ((cnt <= 0) && ((cnt = buf_fill()) <= 0))
7801556Srgrimes			break;
7811556Srgrimes		cnt = MIN(cnt, size);
7821556Srgrimes		if ((res = file_write(ofd,bufpt,cnt,&rem,&isem,sz,fnm)) <= 0) {
7831556Srgrimes			*left = size;
7841556Srgrimes			break;
7851556Srgrimes		}
7861556Srgrimes
7871556Srgrimes		if (docrc) {
7881556Srgrimes			/*
7891556Srgrimes			 * update the actual crc value
7901556Srgrimes			 */
7911556Srgrimes			cnt = res;
7921556Srgrimes			while (--cnt >= 0)
7931556Srgrimes				crc += *bufpt++ & 0xff;
7941556Srgrimes		} else
7951556Srgrimes			bufpt += res;
7961556Srgrimes		size -= res;
7971556Srgrimes	}
7981556Srgrimes
7991556Srgrimes	/*
8001556Srgrimes	 * if the last block has a file hole (all zero), we must make sure this
8011556Srgrimes	 * gets updated in the file. We force the last block of zeros to be
80246684Skris	 * written. just closing with the file offset moved forward may not put
8031556Srgrimes	 * a hole at the end of the file.
8041556Srgrimes	 */
8051556Srgrimes	if (isem && (arcn->sb.st_size > 0L))
8061556Srgrimes		file_flush(ofd, fnm, isem);
8071556Srgrimes
8081556Srgrimes	/*
8091556Srgrimes	 * if we failed from archive read, we do not want to skip
8101556Srgrimes	 */
8118855Srgrimes	if ((size > 0L) && (*left == 0L))
8121556Srgrimes		return(-1);
8131556Srgrimes
8141556Srgrimes	/*
8151556Srgrimes	 * some formats record a crc on file data. If so, then we compare the
8161556Srgrimes	 * calculated crc to the crc stored in the archive
8171556Srgrimes	 */
8181556Srgrimes	if (docrc && (size == 0L) && (arcn->crc != crc))
81928904Ssos		pax_warn(1,"Actual crc does not match expected crc %s",arcn->name);
8201556Srgrimes	return(0);
8211556Srgrimes}
8221556Srgrimes
8231556Srgrimes/*
8241556Srgrimes * cp_file()
8251556Srgrimes *	copy the contents of one file to another. used during -rw phase of pax
8261556Srgrimes *	just as in rd_wrfile() we use a special write function to write the
8271556Srgrimes *	destination file so we can properly copy files with holes.
8281556Srgrimes */
8291556Srgrimes
8301556Srgrimes#if __STDC__
8311556Srgrimesvoid
8321556Srgrimescp_file(ARCHD *arcn, int fd1, int fd2)
8331556Srgrimes#else
8341556Srgrimesvoid
8351556Srgrimescp_file(arcn, fd1, fd2)
8361556Srgrimes	ARCHD *arcn;
8371556Srgrimes	int fd1;
8381556Srgrimes	int fd2;
8391556Srgrimes#endif
8401556Srgrimes{
8411556Srgrimes	register int cnt;
8421556Srgrimes	register off_t cpcnt = 0L;
8431556Srgrimes	register int res = 0;
8441556Srgrimes	register char *fnm = arcn->name;
8451556Srgrimes	register int no_hole = 0;
8461556Srgrimes	int isem = 1;
8471556Srgrimes	int rem;
8481556Srgrimes	int sz = MINFBSZ;
8491556Srgrimes	struct stat sb;
8501556Srgrimes
8511556Srgrimes	/*
8521556Srgrimes	 * check for holes in the source file. If none, we will use regular
8531556Srgrimes	 * write instead of file write.
8541556Srgrimes	 */
8551556Srgrimes	 if (((off_t)(arcn->sb.st_blocks * BLKMULT)) >= arcn->sb.st_size)
8561556Srgrimes		++no_hole;
8571556Srgrimes
8581556Srgrimes	/*
8591556Srgrimes	 * pass the blocksize of the file being written to the write routine,
8601556Srgrimes	 * if the size is zero, use the default MINFBSZ
8611556Srgrimes	 */
8621556Srgrimes        if (fstat(fd2, &sb) == 0) {
8631556Srgrimes		if (sb.st_blksize > 0)
8641556Srgrimes			sz = sb.st_blksize;
8651556Srgrimes        } else
86628904Ssos                sys_warn(0,errno,"Unable to obtain block size for file %s",fnm);
8671556Srgrimes	rem = sz;
8681556Srgrimes
8691556Srgrimes	/*
8701556Srgrimes	 * read the source file and copy to destination file until EOF
8711556Srgrimes	 */
8721556Srgrimes	for(;;) {
8731556Srgrimes		if ((cnt = read(fd1, buf, blksz)) <= 0)
8741556Srgrimes			break;
8751556Srgrimes		if (no_hole)
8761556Srgrimes			res = write(fd2, buf, cnt);
8771556Srgrimes		else
8781556Srgrimes			res = file_write(fd2, buf, cnt, &rem, &isem, sz, fnm);
8791556Srgrimes		if (res != cnt)
8801556Srgrimes			break;
8811556Srgrimes		cpcnt += cnt;
8821556Srgrimes	}
8831556Srgrimes
8841556Srgrimes	/*
8851556Srgrimes	 * check to make sure the copy is valid.
8861556Srgrimes	 */
8871556Srgrimes	if (res < 0)
88828904Ssos		sys_warn(1, errno, "Failed write during copy of %s to %s",
8891556Srgrimes			arcn->org_name, arcn->name);
8901556Srgrimes	else if (cpcnt != arcn->sb.st_size)
89128904Ssos		pax_warn(1, "File %s changed size during copy to %s",
8921556Srgrimes			arcn->org_name, arcn->name);
8931556Srgrimes	else if (fstat(fd1, &sb) < 0)
89428904Ssos		sys_warn(1, errno, "Failed stat of %s", arcn->org_name);
8951556Srgrimes	else if (arcn->sb.st_mtime != sb.st_mtime)
89628904Ssos		pax_warn(1, "File %s was modified during copy to %s",
8971556Srgrimes			arcn->org_name, arcn->name);
8981556Srgrimes
8991556Srgrimes	/*
9001556Srgrimes	 * if the last block has a file hole (all zero), we must make sure this
9011556Srgrimes	 * gets updated in the file. We force the last block of zeros to be
90246684Skris	 * written. just closing with the file offset moved forward may not put
9031556Srgrimes	 * a hole at the end of the file.
9041556Srgrimes	 */
9051556Srgrimes	if (!no_hole && isem && (arcn->sb.st_size > 0L))
9061556Srgrimes		file_flush(fd2, fnm, isem);
9071556Srgrimes	return;
9081556Srgrimes}
9091556Srgrimes
9101556Srgrimes/*
9111556Srgrimes * buf_fill()
9121556Srgrimes *	fill the read buffer with the next record (or what we can get) from
9131556Srgrimes *	the archive volume.
9141556Srgrimes * Return:
9151556Srgrimes *	Number of bytes of data in the read buffer, -1 for read error, and
9161556Srgrimes *	0 when finished (user specified termination in ar_next()).
9171556Srgrimes */
9181556Srgrimes
9191556Srgrimes#if __STDC__
9201556Srgrimesint
9211556Srgrimesbuf_fill(void)
9221556Srgrimes#else
9231556Srgrimesint
9241556Srgrimesbuf_fill()
9251556Srgrimes#endif
9261556Srgrimes{
9271556Srgrimes	register int cnt;
9281556Srgrimes	static int fini = 0;
9291556Srgrimes
9301556Srgrimes	if (fini)
9311556Srgrimes		return(0);
9321556Srgrimes
9331556Srgrimes	for(;;) {
9341556Srgrimes		/*
9351556Srgrimes		 * try to fill the buffer. on error the next archive volume is
9361556Srgrimes		 * opened and we try again.
9371556Srgrimes		 */
9381556Srgrimes		if ((cnt = ar_read(buf, blksz)) > 0) {
9391556Srgrimes			bufpt = buf;
9401556Srgrimes			bufend = buf + cnt;
9411556Srgrimes			rdcnt += cnt;
9421556Srgrimes			return(cnt);
9431556Srgrimes		}
9441556Srgrimes
9451556Srgrimes		/*
9461556Srgrimes		 * errors require resync, EOF goes to next archive
9471556Srgrimes		 */
9481556Srgrimes		if (cnt < 0)
9491556Srgrimes			break;
9501556Srgrimes		if (ar_next() < 0) {
9511556Srgrimes			fini = 1;
9521556Srgrimes			return(0);
9531556Srgrimes		}
9541556Srgrimes		rdcnt = 0;
9551556Srgrimes	}
9561556Srgrimes	exit_val = 1;
9571556Srgrimes	return(-1);
9581556Srgrimes}
9591556Srgrimes
9601556Srgrimes/*
9611556Srgrimes * buf_flush()
9621556Srgrimes *	force the write buffer to the archive. We are passed the number of
9631556Srgrimes *	bytes in the buffer at the point of the flush. When we change archives
9641556Srgrimes *	the record size might change. (either larger or smaller).
9651556Srgrimes * Return:
9661556Srgrimes *	0 if all is ok, -1 when a write error occurs.
9671556Srgrimes */
9681556Srgrimes
9691556Srgrimes#if __STDC__
9701556Srgrimesint
9711556Srgrimesbuf_flush(register int bufcnt)
9721556Srgrimes#else
9731556Srgrimesint
9741556Srgrimesbuf_flush(bufcnt)
9751556Srgrimes	register int bufcnt;
9761556Srgrimes#endif
9771556Srgrimes{
9781556Srgrimes	register int cnt;
9791556Srgrimes	register int push = 0;
9801556Srgrimes	register int totcnt = 0;
9811556Srgrimes
9821556Srgrimes	/*
9831556Srgrimes	 * if we have reached the user specified byte count for each archive
9841556Srgrimes	 * volume, prompt for the next volume. (The non-standrad -R flag).
9851556Srgrimes	 * NOTE: If the wrlimit is smaller than wrcnt, we will always write
9861556Srgrimes	 * at least one record. We always round limit UP to next blocksize.
9871556Srgrimes	 */
9881556Srgrimes	if ((wrlimit > 0) && (wrcnt > wrlimit)) {
98928904Ssos		pax_warn(0, "User specified archive volume byte limit reached.");
9901556Srgrimes		if (ar_next() < 0) {
9911556Srgrimes			wrcnt = 0;
9921556Srgrimes			exit_val = 1;
9931556Srgrimes			return(-1);
9941556Srgrimes		}
9951556Srgrimes		wrcnt = 0;
9961556Srgrimes
9971556Srgrimes		/*
9981556Srgrimes		 * The new archive volume might have changed the size of the
9991556Srgrimes		 * write blocksize. if so we figure out if we need to write
10001556Srgrimes		 * (one or more times), or if there is now free space left in
10011556Srgrimes		 * the buffer (it is no longer full). bufcnt has the number of
10021556Srgrimes		 * bytes in the buffer, (the blocksize, at the point we were
10031556Srgrimes		 * CALLED). Push has the amount of "extra" data in the buffer
10041556Srgrimes		 * if the block size has shrunk from a volume change.
10051556Srgrimes		 */
10061556Srgrimes		bufend = buf + blksz;
10071556Srgrimes		if (blksz > bufcnt)
10081556Srgrimes			return(0);
10091556Srgrimes		if (blksz < bufcnt)
10101556Srgrimes			push = bufcnt - blksz;
10111556Srgrimes	}
10121556Srgrimes
10131556Srgrimes	/*
10141556Srgrimes	 * We have enough data to write at least one archive block
10151556Srgrimes	 */
10161556Srgrimes	for (;;) {
10171556Srgrimes		/*
10181556Srgrimes		 * write a block and check if it all went out ok
10191556Srgrimes		 */
10208855Srgrimes		cnt = ar_write(buf, blksz);
10211556Srgrimes		if (cnt == blksz) {
10221556Srgrimes			/*
10231556Srgrimes			 * the write went ok
10241556Srgrimes			 */
10251556Srgrimes			wrcnt += cnt;
10261556Srgrimes			totcnt += cnt;
10271556Srgrimes			if (push > 0) {
10281556Srgrimes				/* we have extra data to push to the front.
10291556Srgrimes				 * check for more than 1 block of push, and if
10301556Srgrimes				 * so we loop back to write again
10311556Srgrimes				 */
10321556Srgrimes				bcopy(bufend, buf, push);
10331556Srgrimes				bufpt = buf + push;
10341556Srgrimes				if (push >= blksz) {
10351556Srgrimes					push -= blksz;
10361556Srgrimes					continue;
10371556Srgrimes				}
10381556Srgrimes			} else
10391556Srgrimes				bufpt = buf;
10401556Srgrimes			return(totcnt);
10411556Srgrimes		} else if (cnt > 0) {
10421556Srgrimes			/*
10431556Srgrimes			 * Oh drat we got a partial write!
10441556Srgrimes			 * if format doesnt care about alignment let it go,
104528904Ssos			 * we pax_warned the user in ar_write().... but this means
10461556Srgrimes			 * the last record on this volume violates pax spec....
10471556Srgrimes			 */
10481556Srgrimes			totcnt += cnt;
10491556Srgrimes			wrcnt += cnt;
10501556Srgrimes			bufpt = buf + cnt;
10511556Srgrimes			cnt = bufcnt - cnt;
10521556Srgrimes			bcopy(bufpt, buf, cnt);
10531556Srgrimes			bufpt = buf + cnt;
10541556Srgrimes			if (!frmt->blkalgn || ((cnt % frmt->blkalgn) == 0))
10551556Srgrimes				return(totcnt);
10561556Srgrimes			break;
10571556Srgrimes		}
10581556Srgrimes
10591556Srgrimes		/*
10601556Srgrimes		 * All done, go to next archive
10611556Srgrimes		 */
10621556Srgrimes		wrcnt = 0;
10631556Srgrimes		if (ar_next() < 0)
10641556Srgrimes			break;
10651556Srgrimes
10661556Srgrimes		/*
10671556Srgrimes		 * The new archive volume might also have changed the block
10681556Srgrimes		 * size. if so, figure out if we have too much or too little
10691556Srgrimes		 * data for using the new block size
10701556Srgrimes		 */
10711556Srgrimes		bufend = buf + blksz;
10721556Srgrimes		if (blksz > bufcnt)
10731556Srgrimes			return(0);
10741556Srgrimes		if (blksz < bufcnt)
10751556Srgrimes			push = bufcnt - blksz;
10761556Srgrimes	}
10771556Srgrimes
10781556Srgrimes	/*
10791556Srgrimes	 * write failed, stop pax. we must not create a bad archive!
10801556Srgrimes	 */
10811556Srgrimes	exit_val = 1;
10821556Srgrimes	return(-1);
10831556Srgrimes}
1084