buf_subs.c revision 76019
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[] = 4350471Speter "$FreeBSD: head/bin/pax/buf_subs.c 76019 2001-04-26 09:22:28Z kris $"; 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 */ 6076019Skris#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 */ 7176019Skrisint blksz = MAXBLK; /* block input/output size in bytes */ 7276019Skrisint 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 8676017Skris#ifdef __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) { 10576017Skris paxwarn(1, "Write block size of %d too large, maximum is: %d", 1061556Srgrimes wrblksz, MAXBLK); 1071556Srgrimes return(-1); 1081556Srgrimes } 1091556Srgrimes if (wrblksz % BLKMULT) { 11076017Skris paxwarn(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 13476017Skris#ifdef __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) { 15076017Skris paxwarn(1,"Write block size %d too large, maximum is: %d", 1511556Srgrimes wrblksz, MAXBLK); 1521556Srgrimes return(-1); 1531556Srgrimes } 1541556Srgrimes if (wrblksz % BLKMULT) { 15576017Skris paxwarn(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 17776017Skris#ifdef __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 22176017Skris#ifdef __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) { 23476017Skris paxwarn(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: 31176017Skris paxwarn(1, "Unable to rewrite archive trailer, cannot append."); 3121556Srgrimes return(-1); 3131556Srgrimes} 31476019Skris 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 32676017Skris#ifdef __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) { 34376017Skris paxwarn(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)) 37776017Skris paxwarn(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 39976017Skris#ifdef __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; 41076017Skris memcpy(bufpt, pt, 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 42276017Skris#ifdef __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 49776017Skris#ifdef __STDC__ 4981556Srgrimesvoid 4991556Srgrimeswr_fin(void) 5001556Srgrimes#else 5011556Srgrimesvoid 5021556Srgrimeswr_fin() 5031556Srgrimes#endif 5041556Srgrimes{ 5051556Srgrimes if (bufpt > buf) { 50676017Skris memset(bufpt, 0, 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 52376017Skris#ifdef __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); 54776017Skris memcpy(bufpt, out, 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 56676017Skris#ifdef __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); 60276017Skris memcpy(in, bufpt, 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 62176017Skris#ifdef __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); 64076017Skris memset(bufpt, 0, 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, 65676017Skris * we just detect this case and 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 66576017Skris#ifdef __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) 70276017Skris syswarn(1, errno, "Read fault on %s", arcn->org_name); 7031556Srgrimes else if (size != 0L) 70476017Skris paxwarn(1, "File changed size during read %s", arcn->org_name); 7051556Srgrimes else if (fstat(ifd, &sb) < 0) 70676017Skris syswarn(1, errno, "Failed stat on %s", arcn->org_name); 7071556Srgrimes else if (arcn->sb.st_mtime != sb.st_mtime) 70876017Skris paxwarn(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 73476017Skris#ifdef __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 */ 75976019Skris if (fstat(ofd, &sb) == 0) { 7601556Srgrimes if (sb.st_blksize > 0) 7611556Srgrimes sz = (int)sb.st_blksize; 76276019Skris } else 76376019Skris syswarn(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)) 81976017Skris paxwarn(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 83076017Skris#ifdef __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 */ 86276019Skris if (fstat(fd2, &sb) == 0) { 8631556Srgrimes if (sb.st_blksize > 0) 8641556Srgrimes sz = sb.st_blksize; 86576019Skris } else 86676019Skris syswarn(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) 88876017Skris syswarn(1, errno, "Failed write during copy of %s to %s", 8891556Srgrimes arcn->org_name, arcn->name); 8901556Srgrimes else if (cpcnt != arcn->sb.st_size) 89176017Skris paxwarn(1, "File %s changed size during copy to %s", 8921556Srgrimes arcn->org_name, arcn->name); 8931556Srgrimes else if (fstat(fd1, &sb) < 0) 89476017Skris syswarn(1, errno, "Failed stat of %s", arcn->org_name); 8951556Srgrimes else if (arcn->sb.st_mtime != sb.st_mtime) 89676017Skris paxwarn(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 91976017Skris#ifdef __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 96976017Skris#ifdef __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)) { 98976017Skris paxwarn(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 */ 103276017Skris memcpy(buf, bufend, 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, 104576017Skris * we 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; 105276017Skris memcpy(buf, bufpt, 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