1*5b28f239Srillig /* $NetBSD: buf_subs.c,v 1.32 2024/09/08 09:36:45 rillig Exp $ */ 2b5b29542Sagc 3b5b29542Sagc /*- 4ed6ed8e6Sagc * Copyright (c) 1992 Keith Muller. 5b5b29542Sagc * Copyright (c) 1992, 1993 6b5b29542Sagc * The Regents of the University of California. All rights reserved. 7b5b29542Sagc * 8b5b29542Sagc * This code is derived from software contributed to Berkeley by 9b5b29542Sagc * Keith Muller of the University of California, San Diego. 10b5b29542Sagc * 11b5b29542Sagc * Redistribution and use in source and binary forms, with or without 12b5b29542Sagc * modification, are permitted provided that the following conditions 13b5b29542Sagc * are met: 14b5b29542Sagc * 1. Redistributions of source code must retain the above copyright 15b5b29542Sagc * notice, this list of conditions and the following disclaimer. 16b5b29542Sagc * 2. Redistributions in binary form must reproduce the above copyright 17b5b29542Sagc * notice, this list of conditions and the following disclaimer in the 18b5b29542Sagc * documentation and/or other materials provided with the distribution. 19b5b29542Sagc * 3. Neither the name of the University nor the names of its contributors 20b5b29542Sagc * may be used to endorse or promote products derived from this software 21b5b29542Sagc * without specific prior written permission. 22b5b29542Sagc * 23b5b29542Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24b5b29542Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25b5b29542Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26b5b29542Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27b5b29542Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28b5b29542Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29b5b29542Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30b5b29542Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31b5b29542Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32b5b29542Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33b5b29542Sagc * SUCH DAMAGE. 34b5b29542Sagc */ 3549f0ad86Scgd 36171d6532Slukem #if HAVE_NBTOOL_CONFIG_H 37171d6532Slukem #include "nbtool_config.h" 38171d6532Slukem #endif 39171d6532Slukem 40f3cd6022Schristos #include <sys/cdefs.h> 41171d6532Slukem #if !defined(lint) 4249f0ad86Scgd #if 0 4349f0ad86Scgd static char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94"; 4449f0ad86Scgd #else 45*5b28f239Srillig __RCSID("$NetBSD: buf_subs.c,v 1.32 2024/09/08 09:36:45 rillig Exp $"); 4649f0ad86Scgd #endif 478b35abe2Sjtc #endif /* not lint */ 488b35abe2Sjtc 498b35abe2Sjtc #include <sys/types.h> 508b35abe2Sjtc #include <sys/time.h> 518b35abe2Sjtc #include <sys/stat.h> 528b35abe2Sjtc #include <sys/param.h> 538b35abe2Sjtc #include <stdio.h> 548b35abe2Sjtc #include <ctype.h> 558b35abe2Sjtc #include <errno.h> 568b35abe2Sjtc #include <unistd.h> 578b35abe2Sjtc #include <stdlib.h> 588b35abe2Sjtc #include <string.h> 598b35abe2Sjtc #include "pax.h" 608b35abe2Sjtc #include "extern.h" 618b35abe2Sjtc 628b35abe2Sjtc /* 638b35abe2Sjtc * routines which implement archive and file buffering 648b35abe2Sjtc */ 658b35abe2Sjtc 668b35abe2Sjtc #define MINFBSZ 512 /* default block size for hole detect */ 678b35abe2Sjtc #define MAXFLT 10 /* default media read error limit */ 688b35abe2Sjtc 698b35abe2Sjtc /* 708b35abe2Sjtc * Need to change bufmem to dynamic allocation when the upper 718b35abe2Sjtc * limit on blocking size is removed (though that will violate pax spec) 728b35abe2Sjtc * MAXBLK define and tests will also need to be updated. 738b35abe2Sjtc */ 748b35abe2Sjtc static char bufmem[MAXBLK+BLKMULT]; /* i/o buffer + pushback id space */ 758b35abe2Sjtc static char *buf; /* normal start of i/o buffer */ 768b35abe2Sjtc static char *bufend; /* end or last char in i/o buffer */ 778b35abe2Sjtc static char *bufpt; /* read/write point in i/o buffer */ 788b35abe2Sjtc int blksz = MAXBLK; /* block input/output size in bytes */ 798b35abe2Sjtc int wrblksz; /* user spec output size in bytes */ 808b35abe2Sjtc int maxflt = MAXFLT; /* MAX consecutive media errors */ 818b35abe2Sjtc int rdblksz; /* first read blksize (tapes only) */ 828b35abe2Sjtc off_t wrlimit; /* # of bytes written per archive vol */ 838b35abe2Sjtc off_t wrcnt; /* # of bytes written on current vol */ 848b35abe2Sjtc off_t rdcnt; /* # of bytes read on current vol */ 858b35abe2Sjtc 868b35abe2Sjtc /* 878b35abe2Sjtc * wr_start() 888b35abe2Sjtc * set up the buffering system to operate in a write mode 898b35abe2Sjtc * Return: 908b35abe2Sjtc * 0 if ok, -1 if the user specified write block size violates pax spec 918b35abe2Sjtc */ 928b35abe2Sjtc 938b35abe2Sjtc int 948b35abe2Sjtc wr_start(void) 958b35abe2Sjtc { 968b35abe2Sjtc buf = &(bufmem[BLKMULT]); 978b35abe2Sjtc /* 988b35abe2Sjtc * Check to make sure the write block size meets pax specs. If the user 998b35abe2Sjtc * does not specify a blocksize, we use the format default blocksize. 1008b35abe2Sjtc * We must be picky on writes, so we do not allow the user to create an 1018b35abe2Sjtc * archive that might be hard to read elsewhere. If all ok, we then 1028b35abe2Sjtc * open the first archive volume 1038b35abe2Sjtc */ 1048b35abe2Sjtc if (!wrblksz) 1058b35abe2Sjtc wrblksz = frmt->bsz; 1068b35abe2Sjtc if (wrblksz > MAXBLK) { 107f8adf56dSitohy tty_warn(1, "Write block size of %d too large, maximum is: %d", 1088b35abe2Sjtc wrblksz, MAXBLK); 109cdec4ac1Sdsl return -1; 1108b35abe2Sjtc } 1118b35abe2Sjtc if (wrblksz % BLKMULT) { 112f3cd6022Schristos tty_warn(1, "Write block size of %d is not a %d byte multiple", 1138b35abe2Sjtc wrblksz, BLKMULT); 114cdec4ac1Sdsl return -1; 1158b35abe2Sjtc } 1168b35abe2Sjtc 1178b35abe2Sjtc /* 1188b35abe2Sjtc * we only allow wrblksz to be used with all archive operations 1198b35abe2Sjtc */ 1208b35abe2Sjtc blksz = rdblksz = wrblksz; 1218b35abe2Sjtc if ((ar_open(arcname) < 0) && (ar_next() < 0)) 122cdec4ac1Sdsl return -1; 1238b35abe2Sjtc wrcnt = 0; 1248b35abe2Sjtc bufend = buf + wrblksz; 1258b35abe2Sjtc bufpt = buf; 126cdec4ac1Sdsl return 0; 1278b35abe2Sjtc } 1288b35abe2Sjtc 1298b35abe2Sjtc /* 1308b35abe2Sjtc * rd_start() 1318b35abe2Sjtc * set up buffering system to read an archive 1328b35abe2Sjtc * Return: 1338b35abe2Sjtc * 0 if ok, -1 otherwise 1348b35abe2Sjtc */ 1358b35abe2Sjtc 1368b35abe2Sjtc int 1378b35abe2Sjtc rd_start(void) 1388b35abe2Sjtc { 1398b35abe2Sjtc /* 1408b35abe2Sjtc * leave space for the header pushback (see get_arc()). If we are 1418b35abe2Sjtc * going to append and user specified a write block size, check it 1428b35abe2Sjtc * right away 1438b35abe2Sjtc */ 1448b35abe2Sjtc buf = &(bufmem[BLKMULT]); 1458b35abe2Sjtc if ((act == APPND) && wrblksz) { 1468b35abe2Sjtc if (wrblksz > MAXBLK) { 147f3cd6022Schristos tty_warn(1, 148f8adf56dSitohy "Write block size %d too large, maximum is: %d", 1498b35abe2Sjtc wrblksz, MAXBLK); 150cdec4ac1Sdsl return -1; 1518b35abe2Sjtc } 1528b35abe2Sjtc if (wrblksz % BLKMULT) { 153f3cd6022Schristos tty_warn(1, 154f3cd6022Schristos "Write block size %d is not a %d byte multiple", 1558b35abe2Sjtc wrblksz, BLKMULT); 156cdec4ac1Sdsl return -1; 1578b35abe2Sjtc } 1588b35abe2Sjtc } 1598b35abe2Sjtc 1608b35abe2Sjtc /* 1618b35abe2Sjtc * open the archive 1628b35abe2Sjtc */ 1638b35abe2Sjtc if ((ar_open(arcname) < 0) && (ar_next() < 0)) 164cdec4ac1Sdsl return -1; 1658b35abe2Sjtc bufend = buf + rdblksz; 1668b35abe2Sjtc bufpt = bufend; 1678b35abe2Sjtc rdcnt = 0; 168cdec4ac1Sdsl return 0; 1698b35abe2Sjtc } 1708b35abe2Sjtc 1718b35abe2Sjtc /* 1728b35abe2Sjtc * cp_start() 1738b35abe2Sjtc * set up buffer system for copying within the file system 1748b35abe2Sjtc */ 1758b35abe2Sjtc 1768b35abe2Sjtc void 1778b35abe2Sjtc cp_start(void) 1788b35abe2Sjtc { 1798b35abe2Sjtc buf = &(bufmem[BLKMULT]); 1808b35abe2Sjtc rdblksz = blksz = MAXBLK; 1818b35abe2Sjtc } 1828b35abe2Sjtc 1838b35abe2Sjtc /* 1848b35abe2Sjtc * appnd_start() 1858b35abe2Sjtc * Set up the buffering system to append new members to an archive that 1868b35abe2Sjtc * was just read. The last block(s) of an archive may contain a format 1878b35abe2Sjtc * specific trailer. To append a new member, this trailer has to be 1888b35abe2Sjtc * removed from the archive. The first byte of the trailer is replaced by 1898b35abe2Sjtc * the start of the header of the first file added to the archive. The 1908b35abe2Sjtc * format specific end read function tells us how many bytes to move 1918b35abe2Sjtc * backwards in the archive to be positioned BEFORE the trailer. Two 192f8adf56dSitohy * different positions have to be adjusted, the O.S. file offset (e.g. the 1938b35abe2Sjtc * position of the tape head) and the write point within the data we have 1948b35abe2Sjtc * stored in the read (soon to become write) buffer. We may have to move 1958b35abe2Sjtc * back several records (the number depends on the size of the archive 1968b35abe2Sjtc * record and the size of the format trailer) to read up the record where 1978b35abe2Sjtc * the first byte of the trailer is recorded. Trailers may span (and 198f8adf56dSitohy * overlap) record boundaries. 1998b35abe2Sjtc * We first calculate which record has the first byte of the trailer. We 2008b35abe2Sjtc * move the OS file offset back to the start of this record and read it 2018b35abe2Sjtc * up. We set the buffer write pointer to be at this byte (the byte where 2028b35abe2Sjtc * the trailer starts). We then move the OS file pointer back to the 2038b35abe2Sjtc * start of this record so a flush of this buffer will replace the record 2048b35abe2Sjtc * in the archive. 2058b35abe2Sjtc * A major problem is rewriting this last record. For archives stored 2063ac7ce18Swiz * on disk files, this is trivial. However, many devices are really picky 2078b35abe2Sjtc * about the conditions under which they will allow a write to occur. 2083ac7ce18Swiz * Often devices restrict the conditions where writes can be made, 20986c30724Sandvar * so it may not be feasible to append archives stored on all types of 2108b35abe2Sjtc * devices. 2118b35abe2Sjtc * Return: 2128b35abe2Sjtc * 0 for success, -1 for failure 2138b35abe2Sjtc */ 2148b35abe2Sjtc 2158b35abe2Sjtc int 2168b35abe2Sjtc appnd_start(off_t skcnt) 2178b35abe2Sjtc { 21848250187Stls int res; 2198b35abe2Sjtc off_t cnt; 2208b35abe2Sjtc 2218b35abe2Sjtc if (exit_val != 0) { 222f3cd6022Schristos tty_warn(0, "Cannot append to an archive that may have flaws."); 223cdec4ac1Sdsl return -1; 2248b35abe2Sjtc } 2258b35abe2Sjtc /* 2268b35abe2Sjtc * if the user did not specify a write blocksize, inherit the size used 2278b35abe2Sjtc * in the last archive volume read. (If a is set we still use rdblksz 2288b35abe2Sjtc * until next volume, cannot shift sizes within a single volume). 2298b35abe2Sjtc */ 2308b35abe2Sjtc if (!wrblksz) 2318b35abe2Sjtc wrblksz = blksz = rdblksz; 2328b35abe2Sjtc else 2338b35abe2Sjtc blksz = rdblksz; 2348b35abe2Sjtc 2358b35abe2Sjtc /* 2368b35abe2Sjtc * make sure that this volume allows appends 2378b35abe2Sjtc */ 2388b35abe2Sjtc if (ar_app_ok() < 0) 239cdec4ac1Sdsl return -1; 2408b35abe2Sjtc 2418b35abe2Sjtc /* 2428b35abe2Sjtc * Calculate bytes to move back and move in front of record where we 2438b35abe2Sjtc * need to start writing from. Remember we have to add in any padding 2448b35abe2Sjtc * that might be in the buffer after the trailer in the last block. We 2458b35abe2Sjtc * travel skcnt + padding ROUNDED UP to blksize. 2468b35abe2Sjtc */ 2478b35abe2Sjtc skcnt += bufend - bufpt; 2488b35abe2Sjtc if ((cnt = (skcnt/blksz) * blksz) < skcnt) 2498b35abe2Sjtc cnt += blksz; 2508b35abe2Sjtc if (ar_rev((off_t)cnt) < 0) 2518b35abe2Sjtc goto out; 2528b35abe2Sjtc 2538b35abe2Sjtc /* 2548b35abe2Sjtc * We may have gone too far if there is valid data in the block we are 2558b35abe2Sjtc * now in front of, read up the block and position the pointer after 2568b35abe2Sjtc * the valid data. 2578b35abe2Sjtc */ 2588b35abe2Sjtc if ((cnt -= skcnt) > 0) { 2598b35abe2Sjtc /* 2608b35abe2Sjtc * watch out for stupid tape drives. ar_rev() will set rdblksz 2618b35abe2Sjtc * to be real physical blocksize so we must loop until we get 2628b35abe2Sjtc * the old rdblksz (now in blksz). If ar_rev() fouls up the 2638b35abe2Sjtc * determination of the physical block size, we will fail. 2648b35abe2Sjtc */ 2658b35abe2Sjtc bufpt = buf; 2668b35abe2Sjtc bufend = buf + blksz; 2678b35abe2Sjtc while (bufpt < bufend) { 2688b35abe2Sjtc if ((res = ar_read(bufpt, rdblksz)) <= 0) 2698b35abe2Sjtc goto out; 2708b35abe2Sjtc bufpt += res; 2718b35abe2Sjtc } 2728b35abe2Sjtc if (ar_rev((off_t)(bufpt - buf)) < 0) 2738b35abe2Sjtc goto out; 2748b35abe2Sjtc bufpt = buf + cnt; 2758b35abe2Sjtc bufend = buf + blksz; 2768b35abe2Sjtc } else { 2778b35abe2Sjtc /* 2788b35abe2Sjtc * buffer is empty 2798b35abe2Sjtc */ 2808b35abe2Sjtc bufend = buf + blksz; 2818b35abe2Sjtc bufpt = buf; 2828b35abe2Sjtc } 2838b35abe2Sjtc rdblksz = blksz; 2848b35abe2Sjtc rdcnt -= skcnt; 2858b35abe2Sjtc wrcnt = 0; 2868b35abe2Sjtc 2878b35abe2Sjtc /* 2888b35abe2Sjtc * At this point we are ready to write. If the device requires special 2898b35abe2Sjtc * handling to write at a point were previously recorded data resides, 2908b35abe2Sjtc * that is handled in ar_set_wr(). From now on we operate under normal 2918b35abe2Sjtc * ARCHIVE mode (write) conditions 2928b35abe2Sjtc */ 2938b35abe2Sjtc if (ar_set_wr() < 0) 294cdec4ac1Sdsl return -1; 2958b35abe2Sjtc act = ARCHIVE; 296cdec4ac1Sdsl return 0; 2978b35abe2Sjtc 2988b35abe2Sjtc out: 299f3cd6022Schristos tty_warn(1, "Unable to rewrite archive trailer, cannot append."); 300cdec4ac1Sdsl return -1; 3018b35abe2Sjtc } 3028b35abe2Sjtc 3038b35abe2Sjtc /* 3048b35abe2Sjtc * rd_sync() 3058b35abe2Sjtc * A read error occurred on this archive volume. Resync the buffer and 3068b35abe2Sjtc * try to reset the device (if possible) so we can continue to read. Keep 3078b35abe2Sjtc * trying to do this until we get a valid read, or we reach the limit on 3088b35abe2Sjtc * consecutive read faults (at which point we give up). The user can 3098b35abe2Sjtc * adjust the read error limit through a command line option. 3108b35abe2Sjtc * Returns: 3118b35abe2Sjtc * 0 on success, and -1 on failure 3128b35abe2Sjtc */ 3138b35abe2Sjtc 3148b35abe2Sjtc int 3158b35abe2Sjtc rd_sync(void) 3168b35abe2Sjtc { 31748250187Stls int errcnt = 0; 31848250187Stls int res; 3198b35abe2Sjtc 3208b35abe2Sjtc /* 3218b35abe2Sjtc * if the user says bail out on first fault, we are out of here... 3228b35abe2Sjtc */ 3238b35abe2Sjtc if (maxflt == 0) 324cdec4ac1Sdsl return -1; 3258b35abe2Sjtc if (act == APPND) { 326f3cd6022Schristos tty_warn(1, 327f3cd6022Schristos "Unable to append when there are archive read errors."); 328cdec4ac1Sdsl return -1; 3298b35abe2Sjtc } 3308b35abe2Sjtc 3318b35abe2Sjtc /* 3328b35abe2Sjtc * poke at device and try to get past media error 3338b35abe2Sjtc */ 3348b35abe2Sjtc if (ar_rdsync() < 0) { 3358b35abe2Sjtc if (ar_next() < 0) 336cdec4ac1Sdsl return -1; 3378b35abe2Sjtc else 3388b35abe2Sjtc rdcnt = 0; 3398b35abe2Sjtc } 3408b35abe2Sjtc 3418b35abe2Sjtc for (;;) { 3428b35abe2Sjtc if ((res = ar_read(buf, blksz)) > 0) { 3438b35abe2Sjtc /* 3448b35abe2Sjtc * All right! got some data, fill that buffer 3458b35abe2Sjtc */ 3468b35abe2Sjtc bufpt = buf; 3478b35abe2Sjtc bufend = buf + res; 3488b35abe2Sjtc rdcnt += res; 349cdec4ac1Sdsl return 0; 3508b35abe2Sjtc } 3518b35abe2Sjtc 3528b35abe2Sjtc /* 3538b35abe2Sjtc * Oh well, yet another failed read... 3543ac7ce18Swiz * if error limit reached, ditch. otherwise poke device to move past 3558b35abe2Sjtc * bad media and try again. if media is badly damaged, we ask 3568b35abe2Sjtc * the poor (and upset user at this point) for the next archive 3578b35abe2Sjtc * volume. remember the goal on reads is to get the most we 3588b35abe2Sjtc * can extract out of the archive. 3598b35abe2Sjtc */ 3608b35abe2Sjtc if ((maxflt > 0) && (++errcnt > maxflt)) 361f3cd6022Schristos tty_warn(0, 362f3cd6022Schristos "Archive read error limit (%d) reached",maxflt); 3638b35abe2Sjtc else if (ar_rdsync() == 0) 3648b35abe2Sjtc continue; 3658b35abe2Sjtc if (ar_next() < 0) 3668b35abe2Sjtc break; 3678b35abe2Sjtc rdcnt = 0; 3688b35abe2Sjtc errcnt = 0; 3698b35abe2Sjtc } 370cdec4ac1Sdsl return -1; 3718b35abe2Sjtc } 3728b35abe2Sjtc 3738b35abe2Sjtc /* 3748b35abe2Sjtc * pback() 3758b35abe2Sjtc * push the data used during the archive id phase back into the I/O 3768b35abe2Sjtc * buffer. This is required as we cannot be sure that the header does NOT 377f8adf56dSitohy * overlap a block boundary (as in the case we are trying to recover a 3788b35abe2Sjtc * flawed archived). This was not designed to be used for any other 3798b35abe2Sjtc * purpose. (What software engineering, HA!) 3808b35abe2Sjtc * WARNING: do not even THINK of pback greater than BLKMULT, unless the 3818b35abe2Sjtc * pback space is increased. 3828b35abe2Sjtc */ 3838b35abe2Sjtc 3848b35abe2Sjtc void 3858b35abe2Sjtc pback(char *pt, int cnt) 3868b35abe2Sjtc { 3878b35abe2Sjtc bufpt -= cnt; 38806f53b68Smycroft memcpy(bufpt, pt, cnt); 3898b35abe2Sjtc return; 3908b35abe2Sjtc } 3918b35abe2Sjtc 3928b35abe2Sjtc /* 3938b35abe2Sjtc * rd_skip() 3948ce1f4ffSmsaitoh * skip forward in the archive during an archive read. Used to get quickly 3958b35abe2Sjtc * past file data and padding for files the user did NOT select. 3968b35abe2Sjtc * Return: 3978b35abe2Sjtc * 0 if ok, -1 failure, and 1 when EOF on the archive volume was detected. 3988b35abe2Sjtc */ 3998b35abe2Sjtc 4008b35abe2Sjtc int 4018b35abe2Sjtc rd_skip(off_t skcnt) 4028b35abe2Sjtc { 4038b35abe2Sjtc off_t res; 4048b35abe2Sjtc off_t cnt; 4058b35abe2Sjtc off_t skipped = 0; 4068b35abe2Sjtc 4078b35abe2Sjtc /* 408f8adf56dSitohy * consume what data we have in the buffer. If we have to move forward 4098b35abe2Sjtc * whole records, we call the low level skip function to see if we can 4108b35abe2Sjtc * move within the archive without doing the expensive reads on data we 4118b35abe2Sjtc * do not want. 4128b35abe2Sjtc */ 4138b35abe2Sjtc if (skcnt == 0) 414cdec4ac1Sdsl return 0; 4158b35abe2Sjtc res = MIN((bufend - bufpt), skcnt); 4168b35abe2Sjtc bufpt += res; 4178b35abe2Sjtc skcnt -= res; 4188b35abe2Sjtc 4198b35abe2Sjtc /* 4208b35abe2Sjtc * if skcnt is now 0, then no additional i/o is needed 4218b35abe2Sjtc */ 4228b35abe2Sjtc if (skcnt == 0) 423cdec4ac1Sdsl return 0; 4248b35abe2Sjtc 4258b35abe2Sjtc /* 4268b35abe2Sjtc * We have to read more, calculate complete and partial record reads 4278b35abe2Sjtc * based on rdblksz. we skip over "cnt" complete records 4288b35abe2Sjtc */ 4298b35abe2Sjtc res = skcnt%rdblksz; 4308b35abe2Sjtc cnt = (skcnt/rdblksz) * rdblksz; 4318b35abe2Sjtc 4328b35abe2Sjtc /* 4338b35abe2Sjtc * if the skip fails, we will have to resync. ar_fow will tell us 4348b35abe2Sjtc * how much it can skip over. We will have to read the rest. 4358b35abe2Sjtc */ 4368b35abe2Sjtc if (ar_fow(cnt, &skipped) < 0) 437cdec4ac1Sdsl return -1; 4388b35abe2Sjtc res += cnt - skipped; 4398b35abe2Sjtc rdcnt += skipped; 4408b35abe2Sjtc 4418b35abe2Sjtc /* 4428b35abe2Sjtc * what is left we have to read (which may be the whole thing if 4438b35abe2Sjtc * ar_fow() told us the device can only read to skip records); 4448b35abe2Sjtc */ 4458b35abe2Sjtc while (res > 0L) { 4468b35abe2Sjtc cnt = bufend - bufpt; 4478b35abe2Sjtc /* 4488b35abe2Sjtc * if the read fails, we will have to resync 4498b35abe2Sjtc */ 4508b35abe2Sjtc if ((cnt <= 0) && ((cnt = buf_fill()) < 0)) 451cdec4ac1Sdsl return -1; 4528b35abe2Sjtc if (cnt == 0) 453cdec4ac1Sdsl return 1; 4548b35abe2Sjtc cnt = MIN(cnt, res); 4558b35abe2Sjtc bufpt += cnt; 4568b35abe2Sjtc res -= cnt; 4578b35abe2Sjtc } 458cdec4ac1Sdsl return 0; 4598b35abe2Sjtc } 4608b35abe2Sjtc 4618b35abe2Sjtc /* 4628b35abe2Sjtc * wr_fin() 4638b35abe2Sjtc * flush out any data (and pad if required) the last block. We always pad 4648b35abe2Sjtc * with zero (even though we do not have to). Padding with 0 makes it a 46586c30724Sandvar * lot easier to recover if the archive is damaged. zero padding SHOULD 4668b35abe2Sjtc * BE a requirement.... 4678b35abe2Sjtc */ 4688b35abe2Sjtc 4698b35abe2Sjtc void 4708b35abe2Sjtc wr_fin(void) 4718b35abe2Sjtc { 4728b35abe2Sjtc if (bufpt > buf) { 47306f53b68Smycroft memset(bufpt, 0, bufend - bufpt); 4748b35abe2Sjtc bufpt = bufend; 4758b35abe2Sjtc (void)buf_flush(blksz); 4768b35abe2Sjtc } 4778b35abe2Sjtc } 4788b35abe2Sjtc 4798b35abe2Sjtc /* 4808b35abe2Sjtc * wr_rdbuf() 4818b35abe2Sjtc * fill the write buffer from data passed to it in a buffer (usually used 4828b35abe2Sjtc * by format specific write routines to pass a file header). On failure we 4838b35abe2Sjtc * punt. We do not allow the user to continue to write flawed archives. 4848b35abe2Sjtc * We assume these headers are not very large (the memory copy we use is 4858b35abe2Sjtc * a bit expensive). 4868b35abe2Sjtc * Return: 4878b35abe2Sjtc * 0 if buffer was filled ok, -1 o.w. (buffer flush failure) 4888b35abe2Sjtc */ 4898b35abe2Sjtc 4908b35abe2Sjtc int 49148250187Stls wr_rdbuf(char *out, int outcnt) 4928b35abe2Sjtc { 49348250187Stls int cnt; 4948b35abe2Sjtc 4958b35abe2Sjtc /* 496f96d27e8Smsaitoh * while there is data to copy into the write buffer. when the 4978b35abe2Sjtc * write buffer fills, flush it to the archive and continue 4988b35abe2Sjtc */ 4998b35abe2Sjtc while (outcnt > 0) { 5008b35abe2Sjtc cnt = bufend - bufpt; 5018b35abe2Sjtc if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) 502cdec4ac1Sdsl return -1; 5038b35abe2Sjtc /* 5048b35abe2Sjtc * only move what we have space for 5058b35abe2Sjtc */ 5068b35abe2Sjtc cnt = MIN(cnt, outcnt); 50706f53b68Smycroft memcpy(bufpt, out, cnt); 5088b35abe2Sjtc bufpt += cnt; 5098b35abe2Sjtc out += cnt; 5108b35abe2Sjtc outcnt -= cnt; 5118b35abe2Sjtc } 512cdec4ac1Sdsl return 0; 5138b35abe2Sjtc } 5148b35abe2Sjtc 5158b35abe2Sjtc /* 5168b35abe2Sjtc * rd_wrbuf() 5178b35abe2Sjtc * copy from the read buffer into a supplied buffer a specified number of 5188b35abe2Sjtc * bytes. If the read buffer is empty fill it and continue to copy. 5198b35abe2Sjtc * usually used to obtain a file header for processing by a format 5208b35abe2Sjtc * specific read routine. 5218b35abe2Sjtc * Return 5228b35abe2Sjtc * number of bytes copied to the buffer, 0 indicates EOF on archive volume, 5238b35abe2Sjtc * -1 is a read error 5248b35abe2Sjtc */ 5258b35abe2Sjtc 5268b35abe2Sjtc int 52748250187Stls rd_wrbuf(char *in, int cpcnt) 5288b35abe2Sjtc { 52948250187Stls int res; 53048250187Stls int cnt; 53148250187Stls int incnt = cpcnt; 5328b35abe2Sjtc 5338b35abe2Sjtc /* 5348b35abe2Sjtc * loop until we fill the buffer with the requested number of bytes 5358b35abe2Sjtc */ 5368b35abe2Sjtc while (incnt > 0) { 5378b35abe2Sjtc cnt = bufend - bufpt; 5388b35abe2Sjtc if ((cnt <= 0) && ((cnt = buf_fill()) <= 0)) { 5398b35abe2Sjtc /* 5408b35abe2Sjtc * read error, return what we got (or the error if 5418b35abe2Sjtc * no data was copied). The caller must know that an 542456dff6cSwiz * error occurred and has the best knowledge what to 5438b35abe2Sjtc * do with it 5448b35abe2Sjtc */ 5458b35abe2Sjtc if ((res = cpcnt - incnt) > 0) 546cdec4ac1Sdsl return res; 547cdec4ac1Sdsl return cnt; 5488b35abe2Sjtc } 5498b35abe2Sjtc 5508b35abe2Sjtc /* 5518b35abe2Sjtc * calculate how much data to copy based on whats left and 5528b35abe2Sjtc * state of buffer 5538b35abe2Sjtc */ 5548b35abe2Sjtc cnt = MIN(cnt, incnt); 55506f53b68Smycroft memcpy(in, bufpt, cnt); 5568b35abe2Sjtc bufpt += cnt; 5578b35abe2Sjtc incnt -= cnt; 5588b35abe2Sjtc in += cnt; 5598b35abe2Sjtc } 560cdec4ac1Sdsl return cpcnt; 5618b35abe2Sjtc } 5628b35abe2Sjtc 5638b35abe2Sjtc /* 5648b35abe2Sjtc * wr_skip() 565f8adf56dSitohy * skip forward during a write. In other words add padding to the file. 5668b35abe2Sjtc * we add zero filled padding as it makes flawed archives much easier to 5678b35abe2Sjtc * recover from. the caller tells us how many bytes of padding to add 5688b35abe2Sjtc * This routine was not designed to add HUGE amount of padding, just small 5698b35abe2Sjtc * amounts (a few 512 byte blocks at most) 5708b35abe2Sjtc * Return: 5718b35abe2Sjtc * 0 if ok, -1 if there was a buf_flush failure 5728b35abe2Sjtc */ 5738b35abe2Sjtc 5748b35abe2Sjtc int 5758b35abe2Sjtc wr_skip(off_t skcnt) 5768b35abe2Sjtc { 57748250187Stls int cnt; 5788b35abe2Sjtc 5798b35abe2Sjtc /* 5808b35abe2Sjtc * loop while there is more padding to add 5818b35abe2Sjtc */ 5828b35abe2Sjtc while (skcnt > 0L) { 5838b35abe2Sjtc cnt = bufend - bufpt; 5848b35abe2Sjtc if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) 585cdec4ac1Sdsl return -1; 5868b35abe2Sjtc cnt = MIN(cnt, skcnt); 58706f53b68Smycroft memset(bufpt, 0, cnt); 5888b35abe2Sjtc bufpt += cnt; 5898b35abe2Sjtc skcnt -= cnt; 5908b35abe2Sjtc } 591cdec4ac1Sdsl return 0; 5928b35abe2Sjtc } 5938b35abe2Sjtc 5948b35abe2Sjtc /* 5958b35abe2Sjtc * wr_rdfile() 5968b35abe2Sjtc * fill write buffer with the contents of a file. We are passed an open 597*5b28f239Srillig * file descriptor to the file and the archive structure that describes the 5988b35abe2Sjtc * file we are storing. The variable "left" is modified to contain the 5998b35abe2Sjtc * number of bytes of the file we were NOT able to write to the archive. 6008b35abe2Sjtc * it is important that we always write EXACTLY the number of bytes that 6018b35abe2Sjtc * the format specific write routine told us to. The file can also get 6028b35abe2Sjtc * bigger, so reading to the end of file would create an improper archive, 6038b35abe2Sjtc * we just detect this case and warn the user. We never create a bad 6048b35abe2Sjtc * archive if we can avoid it. Of course trying to archive files that are 6058b35abe2Sjtc * active is asking for trouble. It we fail, we pass back how much we 6068b35abe2Sjtc * could NOT copy and let the caller deal with it. 6078b35abe2Sjtc * Return: 6088b35abe2Sjtc * 0 ok, -1 if archive write failure. a short read of the file returns a 6098b35abe2Sjtc * 0, but "left" is set to be greater than zero. 6108b35abe2Sjtc */ 6118b35abe2Sjtc 6128b35abe2Sjtc int 6138b35abe2Sjtc wr_rdfile(ARCHD *arcn, int ifd, off_t *left) 6148b35abe2Sjtc { 61548250187Stls int cnt; 61648250187Stls int res = 0; 61748250187Stls off_t size = arcn->sb.st_size; 61868df8738Slukem struct stat origsb, sb; 61968df8738Slukem 62068df8738Slukem /* 62168df8738Slukem * by default, remember the previously obtained stat information 62268df8738Slukem * (in arcn->sb) for comparing the mtime after reading. 62368df8738Slukem * if Mflag is set, use the actual mtime instead. 62468df8738Slukem */ 62568df8738Slukem origsb = arcn->sb; 62668df8738Slukem if (Mflag && (fstat(ifd, &origsb) < 0)) 62768df8738Slukem syswarn(1, errno, "Failed stat on %s", arcn->org_name); 6288b35abe2Sjtc 6298b35abe2Sjtc /* 6308b35abe2Sjtc * while there are more bytes to write 6318b35abe2Sjtc */ 6328b35abe2Sjtc while (size > 0L) { 6338b35abe2Sjtc cnt = bufend - bufpt; 6348b35abe2Sjtc if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) { 6358b35abe2Sjtc *left = size; 636cdec4ac1Sdsl return -1; 6378b35abe2Sjtc } 6388b35abe2Sjtc cnt = MIN(cnt, size); 639ba0ae447Sitohy if ((res = read_with_restart(ifd, bufpt, cnt)) <= 0) 6408b35abe2Sjtc break; 6418b35abe2Sjtc size -= res; 6428b35abe2Sjtc bufpt += res; 6438b35abe2Sjtc } 6448b35abe2Sjtc 6458b35abe2Sjtc /* 6468b35abe2Sjtc * better check the file did not change during this operation 6478b35abe2Sjtc * or the file read failed. 6488b35abe2Sjtc */ 6498b35abe2Sjtc if (res < 0) 6508b35abe2Sjtc syswarn(1, errno, "Read fault on %s", arcn->org_name); 6518b35abe2Sjtc else if (size != 0L) 652f3cd6022Schristos tty_warn(1, "File changed size during read %s", arcn->org_name); 6538b35abe2Sjtc else if (fstat(ifd, &sb) < 0) 6548b35abe2Sjtc syswarn(1, errno, "Failed stat on %s", arcn->org_name); 65568df8738Slukem else if (origsb.st_mtime != sb.st_mtime) 656f3cd6022Schristos tty_warn(1, "File %s was modified during copy to archive", 6578b35abe2Sjtc arcn->org_name); 6588b35abe2Sjtc *left = size; 659cdec4ac1Sdsl return 0; 6608b35abe2Sjtc } 6618b35abe2Sjtc 6628b35abe2Sjtc /* 6638b35abe2Sjtc * rd_wrfile() 6648b35abe2Sjtc * extract the contents of a file from the archive. If we are unable to 6658b35abe2Sjtc * extract the entire file (due to failure to write the file) we return 6668b35abe2Sjtc * the numbers of bytes we did NOT process. This way the caller knows how 6678b35abe2Sjtc * many bytes to skip past to find the next archive header. If the failure 6688b35abe2Sjtc * was due to an archive read, we will catch that when we try to skip. If 6698b35abe2Sjtc * the format supplies a file data crc value, we calculate the actual crc 6708b35abe2Sjtc * so that it can be compared to the value stored in the header 6718b35abe2Sjtc * NOTE: 6728b35abe2Sjtc * We call a special function to write the file. This function attempts to 6738b35abe2Sjtc * restore file holes (blocks of zeros) into the file. When files are 6748b35abe2Sjtc * sparse this saves space, and is a LOT faster. For non sparse files 6758b35abe2Sjtc * the performance hit is small. As of this writing, no archive supports 6768b35abe2Sjtc * information on where the file holes are. 6778b35abe2Sjtc * Return: 6788b35abe2Sjtc * 0 ok, -1 if archive read failure. if we cannot write the entire file, 6798b35abe2Sjtc * we return a 0 but "left" is set to be the amount unwritten 6808b35abe2Sjtc */ 6818b35abe2Sjtc 6828b35abe2Sjtc int 6838b35abe2Sjtc rd_wrfile(ARCHD *arcn, int ofd, off_t *left) 6848b35abe2Sjtc { 68548250187Stls int cnt = 0; 68648250187Stls off_t size = arcn->sb.st_size; 68748250187Stls int res = 0; 68848250187Stls char *fnm = arcn->name; 6898b35abe2Sjtc int isem = 1; 6908b35abe2Sjtc int rem; 6918b35abe2Sjtc int sz = MINFBSZ; 6928b35abe2Sjtc struct stat sb; 6938b35abe2Sjtc u_long crc = 0L; 6948b35abe2Sjtc 6958b35abe2Sjtc /* 6968b35abe2Sjtc * pass the blocksize of the file being written to the write routine, 6978b35abe2Sjtc * if the size is zero, use the default MINFBSZ 6988b35abe2Sjtc */ 69924aca7f6Schristos if (ofd < 0) 70078e294d1Smrg sz = PAXPATHLEN+1; 70178e294d1Smrg else if (fstat(ofd, &sb) == 0) { 7028b35abe2Sjtc if (sb.st_blksize > 0) 7038b35abe2Sjtc sz = (int)sb.st_blksize; 7048b35abe2Sjtc } else 705d1391f9fSgrant syswarn(0, errno, 706d1391f9fSgrant "Unable to obtain block size for file %s", fnm); 7078b35abe2Sjtc rem = sz; 7088b35abe2Sjtc *left = 0L; 7098b35abe2Sjtc 7108b35abe2Sjtc /* 7118b35abe2Sjtc * Copy the archive to the file the number of bytes specified. We have 7128b35abe2Sjtc * to assume that we want to recover file holes as none of the archive 7138b35abe2Sjtc * formats can record the location of file holes. 7148b35abe2Sjtc */ 7158b35abe2Sjtc while (size > 0L) { 7168b35abe2Sjtc cnt = bufend - bufpt; 7178b35abe2Sjtc /* 7188b35abe2Sjtc * if we get a read error, we do not want to skip, as we may 7198b35abe2Sjtc * miss a header, so we do not set left, but if we get a write 7208b35abe2Sjtc * error, we do want to skip over the unprocessed data. 7218b35abe2Sjtc */ 7228b35abe2Sjtc if ((cnt <= 0) && ((cnt = buf_fill()) <= 0)) 7238b35abe2Sjtc break; 7248b35abe2Sjtc cnt = MIN(cnt, size); 7258b35abe2Sjtc if ((res = file_write(ofd,bufpt,cnt,&rem,&isem,sz,fnm)) <= 0) { 7268b35abe2Sjtc *left = size; 7278b35abe2Sjtc break; 7288b35abe2Sjtc } 7298b35abe2Sjtc 7308b35abe2Sjtc if (docrc) { 7318b35abe2Sjtc /* 7328b35abe2Sjtc * update the actual crc value 7338b35abe2Sjtc */ 7348b35abe2Sjtc cnt = res; 7358b35abe2Sjtc while (--cnt >= 0) 7368b35abe2Sjtc crc += *bufpt++ & 0xff; 7378b35abe2Sjtc } else 7388b35abe2Sjtc bufpt += res; 7398b35abe2Sjtc size -= res; 7408b35abe2Sjtc } 7418b35abe2Sjtc 7428b35abe2Sjtc /* 7438b35abe2Sjtc * if the last block has a file hole (all zero), we must make sure this 7448b35abe2Sjtc * gets updated in the file. We force the last block of zeros to be 745f8adf56dSitohy * written. just closing with the file offset moved forward may not put 7468b35abe2Sjtc * a hole at the end of the file. 7478b35abe2Sjtc */ 748d2813c52Slukem if (ofd >= 0 && isem && (arcn->sb.st_size > 0L)) { 749d2813c52Slukem if (file_flush(ofd, fnm, isem) < 0) { 750d2813c52Slukem /* write flush errors are not an error here */; 751d2813c52Slukem } 752d2813c52Slukem } 7538b35abe2Sjtc 7548b35abe2Sjtc /* 7558b35abe2Sjtc * if we failed from archive read, we do not want to skip 7568b35abe2Sjtc */ 7578b35abe2Sjtc if ((size > 0L) && (*left == 0L)) 758cdec4ac1Sdsl return -1; 7598b35abe2Sjtc 7608b35abe2Sjtc /* 7618b35abe2Sjtc * some formats record a crc on file data. If so, then we compare the 7628b35abe2Sjtc * calculated crc to the crc stored in the archive 7638b35abe2Sjtc */ 764d2813c52Slukem if (docrc && (size == 0L) && (arcn->crc != crc)) { 765f3cd6022Schristos tty_warn(1,"Actual crc does not match expected crc %s", 766f3cd6022Schristos arcn->name); 767d2813c52Slukem /* crc warning is not an error */ 768d2813c52Slukem } 769cdec4ac1Sdsl return 0; 7708b35abe2Sjtc } 7718b35abe2Sjtc 7728b35abe2Sjtc /* 7738b35abe2Sjtc * cp_file() 7748b35abe2Sjtc * copy the contents of one file to another. used during -rw phase of pax 7758b35abe2Sjtc * just as in rd_wrfile() we use a special write function to write the 7768b35abe2Sjtc * destination file so we can properly copy files with holes. 777d2813c52Slukem * Return: 778d2813c52Slukem * 0 if ok, -1 if any error. 7798b35abe2Sjtc */ 7808b35abe2Sjtc 781d2813c52Slukem int 7828b35abe2Sjtc cp_file(ARCHD *arcn, int fd1, int fd2) 7838b35abe2Sjtc { 78448250187Stls int cnt; 78548250187Stls off_t cpcnt = 0L; 78648250187Stls int res = 0; 78748250187Stls char *fnm = arcn->name; 78848250187Stls int no_hole = 0; 7898b35abe2Sjtc int isem = 1; 7908b35abe2Sjtc int rem; 7918b35abe2Sjtc int sz = MINFBSZ; 79268df8738Slukem struct stat sb, origsb; 793d2813c52Slukem int rv = 0; 7948b35abe2Sjtc 7958b35abe2Sjtc /* 7968b35abe2Sjtc * check for holes in the source file. If none, we will use regular 7978b35abe2Sjtc * write instead of file write. 7988b35abe2Sjtc */ 7998b35abe2Sjtc if (((off_t)(arcn->sb.st_blocks * BLKMULT)) >= arcn->sb.st_size) 8008b35abe2Sjtc ++no_hole; 8018b35abe2Sjtc 8028b35abe2Sjtc /* 80368df8738Slukem * by default, remember the previously obtained stat information 80468df8738Slukem * (in arcn->sb) for comparing the mtime after reading. 80568df8738Slukem * if Mflag is set, use the actual mtime instead. 80668df8738Slukem */ 80768df8738Slukem origsb = arcn->sb; 808d2813c52Slukem if (Mflag && (fstat(fd1, &origsb) < 0)) { 80968df8738Slukem syswarn(1, errno, "Failed stat on %s", arcn->org_name); 810d2813c52Slukem rv = -1; 811d2813c52Slukem } 81268df8738Slukem 81368df8738Slukem /* 8148b35abe2Sjtc * pass the blocksize of the file being written to the write routine, 8158b35abe2Sjtc * if the size is zero, use the default MINFBSZ 8168b35abe2Sjtc */ 8178b35abe2Sjtc if (fstat(fd2, &sb) == 0) { 8188b35abe2Sjtc if (sb.st_blksize > 0) 8198b35abe2Sjtc sz = sb.st_blksize; 8208b35abe2Sjtc } else 821d1391f9fSgrant syswarn(0, errno, 822d1391f9fSgrant "Unable to obtain block size for file %s", fnm); 8238b35abe2Sjtc rem = sz; 8248b35abe2Sjtc 8258b35abe2Sjtc /* 8268b35abe2Sjtc * read the source file and copy to destination file until EOF 8278b35abe2Sjtc */ 8288b35abe2Sjtc for(;;) { 829ba0ae447Sitohy if ((cnt = read_with_restart(fd1, buf, blksz)) <= 0) 8308b35abe2Sjtc break; 8318b35abe2Sjtc if (no_hole) 832ba0ae447Sitohy res = xwrite(fd2, buf, cnt); 8338b35abe2Sjtc else 8348b35abe2Sjtc res = file_write(fd2, buf, cnt, &rem, &isem, sz, fnm); 8358b35abe2Sjtc if (res != cnt) 8368b35abe2Sjtc break; 8378b35abe2Sjtc cpcnt += cnt; 8388b35abe2Sjtc } 8398b35abe2Sjtc 8408b35abe2Sjtc /* 8418b35abe2Sjtc * check to make sure the copy is valid. 8428b35abe2Sjtc */ 843d2813c52Slukem if (res < 0) { 8448b35abe2Sjtc syswarn(1, errno, "Failed write during copy of %s to %s", 8458b35abe2Sjtc arcn->org_name, arcn->name); 846d2813c52Slukem rv = -1; 847d2813c52Slukem } else if (cpcnt != arcn->sb.st_size) { 848f3cd6022Schristos tty_warn(1, "File %s changed size during copy to %s", 8498b35abe2Sjtc arcn->org_name, arcn->name); 850d2813c52Slukem rv = -1; 851d2813c52Slukem } else if (fstat(fd1, &sb) < 0) { 8528b35abe2Sjtc syswarn(1, errno, "Failed stat of %s", arcn->org_name); 853d2813c52Slukem rv = -1; 854d2813c52Slukem } else if (origsb.st_mtime != sb.st_mtime) { 855f3cd6022Schristos tty_warn(1, "File %s was modified during copy to %s", 8568b35abe2Sjtc arcn->org_name, arcn->name); 857d2813c52Slukem rv = -1; 858d2813c52Slukem } 8598b35abe2Sjtc 8608b35abe2Sjtc /* 8618b35abe2Sjtc * if the last block has a file hole (all zero), we must make sure this 8628b35abe2Sjtc * gets updated in the file. We force the last block of zeros to be 863f8adf56dSitohy * written. just closing with the file offset moved forward may not put 8648b35abe2Sjtc * a hole at the end of the file. 8658b35abe2Sjtc */ 866d2813c52Slukem if (!no_hole && isem && (arcn->sb.st_size > 0L)) { 867d2813c52Slukem if (file_flush(fd2, fnm, isem) < 0) 868d2813c52Slukem rv = -1; 869d2813c52Slukem } 870d2813c52Slukem return rv; 8718b35abe2Sjtc } 8728b35abe2Sjtc 8738b35abe2Sjtc /* 8748b35abe2Sjtc * buf_fill() 8758b35abe2Sjtc * fill the read buffer with the next record (or what we can get) from 8768b35abe2Sjtc * the archive volume. 8778b35abe2Sjtc * Return: 8788b35abe2Sjtc * Number of bytes of data in the read buffer, -1 for read error, and 8798b35abe2Sjtc * 0 when finished (user specified termination in ar_next()). 8808b35abe2Sjtc */ 8818b35abe2Sjtc 8828b35abe2Sjtc int 8838b35abe2Sjtc buf_fill(void) 8848b35abe2Sjtc { 88548250187Stls int cnt; 8868b35abe2Sjtc static int fini = 0; 8878b35abe2Sjtc 8888b35abe2Sjtc if (fini) 889cdec4ac1Sdsl return 0; 8908b35abe2Sjtc 8918b35abe2Sjtc for(;;) { 8928b35abe2Sjtc /* 8938b35abe2Sjtc * try to fill the buffer. on error the next archive volume is 8948b35abe2Sjtc * opened and we try again. 8958b35abe2Sjtc */ 8968b35abe2Sjtc if ((cnt = ar_read(buf, blksz)) > 0) { 8978b35abe2Sjtc bufpt = buf; 8988b35abe2Sjtc bufend = buf + cnt; 8998b35abe2Sjtc rdcnt += cnt; 900cdec4ac1Sdsl return cnt; 9018b35abe2Sjtc } 9028b35abe2Sjtc 9038b35abe2Sjtc /* 9048b35abe2Sjtc * errors require resync, EOF goes to next archive 905bc5cd54eSchristos * but in case we have not determined yet the format, 906bc5cd54eSchristos * this means that we have a very short file, so we 907bc5cd54eSchristos * are done again. 9088b35abe2Sjtc */ 9098b35abe2Sjtc if (cnt < 0) 9108b35abe2Sjtc break; 911bc5cd54eSchristos if (frmt == NULL || ar_next() < 0) { 9128b35abe2Sjtc fini = 1; 913cdec4ac1Sdsl return 0; 9148b35abe2Sjtc } 9158b35abe2Sjtc rdcnt = 0; 9168b35abe2Sjtc } 9178b35abe2Sjtc exit_val = 1; 918cdec4ac1Sdsl return -1; 9198b35abe2Sjtc } 9208b35abe2Sjtc 9218b35abe2Sjtc /* 9228b35abe2Sjtc * buf_flush() 9238b35abe2Sjtc * force the write buffer to the archive. We are passed the number of 9248b35abe2Sjtc * bytes in the buffer at the point of the flush. When we change archives 9258b35abe2Sjtc * the record size might change. (either larger or smaller). 9268b35abe2Sjtc * Return: 9278b35abe2Sjtc * 0 if all is ok, -1 when a write error occurs. 9288b35abe2Sjtc */ 9298b35abe2Sjtc 9308b35abe2Sjtc int 93148250187Stls buf_flush(int bufcnt) 9328b35abe2Sjtc { 93348250187Stls int cnt; 93448250187Stls int push = 0; 93548250187Stls int totcnt = 0; 9368b35abe2Sjtc 9378b35abe2Sjtc /* 9388b35abe2Sjtc * if we have reached the user specified byte count for each archive 9395893dbb3Swiz * volume, prompt for the next volume. (The non-standard -R flag). 9408b35abe2Sjtc * NOTE: If the wrlimit is smaller than wrcnt, we will always write 9418b35abe2Sjtc * at least one record. We always round limit UP to next blocksize. 9428b35abe2Sjtc */ 9438b35abe2Sjtc if ((wrlimit > 0) && (wrcnt > wrlimit)) { 944f3cd6022Schristos tty_warn(0, 945f3cd6022Schristos "User specified archive volume byte limit reached."); 9468b35abe2Sjtc if (ar_next() < 0) { 9478b35abe2Sjtc wrcnt = 0; 9488b35abe2Sjtc exit_val = 1; 949cdec4ac1Sdsl return -1; 9508b35abe2Sjtc } 9518b35abe2Sjtc wrcnt = 0; 9528b35abe2Sjtc 9538b35abe2Sjtc /* 9548b35abe2Sjtc * The new archive volume might have changed the size of the 9558b35abe2Sjtc * write blocksize. if so we figure out if we need to write 9568b35abe2Sjtc * (one or more times), or if there is now free space left in 9578b35abe2Sjtc * the buffer (it is no longer full). bufcnt has the number of 9588b35abe2Sjtc * bytes in the buffer, (the blocksize, at the point we were 9598b35abe2Sjtc * CALLED). Push has the amount of "extra" data in the buffer 9608b35abe2Sjtc * if the block size has shrunk from a volume change. 9618b35abe2Sjtc */ 9628b35abe2Sjtc bufend = buf + blksz; 9638b35abe2Sjtc if (blksz > bufcnt) 964cdec4ac1Sdsl return 0; 9658b35abe2Sjtc if (blksz < bufcnt) 9668b35abe2Sjtc push = bufcnt - blksz; 9678b35abe2Sjtc } 9688b35abe2Sjtc 9698b35abe2Sjtc /* 9708b35abe2Sjtc * We have enough data to write at least one archive block 9718b35abe2Sjtc */ 9728b35abe2Sjtc for (;;) { 9738b35abe2Sjtc /* 9748b35abe2Sjtc * write a block and check if it all went out ok 9758b35abe2Sjtc */ 9768b35abe2Sjtc cnt = ar_write(buf, blksz); 9778b35abe2Sjtc if (cnt == blksz) { 9788b35abe2Sjtc /* 9798b35abe2Sjtc * the write went ok 9808b35abe2Sjtc */ 9818b35abe2Sjtc wrcnt += cnt; 9828b35abe2Sjtc totcnt += cnt; 9838b35abe2Sjtc if (push > 0) { 9848b35abe2Sjtc /* we have extra data to push to the front. 9858b35abe2Sjtc * check for more than 1 block of push, and if 9868b35abe2Sjtc * so we loop back to write again 9878b35abe2Sjtc */ 98806f53b68Smycroft memcpy(buf, bufend, push); 9898b35abe2Sjtc bufpt = buf + push; 9908b35abe2Sjtc if (push >= blksz) { 9918b35abe2Sjtc push -= blksz; 9928b35abe2Sjtc continue; 9938b35abe2Sjtc } 9948b35abe2Sjtc } else 9958b35abe2Sjtc bufpt = buf; 996cdec4ac1Sdsl return totcnt; 9978b35abe2Sjtc } else if (cnt > 0) { 9988b35abe2Sjtc /* 9998b35abe2Sjtc * Oh drat we got a partial write! 10008b35abe2Sjtc * if format doesnt care about alignment let it go, 10018b35abe2Sjtc * we warned the user in ar_write().... but this means 10028b35abe2Sjtc * the last record on this volume violates pax spec.... 10038b35abe2Sjtc */ 10048b35abe2Sjtc totcnt += cnt; 10058b35abe2Sjtc wrcnt += cnt; 10068b35abe2Sjtc bufpt = buf + cnt; 10078b35abe2Sjtc cnt = bufcnt - cnt; 100806f53b68Smycroft memcpy(buf, bufpt, cnt); 10098b35abe2Sjtc bufpt = buf + cnt; 10108b35abe2Sjtc if (!frmt->blkalgn || ((cnt % frmt->blkalgn) == 0)) 1011cdec4ac1Sdsl return totcnt; 10128b35abe2Sjtc break; 10138b35abe2Sjtc } 10148b35abe2Sjtc 10158b35abe2Sjtc /* 10168b35abe2Sjtc * All done, go to next archive 10178b35abe2Sjtc */ 10188b35abe2Sjtc wrcnt = 0; 10198b35abe2Sjtc if (ar_next() < 0) 10208b35abe2Sjtc break; 10218b35abe2Sjtc 10228b35abe2Sjtc /* 10238b35abe2Sjtc * The new archive volume might also have changed the block 10248b35abe2Sjtc * size. if so, figure out if we have too much or too little 10258b35abe2Sjtc * data for using the new block size 10268b35abe2Sjtc */ 10278b35abe2Sjtc bufend = buf + blksz; 10288b35abe2Sjtc if (blksz > bufcnt) 1029cdec4ac1Sdsl return 0; 10308b35abe2Sjtc if (blksz < bufcnt) 10318b35abe2Sjtc push = bufcnt - blksz; 10328b35abe2Sjtc } 10338b35abe2Sjtc 10348b35abe2Sjtc /* 10358b35abe2Sjtc * write failed, stop pax. we must not create a bad archive! 10368b35abe2Sjtc */ 10378b35abe2Sjtc exit_val = 1; 1038cdec4ac1Sdsl return -1; 10398b35abe2Sjtc } 1040