home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Archiwiz / Tar320 / SOURCES.ZIP / EXTRACT.C < prev    next >
Text File  |  1995-04-14  |  15KB  |  526 lines

  1. /* extarct.c - extract files from (tape) archive.
  2.  * This is a part of the Tar program (see file tar.c)
  3.  * Author: T.V.Shaporev
  4.  * Creation date: 14 Dec 1990
  5.  */
  6. #include <stdio.h>
  7.  
  8. #include "sysup.h"
  9. #include "nodedef.h"
  10. #include "modern.h"
  11. #ifdef MODERN
  12. #    include <string.h>
  13. #else
  14.     char *strncpy();
  15.     int  strlen();
  16. #endif
  17. #ifndef MSDOS
  18.     int  mknod(), chown(), utime();
  19.     long time();
  20. #endif
  21.  
  22. #include "zippipe.h"
  23. #include "zipdefs.h"
  24. #include "lzwbits.h"
  25. #include "lzwhead.h"
  26. #include "compress.h"
  27. #include "define.h"
  28. #include "lzpack.h"
  29.  
  30. static int soctus   __ARGS__(( register char *, register short* ));
  31.        int soctul   __ARGS__(( register char *, register long * ));
  32.        int shexul   __ARGS__(( register char *, register long * ));
  33.  
  34. #define octal(c) (((c)&0370)=='0')
  35.  
  36. static char unknown[] = "Tar: \'%s\' unknown file type \'%c\'\n";
  37. #define _unknown (unknown+9)
  38.  
  39. static int soctus(s, u)
  40. register short *u;
  41. register char *s;
  42. {
  43.    register i;
  44.    while (*s == ' ') ++s;
  45.    for (*u=0, i=0; octal(*s) && i<7; i++, s++) *u = (*u<<3)|(*s&7);
  46.    return *s!=' ' && *s!='\0';
  47. }
  48.  
  49. int soctul(s, u)
  50. register long *u;
  51. register char *s;
  52. {
  53.    register i;
  54.    while (*s == ' ') ++s;
  55.    for (*u=0, i=0; octal(*s) && i<11; i++, s++) *u = (*u<<3)|(*s&7);
  56.    return *s!=' ' && *s!='\0';
  57. }
  58.  
  59. int shexul(s, u)
  60. register long *u;
  61. register char *s;
  62. {
  63.    register i, k;
  64.    while (*s == ' ') ++s;
  65.    for (*u=0, i=0; i<8; i++, s++) {
  66.       k = *s;
  67.       if      (k >= '0' && k <= '9') k -= '0';
  68.       else if (k >= 'A' && k <= 'F') k -= 'A'-10;
  69.       else if (k >= 'a' && k <= 'f') k -= 'a'-10;
  70.       else break;
  71.       *u = (*u << 4) | k;
  72.    }
  73.    return *s!=' ' && *s!='\0';
  74. }
  75.  
  76. int pktest(p)
  77. unsigned char *p;
  78. {
  79.    register unsigned k;
  80.  
  81.    if (pklock || i_flag || pktype != PKNONE) return ERROR;
  82.    pklock = TRUE;
  83.  
  84.    k = ((unsigned)(p[1]) << 8) | p[0];
  85.    if (k == (unsigned)((LZW_1ST_MAGIC << 8) | LZW_0TH_MAGIC)) {
  86.       pktype = PKpLZW;
  87.    } else if (k == GZIP_MAGIC ||
  88.               k == PKW_01_MAGIC &&
  89.               (((unsigned)(p[3]) << 8) | p[2]) == PKW_23_MAGIC) {
  90.       pktype = PKZIP;
  91.    } else {
  92.       return ERROR;
  93.    }
  94.    if (pkalloc()) {
  95.       (void)fprintf(stderr, "No memory for decompression\n");
  96.       done(ESMALL);
  97.    }
  98.    if (redirect()) done(EINTER);
  99.    return CORRECT;
  100. }
  101.  
  102. int gethead()
  103. {
  104.    short n;
  105.    static short errcount = 0;
  106.    register char *err_text = "Tar: bad directory structure\n";
  107.  
  108.    for (;;) {
  109.       if ((hblock = readtape()) == NULL) return ERROR;
  110.       if ((hblock->m.name[0]) == '\0') {
  111.          return errcount ? (++errcount, ERROR) : FALSE;
  112.       }
  113.       if (soctus(hblock->m.chksum, &n) == CORRECT) {
  114.          if (n == headsum(hblock)) break;
  115.          err_text = "Tar: directory checksum error\n";
  116.       }
  117.       if (pktest((unsigned char*)(hblock->m.name))) goto bad;
  118.    }
  119.    if (soctus(hblock->m.mode,  (short*)&(st.st_mode)) ||
  120.        soctus(hblock->m.uid,   (short*)&(st.st_uid))  ||
  121.        soctus(hblock->m.gid,   (short*)&(st.st_gid))  ||
  122.        soctul(hblock->m.size,  (long *)&(st.st_size)) ||
  123.        soctul(hblock->m.mtime, (long *)&(st.st_mtime))) goto bad;
  124.    if (hblock->m.filetype == TF_CHR || hblock->m.filetype == TF_BLK) {
  125.       if (soctus(hblock->x.devmajor, &dmajor) ||
  126.           soctus(hblock->x.devminor, &dminor)) goto bad;
  127.    }
  128.    if (errcount != 0) {
  129.       (void)fprintf(myout,
  130.                     "Tar: %d blocks skipped to find header\n", errcount);
  131.       errcount = 0;
  132.    }
  133.    if (hblock->m.filetype != TF_OLD && hblock->m.filetype != TF_REG) {
  134.       longcsum = codesize = 0L;
  135.    } else if (hblock->m.srcsum[1]!='x' || hblock->m.srcsum[0]!='0') {
  136.       (void)soctul(hblock->m.srclen, &codesize); /* no sence for    */
  137.       (void)soctul(hblock->m.srcsum, &longcsum); /* non-packed file */
  138.    } else {
  139.       (void)shexul(hblock->m.srclen + 2, &codesize);
  140.       (void)shexul(hblock->m.srcsum + 2, &longcsum);
  141.    }
  142.    return TRUE;
  143. bad:
  144.    if (errcount++ == 0) (void)fprintf(myout, err_text);
  145.    if (!i_flag) done(ERREAD);
  146.    return ERROR;
  147. }
  148.  
  149. static int tstfield __ARGS__(( char *, int ));
  150.  
  151. static int tstfield(s,n) /* is the field a valid octal number? */
  152. char *s; int n;
  153. {
  154.    register j;
  155.  
  156.    for (j=0; j<n && octal(s[j]); j++);
  157.    if (!j || j >= n) return FALSE;
  158.    if (s[j] == ' ') ++j;
  159.    while (j<n && !s[j++]);
  160.    return j>=n;
  161. }
  162.  
  163. #define TstField(x) tstfield(x, sizeof(x))
  164.  
  165. short isextent(allx, allb)
  166. short *allx; long *allb;
  167. {
  168.    short n;
  169.  
  170.    if ((hblock->m.filetype != TF_OLD && hblock->m.filetype != TF_REG) ||
  171.        !TstField(hblock->s.extent) ||
  172.        !TstField(hblock->s.allext) ||
  173.        !TstField(hblock->s.total)) return ERROR;
  174.    (void)soctus(hblock->s.extent, &n);
  175.    (void)soctus(hblock->s.allext, allx);
  176.    (void)soctul(hblock->s.total,  allb);
  177.    return n < 1 || n > *allx || *allb <= st.st_size ? ERROR : n;
  178. }
  179.  
  180. int ismagic()
  181. {
  182.    register i;
  183.    register char *p, *q;
  184.    static char magic_list[][8] = { TMAGIC, GMAGIC };
  185.  
  186.    if (hblock->m.filetype != TF_OLD) {
  187.       for (i=0; i<dimof(magic_list); i++) {
  188.          p = magic_list[i];
  189.          q = hblock->x.magic;
  190.          while (*q && *q == *p) {
  191.             ++q; p++;
  192.          }
  193.          if (*q == '\0' && (*p == '\0' || *p == ' '))
  194.             return magic_list[i][0];
  195.       }
  196.    }
  197.    return 0;
  198. }
  199.  
  200. char prefix()
  201. {
  202.    switch (hblock->m.filetype) {
  203.       case TF_CTG: /* ??? contiguous file */
  204.       case TF_OLD:
  205.       case TF_REG:
  206.       case TF_LNK: return ' ';
  207.       case TF_SYM: return 'l';
  208.       case TF_CHR: return 'c';
  209.       case TF_BLK: return 'b';
  210.       case TF_DIR: return 'd';
  211.       case TF_QUE: return 'p';
  212.       case GF_DMP: return 'D';
  213.       case GF_MUL: return ',';
  214.       case GF_VOL: return 'v';
  215.    }
  216.    return '?';
  217. }
  218.  
  219. int usize() /* is it valid to use file size in header */
  220. {
  221.    switch (hblock->m.filetype) {
  222.       case TF_OLD: case TF_REG: case TF_CTG:
  223.       case GF_DMP: case GF_MUL: case GF_SPR: /* what's it? I wonder */
  224.          return TRUE;
  225.    }
  226.    return FALSE;
  227. }
  228.  
  229. void skipfile()
  230. {
  231.    register long blocks;
  232.  
  233.    for (blocks=(st.st_size+BLKSIZE-1)/BLKSIZE; blocks>0; blocks--) {
  234.       if (readtape() == NULL) {
  235.          (void)fprintf(myout, "Tar: tape read error\n");
  236.          if (i_flag) done(ERREAD);
  237.          return;
  238.       }
  239.    }
  240. }
  241.  
  242. static inlist __ARGS__((int, char**, char*));
  243.  
  244. static int inlist(argc, argv, n)
  245. int argc; register char *argv[], *n;
  246. {
  247.    register i; register j; register k;
  248.    register char *p;
  249.  
  250.    for (i=0; i<argc; i++) {
  251.       if (s_flag) {
  252.          for (p=argv[i], j=0; j<MAXTNAME && p[j]==n[j] && p[j]!=0; j++);
  253.          if (j<MAXTNAME && p[j]==0 && (n[j]==0 || n[j]=='/')) return TRUE;
  254.       } else {
  255.          for (j=0; j<MAXTNAME && n[j];) {
  256.             do ++j; while (n[j]!='/' && n[j]!=0);
  257.             if ((k = mismatch(argv[i], n, j)) == ERROR) break;
  258.             if (!k) return TRUE;
  259.          }
  260.       }
  261.    }
  262.    return FALSE;
  263. }
  264.  
  265. int inargs(argc, argv, n)
  266. int argc; char *argv[], *n;
  267. {
  268.    return inlist(argc, argv, n) && !inlist(xcnt, xarg, n);
  269. }
  270.  
  271. void scantape(argc, argv, handler)
  272. int argc; char *argv[]; void (*handler)__ARGS__((void));
  273. {
  274.    register k;
  275.    register char *p;
  276.  
  277. #ifdef MSDOS
  278.    for (k=0; k<argc; k++) for (p=argv[k]; *p; p++) if (*p=='\\') *p='/';
  279.    for (k=0; k<xcnt; k++) for (p=xarg[k]; *p; p++) if (*p=='\\') *p='/';
  280. #endif
  281.    while ((k=gethead()) != FALSE) {
  282.       pklock = TRUE;
  283.       if (k == ERROR) continue;
  284.       if ((argc < 1 ||  inlist(argc, argv, hblock->m.name)) &&
  285.           (xcnt < 1 || !inlist(xcnt, xarg, hblock->m.name))) {
  286.          (*handler)();
  287.       } else {
  288.          if (usize()) skipfile();
  289.       }
  290.    }
  291.    if (pktype == PKZIP) {
  292.       while ((k=unzread((char*)hblock, BLKSIZE)) == BLKSIZE);
  293.       if (k != ERROR) {
  294.          if (k) (void)fprintf(myout, "Tar: final block misaligned\n");
  295.          k = unzclose();
  296.       }
  297.       if (k) {
  298.          p = k == -1 ? "error" : v_flag ? "warning" : NULL;
  299.          if (p) (void)fprintf(myout, "Tar: unzip %s: %s\n",
  300.                                      p, ziperrlist[ziperror]);
  301.       }
  302.    }
  303. }
  304.  
  305. extern long thisread;
  306. extern int arcget __ARGS__(( void ));
  307.  
  308. void catalog()
  309. {
  310.    register long thislen;
  311.    register reverse = FALSE, skipped = FALSE;
  312.    register char *p;
  313.    static no_mem = FALSE;
  314.    short nx = 1, allx; long xinfo;
  315.    extern char ofname[];
  316.    register c;
  317.  
  318.    p = hblock->m.name;
  319.    c = hblock->m.filetype;
  320.  
  321.    if (v_flag) prmode(prefix(), (int)(st.st_mode));
  322.    if ((c == TF_OLD || c == TF_REG) && (nx=isextent(&allx, &xinfo)) < 1) {
  323.       if (st.st_size <= codesize) {
  324.          reverse = TRUE;
  325.       } else if (pktype == PKfLZW) {
  326.          register i, j;
  327.  
  328.          i = strlen(hblock->m.name);
  329.          if (hblock->m.name[--i] == 'Z' && hblock->m.name[--i] == '.') {
  330.             p = strncpy(ofname, hblock->m.name, MAXTNAME);
  331.             (void)z_getmem(BITS);
  332.             codesize = 0; thisread = 0;
  333.             if ((j = dbegin(arcget)) == 0) {
  334.                do {
  335.                   if ((j = dpiece(pk_out, pksize)) > 0) codesize += j;
  336.                } while (j == pksize);
  337.                skipped = TRUE;
  338.             } else if (j > 0) {
  339.                bacouple(); /* file is not in compressed format */
  340.             } else if (!no_mem) {
  341.                (void)fprintf(myout, "Tar: not enough memory to uncompress\n");
  342.                no_mem = TRUE;
  343.             }
  344.          }
  345.       }
  346.       thislen = codesize > st.st_size ? codesize : st.st_size;
  347.    } else {
  348.       thislen = st.st_size;
  349.    }
  350.    if (v_flag) {
  351.       (void)fprintf(myout, " %3d/%1d ", st.st_uid, st.st_gid);
  352.       if (c == TF_CHR || c == TF_BLK) {
  353.          (void)fprintf(myout,
  354.             pkfile ? "%10d,%-5d " : "%3d,%-3d ", dmajor, dminor);
  355.       } else {
  356.          (void)fprintf(myout, "%7ld ", reverse ? thislen : st.st_size);
  357.          if (pkfile) {
  358.             if ((c == TF_OLD || c == TF_REG) && st.st_size <= codesize) {
  359.                (void)fprintf(myout,
  360.                   reverse && hblock->m.srcsum[1] != 'x' ?
  361.                      "{%7ld} " : "(%7ld) ",
  362.                   reverse ? st.st_size : codesize);
  363.             } else {
  364.                (void)fprintf(myout, "          ");
  365.             }
  366.          }
  367.       }
  368.    }
  369.    (void)fprintf(myout, "%-.*s", MAXTNAME, p);
  370.  
  371.    switch (c) {
  372.       case TF_LNK:
  373.       case TF_SYM:
  374.          if (v_flag) (void)fprintf(myout, "\n");
  375.          (void)fprintf(myout, " %s to %s\n",
  376.             c == TF_SYM ? "symlink" : "linked",
  377.             hblock->m.linkname);
  378.          break;
  379.       case TF_OLD:
  380.       case TF_REG:
  381.          if (nx >= 1) {
  382.             if (v_flag) (void)fprintf(myout, "\n");
  383.             (void)fprintf(myout, " [extent #%d of %d]", nx, allx);
  384.             if (v_flag) (void)fprintf(myout, " %ld bytes total", xinfo);
  385.          }
  386.       case TF_CHR: case TF_BLK:
  387.       case TF_DIR: case TF_QUE: case TF_CTG:
  388.       case GF_DMP: case GF_VOL:
  389.          (void)fprintf(myout, "\n");
  390.          break;
  391.       case GF_MUL:
  392.          if (v_flag) (void)fprintf(myout, "\n");
  393.          (void)soctul(hblock->x.offset, &xinfo);
  394.          (void)fprintf(myout, "[from %ld to %ld]",
  395.                               xinfo, xinfo+st.st_size-1);
  396.          (void)fprintf(myout, "\n");
  397.          break;
  398.       default:
  399.          if (v_flag) (void)fprintf(myout, "\n");
  400.          (void)fprintf(myout, _unknown, c);
  401.    }
  402.    if (nx < 1 && v_flag && j_flag && /*dummy*/!skipped &&
  403.        hblock->m.comment[0] && !ismagic()) {
  404.       (void)fprintf(myout, "> %s\n", hblock->m.comment);
  405.    }
  406.    if (usize()) {
  407.       if (!skipped) skipfile();
  408.       allbytes += thislen;
  409.    }
  410.    ++allfiles;
  411. }
  412.  
  413. static char *cutname __ARGS__((register char *p));
  414.  
  415. static char *cutname(p)
  416. register char *p;
  417. {
  418.    register j;
  419.  
  420.    if (nonest) {
  421.       j = strlen(p);
  422.       while (j>0 && p[j-1] != '/'
  423. #ifdef MSDOS
  424.              && p[j-1] != ':'
  425. #endif
  426.             ) --j;
  427.       p += j;
  428.    } else {
  429. #ifdef MSDOS
  430.       if (deldrv && p[1] == ':' &&
  431.                    (p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z'))
  432.          p += 2;
  433. #endif
  434.       if (dslash && *p == '/') ++p;
  435.    }
  436.    return p;
  437. }
  438.  
  439. void extract()
  440. {
  441.    register j, k;
  442.    register char *p;
  443.    extern int makedir __ARGS__((char *, int));
  444.    extern int testdir __ARGS__((char *));
  445.  
  446.    p = cutname(hblock->m.name);
  447.    if (u_flag) {
  448.       struct stat s;
  449.  
  450.       if (stat(p, &s)==0 && s.st_mtime >= st.st_mtime) {
  451.          if (usize()) skipfile(); return;
  452.       }
  453.    }
  454.    if (w_flag && !okwork('x', prefix(), &st, p)) {
  455.       if (usize()) skipfile(); return;
  456.    }
  457.    if ((j=strlen(p)-1) >= 0 && p[j] == '/') {/* directory with permissions */
  458.       if (testdir(p) != TRUE) return;
  459.       p[j] = '\0';
  460.    } else if (hblock->m.filetype == TF_DIR || hblock->m.filetype == GF_DMP) {
  461.       k = FALSE;
  462.       if (makedir(p, FALSE) != 0) {
  463.          if (testdir(p) != TRUE || makedir(p, TRUE) != 0) k = TRUE;
  464.       }
  465.       if (usize()) skipfile();
  466.       if (k) return;
  467.    } else if (hblock->m.filetype == TF_LNK) {
  468.       makelink(p, cutname(hblock->m.linkname)); return;
  469.    } else if (hblock->m.filetype == TF_OLD || hblock->m.filetype == TF_REG) {
  470.       if (restore(p) != 0) return;
  471. #ifdef UNIX
  472.    } else if (hblock->m.filetype == TF_CHR || hblock->m.filetype == TF_BLK ||
  473.               hblock->m.filetype == TF_QUE) {
  474.       st.st_mode &= 07777;
  475.       if (hblock->m.filetype != TF_QUE) {
  476.          st.st_mode |= hblock->m.filetype == TF_BLK ? S_IFBLK : S_IFCHR;
  477.          st.st_rdev  = makedev(dmajor, dminor);
  478.       } else {
  479.          st.st_mode |= S_IFIFO;
  480.          st.st_rdev  = 0;
  481.       }
  482.       j = 0;
  483.       k = FALSE;
  484.       do {
  485.          if (mknod(p, st.st_mode, st.st_rdev) == 0) break;
  486.       } while (++j < 2 && (k = testdir(p)) == TRUE);
  487.       if (j > 1) (void)fprintf(myout, "Tar: can\'t create \'%s\'\n", p);
  488.       if (j > 1 || k == ERROR) return;
  489.       if (v_flag) (void)fprintf(myout, "x %s\n", p);
  490. #endif
  491.    } else {
  492.       (void)fprintf(myout, unknown, p, hblock->m.filetype);
  493.       return;
  494.    }
  495. #ifdef UNIX
  496.    if (!o_flag) (void)chown(p, (int)st.st_uid, (int)st.st_gid);
  497.    if (!m_flag) {
  498.       long t[2];
  499.  
  500.       t[0] = time(t);
  501.       t[1] = st.st_mtime;
  502.       (void)utime(p, t);
  503.    }
  504. #endif
  505. }
  506.  
  507. void uplist()
  508. {
  509.    register node *this; node *prev;
  510.  
  511.    if ((this = finditem(hblock->m.name, &prev, timehead)) == NONE) {
  512.       if ((this = additem(hblock->m.name, prev, &timehead)) == NONE) {
  513.          outmem(myout);
  514.       }
  515.       this->info.time = st.st_mtime;
  516.    } else {
  517.       if (this->info.time < st.st_mtime) this->info.time = st.st_mtime;
  518.    }
  519. }
  520.  
  521. void acctime()
  522. {
  523.    if (u_flag) uplist();
  524.    if (usize()) skipfile();
  525. }
  526.