00001 /*- 00002 * Copyright (c) 1992 Keith Muller. 00003 * Copyright (c) 1992, 1993 00004 * The Regents of the University of California. All rights reserved. 00005 * 00006 * This code is derived from software contributed to Berkeley by 00007 * Keith Muller of the University of California, San Diego. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 1. Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * 2. Redistributions in binary form must reproduce the above copyright 00015 * notice, this list of conditions and the following disclaimer in the 00016 * documentation and/or other materials provided with the distribution. 00017 * 4. Neither the name of the University nor the names of its contributors 00018 * may be used to endorse or promote products derived from this software 00019 * without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00022 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00023 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00024 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00025 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00026 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00027 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00028 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00029 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00030 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00031 * SUCH DAMAGE. 00032 */ 00033 00034 #ifndef lint 00035 #if 0 00036 static char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94"; 00037 #endif 00038 #endif /* not lint */ 00039 00040 #include <sys/types.h> 00041 #include <sys/stat.h> 00042 #include <errno.h> 00043 #include <unistd.h> 00044 #include <stdio.h> 00045 #include <stdlib.h> 00046 #include <string.h> 00047 #include "pax.h" 00048 #include "extern.h" 00049 00050 /* 00051 * routines which implement archive and file buffering 00052 */ 00053 00054 #define MINFBSZ 512 /* default block size for hole detect */ 00055 #define MAXFLT 10 /* default media read error limit */ 00056 00057 /* 00058 * Need to change bufmem to dynamic allocation when the upper 00059 * limit on blocking size is removed (though that will violate pax spec) 00060 * MAXBLK define and tests will also need to be updated. 00061 */ 00062 static char bufmem[MAXBLK+BLKMULT]; /* i/o buffer + pushback id space */ 00063 static char *buf; /* normal start of i/o buffer */ 00064 static char *bufend; /* end or last char in i/o buffer */ 00065 static char *bufpt; /* read/write point in i/o buffer */ 00066 int blksz = MAXBLK; /* block input/output size in bytes */ 00067 int wrblksz; /* user spec output size in bytes */ 00068 int maxflt = MAXFLT; /* MAX consecutive media errors */ 00069 int rdblksz; /* first read blksize (tapes only) */ 00070 off_t wrlimit; /* # of bytes written per archive vol */ 00071 off_t wrcnt; /* # of bytes written on current vol */ 00072 off_t rdcnt; /* # of bytes read on current vol */ 00073 00074 /* 00075 * wr_start() 00076 * set up the buffering system to operate in a write mode 00077 * Return: 00078 * 0 if ok, -1 if the user specified write block size violates pax spec 00079 */ 00080 00081 int 00082 wr_start(void) 00083 { 00084 buf = &(bufmem[BLKMULT]); 00085 /* 00086 * Check to make sure the write block size meets pax specs. If the user 00087 * does not specify a blocksize, we use the format default blocksize. 00088 * We must be picky on writes, so we do not allow the user to create an 00089 * archive that might be hard to read elsewhere. If all ok, we then 00090 * open the first archive volume 00091 */ 00092 if (!wrblksz) 00093 wrblksz = frmt->bsz; 00094 if (wrblksz > MAXBLK) { 00095 paxwarn(1, "Write block size of %d too large, maximum is: %d", 00096 wrblksz, MAXBLK); 00097 return(-1); 00098 } 00099 if (wrblksz % BLKMULT) { 00100 paxwarn(1, "Write block size of %d is not a %d byte multiple", 00101 wrblksz, BLKMULT); 00102 return(-1); 00103 } 00104 if (wrblksz > MAXBLK_POSIX) { 00105 paxwarn(0, "Write block size of %d larger than POSIX max %d, archive may not be portable", 00106 wrblksz, MAXBLK_POSIX); 00107 return(-1); 00108 } 00109 00110 /* 00111 * we only allow wrblksz to be used with all archive operations 00112 */ 00113 blksz = rdblksz = wrblksz; 00114 if ((ar_open(arcname) < 0) && (ar_next() < 0)) 00115 return(-1); 00116 wrcnt = 0; 00117 bufend = buf + wrblksz; 00118 bufpt = buf; 00119 return(0); 00120 } 00121 00122 /* 00123 * rd_start() 00124 * set up buffering system to read an archive 00125 * Return: 00126 * 0 if ok, -1 otherwise 00127 */ 00128 00129 int 00130 rd_start(void) 00131 { 00132 /* 00133 * leave space for the header pushback (see get_arc()). If we are 00134 * going to append and user specified a write block size, check it 00135 * right away 00136 */ 00137 buf = &(bufmem[BLKMULT]); 00138 if ((act == APPND) && wrblksz) { 00139 if (wrblksz > MAXBLK) { 00140 paxwarn(1,"Write block size %d too large, maximum is: %d", 00141 wrblksz, MAXBLK); 00142 return(-1); 00143 } 00144 if (wrblksz % BLKMULT) { 00145 paxwarn(1, "Write block size %d is not a %d byte multiple", 00146 wrblksz, BLKMULT); 00147 return(-1); 00148 } 00149 } 00150 00151 /* 00152 * open the archive 00153 */ 00154 if ((ar_open(arcname) < 0) && (ar_next() < 0)) 00155 return(-1); 00156 bufend = buf + rdblksz; 00157 bufpt = bufend; 00158 rdcnt = 0; 00159 return(0); 00160 } 00161 00162 /* 00163 * cp_start() 00164 * set up buffer system for copying within the file system 00165 */ 00166 00167 void 00168 cp_start(void) 00169 { 00170 buf = &(bufmem[BLKMULT]); 00171 rdblksz = blksz = MAXBLK; 00172 } 00173 00174 /* 00175 * appnd_start() 00176 * Set up the buffering system to append new members to an archive that 00177 * was just read. The last block(s) of an archive may contain a format 00178 * specific trailer. To append a new member, this trailer has to be 00179 * removed from the archive. The first byte of the trailer is replaced by 00180 * the start of the header of the first file added to the archive. The 00181 * format specific end read function tells us how many bytes to move 00182 * backwards in the archive to be positioned BEFORE the trailer. Two 00183 * different postions have to be adjusted, the O.S. file offset (e.g. the 00184 * position of the tape head) and the write point within the data we have 00185 * stored in the read (soon to become write) buffer. We may have to move 00186 * back several records (the number depends on the size of the archive 00187 * record and the size of the format trailer) to read up the record where 00188 * the first byte of the trailer is recorded. Trailers may span (and 00189 * overlap) record boundries. 00190 * We first calculate which record has the first byte of the trailer. We 00191 * move the OS file offset back to the start of this record and read it 00192 * up. We set the buffer write pointer to be at this byte (the byte where 00193 * the trailer starts). We then move the OS file pointer back to the 00194 * start of this record so a flush of this buffer will replace the record 00195 * in the archive. 00196 * A major problem is rewriting this last record. For archives stored 00197 * on disk files, this is trival. However, many devices are really picky 00198 * about the conditions under which they will allow a write to occur. 00199 * Often devices restrict the conditions where writes can be made writes, 00200 * so it may not be feasable to append archives stored on all types of 00201 * devices. 00202 * Return: 00203 * 0 for success, -1 for failure 00204 */ 00205 00206 int 00207 appnd_start(off_t skcnt) 00208 { 00209 int res; 00210 off_t cnt; 00211 00212 if (exit_val != 0) { 00213 paxwarn(0, "Cannot append to an archive that may have flaws."); 00214 return(-1); 00215 } 00216 /* 00217 * if the user did not specify a write blocksize, inherit the size used 00218 * in the last archive volume read. (If a is set we still use rdblksz 00219 * until next volume, cannot shift sizes within a single volume). 00220 */ 00221 if (!wrblksz) 00222 wrblksz = blksz = rdblksz; 00223 else 00224 blksz = rdblksz; 00225 00226 /* 00227 * make sure that this volume allows appends 00228 */ 00229 if (ar_app_ok() < 0) 00230 return(-1); 00231 00232 /* 00233 * Calculate bytes to move back and move in front of record where we 00234 * need to start writing from. Remember we have to add in any padding 00235 * that might be in the buffer after the trailer in the last block. We 00236 * travel skcnt + padding ROUNDED UP to blksize. 00237 */ 00238 skcnt += bufend - bufpt; 00239 if ((cnt = (skcnt/blksz) * blksz) < skcnt) 00240 cnt += blksz; 00241 if (ar_rev((off_t)cnt) < 0) 00242 goto out; 00243 00244 /* 00245 * We may have gone too far if there is valid data in the block we are 00246 * now in front of, read up the block and position the pointer after 00247 * the valid data. 00248 */ 00249 if ((cnt -= skcnt) > 0) { 00250 /* 00251 * watch out for stupid tape drives. ar_rev() will set rdblksz 00252 * to be real physical blocksize so we must loop until we get 00253 * the old rdblksz (now in blksz). If ar_rev() fouls up the 00254 * determination of the physical block size, we will fail. 00255 */ 00256 bufpt = buf; 00257 bufend = buf + blksz; 00258 while (bufpt < bufend) { 00259 if ((res = ar_read(bufpt, rdblksz)) <= 0) 00260 goto out; 00261 bufpt += res; 00262 } 00263 if (ar_rev((off_t)(bufpt - buf)) < 0) 00264 goto out; 00265 bufpt = buf + cnt; 00266 bufend = buf + blksz; 00267 } else { 00268 /* 00269 * buffer is empty 00270 */ 00271 bufend = buf + blksz; 00272 bufpt = buf; 00273 } 00274 rdblksz = blksz; 00275 rdcnt -= skcnt; 00276 wrcnt = 0; 00277 00278 /* 00279 * At this point we are ready to write. If the device requires special 00280 * handling to write at a point were previously recorded data resides, 00281 * that is handled in ar_set_wr(). From now on we operate under normal 00282 * ARCHIVE mode (write) conditions 00283 */ 00284 if (ar_set_wr() < 0) 00285 return(-1); 00286 act = ARCHIVE; 00287 return(0); 00288 00289 out: 00290 paxwarn(1, "Unable to rewrite archive trailer, cannot append."); 00291 return(-1); 00292 } 00293 00294 /* 00295 * rd_sync() 00296 * A read error occurred on this archive volume. Resync the buffer and 00297 * try to reset the device (if possible) so we can continue to read. Keep 00298 * trying to do this until we get a valid read, or we reach the limit on 00299 * consecutive read faults (at which point we give up). The user can 00300 * adjust the read error limit through a command line option. 00301 * Returns: 00302 * 0 on success, and -1 on failure 00303 */ 00304 00305 int 00306 rd_sync(void) 00307 { 00308 int errcnt = 0; 00309 int res; 00310 00311 /* 00312 * if the user says bail out on first fault, we are out of here... 00313 */ 00314 if (maxflt == 0) 00315 return(-1); 00316 if (act == APPND) { 00317 paxwarn(1, "Unable to append when there are archive read errors."); 00318 return(-1); 00319 } 00320 00321 /* 00322 * poke at device and try to get past media error 00323 */ 00324 if (ar_rdsync() < 0) { 00325 if (ar_next() < 0) 00326 return(-1); 00327 else 00328 rdcnt = 0; 00329 } 00330 00331 for (;;) { 00332 if ((res = ar_read(buf, blksz)) > 0) { 00333 /* 00334 * All right! got some data, fill that buffer 00335 */ 00336 bufpt = buf; 00337 bufend = buf + res; 00338 rdcnt += res; 00339 return(0); 00340 } 00341 00342 /* 00343 * Oh well, yet another failed read... 00344 * if error limit reached, ditch. o.w. poke device to move past 00345 * bad media and try again. if media is badly damaged, we ask 00346 * the poor (and upset user at this point) for the next archive 00347 * volume. remember the goal on reads is to get the most we 00348 * can extract out of the archive. 00349 */ 00350 if ((maxflt > 0) && (++errcnt > maxflt)) 00351 paxwarn(0,"Archive read error limit (%d) reached",maxflt); 00352 else if (ar_rdsync() == 0) 00353 continue; 00354 if (ar_next() < 0) 00355 break; 00356 rdcnt = 0; 00357 errcnt = 0; 00358 } 00359 return(-1); 00360 } 00361 00362 /* 00363 * pback() 00364 * push the data used during the archive id phase back into the I/O 00365 * buffer. This is required as we cannot be sure that the header does NOT 00366 * overlap a block boundry (as in the case we are trying to recover a 00367 * flawed archived). This was not designed to be used for any other 00368 * purpose. (What software engineering, HA!) 00369 * WARNING: do not even THINK of pback greater than BLKMULT, unless the 00370 * pback space is increased. 00371 */ 00372 00373 void 00374 pback(char *pt, int cnt) 00375 { 00376 bufpt -= cnt; 00377 memcpy(bufpt, pt, cnt); 00378 return; 00379 } 00380 00381 /* 00382 * rd_skip() 00383 * skip foward in the archive during an archive read. Used to get quickly 00384 * past file data and padding for files the user did NOT select. 00385 * Return: 00386 * 0 if ok, -1 failure, and 1 when EOF on the archive volume was detected. 00387 */ 00388 00389 int 00390 rd_skip(off_t skcnt) 00391 { 00392 off_t res; 00393 off_t cnt; 00394 off_t skipped = 0; 00395 00396 /* 00397 * consume what data we have in the buffer. If we have to move foward 00398 * whole records, we call the low level skip function to see if we can 00399 * move within the archive without doing the expensive reads on data we 00400 * do not want. 00401 */ 00402 if (skcnt == 0) 00403 return(0); 00404 res = MIN((bufend - bufpt), skcnt); 00405 bufpt += res; 00406 skcnt -= res; 00407 00408 /* 00409 * if skcnt is now 0, then no additional i/o is needed 00410 */ 00411 if (skcnt == 0) 00412 return(0); 00413 00414 /* 00415 * We have to read more, calculate complete and partial record reads 00416 * based on rdblksz. we skip over "cnt" complete records 00417 */ 00418 res = skcnt%rdblksz; 00419 cnt = (skcnt/rdblksz) * rdblksz; 00420 00421 /* 00422 * if the skip fails, we will have to resync. ar_fow will tell us 00423 * how much it can skip over. We will have to read the rest. 00424 */ 00425 if (ar_fow(cnt, &skipped) < 0) 00426 return(-1); 00427 res += cnt - skipped; 00428 rdcnt += skipped; 00429 00430 /* 00431 * what is left we have to read (which may be the whole thing if 00432 * ar_fow() told us the device can only read to skip records); 00433 */ 00434 while (res > 0L) { 00435 cnt = bufend - bufpt; 00436 /* 00437 * if the read fails, we will have to resync 00438 */ 00439 if ((cnt <= 0) && ((cnt = buf_fill()) < 0)) 00440 return(-1); 00441 if (cnt == 0) 00442 return(1); 00443 cnt = MIN(cnt, res); 00444 bufpt += cnt; 00445 res -= cnt; 00446 } 00447 return(0); 00448 } 00449 00450 /* 00451 * wr_fin() 00452 * flush out any data (and pad if required) the last block. We always pad 00453 * with zero (even though we do not have to). Padding with 0 makes it a 00454 * lot easier to recover if the archive is damaged. zero paddding SHOULD 00455 * BE a requirement.... 00456 */ 00457 00458 void 00459 wr_fin(void) 00460 { 00461 if (bufpt > buf) { 00462 memset(bufpt, 0, bufend - bufpt); 00463 bufpt = bufend; 00464 (void)buf_flush(blksz); 00465 } 00466 } 00467 00468 /* 00469 * wr_rdbuf() 00470 * fill the write buffer from data passed to it in a buffer (usually used 00471 * by format specific write routines to pass a file header). On failure we 00472 * punt. We do not allow the user to continue to write flawed archives. 00473 * We assume these headers are not very large (the memory copy we use is 00474 * a bit expensive). 00475 * Return: 00476 * 0 if buffer was filled ok, -1 o.w. (buffer flush failure) 00477 */ 00478 00479 int 00480 wr_rdbuf(char *out, int outcnt) 00481 { 00482 int cnt; 00483 00484 /* 00485 * while there is data to copy copy into the write buffer. when the 00486 * write buffer fills, flush it to the archive and continue 00487 */ 00488 while (outcnt > 0) { 00489 cnt = bufend - bufpt; 00490 if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) 00491 return(-1); 00492 /* 00493 * only move what we have space for 00494 */ 00495 cnt = MIN(cnt, outcnt); 00496 memcpy(bufpt, out, cnt); 00497 bufpt += cnt; 00498 out += cnt; 00499 outcnt -= cnt; 00500 } 00501 return(0); 00502 } 00503 00504 /* 00505 * rd_wrbuf() 00506 * copy from the read buffer into a supplied buffer a specified number of 00507 * bytes. If the read buffer is empty fill it and continue to copy. 00508 * usually used to obtain a file header for processing by a format 00509 * specific read routine. 00510 * Return 00511 * number of bytes copied to the buffer, 0 indicates EOF on archive volume, 00512 * -1 is a read error 00513 */ 00514 00515 int 00516 rd_wrbuf(char *in, int cpcnt) 00517 { 00518 int res; 00519 int cnt; 00520 int incnt = cpcnt; 00521 00522 /* 00523 * loop until we fill the buffer with the requested number of bytes 00524 */ 00525 while (incnt > 0) { 00526 cnt = bufend - bufpt; 00527 if ((cnt <= 0) && ((cnt = buf_fill()) <= 0)) { 00528 /* 00529 * read error, return what we got (or the error if 00530 * no data was copied). The caller must know that an 00531 * error occured and has the best knowledge what to 00532 * do with it 00533 */ 00534 if ((res = cpcnt - incnt) > 0) 00535 return(res); 00536 return(cnt); 00537 } 00538 00539 /* 00540 * calculate how much data to copy based on whats left and 00541 * state of buffer 00542 */ 00543 cnt = MIN(cnt, incnt); 00544 memcpy(in, bufpt, cnt); 00545 bufpt += cnt; 00546 incnt -= cnt; 00547 in += cnt; 00548 } 00549 return(cpcnt); 00550 } 00551 00552 /* 00553 * wr_skip() 00554 * skip forward during a write. In other words add padding to the file. 00555 * we add zero filled padding as it makes flawed archives much easier to 00556 * recover from. the caller tells us how many bytes of padding to add 00557 * This routine was not designed to add HUGE amount of padding, just small 00558 * amounts (a few 512 byte blocks at most) 00559 * Return: 00560 * 0 if ok, -1 if there was a buf_flush failure 00561 */ 00562 00563 int 00564 wr_skip(off_t skcnt) 00565 { 00566 int cnt; 00567 00568 /* 00569 * loop while there is more padding to add 00570 */ 00571 while (skcnt > 0L) { 00572 cnt = bufend - bufpt; 00573 if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) 00574 return(-1); 00575 cnt = MIN(cnt, skcnt); 00576 memset(bufpt, 0, cnt); 00577 bufpt += cnt; 00578 skcnt -= cnt; 00579 } 00580 return(0); 00581 } 00582 00583 /* 00584 * wr_rdfile() 00585 * fill write buffer with the contents of a file. We are passed an open 00586 * file descriptor to the file and the archive structure that describes the 00587 * file we are storing. The variable "left" is modified to contain the 00588 * number of bytes of the file we were NOT able to write to the archive. 00589 * it is important that we always write EXACTLY the number of bytes that 00590 * the format specific write routine told us to. The file can also get 00591 * bigger, so reading to the end of file would create an improper archive, 00592 * we just detect this case and warn the user. We never create a bad 00593 * archive if we can avoid it. Of course trying to archive files that are 00594 * active is asking for trouble. It we fail, we pass back how much we 00595 * could NOT copy and let the caller deal with it. 00596 * Return: 00597 * 0 ok, -1 if archive write failure. a short read of the file returns a 00598 * 0, but "left" is set to be greater than zero. 00599 */ 00600 00601 int 00602 wr_rdfile(ARCHD *arcn, int ifd, off_t *left) 00603 { 00604 int cnt; 00605 int res = 0; 00606 off_t size = arcn->sb.st_size; 00607 struct stat sb; 00608 00609 /* 00610 * while there are more bytes to write 00611 */ 00612 while (size > 0L) { 00613 cnt = bufend - bufpt; 00614 if ((cnt <= 0) && ((cnt = buf_flush(blksz)) < 0)) { 00615 *left = size; 00616 return(-1); 00617 } 00618 cnt = MIN(cnt, size); 00619 if ((res = read(ifd, bufpt, cnt)) <= 0) 00620 break; 00621 size -= res; 00622 bufpt += res; 00623 } 00624 00625 /* 00626 * better check the file did not change during this operation 00627 * or the file read failed. 00628 */ 00629 if (res < 0) 00630 syswarn(1, errno, "Read fault on %s", arcn->org_name); 00631 else if (size != 0L) 00632 paxwarn(1, "File changed size during read %s", arcn->org_name); 00633 else if (fstat(ifd, &sb) < 0) 00634 syswarn(1, errno, "Failed stat on %s", arcn->org_name); 00635 else if (arcn->sb.st_mtime != sb.st_mtime) 00636 paxwarn(1, "File %s was modified during copy to archive", 00637 arcn->org_name); 00638 *left = size; 00639 return(0); 00640 } 00641 00642 /* 00643 * rd_wrfile() 00644 * extract the contents of a file from the archive. If we are unable to 00645 * extract the entire file (due to failure to write the file) we return 00646 * the numbers of bytes we did NOT process. This way the caller knows how 00647 * many bytes to skip past to find the next archive header. If the failure 00648 * was due to an archive read, we will catch that when we try to skip. If 00649 * the format supplies a file data crc value, we calculate the actual crc 00650 * so that it can be compared to the value stored in the header 00651 * NOTE: 00652 * We call a special function to write the file. This function attempts to 00653 * restore file holes (blocks of zeros) into the file. When files are 00654 * sparse this saves space, and is a LOT faster. For non sparse files 00655 * the performance hit is small. As of this writing, no archive supports 00656 * information on where the file holes are. 00657 * Return: 00658 * 0 ok, -1 if archive read failure. if we cannot write the entire file, 00659 * we return a 0 but "left" is set to be the amount unwritten 00660 */ 00661 00662 int 00663 rd_wrfile(ARCHD *arcn, int ofd, off_t *left) 00664 { 00665 int cnt = 0; 00666 off_t size = arcn->sb.st_size; 00667 int res = 0; 00668 char *fnm = arcn->name; 00669 int isem = 1; 00670 int rem; 00671 int sz = MINFBSZ; 00672 struct stat sb; 00673 u_long crc = 0L; 00674 00675 /* 00676 * pass the blocksize of the file being written to the write routine, 00677 * if the size is zero, use the default MINFBSZ 00678 */ 00679 if (fstat(ofd, &sb) == 0) { 00680 #if 0 00681 /* not under minix */ 00682 if (sb.st_blksize > 0) 00683 sz = (int)sb.st_blksize; 00684 #endif 00685 } else 00686 syswarn(0,errno,"Unable to obtain block size for file %s",fnm); 00687 rem = sz; 00688 *left = 0L; 00689 00690 /* 00691 * Copy the archive to the file the number of bytes specified. We have 00692 * to assume that we want to recover file holes as none of the archive 00693 * formats can record the location of file holes. 00694 */ 00695 while (size > 0L) { 00696 cnt = bufend - bufpt; 00697 /* 00698 * if we get a read error, we do not want to skip, as we may 00699 * miss a header, so we do not set left, but if we get a write 00700 * error, we do want to skip over the unprocessed data. 00701 */ 00702 if ((cnt <= 0) && ((cnt = buf_fill()) <= 0)) 00703 break; 00704 cnt = MIN(cnt, size); 00705 if ((res = file_write(ofd,bufpt,cnt,&rem,&isem,sz,fnm)) <= 0) { 00706 *left = size; 00707 break; 00708 } 00709 00710 if (docrc) { 00711 /* 00712 * update the actual crc value 00713 */ 00714 cnt = res; 00715 while (--cnt >= 0) 00716 crc += *bufpt++ & 0xff; 00717 } else 00718 bufpt += res; 00719 size -= res; 00720 } 00721 00722 /* 00723 * if the last block has a file hole (all zero), we must make sure this 00724 * gets updated in the file. We force the last block of zeros to be 00725 * written. just closing with the file offset moved forward may not put 00726 * a hole at the end of the file. 00727 */ 00728 if (isem && (arcn->sb.st_size > 0L)) 00729 file_flush(ofd, fnm, isem); 00730 00731 /* 00732 * if we failed from archive read, we do not want to skip 00733 */ 00734 if ((size > 0L) && (*left == 0L)) 00735 return(-1); 00736 00737 /* 00738 * some formats record a crc on file data. If so, then we compare the 00739 * calculated crc to the crc stored in the archive 00740 */ 00741 if (docrc && (size == 0L) && (arcn->crc != crc)) 00742 paxwarn(1,"Actual crc does not match expected crc %s",arcn->name); 00743 return(0); 00744 } 00745 00746 /* 00747 * cp_file() 00748 * copy the contents of one file to another. used during -rw phase of pax 00749 * just as in rd_wrfile() we use a special write function to write the 00750 * destination file so we can properly copy files with holes. 00751 */ 00752 00753 void 00754 cp_file(ARCHD *arcn, int fd1, int fd2) 00755 { 00756 int cnt; 00757 off_t cpcnt = 0L; 00758 int res = 0; 00759 char *fnm = arcn->name; 00760 int no_hole = 0; 00761 int isem = 1; 00762 int rem; 00763 int sz = MINFBSZ; 00764 struct stat sb; 00765 00766 /* 00767 * check for holes in the source file. If none, we will use regular 00768 * write instead of file write. 00769 */ 00770 #if 0 00771 /* not under minix */ 00772 if (((off_t)(arcn->sb.st_blocks * BLKMULT)) >= arcn->sb.st_size) 00773 #endif 00774 ++no_hole; 00775 00776 /* 00777 * pass the blocksize of the file being written to the write routine, 00778 * if the size is zero, use the default MINFBSZ 00779 */ 00780 if (fstat(fd2, &sb) == 0) { 00781 #if 0 00782 /* not under minix */ 00783 if (sb.st_blksize > 0) 00784 sz = sb.st_blksize; 00785 #endif 00786 } else 00787 syswarn(0,errno,"Unable to obtain block size for file %s",fnm); 00788 rem = sz; 00789 00790 /* 00791 * read the source file and copy to destination file until EOF 00792 */ 00793 for(;;) { 00794 if ((cnt = read(fd1, buf, blksz)) <= 0) 00795 break; 00796 if (no_hole) 00797 res = write(fd2, buf, cnt); 00798 else 00799 res = file_write(fd2, buf, cnt, &rem, &isem, sz, fnm); 00800 if (res != cnt) 00801 break; 00802 cpcnt += cnt; 00803 } 00804 00805 /* 00806 * check to make sure the copy is valid. 00807 */ 00808 if (res < 0) 00809 syswarn(1, errno, "Failed write during copy of %s to %s", 00810 arcn->org_name, arcn->name); 00811 else if (cpcnt != arcn->sb.st_size) 00812 paxwarn(1, "File %s changed size during copy to %s", 00813 arcn->org_name, arcn->name); 00814 else if (fstat(fd1, &sb) < 0) 00815 syswarn(1, errno, "Failed stat of %s", arcn->org_name); 00816 else if (arcn->sb.st_mtime != sb.st_mtime) 00817 paxwarn(1, "File %s was modified during copy to %s", 00818 arcn->org_name, arcn->name); 00819 00820 /* 00821 * if the last block has a file hole (all zero), we must make sure this 00822 * gets updated in the file. We force the last block of zeros to be 00823 * written. just closing with the file offset moved forward may not put 00824 * a hole at the end of the file. 00825 */ 00826 if (!no_hole && isem && (arcn->sb.st_size > 0L)) 00827 file_flush(fd2, fnm, isem); 00828 return; 00829 } 00830 00831 /* 00832 * buf_fill() 00833 * fill the read buffer with the next record (or what we can get) from 00834 * the archive volume. 00835 * Return: 00836 * Number of bytes of data in the read buffer, -1 for read error, and 00837 * 0 when finished (user specified termination in ar_next()). 00838 */ 00839 00840 int 00841 buf_fill(void) 00842 { 00843 int cnt; 00844 static int fini = 0; 00845 00846 if (fini) 00847 return(0); 00848 00849 for(;;) { 00850 /* 00851 * try to fill the buffer. on error the next archive volume is 00852 * opened and we try again. 00853 */ 00854 if ((cnt = ar_read(buf, blksz)) > 0) { 00855 bufpt = buf; 00856 bufend = buf + cnt; 00857 rdcnt += cnt; 00858 return(cnt); 00859 } 00860 00861 /* 00862 * errors require resync, EOF goes to next archive 00863 */ 00864 if (cnt < 0) 00865 break; 00866 if (ar_next() < 0) { 00867 fini = 1; 00868 return(0); 00869 } 00870 rdcnt = 0; 00871 } 00872 exit_val = 1; 00873 return(-1); 00874 } 00875 00876 /* 00877 * buf_flush() 00878 * force the write buffer to the archive. We are passed the number of 00879 * bytes in the buffer at the point of the flush. When we change archives 00880 * the record size might change. (either larger or smaller). 00881 * Return: 00882 * 0 if all is ok, -1 when a write error occurs. 00883 */ 00884 00885 int 00886 buf_flush(int bufcnt) 00887 { 00888 int cnt; 00889 int push = 0; 00890 int totcnt = 0; 00891 00892 /* 00893 * if we have reached the user specified byte count for each archive 00894 * volume, prompt for the next volume. (The non-standrad -R flag). 00895 * NOTE: If the wrlimit is smaller than wrcnt, we will always write 00896 * at least one record. We always round limit UP to next blocksize. 00897 */ 00898 if ((wrlimit > 0) && (wrcnt > wrlimit)) { 00899 paxwarn(0, "User specified archive volume byte limit reached."); 00900 if (ar_next() < 0) { 00901 wrcnt = 0; 00902 exit_val = 1; 00903 return(-1); 00904 } 00905 wrcnt = 0; 00906 00907 /* 00908 * The new archive volume might have changed the size of the 00909 * write blocksize. if so we figure out if we need to write 00910 * (one or more times), or if there is now free space left in 00911 * the buffer (it is no longer full). bufcnt has the number of 00912 * bytes in the buffer, (the blocksize, at the point we were 00913 * CALLED). Push has the amount of "extra" data in the buffer 00914 * if the block size has shrunk from a volume change. 00915 */ 00916 bufend = buf + blksz; 00917 if (blksz > bufcnt) 00918 return(0); 00919 if (blksz < bufcnt) 00920 push = bufcnt - blksz; 00921 } 00922 00923 /* 00924 * We have enough data to write at least one archive block 00925 */ 00926 for (;;) { 00927 /* 00928 * write a block and check if it all went out ok 00929 */ 00930 cnt = ar_write(buf, blksz); 00931 if (cnt == blksz) { 00932 /* 00933 * the write went ok 00934 */ 00935 wrcnt += cnt; 00936 totcnt += cnt; 00937 if (push > 0) { 00938 /* we have extra data to push to the front. 00939 * check for more than 1 block of push, and if 00940 * so we loop back to write again 00941 */ 00942 memcpy(buf, bufend, push); 00943 bufpt = buf + push; 00944 if (push >= blksz) { 00945 push -= blksz; 00946 continue; 00947 } 00948 } else 00949 bufpt = buf; 00950 return(totcnt); 00951 } else if (cnt > 0) { 00952 /* 00953 * Oh drat we got a partial write! 00954 * if format doesnt care about alignment let it go, 00955 * we warned the user in ar_write().... but this means 00956 * the last record on this volume violates pax spec.... 00957 */ 00958 totcnt += cnt; 00959 wrcnt += cnt; 00960 bufpt = buf + cnt; 00961 cnt = bufcnt - cnt; 00962 memcpy(buf, bufpt, cnt); 00963 bufpt = buf + cnt; 00964 if (!frmt->blkalgn || ((cnt % frmt->blkalgn) == 0)) 00965 return(totcnt); 00966 break; 00967 } 00968 00969 /* 00970 * All done, go to next archive 00971 */ 00972 wrcnt = 0; 00973 if (ar_next() < 0) 00974 break; 00975 00976 /* 00977 * The new archive volume might also have changed the block 00978 * size. if so, figure out if we have too much or too little 00979 * data for using the new block size 00980 */ 00981 bufend = buf + blksz; 00982 if (blksz > bufcnt) 00983 return(0); 00984 if (blksz < bufcnt) 00985 push = bufcnt - blksz; 00986 } 00987 00988 /* 00989 * write failed, stop pax. we must not create a bad archive! 00990 */ 00991 exit_val = 1; 00992 return(-1); 00993 }
1.4.6