home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / vmsnet / sources / 319 < prev    next >
Encoding:
Internet Message Format  |  1992-09-01  |  47.2 KB

  1. Path: sparky!uunet!elroy.jpl.nasa.gov!ames!network.ucsd.edu!mvb.saic.com!vmsnet-sources
  2. From: goathunter@wkuvx1.bitnet
  3. Newsgroups: vmsnet.sources
  4. Subject: Zip v1.9 & UnZip v5.0, part 02/22
  5. Message-ID: <8009582@MVB.SAIC.COM>
  6. Date: Tue, 01 Sep 1992 22:48:37 GMT
  7. Organization: Western Kentucky University, Bowling Green, KY
  8. Lines: 1377
  9. Approved: Mark.Berryman@Mvb.Saic.Com
  10.  
  11. Submitted-by: goathunter@wkuvx1.bitnet
  12. Posting-number: Volume 3, Issue 124
  13. Archive-name: zip_unzip/part02
  14.  
  15. -+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
  16. X          else                  /* do it slow to avoid memcpy() overlap */
  17. X#endif /* !NOMEMCPY */
  18. X            do `7B
  19. X              slide`5Bw++`5D = slide`5Bd++`5D;
  20. X            `7D while (--e);
  21. X        if (w == WSIZE)
  22. X        `7B
  23. X          flush(w);
  24. X          w = u = 0;
  25. X        `7D
  26. X      `7D while (n);
  27. X    `7D
  28. X  `7D
  29. X
  30. X  /* flush out slide */
  31. X  flush(w);
  32. X  return csize ? 5 : 0;         /* should have read csize bytes */
  33. X`7D
  34. X
  35. X
  36. X
  37. Xint explode_nolit8(tl, td, bl, bd)
  38. Xstruct huft *tl, *td;   /* length and distance decoder tables */
  39. Xint bl, bd;             /* number of bits decoded by tl`5B`5D and td`5B`5D *
  40. V/
  41. X/* Decompress the imploded data using uncoded literals and an 8K sliding
  42. X   window. */
  43. X`7B
  44. X  longint s;            /* bytes to decompress */
  45. X  register unsigned e;  /* table entry flag/number of extra bits */
  46. X  unsigned n, d;        /* length and index for copy */
  47. X  unsigned w;           /* current window position */
  48. X  struct huft *t;       /* pointer to table entry */
  49. X  unsigned ml, md;      /* masks for bl and bd bits */
  50. X  register ULONG b;     /* bit buffer */
  51. X  register unsigned k;  /* number of bits in bit buffer */
  52. X  unsigned u;           /* true if unflushed */
  53. X
  54. X
  55. X  /* explode the coded data */
  56. X  b = k = w = 0;                /* initialize bit buffer, window */
  57. X  u = 1;                        /* buffer unflushed */
  58. X  ml = mask_bits`5Bbl`5D;           /* precompute masks for speed */
  59. X  md = mask_bits`5Bbd`5D;
  60. X  s = ucsize;
  61. X  while (s > 0)                 /* do until ucsize bytes uncompressed */
  62. X  `7B
  63. X    NEEDBITS(1)
  64. X    if (b & 1)                  /* then literal--get eight bits */
  65. X    `7B
  66. X      DUMPBITS(1)
  67. X      s--;
  68. X      NEEDBITS(8)
  69. X      slide`5Bw++`5D = (byte)b;
  70. X      if (w == WSIZE)
  71. X      `7B
  72. X        flush(w);
  73. X        w = u = 0;
  74. X      `7D
  75. X      DUMPBITS(8)
  76. X    `7D
  77. X    else                        /* else distance/length */
  78. X    `7B
  79. X      DUMPBITS(1)
  80. X      NEEDBITS(7)               /* get distance low bits */
  81. X      d = (unsigned)b & 0x7f;
  82. X      DUMPBITS(7)
  83. X      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
  84. X      if ((e = (t = td + ((`7E(unsigned)b) & md))->e) > 16)
  85. X        do `7B
  86. X          if (e == 99)
  87. X            return 1;
  88. X          DUMPBITS(t->b)
  89. X          e -= 16;
  90. X          NEEDBITS(e)
  91. X        `7D while ((e = (t = t->v.t + ((`7E(unsigned)b) & mask_bits`5Be`5D))
  92. V->e) > 16);
  93. X      DUMPBITS(t->b)
  94. X      d = w - d - t->v.n;       /* construct offset */
  95. X      NEEDBITS((unsigned)bl)    /* get coded length */
  96. X      if ((e = (t = tl + ((`7E(unsigned)b) & ml))->e) > 16)
  97. X        do `7B
  98. X          if (e == 99)
  99. X            return 1;
  100. X          DUMPBITS(t->b)
  101. X          e -= 16;
  102. X          NEEDBITS(e)
  103. X        `7D while ((e = (t = t->v.t + ((`7E(unsigned)b) & mask_bits`5Be`5D))
  104. V->e) > 16);
  105. X      DUMPBITS(t->b)
  106. X      n = t->v.n;
  107. X      if (e)                    /* get length extra bits */
  108. X      `7B
  109. X        NEEDBITS(8)
  110. X        n += (unsigned)b & 0xff;
  111. X        DUMPBITS(8)
  112. X      `7D
  113. X
  114. X      /* do the copy */
  115. X      s -= n;
  116. X      do `7B
  117. X        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
  118. X        if (u && w <= d)
  119. X        `7B
  120. X          memset(slide + w, 0, e);
  121. X          w += e;
  122. X          d += e;
  123. X        `7D
  124. X        else
  125. X#ifndef NOMEMCPY
  126. X          if (w - d >= e)       /* (this test assumes unsigned comparison) *
  127. V/
  128. X          `7B
  129. X            memcpy(slide + w, slide + d, e);
  130. X            w += e;
  131. X            d += e;
  132. X          `7D
  133. X          else                  /* do it slow to avoid memcpy() overlap */
  134. X#endif /* !NOMEMCPY */
  135. X            do `7B
  136. X              slide`5Bw++`5D = slide`5Bd++`5D;
  137. X            `7D while (--e);
  138. X        if (w == WSIZE)
  139. X        `7B
  140. X          flush(w);
  141. X          w = u = 0;
  142. X        `7D
  143. X      `7D while (n);
  144. X    `7D
  145. X  `7D
  146. X
  147. X  /* flush out slide */
  148. X  flush(w);
  149. X  return csize ? 5 : 0;         /* should have read csize bytes */
  150. X`7D
  151. X
  152. X
  153. X
  154. Xint explode_nolit4(tl, td, bl, bd)
  155. Xstruct huft *tl, *td;   /* length and distance decoder tables */
  156. Xint bl, bd;             /* number of bits decoded by tl`5B`5D and td`5B`5D *
  157. V/
  158. X/* Decompress the imploded data using uncoded literals and a 4K sliding
  159. X   window. */
  160. X`7B
  161. X  longint s;            /* bytes to decompress */
  162. X  register unsigned e;  /* table entry flag/number of extra bits */
  163. X  unsigned n, d;        /* length and index for copy */
  164. X  unsigned w;           /* current window position */
  165. X  struct huft *t;       /* pointer to table entry */
  166. X  unsigned ml, md;      /* masks for bl and bd bits */
  167. X  register ULONG b;     /* bit buffer */
  168. X  register unsigned k;  /* number of bits in bit buffer */
  169. X  unsigned u;           /* true if unflushed */
  170. X
  171. X
  172. X  /* explode the coded data */
  173. X  b = k = w = 0;                /* initialize bit buffer, window */
  174. X  u = 1;                        /* buffer unflushed */
  175. X  ml = mask_bits`5Bbl`5D;           /* precompute masks for speed */
  176. X  md = mask_bits`5Bbd`5D;
  177. X  s = ucsize;
  178. X  while (s > 0)                 /* do until ucsize bytes uncompressed */
  179. X  `7B
  180. X    NEEDBITS(1)
  181. X    if (b & 1)                  /* then literal--get eight bits */
  182. X    `7B
  183. X      DUMPBITS(1)
  184. X      s--;
  185. X      NEEDBITS(8)
  186. X      slide`5Bw++`5D = (byte)b;
  187. X      if (w == WSIZE)
  188. X      `7B
  189. X        flush(w);
  190. X        w = u = 0;
  191. X      `7D
  192. X      DUMPBITS(8)
  193. X    `7D
  194. X    else                        /* else distance/length */
  195. X    `7B
  196. X      DUMPBITS(1)
  197. X      NEEDBITS(6)               /* get distance low bits */
  198. X      d = (unsigned)b & 0x3f;
  199. X      DUMPBITS(6)
  200. X      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
  201. X      if ((e = (t = td + ((`7E(unsigned)b) & md))->e) > 16)
  202. X        do `7B
  203. X          if (e == 99)
  204. X            return 1;
  205. X          DUMPBITS(t->b)
  206. X          e -= 16;
  207. X          NEEDBITS(e)
  208. X        `7D while ((e = (t = t->v.t + ((`7E(unsigned)b) & mask_bits`5Be`5D))
  209. V->e) > 16);
  210. X      DUMPBITS(t->b)
  211. X      d = w - d - t->v.n;       /* construct offset */
  212. X      NEEDBITS((unsigned)bl)    /* get coded length */
  213. X      if ((e = (t = tl + ((`7E(unsigned)b) & ml))->e) > 16)
  214. X        do `7B
  215. X          if (e == 99)
  216. X            return 1;
  217. X          DUMPBITS(t->b)
  218. X          e -= 16;
  219. X          NEEDBITS(e)
  220. X        `7D while ((e = (t = t->v.t + ((`7E(unsigned)b) & mask_bits`5Be`5D))
  221. V->e) > 16);
  222. X      DUMPBITS(t->b)
  223. X      n = t->v.n;
  224. X      if (e)                    /* get length extra bits */
  225. X      `7B
  226. X        NEEDBITS(8)
  227. X        n += (unsigned)b & 0xff;
  228. X        DUMPBITS(8)
  229. X      `7D
  230. X
  231. X      /* do the copy */
  232. X      s -= n;
  233. X      do `7B
  234. X        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
  235. X        if (u && w <= d)
  236. X        `7B
  237. X          memset(slide + w, 0, e);
  238. X          w += e;
  239. X          d += e;
  240. X        `7D
  241. X        else
  242. X#ifndef NOMEMCPY
  243. X          if (w - d >= e)       /* (this test assumes unsigned comparison) *
  244. V/
  245. X          `7B
  246. X            memcpy(slide + w, slide + d, e);
  247. X            w += e;
  248. X            d += e;
  249. X          `7D
  250. X          else                  /* do it slow to avoid memcpy() overlap */
  251. X#endif /* !NOMEMCPY */
  252. X            do `7B
  253. X              slide`5Bw++`5D = slide`5Bd++`5D;
  254. X            `7D while (--e);
  255. X        if (w == WSIZE)
  256. X        `7B
  257. X          flush(w);
  258. X          w = u = 0;
  259. X        `7D
  260. X      `7D while (n);
  261. X    `7D
  262. X  `7D
  263. X
  264. X  /* flush out slide */
  265. X  flush(w);
  266. X  return csize ? 5 : 0;         /* should have read csize bytes */
  267. X`7D
  268. X
  269. X
  270. X
  271. Xint explode()
  272. X/* Explode an imploded compressed stream.  Based on the general purpose
  273. X   bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding
  274. X   window.  Construct the literal (if any), length, and distance codes and
  275. X   the tables needed to decode them (using huft_build() from inflate.c),
  276. X   and call the appropriate routine for the type of data in the remainder
  277. X   of the stream.  The four routines are nearly identical, differing only
  278. X   in whether the literal is decoded or simply read in, and in how many
  279. X   bits are read in, uncoded, for the low distance bits. */
  280. X`7B
  281. X  unsigned r;           /* return codes */
  282. X  struct huft *tb;      /* literal code table */
  283. X  struct huft *tl;      /* length code table */
  284. X  struct huft *td;      /* distance code table */
  285. X  int bb;               /* bits for tb */
  286. X  int bl;               /* bits for tl */
  287. X  int bd;               /* bits for td */
  288. X  unsigned l`5B256`5D;      /* bit lengths for codes */
  289. X
  290. X
  291. X  /* Tune base table sizes.  Note: I thought that to truly optimize speed,
  292. X     I would have to select different bl, bd, and bb values for different
  293. X     compressed file sizes.  I was suprised to find out the the values of
  294. X     7, 7, and 9 worked best over a very wide range of sizes, except that
  295. X     bd = 8 worked marginally better for large compressed sizes. */
  296. X  bl = 7;
  297. X  bd = csize > 200000L ? 8 : 7;
  298. X
  299. X
  300. X  /* With literal tree--minimum match length is 3 */
  301. X  hufts = 0;                    /* initialze huft's malloc'ed */
  302. X  if (lrec.general_purpose_bit_flag & 4)
  303. X  `7B
  304. X    bb = 9;                     /* base table size for literals */
  305. X    if ((r = get_tree(l, 256)) != 0)
  306. X      return r;
  307. X    if ((r = huft_build(l, 256, 256, NULL, NULL, &tb, &bb)) != 0)
  308. X    `7B
  309. X      if (r == 1)
  310. X        huft_free(tb);
  311. X      return r;
  312. X    `7D
  313. X    if ((r = get_tree(l, 64)) != 0)
  314. X      return r;
  315. X    if ((r = huft_build(l, 64, 0, cplen3, extra, &tl, &bl)) != 0)
  316. X    `7B
  317. X      if (r == 1)
  318. X        huft_free(tl);
  319. X      huft_free(tb);
  320. X      return r;
  321. X    `7D
  322. X    if ((r = get_tree(l, 64)) != 0)
  323. X      return r;
  324. X    if (lrec.general_purpose_bit_flag & 2)      /* true if 8K */
  325. X    `7B
  326. X      if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
  327. X      `7B
  328. X        if (r == 1)
  329. X          huft_free(td);
  330. X        huft_free(tl);
  331. X        huft_free(tb);
  332. X        return r;
  333. X      `7D
  334. X      r = explode_lit8(tb, tl, td, bb, bl, bd);
  335. X    `7D
  336. X    else                                        /* else 4K */
  337. X    `7B
  338. X      if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
  339. X      `7B
  340. X        if (r == 1)
  341. X          huft_free(td);
  342. X        huft_free(tl);
  343. X        huft_free(tb);
  344. X        return r;
  345. X      `7D
  346. X      r = explode_lit4(tb, tl, td, bb, bl, bd);
  347. X    `7D
  348. X    huft_free(td);
  349. X    huft_free(tl);
  350. X    huft_free(tb);
  351. X  `7D
  352. X  else
  353. X
  354. X
  355. X  /* No literal tree--minimum match length is 2 */
  356. X  `7B
  357. X    if ((r = get_tree(l, 64)) != 0)
  358. X      return r;
  359. X    if ((r = huft_build(l, 64, 0, cplen2, extra, &tl, &bl)) != 0)
  360. X    `7B
  361. X      if (r == 1)
  362. X        huft_free(tl);
  363. X      return r;
  364. X    `7D
  365. X    if ((r = get_tree(l, 64)) != 0)
  366. X      return r;
  367. X    if (lrec.general_purpose_bit_flag & 2)      /* true if 8K */
  368. X    `7B
  369. X      if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
  370. X      `7B
  371. X        if (r == 1)
  372. X          huft_free(td);
  373. X        huft_free(tl);
  374. X        return r;
  375. X      `7D
  376. X      r = explode_nolit8(tl, td, bl, bd);
  377. X    `7D
  378. X    else                                        /* else 4K */
  379. X    `7B
  380. X      if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
  381. X      `7B
  382. X        if (r == 1)
  383. X          huft_free(td);
  384. X        huft_free(tl);
  385. X        return r;
  386. X      `7D
  387. X      r = explode_nolit4(tl, td, bl, bd);
  388. X    `7D
  389. X    huft_free(td);
  390. X    huft_free(tl);
  391. X  `7D
  392. X#ifdef DEBUG
  393. X  fprintf(stderr, "<%u > ", hufts);
  394. X#endif /* DEBUG */
  395. X  return r;
  396. X`7D
  397. $ CALL UNPACK [.UNZIP50]EXPLODE.C;1 811679058
  398. $ create 'f'
  399. X/*--------------------------------------------------------------------------
  400. V-
  401. X
  402. X  extract.c
  403. X
  404. X  This file contains the high-level routines ("driver routines") for extrac-
  405. X  ting and testing zipfile members.  It calls the low-level routines in file
  406. Vs
  407. X  inflate.c, unimplod.c, unreduce.c and unshrink.c.
  408. X
  409. X  --------------------------------------------------------------------------
  410. V-*/
  411. X
  412. X
  413. X#include "unzip.h"
  414. X#ifdef  MSWIN
  415. X#  include "wizunzip.h"
  416. X#  include "replace.h"
  417. X#endif /* MSWIN */
  418. X
  419. X
  420. X/************************************/
  421. X/*  Extract Local Prototypes, etc.  */
  422. X/************************************/
  423. X
  424. Xstatic int store_info __((void));
  425. Xstatic int extract_or_test_member __((void));
  426. X#ifdef CRYPT
  427. X   static int decrypt_member __((void));
  428. X   static int testp __((byte *hdr));
  429. X#endif
  430. X
  431. Xstatic byte *mem_i_buffer;
  432. Xstatic byte *mem_o_buffer;
  433. Xstatic ULONG mem_i_size, mem_i_offset;
  434. Xstatic ULONG mem_o_size, mem_o_offset;
  435. X
  436. Xstatic char *VersionMsg =
  437. X  " skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
  438. Xstatic char *ComprMsg =
  439. X  " skipping: %-22s  compression method %d\n";
  440. Xstatic char *FilNamMsg =
  441. X  "%s:  bad filename length (%s)\n";
  442. Xstatic char *ExtFieldMsg =
  443. X  "%s:  bad extra field length (%s)\n";
  444. Xstatic char *OffsetMsg =
  445. X  "file #%d:  bad zipfile offset (%s)\n";
  446. X
  447. X
  448. X
  449. X
  450. X
  451. X/**************************************/
  452. X/*  Function extract_or_test_files()  */
  453. X/**************************************/
  454. X
  455. Xint extract_or_test_files()    /* return PK-type error code */
  456. X`7B
  457. X    char **fnamev;
  458. X    byte *cd_inptr;
  459. X    int cd_incnt, error, error_in_archive=0;
  460. X    int renamed, query, len, filnum=(-1), blknum=0;
  461. X#ifdef OS2
  462. X    extern int longname;  /* from os2unzip.c */
  463. X#endif
  464. X    UWORD i, j, members_remaining, num_skipped=0, num_bad_pwd=0;
  465. X    longint cd_bufstart, bufstart, inbuf_offset, request;
  466. X    min_info info`5BDIR_BLKSIZ`5D;
  467. X
  468. X
  469. X/*--------------------------------------------------------------------------
  470. V-
  471. X    The basic idea of this function is as follows.  Since the central di-
  472. X    rectory lies at the end of the zipfile and the member files lie at the
  473. X    beginning or middle or wherever, it is not very desirable to simply
  474. X    read a central directory entry, jump to the member and extract it, and
  475. X    then jump back to the central directory.  In the case of a large zipfile
  476. X    this would lead to a whole lot of disk-grinding, especially if each mem-
  477. X    ber file is small.  Instead, we read from the central directory the per-
  478. X    tinent information for a block of files, then go extract/test the whole
  479. X    block.  Thus this routine contains two small(er) loops within a very
  480. X    large outer loop:  the first of the small ones reads a block of files
  481. X    from the central directory; the second extracts or tests each file; and
  482. X    the outer one loops over blocks.  There's some file-pointer positioning
  483. X    stuff in between, but that's about it.  Btw, it's because of this jump-
  484. X    ing around that we can afford to be lenient if an error occurs in one of
  485. X    the member files:  we should still be able to go find the other members,
  486. X    since we know the offset of each from the beginning of the zipfile.
  487. X
  488. X    Begin main loop over blocks of member files.  We know the entire central
  489. X    directory is on this disk:  we would not have any of this information un
  490. V-
  491. X    less the end-of-central-directory record was on this disk, and we would
  492. X    not have gotten to this routine unless this is also the disk on which
  493. X    the central directory starts.  In practice, this had better be the ONLY
  494. X    disk in the archive, but maybe someday we'll add multi-disk support.
  495. X  --------------------------------------------------------------------------
  496. V-*/
  497. X
  498. X    pInfo = info;
  499. X    members_remaining = ecrec.total_entries_central_dir;
  500. X
  501. X    while (members_remaining) `7B
  502. X        j = 0;
  503. X
  504. X        /*
  505. X         * Loop through files in central directory, storing offsets, file
  506. X         * attributes, and case-conversion flags until block size is reached
  507. V.
  508. X         */
  509. X
  510. X        while (members_remaining && (j < DIR_BLKSIZ)) `7B
  511. X            --members_remaining;
  512. X            pInfo = &info`5Bj`5D;
  513. X
  514. X            if (readbuf(sig, 4) <= 0) `7B
  515. X                error_in_archive = 51;  /* 51:  unexpected EOF */
  516. X                members_remaining = 0;  /* ...so no more left to do */
  517. X                break;
  518. X            `7D
  519. X            if (strncmp(sig, central_hdr_sig, 4)) `7B  /* just to make sure
  520. V */
  521. X                fprintf(stderr, CentSigMsg, j);  /* sig not found */
  522. X                fprintf(stderr, ReportMsg);   /* check binary transfers */
  523. X                error_in_archive = 3;   /* 3:  error in zipfile */
  524. X                members_remaining = 0;  /* ...so no more left to do */
  525. X                break;
  526. X            `7D
  527. X            /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
  528. X            if ((error = process_cdir_file_hdr()) != 0) `7B
  529. X                error_in_archive = error;   /* only 51 (EOF) defined */
  530. X                members_remaining = 0;  /* ...so no more left to do */
  531. X                break;
  532. X            `7D
  533. X            if ((error = do_string(crec.filename_length, FILENAME)) != 0) `7
  534. VB
  535. X                if (error > error_in_archive)
  536. X                    error_in_archive = error;
  537. X                if (error > 1) `7B  /* fatal:  no more left to do */
  538. X                    fprintf(stderr, FilNamMsg, filename, "central");
  539. X                    members_remaining = 0;
  540. X                    break;
  541. X                `7D
  542. X            `7D
  543. X            if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) !=
  544. V 0)
  545. X            `7B
  546. X                if (error > error_in_archive)
  547. X                    error_in_archive = error;
  548. X                if (error > 1) `7B  /* fatal */
  549. X                    fprintf(stderr, ExtFieldMsg, filename, "central");
  550. X                    members_remaining = 0;
  551. X                    break;
  552. X                `7D
  553. X            `7D
  554. X            if ((error = do_string(crec.file_comment_length, SKIP)) != 0) `7
  555. VB
  556. X                if (error > error_in_archive)
  557. X                    error_in_archive = error;
  558. X                if (error > 1) `7B  /* fatal */
  559. X                    fprintf(stderr, "\n%s:  bad file comment length\n",
  560. X                            filename);
  561. X                    members_remaining = 0;
  562. X                    break;
  563. X                `7D
  564. X            `7D
  565. X            if (process_all_files) `7B
  566. X                if (store_info())
  567. X                    ++num_skipped;
  568. X                else
  569. X                    ++j;  /* file is OK: save info`5B`5D and continue with n
  570. Vext */
  571. X            `7D else `7B
  572. X                fnamev = fnv;   /* don't destroy permanent filename pointer
  573. V */
  574. X                for (--fnamev; *++fnamev;)
  575. X                    if (match(filename, *fnamev)) `7B
  576. X                        if (store_info())
  577. X                            ++num_skipped;
  578. X                        else
  579. X                            ++j;   /* file is OK */
  580. X                        break;  /* found match for filename, so stop looping
  581. V */
  582. X                    `7D /* end if (match), for-loop (fnamev) */
  583. X            `7D /* end if (process_all_files) */
  584. X
  585. X        `7D /* end while-loop (adding files to current block) */
  586. X
  587. X        /* save position in central directory so can come back later */
  588. X        cd_bufstart = cur_zipfile_bufstart;
  589. X        cd_inptr = inptr;
  590. X        cd_incnt = incnt;
  591. X
  592. X    /*----------------------------------------------------------------------
  593. V-
  594. X        Second loop:  process files in current block, extracting or testing
  595. X        each one.
  596. X      ----------------------------------------------------------------------
  597. V-*/
  598. X
  599. X        for (i = 0; i < j; ++i) `7B
  600. X            filnum = i + blknum*DIR_BLKSIZ;
  601. X            pInfo = &info`5Bi`5D;
  602. X            /*
  603. X             * if the target position is not within the current input buffer
  604. X             * (either haven't yet read far enough, or (maybe) skipping back
  605. V-
  606. X             * ward) skip to the target position and reset readbuf().
  607. X             */
  608. X            /* LSEEK(pInfo->offset):  */
  609. X            request = pInfo->offset + extra_bytes;
  610. X            inbuf_offset = request % INBUFSIZ;
  611. X            bufstart = request - inbuf_offset;
  612. X
  613. X            if (request < 0) `7B
  614. X                fprintf(stderr, SeekMsg, ReportMsg);
  615. X                error_in_archive = 3;       /* 3:  severe error in zipfile,
  616. V */
  617. X                continue;                   /*  but can still go on */
  618. X            `7D else if (bufstart != cur_zipfile_bufstart) `7B
  619. X                cur_zipfile_bufstart = lseek(zipfd, bufstart, SEEK_SET);
  620. X                if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) <= 0) `7B
  621. X                    fprintf(stderr, OffsetMsg, filnum, "lseek");
  622. X                    error_in_archive = 3;   /* 3:  error in zipfile, but */
  623. X                    continue;               /*  can still do next file   */
  624. X                `7D
  625. X                inptr = inbuf + (int)inbuf_offset;
  626. X                incnt -= (int)inbuf_offset;
  627. X            `7D else `7B
  628. X                incnt += (inptr-inbuf) - (int)inbuf_offset;
  629. X                inptr = inbuf + (int)inbuf_offset;
  630. X            `7D
  631. X
  632. X            /* should be in proper position now, so check for sig */
  633. X            if (readbuf(sig, 4) <= 0) `7B  /* bad offset */
  634. X                fprintf(stderr, OffsetMsg, filnum, "EOF");
  635. X                error_in_archive = 3;    /* 3:  error in zipfile */
  636. X                continue;       /* but can still try next one */
  637. X            `7D
  638. X            if (strncmp(sig, local_hdr_sig, 4)) `7B
  639. X                fprintf(stderr, OffsetMsg, filnum,
  640. X                        "can't find local header sig");   /* bad offset */
  641. X                error_in_archive = 3;
  642. X                continue;
  643. X            `7D
  644. X            if ((error = process_local_file_hdr()) != 0) `7B
  645. X                fprintf(stderr, "\nfile #%d:  bad local header\n", filnum);
  646. X                error_in_archive = error;       /* only 51 (EOF) defined */
  647. X                continue;       /* can still try next one */
  648. X            `7D
  649. X            if ((error = do_string(lrec.filename_length, FILENAME)) != 0) `7
  650. VB
  651. X                if (error > error_in_archive)
  652. X                    error_in_archive = error;
  653. X                if (error > 1) `7B
  654. X                    fprintf(stderr, FilNamMsg, filename, "local");
  655. X                    continue;   /* go on to next one */
  656. X                `7D
  657. X            `7D
  658. X            if (extra_field != (byte *)NULL)
  659. X                free(extra_field);
  660. X            extra_field = (byte *)NULL;
  661. X            if ((error = do_string(lrec.extra_field_length, EXTRA_FIELD)) !=
  662. V 0)
  663. X            `7B
  664. X                if (error > error_in_archive)
  665. X                    error_in_archive = error;
  666. X                if (error > 1) `7B
  667. X                    fprintf(stderr, ExtFieldMsg, filename, "local");
  668. X                    continue;   /* go on */
  669. X                `7D
  670. X            `7D
  671. X
  672. X            /*
  673. X             * just about to extract file:  if extracting to disk, check if
  674. X             * already exists, and if so, take appropriate action according
  675. V to
  676. X             * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  677. X             * loop because we don't store the possibly renamed filename`5B`
  678. V5D in
  679. X             * info`5B`5D)
  680. X             */
  681. X            if (!tflag && !cflag) `7B
  682. X                renamed = FALSE;   /* user hasn't renamed output file yet */
  683. X#ifdef OS2
  684. X                longname = FALSE;  /* no long name has yet been stored */
  685. X#endif
  686. X
  687. Xstartover:
  688. X                query = FALSE;
  689. X#ifdef MACOS
  690. X                macflag = (pInfo->hostnum == MAC_);
  691. X#endif
  692. X                /* mapname can create dirs if not freshening or if renamed *
  693. V/
  694. X                if ((error = mapname(!fflag `7C`7C renamed)) > 1) `7B    /*
  695. V skip */
  696. X                    if ((error > 2) && (error_in_archive < 2))
  697. X                        error_in_archive = 2;   /* (weak) error in zipfile *
  698. V/
  699. X                    continue;   /* go on to next file */
  700. X                `7D
  701. X
  702. X                switch (check_for_newer(filename)) `7B
  703. X                    case DOES_NOT_EXIST:
  704. X                        if (fflag && !renamed)  /* don't skip if just rename
  705. Vd */
  706. X                            continue;   /* freshen (no new files):  skip */
  707. X                        break;
  708. X                    case EXISTS_AND_OLDER:
  709. X                        if (overwrite_none)
  710. X                            continue;   /* never overwrite:  skip file */
  711. X                        if (!overwrite_all && !force_flag)
  712. X                            query = TRUE;
  713. X                        break;
  714. X                    case EXISTS_AND_NEWER:             /* (or equal) */
  715. X                        if (overwrite_none `7C`7C (uflag && !renamed))
  716. X                            continue;  /* skip if update/freshen & orig name
  717. V */
  718. X                        if (!overwrite_all && !force_flag)
  719. X                            query = TRUE;
  720. X                        break;
  721. X                `7D
  722. X/*#ifndef VMS*/ /* VMS creates higher version number instead of overwriting
  723. X                 * (will have to modify for VMS-style names with specific
  724. X                 *  version numbers:  just check V_flag?  don't use stat?) *
  725. V/
  726. X                if (query) `7B
  727. X#ifdef MSWIN
  728. X                    FARPROC lpfnprocReplace;
  729. X                    int ReplaceDlgRetVal;   /* replace dialog return value *
  730. V/
  731. X
  732. X                    ShowCursor(FALSE);      /* turn off cursor */
  733. X                    SetCursor(hSaveCursor); /* restore the cursor */
  734. X                    lpfnprocReplace = MakeProcInstance(ReplaceProc, hInst);
  735. X                    ReplaceDlgRetVal = DialogBoxParam(hInst, "Replace",
  736. X                      hWndMain, lpfnprocReplace, (DWORD)(LPSTR)filename);
  737. X                    FreeProcInstance(lpfnprocReplace);
  738. X                    hSaveCursor = SetCursor(hHourGlass);
  739. X                    ShowCursor(TRUE);
  740. X                    switch (ReplaceDlgRetVal) `7B
  741. X                        case IDM_REPLACE_RENAME:
  742. X                            renamed = TRUE;
  743. X                            goto startover;   /* sorry for a goto */
  744. X                        case IDM_REPLACE_YES:
  745. X                            break;
  746. X                        case IDM_REPLACE_ALL:
  747. X                            overwrite_all = TRUE;
  748. X                            overwrite_none = FALSE;  /* just to make sure */
  749. X                            break;
  750. X                        case IDM_REPLACE_NONE:
  751. X                            overwrite_none = TRUE;
  752. X                            overwrite_all = FALSE;  /* make sure */
  753. X                            force_flag = FALSE;     /* ditto */
  754. X                            /* FALL THROUGH, skip */
  755. X                        case IDM_REPLACE_NO:
  756. X                            continue;
  757. X                    `7D
  758. X#else /* !MSWIN */
  759. Xreprompt:
  760. X                    fprintf(stderr,
  761. X                      "replace %s? `5By`5Des, `5Bn`5Do, `5BA`5Dll, `5BN`5Don
  762. Ve, `5Br`5Dename: ",
  763. X                      filename);
  764. X                    FFLUSH   /* for Amiga and Mac MPW */
  765. X                    fgets(answerbuf, 9, stdin);
  766. X                    switch (*answerbuf) `7B
  767. X                        case 'A':   /* dangerous option:  force caps */
  768. X                            overwrite_all = TRUE;
  769. X                            overwrite_none = FALSE;  /* just to make sure */
  770. X                            break;
  771. X                        case 'r':
  772. X                        case 'R':
  773. X                            do `7B
  774. X                                fprintf(stderr, "new name: ");
  775. X                                FFLUSH   /* for AMIGA and Mac MPW */
  776. X                                fgets(filename, FILNAMSIZ, stdin);
  777. X                                /* usually get \n here:  better check for it
  778. V */
  779. X                                len = strlen(filename);
  780. X                                if (filename`5Blen-1`5D == '\n')
  781. X                                    filename`5B--len`5D = 0;
  782. X                            `7D while (len == 0);
  783. X                            renamed = TRUE;
  784. X                            goto startover;   /* sorry for a goto */
  785. X                        case 'y':
  786. X                        case 'Y':
  787. X                            break;
  788. X                        case 'N':
  789. X                            overwrite_none = TRUE;
  790. X                            overwrite_all = FALSE;  /* make sure */
  791. X                            force_flag = FALSE;     /* ditto */
  792. X                            /* FALL THROUGH, skip */
  793. X                        case 'n':
  794. X                            continue;   /* skip file */
  795. X                        default:
  796. X                            fprintf(stderr, "error:  invalid response `5B%c`
  797. V5D\n",
  798. X                              *answerbuf);   /* warn the user */
  799. X                            goto reprompt;   /* why not another goto? */
  800. X                    `7D /* end switch (*answerbuf) */
  801. X#endif /* ?MSWIN */
  802. X                `7D /* end if (query) */
  803. X/*#endif*/ /* !VMS */
  804. X            `7D /* end if (extracting to disk) */
  805. X
  806. X#ifdef CRYPT
  807. X            if (pInfo->encrypted && ((error = decrypt_member()) != 0)) `7B
  808. X                if (error == 10) `7B
  809. X                    if (error > error_in_archive)
  810. X                        error_in_archive = error;
  811. X                    fprintf(stderr,
  812. X                      " skipping: %-22s  unable to get password\n", filename
  813. V);
  814. X                `7D else `7B  /* (error == 1) */
  815. X                    fprintf(stderr,
  816. X                      " skipping: %-22s  incorrect password\n", filename);
  817. X                    ++num_bad_pwd;
  818. X                `7D
  819. X                continue;   /* go on to next file */
  820. X            `7D
  821. X#endif /* CRYPT */
  822. X            disk_full = 0;
  823. X            if ((error = extract_or_test_member()) != 0) `7B
  824. X                if (error > error_in_archive)
  825. X                    error_in_archive = error;       /* ...and keep going */
  826. X                if (disk_full > 1)
  827. X                    return error_in_archive;        /* (unless disk full) */
  828. X            `7D
  829. X        `7D /* end for-loop (i:  files in current block) */
  830. X
  831. X
  832. X        /*
  833. X         * Jump back to where we were in the central directory, then go and
  834. V do
  835. X         * the next batch of files.
  836. X         */
  837. X
  838. X        cur_zipfile_bufstart = lseek(zipfd, cd_bufstart, SEEK_SET);
  839. X        read(zipfd, (char *)inbuf, INBUFSIZ);  /* were there b4 ==> no error
  840. V */
  841. X        inptr = cd_inptr;
  842. X        incnt = cd_incnt;
  843. X        ++blknum;
  844. X
  845. X#ifdef TEST
  846. X        printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
  847. X        printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart
  848. V,
  849. X          cur_zipfile_bufstart);
  850. X        printf("inptr-inbuf = %d\n", inptr-inbuf);
  851. X        printf("incnt = %d\n\n", incnt);
  852. X#endif
  853. X
  854. X    `7D /* end while-loop (blocks of files in central directory) */
  855. X
  856. X/*--------------------------------------------------------------------------
  857. V-
  858. X    Double-check that we're back at the end-of-central-directory record, and
  859. X    print quick summary of results, if we were just testing the archive.  We
  860. X    send the summary to stdout so that people doing the testing in the back-
  861. X    ground and redirecting to a file can just do a "tail" on the output file
  862. V.
  863. X  --------------------------------------------------------------------------
  864. V-*/
  865. X
  866. X    readbuf(sig, 4);
  867. X    if (strncmp(sig, end_central_sig, 4)) `7B     /* just to make sure again
  868. V */
  869. X        fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig *
  870. V/
  871. X        fprintf(stderr, ReportMsg);  /* check binary transfers */
  872. X        if (!error_in_archive)       /* don't overwrite stronger error */
  873. X            error_in_archive = 1;    /* 1:  warning error */
  874. X    `7D
  875. X    if (tflag && (quietflg == 1)) `7B
  876. X        int num=filnum+1 - num_bad_pwd;
  877. X
  878. X        if (error_in_archive)
  879. X            printf("At least one error was detected in %s.\n", zipfn);
  880. X        else if (num == 0)
  881. X            printf("Caution:  zero files tested in %s.\n", zipfn);
  882. X        else if (process_all_files && (num_skipped+num_bad_pwd == 0))
  883. X            printf("No errors detected in %s.\n", zipfn);
  884. X        else
  885. X            printf("No errors detected in %s for the %d file%s tested.\n",
  886. X              zipfn, num, (num==1)? "":"s");
  887. X        if (num_skipped > 0)
  888. X            printf("%d file%s skipped because of unsupported compression or\
  889. X encoding.\n",
  890. X              num_skipped, (num_skipped==1)? "":"s");
  891. X#ifdef CRYPT
  892. X        if (num_bad_pwd > 0)
  893. X            printf("%d file%s skipped because of incorrect password.\n",
  894. X              num_bad_pwd, (num_bad_pwd==1)? "":"s");
  895. X#endif /* CRYPT */
  896. X    `7D
  897. X    if ((num_skipped > 0) && !error_in_archive)   /* files not tested or  */
  898. X        error_in_archive = 1;                     /*  extracted:  warning */
  899. X#ifdef CRYPT
  900. X    if ((num_bad_pwd > 0) && !error_in_archive)   /* files not tested or  */
  901. X        error_in_archive = 1;                     /*  extracted:  warning */
  902. X#endif /* CRYPT */
  903. X
  904. X    return (error_in_archive);
  905. X
  906. X`7D /* end function extract_or_test_files() */
  907. X
  908. X
  909. X
  910. X
  911. X
  912. X/***************************/
  913. X/*  Function store_info()  */
  914. X/***************************/
  915. X
  916. Xstatic int store_info()   /* return 1 if skipping, 0 if OK */
  917. X`7B
  918. X    ULONG tmp;
  919. X
  920. X#define UNKN_COMPR \
  921. X   (crec.compression_method>IMPLODED && crec.compression_method!=DEFLATED)
  922. X#if 0  /* old */
  923. X#  define UNKN_COMPR   (crec.compression_method>IMPLODED)
  924. X#endif
  925. X
  926. X
  927. X/*--------------------------------------------------------------------------
  928. V-
  929. X    Check central directory info for version/compatibility requirements.
  930. X  --------------------------------------------------------------------------
  931. V-*/
  932. X
  933. X    pInfo->encrypted = crec.general_purpose_bit_flag & 1;    /* bit field */
  934. X    pInfo->ExtLocHdr = (crec.general_purpose_bit_flag & 8) == 8;  /* bit */
  935. X    pInfo->text = crec.internal_file_attributes & 1;         /* bit field */
  936. X    pInfo->crc = crec.crc32;
  937. X    pInfo->compr_size = crec.compressed_size;
  938. X
  939. X    if (crec.version_needed_to_extract`5B1`5D == VMS_) `7B
  940. X        if (crec.version_needed_to_extract`5B0`5D > VMS_VERSION) `7B
  941. X            fprintf(stderr, VersionMsg, filename, "VMS",
  942. X              crec.version_needed_to_extract`5B0`5D / 10,
  943. X              crec.version_needed_to_extract`5B0`5D % 10,
  944. X              VMS_VERSION / 10, VMS_VERSION % 10);
  945. X            return 1;
  946. X        `7D
  947. X#ifndef VMS   /* won't be able to use extra field, but still have data */
  948. X        else if (!tflag && !force_flag) `7B  /* if forcing, extract regardle
  949. Vss */
  950. X            fprintf(stderr,
  951. X              "\n%s:  stored in VMS format.  Extract anyway? (y/n) ",
  952. X              filename);
  953. X            FFLUSH   /* for Amiga and Mac MPW */
  954. X            fgets(answerbuf, 9, stdin);
  955. X            if ((*answerbuf != 'y') && (*answerbuf != 'Y'))
  956. X                return 1;
  957. X        `7D
  958. X#endif /* !VMS */
  959. X    /* usual file type:  don't need VMS to extract */
  960. X    `7D else if (crec.version_needed_to_extract`5B0`5D > UNZIP_VERSION) `7B
  961. X        fprintf(stderr, VersionMsg, filename, "PK",
  962. X          crec.version_needed_to_extract`5B0`5D / 10,
  963. X          crec.version_needed_to_extract`5B0`5D % 10,
  964. X          UNZIP_VERSION / 10, UNZIP_VERSION % 10);
  965. X        return 1;
  966. X    `7D
  967. X
  968. X    if UNKN_COMPR `7B
  969. X        fprintf(stderr, ComprMsg, filename, crec.compression_method);
  970. X        return 1;
  971. X    `7D
  972. X#ifndef CRYPT
  973. X    if (pInfo->encrypted) `7B
  974. X        fprintf(stderr, " skipping: %-22s  encrypted (not supported)\n",
  975. X          filename);
  976. X        return 1;
  977. X    `7D
  978. X#endif /* !CRYPT */
  979. X
  980. X/*--------------------------------------------------------------------------
  981. V-
  982. X    Store some central-directory information (encryption, file attributes,
  983. X    offsets) for later use.
  984. X  --------------------------------------------------------------------------
  985. V-*/
  986. X
  987. X    tmp = crec.external_file_attributes;
  988. X
  989. X    pInfo->dos_attr = 32;   /* set archive bit:  file is not backed up */
  990. X    switch (pInfo->hostnum) `7B
  991. X        case UNIX_:
  992. X        case VMS_:
  993. X            pInfo->unix_attr = (unsigned) (tmp >> 16);
  994. X            break;
  995. X        case DOS_OS2_FAT_:
  996. X        case OS2_HPFS_:
  997. X            pInfo->dos_attr = (unsigned) tmp;
  998. X            tmp = (!(tmp & 1)) << 1;   /* read-only bit */
  999. X            pInfo->unix_attr = (unsigned) (0444 `7C (tmp<<6) `7C (tmp<<3) `7
  1000. VC tmp);
  1001. X#ifdef UNIX
  1002. X            umask( (int)(tmp=umask(0)) );
  1003. X            pInfo->unix_attr &= `7Etmp;
  1004. X#endif
  1005. X            break;
  1006. X        case MAC_:
  1007. X            pInfo->unix_attr = (unsigned) (tmp & 1);   /* read-only bit */
  1008. X            break;
  1009. X        default:
  1010. X            pInfo->unix_attr = 0666;
  1011. X            break;
  1012. X    `7D /* end switch (host-OS-created-by) */
  1013. X
  1014. X    pInfo->offset = (longint) crec.relative_offset_local_header;
  1015. X    return 0;
  1016. X
  1017. X`7D /* end function store_info() */
  1018. X
  1019. X
  1020. X
  1021. X
  1022. X
  1023. X/***************************************/
  1024. X/*  Function extract_or_test_member()  */
  1025. X/***************************************/
  1026. X
  1027. Xstatic int extract_or_test_member()    /* return PK-type error code */
  1028. X`7B
  1029. X#ifdef S_IFLNK
  1030. X    int symlnk=FALSE;
  1031. X#endif /* S_IFLNK */
  1032. X    int error=0;
  1033. X    UWORD b;
  1034. X
  1035. X
  1036. X
  1037. X/*--------------------------------------------------------------------------
  1038. V-
  1039. X    Initialize variables, buffers, etc.
  1040. X  --------------------------------------------------------------------------
  1041. V-*/
  1042. X
  1043. X    bits_left = 0;
  1044. X    bitbuf = 0L;
  1045. X    outpos = 0L;
  1046. X    outcnt = 0;
  1047. X    outptr = outbuf;
  1048. X    zipeof = 0;
  1049. X    crc32val = 0xFFFFFFFFL;
  1050. X
  1051. X#ifdef S_IFLNK
  1052. X    if ((pInfo->unix_attr & S_IFMT) == S_IFLNK  &&  (pInfo->hostnum == UNIX_
  1053. V)
  1054. X        && !tflag && !cflag)
  1055. X        symlnk = TRUE;
  1056. X#endif /* S_IFLNK */
  1057. X
  1058. X    memset(outbuf, 0xaa, OUTBUFSIZ);
  1059. X#if (!defined(DOS_OS2) `7C`7C defined(MSWIN))
  1060. X    if (aflag)                  /* if we have a scratchpad, clear it out */
  1061. X#ifdef MSWIN
  1062. X        _fmemset(outout, 0xaa, OUTBUFSIZ);
  1063. X#else /* !MSWIN */
  1064. X        memset(outout, 0xaa, OUTBUFSIZ);
  1065. X#endif /* ?MSWIN */
  1066. X#endif /* !DOS_OS2 `7C`7C MSWIN */
  1067. X
  1068. X    if (tflag) `7B
  1069. X        if (!quietflg) `7B
  1070. X            fprintf(stdout, "  Testing: %-22s ", filename);
  1071. X            fflush(stdout);
  1072. X        `7D
  1073. X    `7D else `7B
  1074. X        if (cflag) `7B            /* output to stdout (copy of it) */
  1075. X#if (defined(MACOS) `7C`7C defined(AMIGA))
  1076. X            outfd = 1;
  1077. X#else /* !(MACOS `7C`7C AMIGA) */
  1078. X            outfd = dup(1);     /* GRR: change this to #define for Mac/Amiga
  1079. V */
  1080. X#endif /* ?(MACOS `7C`7C AMIGA) */
  1081. X#ifdef DOS_OS2
  1082. X            if (!aflag)
  1083. X                setmode(outfd, O_BINARY);
  1084. X#endif /* DOS_OS2 */
  1085. X#ifdef VMS
  1086. X            if (create_output_file())   /* VMS version required for stdout!
  1087. V */
  1088. X                return 50;      /* 50:  disk full (?) */
  1089. X#endif
  1090. X        `7D else
  1091. X#ifdef S_IFLNK
  1092. X        if (!symlnk)    /* symlink() takes care of file creation */
  1093. X#endif /* !S_IFLNK */
  1094. X        `7B
  1095. X            if (create_output_file())
  1096. X                return 50;      /* 50:  disk full (?) */
  1097. X        `7D
  1098. X    `7D /* endif (!tflag) */
  1099. X
  1100. X/*--------------------------------------------------------------------------
  1101. V-
  1102. X    Unpack the file.
  1103. X  --------------------------------------------------------------------------
  1104. V-*/
  1105. X
  1106. X    switch (lrec.compression_method) `7B
  1107. X
  1108. X    case STORED:
  1109. X        if (!tflag && (quietflg < 2)) `7B
  1110. X            fprintf(stdout, " Extracting: %-22s ", filename);
  1111. X            if (cflag)
  1112. X                fprintf(stdout, "\n");
  1113. X            fflush(stdout);
  1114. X        `7D
  1115. X#ifdef S_IFLNK
  1116. X        /*
  1117. X         * If file came from Unix and is a symbolic link and we are extracti
  1118. Vng
  1119. X         * to disk, allocate a storage area, put the data in it, and create
  1120. V the
  1121. X         * link.  Since we know it's a symbolic link to start with, shouldn'
  1122. Vt
  1123. X         * have to worry about overflowing unsigned ints with unsigned longs
  1124. V.
  1125. X         * (This doesn't do anything for compressed symlinks, but that can b
  1126. Ve
  1127. X         * added later...it also doesn't set the time or permissions of the
  1128. X         * link, but does anyone really care?)
  1129. X         */
  1130. X        if (symlnk) `7B
  1131. X#if (defined(MTS) `7C`7C defined(MACOS))
  1132. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1133. X            error = 1;          /* 1:  warning error */
  1134. X#else /* !(MTS `7C`7C MACOS) */
  1135. X            char *orig = (char *)malloc((unsigned)lrec.uncompressed_size+1);
  1136. X            char *p = orig;
  1137. X
  1138. X            while (ReadByte(&b))
  1139. X                *p++ = b;
  1140. X            *p = 0;   /* terminate string */
  1141. X            UpdateCRC((unsigned char *)orig, p-orig);
  1142. X            if (symlink(orig, filename))
  1143. X                if ((errno == EEXIST) && overwrite_all) `7B  /* OK to overwr
  1144. Vite */
  1145. X                    unlink(filename);
  1146. X                    if (symlink(orig, filename))
  1147. X                        perror("symlink error");
  1148. X                `7D else
  1149. X                    perror("symlink error");
  1150. X            free(orig);
  1151. X#endif /* ?(MTS `7C`7C MACOS) */
  1152. X        `7D else
  1153. X#endif /* S_IFLNK */
  1154. X        while (ReadByte(&b) && !disk_full)
  1155. X            OUTB(b)
  1156. X        break;
  1157. X
  1158. X    case SHRUNK:
  1159. X        if (!tflag && (quietflg < 2)) `7B
  1160. X            fprintf(stdout, "UnShrinking: %-22s ", filename);
  1161. X            if (cflag)
  1162. X                fprintf(stdout, "\n");
  1163. X            fflush(stdout);
  1164. X        `7D
  1165. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  1166. X        if (symlnk) `7B
  1167. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1168. X            error = 1;          /* 1:  warning error */
  1169. X        `7D
  1170. X#endif /* S_IFLNK */
  1171. X        unShrink();
  1172. X        break;
  1173. X
  1174. X    case REDUCED1:
  1175. X    case REDUCED2:
  1176. X    case REDUCED3:
  1177. X    case REDUCED4:
  1178. X        if (!tflag && (quietflg < 2)) `7B
  1179. X            fprintf(stdout, "  Expanding: %-22s ", filename);
  1180. X            if (cflag)
  1181. X                fprintf(stdout, "\n");
  1182. X            fflush(stdout);
  1183. X        `7D
  1184. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  1185. X        if (symlnk) `7B
  1186. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1187. X            error = 1;          /* 1:  warning error */
  1188. X        `7D
  1189. X#endif /* S_IFLNK */
  1190. X        unReduce();
  1191. X        break;
  1192. X
  1193. X    case IMPLODED:
  1194. X        if (!tflag && (quietflg < 2)) `7B
  1195. X            fprintf(stdout, "  Exploding: %-22s ", filename);
  1196. X            if (cflag)
  1197. X                fprintf(stdout, "\n");
  1198. X            fflush(stdout);
  1199. X        `7D
  1200. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  1201. X        if (symlnk) `7B
  1202. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1203. X            error = 1;          /* 1:  warning error */
  1204. X        `7D
  1205. X#endif /* S_IFLNK */
  1206. X        explode();   /* ignore return code for now */
  1207. X        break;
  1208. X
  1209. X    case DEFLATED:
  1210. X        if (!tflag && (quietflg < 2)) `7B
  1211. X            fprintf(stdout, "  Inflating: %-22s ", filename);
  1212. X            if (cflag)
  1213. X                fprintf(stdout, "\n");
  1214. X            fflush(stdout);
  1215. X        `7D
  1216. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  1217. X        if (symlnk) `7B
  1218. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1219. X            error = 1;          /* 1:  warning error */
  1220. X        `7D
  1221. X#endif /* S_IFLNK */
  1222. X        inflate();
  1223. X        break;
  1224. X
  1225. X    default:   /* should never get to this point */
  1226. X        fprintf(stderr, "%s:  unknown compression method\n", filename);
  1227. X        /* close and delete file before return? */
  1228. X        return 1;               /* 1:  warning error */
  1229. X
  1230. X    `7D /* end switch (compression method) */
  1231. X
  1232. X    if (disk_full) `7B            /* set by FlushOutput()/OUTB() macro */
  1233. X        if (disk_full > 1)
  1234. X            return 50;          /* 50:  disk full */
  1235. X        error = 1;              /* 1:  warning error */
  1236. X    `7D
  1237. X
  1238. X/*--------------------------------------------------------------------------
  1239. V-
  1240. X    Write the last partial buffer, if any; set the file date and time; and
  1241. X    close the file (not necessarily in that order).  Then make sure CRC came
  1242. X    out OK and print result.
  1243. X  --------------------------------------------------------------------------
  1244. V-*/
  1245. X
  1246. X#ifdef S_IFLNK
  1247. X    if (!symlnk) `7B
  1248. X#endif /* S_IFLNK */
  1249. X    if (!disk_full && FlushOutput())
  1250. X        if (disk_full > 1)
  1251. X            return 50;          /* 50:  disk full */
  1252. X        else `7B                  /* disk_full == 1 */
  1253. X            fprintf(stderr, "%s:  probably corrupt\n", filename);
  1254. X            error = 1;          /* 1:  warning error */
  1255. X        `7D
  1256. X
  1257. X    if (!tflag)
  1258. X#ifdef VMS
  1259. X        CloseOutputFile();
  1260. X#else /* !VMS */
  1261. X#ifdef MTS                      /* MTS can't set file time */
  1262. X        close(outfd);
  1263. X#else /* !MTS */
  1264. X        set_file_time_and_close();
  1265. X#endif /* ?MTS */
  1266. X#endif /* ?VMS */
  1267. X
  1268. X#ifdef S_IFLNK
  1269. X    `7D /* endif (!symlnk) */
  1270. X#endif /* S_IFLNK */
  1271. X
  1272. X    /* logical-AND crc32val for 64-bit machines */
  1273. X    if ((crc32val = ((`7Ecrc32val) & 0xFFFFFFFFL)) != lrec.crc32) `7B
  1274. X        /* if quietflg is set, we haven't output the filename yet:  do it */
  1275. X        if (quietflg)
  1276. X            printf("%-22s: ", filename);
  1277. X        fprintf(stdout, " Bad CRC %08lx  (should be %08lx)\n", crc32val,
  1278. X                lrec.crc32);
  1279. X        error = 1;              /* 1:  warning error */
  1280. X    `7D else if (tflag) `7B
  1281. X        if (!quietflg)
  1282. X            fprintf(stdout, " OK\n");
  1283. X    `7D else `7B
  1284. X        if ((quietflg < 2) && !error)
  1285. X            fprintf(stdout, "\n");
  1286. X    `7D
  1287. X
  1288. X    return error;
  1289. X
  1290. X`7D       /* end function extract_or_test_member() */
  1291. X
  1292. X
  1293. X
  1294. X
  1295. X
  1296. X#ifdef CRYPT
  1297. X
  1298. X/*******************************/
  1299. X/*  Function decrypt_member()  */
  1300. X/*******************************/
  1301. X
  1302. Xstatic int decrypt_member()   /* return 10 if out of memory or can't get */
  1303. X`7B                             /*  tty; 1 if password bad; 0 if password OK
  1304. V */
  1305. X    UWORD b;
  1306. X    int n, r;
  1307. X    static int nopwd=FALSE;
  1308. X    char *m, *prompt;
  1309. X    byte h`5B12`5D;
  1310. X
  1311. X
  1312. X    /* get header once */
  1313. X    for (n = 0; n < 12; n++) `7B
  1314. X        ReadByte(&b);
  1315. X        h`5Bn`5D = (byte) b;
  1316. X    `7D
  1317. X
  1318. X    /* if have key already, test it; else allocate memory for it */
  1319. X    if (key) `7B
  1320. X        if (!testp(h))
  1321. X            return 0;      /* existing password OK (else prompt for new) */
  1322. X        else if (nopwd)
  1323. X            return 1;      /* user indicated no more prompting */
  1324. X    `7D else if ((key = (char *)malloc(PWLEN+1)) == (char *)NULL)
  1325. X        return 10;
  1326. X
  1327. X    if ((prompt = (char *)malloc(FILNAMSIZ+15)) != (char *)NULL) `7B
  1328. X        sprintf(prompt, "%s password: ", filename);
  1329. X        m = prompt;
  1330. X    `7D else
  1331. X        m = "Enter password: ";
  1332. X
  1333. X    /* try a few keys */
  1334. X    for (r = 0;  r < 3;  ++r) `7B
  1335. X        m = getp(m, key, PWLEN+1);
  1336. X        if (prompt != (char *)NULL) `7B
  1337. X            free(prompt);
  1338. X            prompt = (char *)NULL;
  1339. X        `7D
  1340. X        if (m == (char *)NULL)
  1341. X            return 10;
  1342. X        if (!testp(h))
  1343. X            return 0;
  1344. X        if (*key == '\0') `7B
  1345. X            nopwd = TRUE;
  1346. X            return 1;
  1347. X        `7D
  1348. X        m = "password incorrect--reenter: ";
  1349. X    `7D
  1350. X    return 1;
  1351. X`7D
  1352. X
  1353. X
  1354. X
  1355. X
  1356. X
  1357. X/**********************/
  1358. X/*  Function testp()  */
  1359. X/**********************/
  1360. X
  1361. Xstatic int testp(h)   /* return -1 if bad password; 0 if OK */
  1362. X    byte *h;
  1363. X`7B
  1364. X    UWORD b, c;
  1365. X    int n, t;
  1366. X    byte *p;
  1367. X
  1368. X    /* set keys */
  1369. X    init_keys(key);
  1370. X
  1371. X    /* check password */
  1372. X    for (n = 0; n < 11; n++)
  1373. X        c = DECRYPT(h`5Bn`5D);
  1374. X    b = DECRYPT(h`5B11`5D);
  1375. X
  1376. X#ifdef CRYPT_DEBUG
  1377. X    printf("   lrec.crc = %08lx  crec.crc = %08lx  pInfo->ExtLocHdr = %s\n",
  1378. X      lrec.crc32, pInfo->crc, pInfo->ExtLocHdr? "true":"false");
  1379. X    printf("   incnt = %d  unzip offset into zipfile = %ld\n", incnt,
  1380. X      cur_zipfile_bufstart+(inptr-inbuf));
  1381. X    printf("   (c `7C (b<<8)) = %04x  (crc >> 16) = %04x  lrec.time = %04x\n
  1382. V",
  1383. X      (UWORD)(c `7C (b<<8)), (UWORD)(lrec.crc32 >> 16), lrec.last_mod_file_t
  1384. Vime);
  1385. X#endif /* CRYPT_DEBUG */
  1386. X
  1387. +-+-+-+-+-+-+-+-  END  OF PART 2 +-+-+-+-+-+-+-+-
  1388.