buf_subs.c

Go to the documentation of this file.
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 }

Generated on Fri Apr 14 22:57:01 2006 for minix by  doxygen 1.4.6