home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Archiwiz / Tar320 / SOURCES.ZIP / TAPE.C < prev    next >
Text File  |  1996-05-05  |  17KB  |  674 lines

  1. /* tape.c - handle (tape) archive for the Tar program (see file tar.c)
  2.  * Author: T.V.Shaporev
  3.  * Creation date: 14 Dec 1990
  4.  * Contains both MS-DOS and UNIX specific codes
  5.  * Called by many functions - see files tar.c store.c extract.c
  6.  */
  7. #include <stdio.h>
  8. #include <errno.h>
  9.  
  10. #include "sysup.h"
  11. #include "modern.h"
  12. #include "zippipe.h"
  13. #include "lzwhead.h"
  14. #include "compress.h"
  15. #include "define.h"
  16.  
  17. #ifdef MODERN
  18. #    include <string.h>
  19. #    include <stdlib.h>
  20. #else
  21. #    ifdef M_XENIX
  22. #        include <string.h>
  23. #    else
  24.         int strlen();
  25.         char *strcpy(), *strncpy(), *mktemp();
  26. #    endif
  27. #endif
  28. #ifdef MSDOS
  29. #    include <io.h>
  30. #    ifdef __TURBOC__
  31. #        include <dir.h>
  32. #    else
  33. #        include <direct.h>
  34. #    endif
  35. #else
  36.     int  creat(), open(), read(), write(), close();
  37.     long lseek();
  38. #endif
  39.  
  40. static int n_read, mblock, nblock, rblock, wblock;
  41. static int indread, indwrite;
  42. static char rerror[] = "Tar: tape read error\n";
  43.  
  44. static int  sread  __ARGS__((char*, int));
  45. static int  swrite __ARGS__((char*, int));
  46. static int  sback  __ARGS__((int));
  47. #ifdef MSDOS
  48. extern int  dread  __ARGS__((char*, int));
  49. extern int  dwrite __ARGS__((char*, int));
  50. extern int  dback  __ARGS__((int));
  51.  
  52. extern int  qparse __ARGS__((char*));
  53. extern int  qbegin __ARGS__((void));
  54. extern int  qread  __ARGS__((char*, int));
  55. extern int  qwrite __ARGS__((char*, int));
  56. extern int  qback  __ARGS__((int));
  57.  
  58. extern int aspiparse __ARGS__((char*));
  59. extern int aspistart __ARGS__((void));
  60. extern int aspiread  __ARGS__((char*, int));
  61. extern int aspiwrite __ARGS__((char*, int));
  62. extern int aspiback  __ARGS__((int));
  63. #endif
  64. static void talign __ARGS__((long));
  65.  
  66. void printbs __ARGS__((int));
  67.  
  68. static void psyserr __ARGS__((void))
  69. {
  70.    extern char *sys_errlist[]; extern sys_nerr;
  71.  
  72.    if (errno < sys_nerr) (void)fprintf(myout, "%s\n", sys_errlist[errno]);
  73.    else                  (void)fprintf(myout, "error %d\n", errno);
  74. }
  75.  
  76. static int sread(buf, n) /* regular file reading */
  77. char *buf; register n;
  78. {
  79.    if ((n = read(handle, buf, n)) == -1) {
  80.       (void)fprintf(myout, "Tar: archive read error: "); psyserr();
  81.    }
  82.    return n;
  83. }
  84.  
  85. static int swrite(buf, n) /* regular file writing */
  86. char *buf; register n;
  87. {
  88.    if (write(hwrite, buf, n) != n) {
  89.       (void)fprintf(myout, "Tar: archive write error: ");
  90. #ifdef MSDOS
  91.       if (n != -1) (void)fprintf(myout,"disk full\n"); else
  92. #endif
  93.       psyserr();
  94.       n = -1;
  95.    }
  96.    return n;
  97. }
  98.  
  99. static int sback(n)
  100. register n;
  101. {
  102.    return lseek(handle, (long)-BLKSIZE*n, 1) < 0 ? -1 : n;
  103. }
  104.  
  105. #ifdef USE_COMPRESS
  106. static int zwrite __ARGS__((char*, int));
  107.  
  108. static int zwrite(buf, n) /* compressed file writing */
  109. char *buf; register n;
  110. {
  111.    cpiece(buf, n); return n;
  112. }
  113. #endif
  114.  
  115. static int gread  __ARGS__((char*, int));
  116. static int gwrite __ARGS__((char*, int));
  117.  
  118. static int gread(buf, n) /* deflated file reading */
  119. char *buf; register n;
  120. {
  121.    if ((n = unzread(buf, n)) == -1) {
  122.       (void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
  123.    }
  124.    return n;
  125. }
  126.  
  127. static int gwrite(buf, n) /* deflated file reading */
  128. char *buf; register n;
  129. {
  130.    if ((n = zipwrite(buf, n)) == -1) {
  131.       (void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
  132.    }
  133.    return n;
  134. }
  135.  
  136. static int ziperr __ARGS__((void))
  137. {
  138.    (void)fprintf(stderr, "Tar: zip error: %s\n", ziperrlist[ziperror]);
  139.    return ziperror == ZNOMEM ? ESMALL : ERINIT;
  140. }
  141.  
  142. #ifndef USE_COMPRESS
  143. static int twofault __ARGS__((char*, int));
  144.  
  145. /*ARGSUSED2*/ static int twofault(buf, n)
  146. char *buf; register n;
  147. {
  148. #ifdef __TURBOC__
  149.    (void)buf; (void)n;
  150. #endif
  151.    return -1;
  152. }
  153. #endif
  154.  
  155. /*ARGSUSED*/ static int onefault(n)
  156. int n;
  157. {
  158. #ifdef __TURBOC__
  159.    (void)n;
  160. #endif
  161.    return -1;
  162. }
  163.  
  164. static int (*pread) __ARGS__((char*, int)) = sread;
  165. static int (*pwrite)__ARGS__((char*, int)) = swrite;
  166. static int (*pback) __ARGS__((int))        = sback;
  167.  
  168. static int (*lread) __ARGS__((char*, int)) = sread;
  169. static int (*lwrite)__ARGS__((char*, int)) = swrite;
  170. static int (*lback) __ARGS__((int))        = sback;
  171. static int (*rcount)__ARGS__((char*, int)) = sread;
  172.  
  173. static int cntread  __ARGS__((char*, int));
  174.  
  175. static int cntread(buf, n)
  176. char *buf; register n;
  177. {
  178.    if ((n = (*rcount)(buf, n)) != -1) {
  179.       allblock += (BLKSIZE-1 + (unsigned)n) / BLKSIZE;
  180.    }
  181.    return n;
  182. }
  183.  
  184. static void talign(i)
  185. long i;
  186. {
  187.    if (i % BLKSIZE) {
  188.       (void)fprintf(myout, "Tar: tape blocksize error\n");
  189.       if (!i_flag) done(ERREAD);
  190.    }
  191. }
  192.  
  193. void printbs(bs)
  194. int bs;
  195. {
  196.    if (v_flag) (void)fprintf(myout, "Tar: blocksize = %d\n", bs);
  197. }
  198.  
  199. static void wrerror __ARGS__((void))
  200. {
  201.    (void)fprintf(myout, "Tar: tape write error\n");
  202.    done(EWRITE);
  203. }
  204.  
  205. static int indget;
  206. static int eof_already = FALSE;
  207. static int got_length;
  208. static int indput;
  209.  
  210. static int getbyte __ARGS__(( void ))
  211. {
  212.    if (eof_already) goto end;
  213.    if (indget >= got_length) {
  214.       if (pksize == 0) {
  215.          if ((got_length = (*lread)(pk_inp, MAXBLOCK*BLKSIZE)) < 0) goto err;
  216.          if ((sa.st_mode & S_IFMT) == S_IFCHR) talign((long)got_length);
  217.          pksize = got_length;
  218.          if (pksize && (pksize % BLKSIZE)==0) printbs(pksize/BLKSIZE);
  219.       } else {
  220.          if (got_length < pksize || got_length % BLKSIZE) goto end;
  221.          if ((got_length = (*lread)(pk_inp, pksize)) < 0) goto err;
  222.       }
  223.       if (got_length < 1) goto end;
  224.       indget = 0;
  225.    }
  226.    return ((unsigned char *)pk_inp)[indget++];
  227. err:
  228.    (void)fprintf(myout, rerror);
  229.    done(ERREAD);
  230. end:
  231.    eof_already = TRUE;
  232.    return EOF;
  233. }
  234.  
  235. static void pkflush __ARGS__((void))
  236. {
  237. #ifdef MSDOS
  238.    if (devtype != DEV_FILE && devtype != DEV_FLOP)
  239. #else
  240.    if (!isfile)
  241. #endif
  242.       while (indput < pksize) pk_out[indput++] = 0;
  243.  
  244.    if ((*lwrite)(pk_out, indput) < indput) wrerror();
  245.    indput = 0;
  246. }
  247.  
  248. static void putbyte(c)
  249. register c;
  250. {
  251.    if (indput >= pksize) {
  252. #ifndef pksize
  253.       /* Buffer size must not be less then 512 bytes, so we */
  254.       /* can wait for blocksize will be detected by reading */
  255.       if (indput < BLKSIZE) goto put;
  256.       if (pksize < BLKSIZE) pksize = BLKSIZE;
  257. #endif
  258.       pkflush();
  259.    }
  260. put:
  261.    pk_out[indput++] = c;
  262. }
  263.  
  264. int initape(name)
  265. char *name;
  266. {
  267. #ifdef UNIX
  268.    char tn[10]; register char *n;
  269. #endif
  270. #ifdef MSDOS
  271.    register k;
  272. #endif
  273.  
  274.    handle = -1;
  275.  
  276.    pread  = lread  = sread;
  277.    pwrite = lwrite = swrite;
  278.    pback  = lback  = sback;
  279.  
  280.    if (name && name[0]=='-' && name[1]==0) {
  281.       if ((a_flag && !c_flag) || d_flag) {
  282.          (void)fprintf(stderr, "Tar: can\'t update stdout\n");
  283.          return ERRARG;
  284.       }
  285. #ifdef myinp
  286.       if (j_flag
  287. #  ifndef MSDOS
  288.           || w_flag
  289. #  endif
  290.          ) {
  291.          (void)fprintf(stderr, "Tar: input must be free\n");
  292.          return ERRARG;
  293.       }
  294. #endif
  295.       handle = a_flag ? /* stdout */ 1 : /* stdin */ 0;
  296.       myout  = stderr;
  297.    } else {
  298. #ifdef UNIX
  299.       if (name && name[0]) {
  300.          n = name;
  301.       } else {
  302.          n = strcpy(tn, "/dev/mt0"); tn[7] = (ndrive & 7) | '0';
  303.       }
  304.       /* Do not create a file unless name specified */
  305.       handle = c_flag && n == name ? creat(n, 0666) :
  306.          open(n, a_flag && !d_flag ? O_RDWR : O_RDONLY);
  307.       if (handle < 0) {
  308.          cantopen(n); return ERINIT;
  309.       }
  310. #endif
  311.  
  312. #ifdef MSDOS
  313.       if (!name || !name[0]) {
  314.          devtype = DEV_FLOP;
  315.      inidisk();
  316.       } else if ((k=qparse(name)) != FALSE) {
  317.          if (k != TRUE) return ERRARG;
  318.          pread   = lread  = qread;
  319.          pwrite  = lwrite = qwrite;
  320.          pback   = lback  = qback;
  321.          devtype = DEV_QIC2;
  322.       } else if ((k=aspiparse(name)) != FALSE) {
  323.          if (k != TRUE) return ERRARG;
  324.          pread   = lread  = aspiread;
  325.          pwrite  = lwrite = aspiwrite;
  326.          pback   = lback  = aspiback;
  327.          devtype = DEV_ASPI;
  328.       } else {
  329.          if (!k_flag && defdev(name)==0) k_flag = TRUE;
  330.          if (k_flag) {
  331.             devtype = DEV_FLOP;
  332.         inidisk();
  333.          } else {
  334.             handle = open(name, !a_flag || d_flag ? O_RDONLY+O_BINARY :
  335.                                  c_flag ? O_CREAT+O_TRUNC+O_WRONLY+O_BINARY :
  336.                                           O_RDWR+O_BINARY,
  337.                                 S_IREAD+S_IWRITE);
  338.             if (handle < 0) {
  339.                cantopen(name); return ERINIT;
  340.             }
  341.             devtype = DEV_FILE;
  342.          }
  343.       }
  344.       if (devtype == DEV_FLOP) {
  345.          pread  = lread  = dread;
  346.          pwrite = lwrite = dwrite;
  347.          pback  = lback  = dback;
  348.       }
  349. #endif
  350.    }
  351.    if (t_flag) {/* yet another redirection */
  352.       rcount = lread; pread = lread = cntread; allblock = 0L;
  353.    }
  354.    if (handle < 0 || fstat(handle, &sa) != 0) sa.st_mode = S_IFBLK;
  355.    hwrite = handle;
  356.    n_read = 0;
  357.    return CORRECT;
  358. }
  359.  
  360. static void swapbufs __ARGS__((void))
  361. {
  362.    register j; register char *p;
  363.  
  364.    p = pk_inp; pk_inp = io_buf; io_buf = p;
  365.    p = pk_out; pk_out = io_2nd; io_2nd = p;
  366.  
  367.    j = pksize;
  368.    pksize = BLKSIZE*cblock;
  369.    cblock = j/BLKSIZE;
  370. }
  371.  
  372. int redirect()
  373. {
  374.    if (pktype == PKpLZW) {
  375.       /* Redirect IO */
  376.       pread  = dpiece;
  377. #ifdef USE_COMPRESS
  378.       pwrite = zwrite;
  379. #else
  380.       pwrite = twofault;
  381. #endif
  382.       pback  = onefault;
  383.  
  384.       swapbufs();
  385.  
  386.       if (x_flag || t_flag || d_flag) {
  387.          register j;
  388.  
  389.          indget = 0; got_length = (int)n_read;
  390.          if ((j=dbegin(getbyte))!=0) {
  391.             if (j < 0) {
  392.                outmem(stderr);
  393.                return ESMALL;
  394.             } else {
  395.                (void)fprintf(stderr,
  396.                   "Tar: archive is not in compressed format\n");
  397.                return ERINIT;
  398.             }
  399.          }
  400.       }
  401.       if (a_flag || d_flag) {
  402. #ifdef USE_COMPRESS
  403.          if (cbegin(lzwbits, putbyte, 0x7fffffffL) != lzwbits) {
  404.             outmem(stderr);
  405.             return ESMALL;
  406.          }
  407. #else
  408.          (void)fprintf(stderr,
  409.          "Tar: this restricted version does not support LZW compression\n");
  410.          return ERRARG;
  411. #endif
  412.       }
  413. #ifdef USE_COMPRESS
  414.       indput = 0;
  415. #endif
  416.    } else if (pktype == PKZIP) {
  417.       /* Redirect IO */
  418.       pread = gread; pwrite = gwrite; pback = onefault;
  419.       swapbufs();
  420.  
  421.       if (x_flag || t_flag || d_flag) {
  422.          indget = 0; got_length = (int)n_read;
  423.          if (unzopen(getbyte, ZIP_ANY) != 0) return ziperr();
  424.       }
  425.       indput = 0;
  426.       if (a_flag || d_flag) {
  427.          if (zipcreat(putbyte, (gnuzip ? ZIP_GNU : ZIP_PKW), ziplevel) != 0)
  428.             return ziperr();
  429.       }
  430.    }
  431.    rblock = mblock = cblock;
  432.    nblock = 0;
  433.    return CORRECT;
  434. }
  435.  
  436. int runtape()
  437. {
  438.    register k;
  439. #ifdef MSDOS
  440.    if      (devtype == DEV_QIC2) { if (qbegin())    return ERINIT; }
  441.    else if (devtype == DEV_ASPI) { if (aspistart()) return ERINIT; }
  442. #endif
  443.    if (!cblock && c_flag) printbs(cblock = MAXBLOCK);
  444.    if ((k = redirect()) != CORRECT) return k;
  445.    if (c_flag && !mblock) printbs(cblock = mblock = MAXBLOCK);
  446.    wblock = 0;
  447.    return CORRECT;
  448. }
  449.  
  450. void duptape(n)
  451. char *n;
  452. {
  453.    register i;
  454.    static char template[] = "XXXXXX";
  455.  
  456.    io_2nd = getbuf(BLKSIZE * (mblock ? mblock : MAXBLOCK));
  457.    if (!io_2nd) done(ESMALL);
  458.  
  459.    i=strlen(n);
  460.    while (i>0 &&
  461. #ifdef MSDOS
  462.                  n[i-1]!='\\' && n[i-1]!=':' &&
  463. #endif
  464.                                                 n[i-1]!='/') --i;
  465.    scratch = salloc((int)(i + sizeof(template)));
  466.    (void)strncpy(scratch, n, i);
  467.    (void)strcpy (scratch+i, template);
  468.    (void)mktemp (scratch);
  469. #ifdef UNIX
  470.    hwrite = creat(scratch, 0666);
  471. #endif
  472. #ifdef MSDOS
  473.    hwrite = open(scratch, O_CREAT+O_TRUNC+O_RDWR+O_BINARY, S_IREAD+S_IWRITE);
  474. #endif
  475.    if (hwrite < 0) {
  476.       (void)fprintf(myout, "Tar: can\'t create scratch file\n");
  477.       done(EWRITE);
  478.    }
  479. }
  480.  
  481. void backtape()
  482. {
  483.    register i;
  484.  
  485.    talign((long)n_read);
  486.    if ((i = (int)(n_read / BLKSIZE % mblock)) == 0) i = mblock;
  487.    if (!isfile) {
  488.       register j;
  489.  
  490.       if ((*pback)(i)!=i) goto fault;
  491.       if ((j=(*pread)(io_buf, BLKSIZE*rblock))<BLKSIZE) goto fault;
  492.       n_read += j;
  493.    }
  494.    if ((*pback)(i) != i) goto fault;
  495.    wblock = --rblock; indread = indwrite = 0;
  496.    return;
  497. fault:
  498.    (void)fprintf(myout, "Tar: tape seek fault\n");
  499.    done(ERREAD);
  500. }
  501.  
  502. void endtape()
  503. {
  504.    nullblock(steptape());
  505.    if (wblock) {
  506.       if ((*pwrite)(io_2nd, BLKSIZE*((
  507. #ifdef MSDOS
  508.                      devtype == DEV_FILE || devtype == DEV_FLOP
  509. #else
  510.                      isfile
  511. #endif
  512. #ifdef USE_COMPRESS
  513.                      || pwrite == zwrite
  514. #endif
  515.                      || pwrite == gwrite)
  516.                      && wblock < mblock ? wblock : mblock)) < 0) {
  517.          wrerror();
  518.       }
  519.    }
  520. #ifdef USE_COMPRESS
  521.    if (pwrite == zwrite) {/* compression on output */
  522.       if (cflush() < 0) wrerror();
  523.       if (indput > 0) pkflush();
  524.    } else
  525. #endif
  526.    if (pwrite == gwrite) {/* zip compression */
  527.       if (zipclose() == -1L) wrerror();
  528.       if (indput > 0) pkflush();
  529.    }
  530.    if (hwrite >= 0 && close(hwrite)!=0) {
  531.       (void)fprintf(myout, "Tar: tape close error\n");
  532.       done(EWRITE);
  533.    }
  534. }
  535.  
  536. static int readbuf __ARGS__(( void ))
  537. {
  538.    register i;
  539.  
  540.    for (;;) {
  541.       if (mblock) {
  542.          if ((i=(*pread)(io_buf, BLKSIZE*mblock)) < BLKSIZE || i%BLKSIZE!=0) {
  543.             (void)fprintf(myout, rerror);
  544.             if (i_flag) return -1;
  545.             done(ERREAD);
  546.          }
  547.          n_read += i;
  548.          nblock = i / BLKSIZE;
  549.       } else {
  550.          if ((i = (*pread)(io_buf, MAXBLOCK*BLKSIZE)) < 1) {
  551.             (void)fprintf(myout, rerror);
  552.             if (i_flag) return -1;
  553.             done(ERREAD);
  554.          }
  555.          n_read += i;
  556.          if (i % BLKSIZE != 0 && pktest((unsigned char*)io_buf) == CORRECT) {
  557.             mblock = cblock; n_read = 0; continue;
  558.          }
  559.          talign((long)i);
  560.          mblock = nblock = i / BLKSIZE;
  561.          printbs(cblock = mblock);
  562.       }
  563.       break;
  564.    }
  565.    rblock = 0;
  566.    return 0;
  567. }
  568.  
  569. header *readtape()
  570. {
  571.    if (rblock>=nblock && readbuf()!=0) return NULL;
  572.    indread = 0;
  573.    return (header *)(io_buf + BLKSIZE * rblock++);
  574. }
  575.  
  576. int readbyte()
  577. {
  578.    register c;
  579.  
  580.    if (indread == 0) ++rblock; /* get 1-st byte - take all the block */
  581.    if (rblock>nblock) {
  582.       if (readbuf()!=0) return -1;
  583.       rblock = 1; /* preserve 1-st block from readtape() */
  584.    }
  585.    c = ((unsigned char *)(io_buf + BLKSIZE * (rblock-1)))[indread];
  586.    indread = (indread+1) & (BLKSIZE-1);
  587.    return c;
  588. }
  589.  
  590. void bacouple()
  591. /* return to the beginning of block after try to uncompress */
  592. {
  593.    indread = 0; --rblock;
  594. }
  595.  
  596. int readarch(h, length)
  597. int h; long length;
  598. {
  599.    register i;
  600.  
  601.    while (length > 0) {
  602.       if (rblock>=nblock && readbuf()!=0) return -1;
  603.       if ((i = (nblock-rblock)*BLKSIZE) > length) i = (int)length;
  604.       if (write(h, io_buf + rblock * BLKSIZE, i)!=i)
  605.          extwrerr();
  606.       rblock += (i + BLKSIZE-1) / BLKSIZE;
  607.       length -= i;
  608.    }
  609.    indread = 0;
  610.    return 0;
  611. }
  612.  
  613. header *steptape()
  614. {
  615.    if (!mblock) mblock = 1;
  616.    if (wblock >= mblock) {
  617.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  618.       wblock = 0;
  619.    }
  620.    indwrite = 0;
  621.    return (header *)(io_2nd + BLKSIZE * wblock++);
  622. }
  623.  
  624. void writebyte(c)
  625. int c;
  626. {
  627.    if (indwrite == 0) ++wblock;
  628.    if (wblock > mblock) {
  629.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  630.       wblock = 1;
  631.    }
  632.    ((unsigned char *)(io_2nd + BLKSIZE * (wblock-1)))[indwrite] = c;
  633.    indwrite = (indwrite+1) & (BLKSIZE-1);
  634. }
  635.  
  636. long writearch(h, length, name)
  637. int h; long length; char *name;
  638. {
  639.    register i; register j; register k;
  640.    register char *p;
  641.    register long b;
  642.  
  643.    if (!mblock) mblock = 1;
  644.  
  645.    b = 0;
  646.    while (length > 0) {
  647.       if (wblock >= mblock) {
  648.          if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  649.          wblock = 0;
  650.       }
  651.       k = BLKSIZE * (mblock-wblock);
  652.       i = length < k ? (int)length : k;
  653.       p = io_2nd + BLKSIZE * wblock;
  654.       if ((j = read(h, p, i)) < 0) {
  655.          (void)fprintf(myout, "Tar: error reading \'%s\'\n", name);
  656.          done(ERREAD);
  657.       }
  658.       /* Calculate number of blocks affected */
  659.       k = (BLKSIZE-1 + j) / BLKSIZE;
  660.       wblock += k;
  661.       b      += k;
  662.       /* Fill the slack area */
  663.       for (p+=j, k=BLKSIZE*k-j; k>0; k--) *p++ = '\0';
  664.       if (j != i) return b;
  665.       length -= i;
  666.    }
  667.    if (wblock >= mblock) {
  668.       if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
  669.       wblock = 0;
  670.    }
  671.    indwrite = 0;
  672.    return b;
  673. }
  674.