home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / sources / misc / 3855 < prev    next >
Encoding:
Text File  |  1992-08-23  |  58.3 KB  |  1,540 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: zip-bugs@cs.ucla.edu (Info-ZIP group)
  4. Subject:  v31i105:  unzip50 - Info-ZIP portable UnZip, version 5.0, Part02/14
  5. Message-ID: <1992Aug24.025225.24144@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 67455a16af9b9121c5ef733b92dfe9e3
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v31i104=unzip50.215137@sparky.IMD.Sterling.COM>
  11. Date: Mon, 24 Aug 1992 02:52:25 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 1525
  14.  
  15. Submitted-by: zip-bugs@cs.ucla.edu (Info-ZIP group)
  16. Posting-number: Volume 31, Issue 105
  17. Archive-name: unzip50/part02
  18. Supersedes: unzip: Volume 29, Issue 31-42
  19. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT AMIGA?, !ATARI, symlink, SGI, DEC, Cray, Convex, Amdahl, Sun
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then feed it
  23. # into a shell via "sh file" or similar.  To overwrite existing files,
  24. # type "sh file -c".
  25. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  26. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  27. # Contents:  MAC/aztec.make.UU extract.c mapname.c
  28. # Wrapped by kent@sparky on Sun Aug 23 21:09:31 1992
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. echo If this archive is complete, you will see the following message:
  31. echo '          "shar: End of archive 2 (of 14)."'
  32. if test -f 'MAC/aztec.make.UU' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'MAC/aztec.make.UU'\"
  34. else
  35.   echo shar: Extracting \"'MAC/aztec.make.UU'\" \(1805 characters\)
  36.   sed "s/^X//" >'MAC/aztec.make.UU' <<'END_OF_FILE'
  37. Xbegin 666 MAC/aztec.make
  38. XM(R @(%1H:7,@35!7(&UA:V5F:6QE(&ES(&1E<VEG;F5D('1O(&)E('5S960@
  39. XM=&\@8V]M<&EL92!A;B!-4%<@=F5R<VEO;@HC(" @;V8@=6YZ:7 @=7-I;F<@
  40. XM=&AE($%Z=&5C($,@8V]M<&EL97(L('9E<G-I;VX@-2XR82X@4VEM<&QY(')E
  41. XM;F%M90HC(" @=&AI<R!F:6QE(&%S('5N>FEP+FUA:V4@86YD(&1O(&%N($U0
  42. XM5R!B=6EL9"X*"@HC(" @1FEL93H@(" @(" @=6YZ:7 N;6%K90HC(" @5&%R
  43. XM9V5T.B @(" @56YZ:7 *(R @(%-O=7)C97,Z(" @('5N>FEP+F,*(R @(" @
  44. XM(" @(" @(" @(&-R>7!T+F,*(R @(" @(" @(" @(" @(&5N=F%R9W,N8PHC
  45. XM(" @(" @(" @(" @(" @97AP;&]D92YC"B,@(" @(" @(" @(" @("!E>'1R
  46. XM86-T+F,*(R @(" @(" @(" @(" @(&9I;&5?:6\N8PHC(" @(" @(" @(" @
  47. XM(" @:6YF;&%T92YC"B,@(" @(" @(" @(" @("!M86-F:6QE+F,*(R @(" @
  48. XM(" @(" @(" @(&UA8W-T870N8PHC(" @(" @(" @(" @(" @;6%P;F%M92YC
  49. XM"B,@(" @(" @(" @(" @("!M871C:"YC"B,@(" @(" @(" @(" @("!M:7-C
  50. XM+F,*(R @(" @(" @(" @(" @('5N<F5D=6-E+F,*(R @(" @(" @(" @(" @
  51. XM('5N<VAR:6YK+F,*(R @($-R96%T960Z(" @(%1U97-D87DL($UA>2 U+" Q
  52. XM.3DR(#<Z,#4Z,# @4$T*"@I#1DQ!1U,@/2 M9"!-4%<@(R M9"!#4EE05 H*
  53. XM3$9,04=3(#T@+6T*"@HN;R#$("YC('5N>FEP+F@@=6YZ:7 N;6%K90H@(" @
  54. XM(" @($,@>T-&3$%'4WT@+6\@>T1E9F%U;'1]+F\@>T1E9F%U;'1]+F,*"BYO
  55. XM(,0@+F%S;0H@(" @(" @(&%S("UO('M$969A=6QT?2YO('M$969A=6QT?2YA
  56. XM<VT*"D]"2D5#5%,@/2"V"B @(" @(" @=6YZ:7 N;R"V"B,@(" @(" @8W)Y
  57. XM<'0N;R"V"B @(" @(" @96YV87)G<RYO(+8*(" @(" @("!E>'!L;V1E+F\@
  58. XMM@H@(" @(" @(&5X=')A8W0N;R"V"B @(" @(" @9FEL95]I;RYO(+8*(" @
  59. XM(" @("!I;F9L871E+F\@M@H@(" @(" @(&UA8V9I;&4N;R"V"B @(" @(" @
  60. XM;6%C<W1A="YO(+8*(" @(" @("!M87!N86UE+F\@M@H@(" @(" @(&UA=&-H
  61. XM+F\@M@H@(" @(" @(&UI<V,N;R"V"B @(" @(" @=6YR961U8V4N;R"V"B @
  62. XM(" @(" @=6YS:')I;FLN;PH*56YZ:7 @Q"![3T)*14-44WT@=6YZ:7 N<@H@
  63. XM(" @(" @(&QN('M,1DQ!1U-]("UO(%5N>FEP('M/0DI%0U13?2 M;&T@+6QM
  64. XM<'<@+6QC"B @(" @(" @<F5Z("UA<'!E;F0@+6\@56YZ:7 @=6YZ:7 N<@H*
  65. XM=6YZ:7 N<B#$('5N>FEP+G1H:6YK8RYR<W)C"B @(" @(" @9&5R97H@=6YZ
  66. X9:7 N=&AI;FMC+G)S<F,@/B!U;GII<"YR"G)C
  67. Xend
  68. END_OF_FILE
  69.  if test 1805 -ne `wc -c <'MAC/aztec.make.UU'`; then
  70.     echo shar: \"'MAC/aztec.make.UU'\" unpacked with wrong size!
  71.   else
  72.     echo shar: Uudecoding \"'MAC/aztec.make'\" \(1285 characters\)
  73.     cat MAC/aztec.make.UU | uudecode
  74.     if test 1285 -ne `wc -c <'MAC/aztec.make'`; then
  75.       echo shar: \"'MAC/aztec.make'\" uudecoded with wrong size!
  76.     else
  77.       rm MAC/aztec.make.UU
  78.     fi
  79.   fi
  80.   # end of 'MAC/aztec.make.UU'
  81. fi
  82. if test -f 'extract.c' -a "${1}" != "-c" ; then 
  83.   echo shar: Will not clobber existing file \"'extract.c'\"
  84. else
  85.   echo shar: Extracting \"'extract.c'\" \(37529 characters\)
  86.   sed "s/^X//" >'extract.c' <<'END_OF_FILE'
  87. X/*---------------------------------------------------------------------------
  88. X
  89. X  extract.c
  90. X
  91. X  This file contains the high-level routines ("driver routines") for extrac-
  92. X  ting and testing zipfile members.  It calls the low-level routines in files
  93. X  inflate.c, unimplod.c, unreduce.c and unshrink.c.
  94. X
  95. X  ---------------------------------------------------------------------------*/
  96. X
  97. X
  98. X#include "unzip.h"
  99. X#ifdef  MSWIN
  100. X#  include "wizunzip.h"
  101. X#  include "replace.h"
  102. X#endif /* MSWIN */
  103. X
  104. X
  105. X/************************************/
  106. X/*  Extract Local Prototypes, etc.  */
  107. X/************************************/
  108. X
  109. Xstatic int store_info __((void));
  110. Xstatic int extract_or_test_member __((void));
  111. X#ifdef CRYPT
  112. X   static int decrypt_member __((void));
  113. X   static int testp __((byte *hdr));
  114. X#endif
  115. X
  116. Xstatic byte *mem_i_buffer;
  117. Xstatic byte *mem_o_buffer;
  118. Xstatic ULONG mem_i_size, mem_i_offset;
  119. Xstatic ULONG mem_o_size, mem_o_offset;
  120. X
  121. Xstatic char *VersionMsg =
  122. X  " skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
  123. Xstatic char *ComprMsg =
  124. X  " skipping: %-22s  compression method %d\n";
  125. Xstatic char *FilNamMsg =
  126. X  "%s:  bad filename length (%s)\n";
  127. Xstatic char *ExtFieldMsg =
  128. X  "%s:  bad extra field length (%s)\n";
  129. Xstatic char *OffsetMsg =
  130. X  "file #%d:  bad zipfile offset (%s)\n";
  131. X
  132. X
  133. X
  134. X
  135. X
  136. X/**************************************/
  137. X/*  Function extract_or_test_files()  */
  138. X/**************************************/
  139. X
  140. Xint extract_or_test_files()    /* return PK-type error code */
  141. X{
  142. X    char **fnamev;
  143. X    byte *cd_inptr;
  144. X    int cd_incnt, error, error_in_archive=0;
  145. X    int renamed, query, len, filnum=(-1), blknum=0;
  146. X#ifdef OS2
  147. X    extern int longname;  /* from os2unzip.c */
  148. X#endif
  149. X    UWORD i, j, members_remaining, num_skipped=0, num_bad_pwd=0;
  150. X    longint cd_bufstart, bufstart, inbuf_offset, request;
  151. X    min_info info[DIR_BLKSIZ];
  152. X
  153. X
  154. X/*---------------------------------------------------------------------------
  155. X    The basic idea of this function is as follows.  Since the central di-
  156. X    rectory lies at the end of the zipfile and the member files lie at the
  157. X    beginning or middle or wherever, it is not very desirable to simply
  158. X    read a central directory entry, jump to the member and extract it, and
  159. X    then jump back to the central directory.  In the case of a large zipfile
  160. X    this would lead to a whole lot of disk-grinding, especially if each mem-
  161. X    ber file is small.  Instead, we read from the central directory the per-
  162. X    tinent information for a block of files, then go extract/test the whole
  163. X    block.  Thus this routine contains two small(er) loops within a very
  164. X    large outer loop:  the first of the small ones reads a block of files
  165. X    from the central directory; the second extracts or tests each file; and
  166. X    the outer one loops over blocks.  There's some file-pointer positioning
  167. X    stuff in between, but that's about it.  Btw, it's because of this jump-
  168. X    ing around that we can afford to be lenient if an error occurs in one of
  169. X    the member files:  we should still be able to go find the other members,
  170. X    since we know the offset of each from the beginning of the zipfile.
  171. X
  172. X    Begin main loop over blocks of member files.  We know the entire central
  173. X    directory is on this disk:  we would not have any of this information un-
  174. X    less the end-of-central-directory record was on this disk, and we would
  175. X    not have gotten to this routine unless this is also the disk on which
  176. X    the central directory starts.  In practice, this had better be the ONLY
  177. X    disk in the archive, but maybe someday we'll add multi-disk support.
  178. X  ---------------------------------------------------------------------------*/
  179. X
  180. X    pInfo = info;
  181. X    members_remaining = ecrec.total_entries_central_dir;
  182. X
  183. X    while (members_remaining) {
  184. X        j = 0;
  185. X
  186. X        /*
  187. X         * Loop through files in central directory, storing offsets, file
  188. X         * attributes, and case-conversion flags until block size is reached.
  189. X         */
  190. X
  191. X        while (members_remaining && (j < DIR_BLKSIZ)) {
  192. X            --members_remaining;
  193. X            pInfo = &info[j];
  194. X
  195. X            if (readbuf(sig, 4) <= 0) {
  196. X                error_in_archive = 51;  /* 51:  unexpected EOF */
  197. X                members_remaining = 0;  /* ...so no more left to do */
  198. X                break;
  199. X            }
  200. X            if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
  201. X                fprintf(stderr, CentSigMsg, j);  /* sig not found */
  202. X                fprintf(stderr, ReportMsg);   /* check binary transfers */
  203. X                error_in_archive = 3;   /* 3:  error in zipfile */
  204. X                members_remaining = 0;  /* ...so no more left to do */
  205. X                break;
  206. X            }
  207. X            /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
  208. X            if ((error = process_cdir_file_hdr()) != 0) {
  209. X                error_in_archive = error;   /* only 51 (EOF) defined */
  210. X                members_remaining = 0;  /* ...so no more left to do */
  211. X                break;
  212. X            }
  213. X            if ((error = do_string(crec.filename_length, FILENAME)) != 0) {
  214. X                if (error > error_in_archive)
  215. X                    error_in_archive = error;
  216. X                if (error > 1) {  /* fatal:  no more left to do */
  217. X                    fprintf(stderr, FilNamMsg, filename, "central");
  218. X                    members_remaining = 0;
  219. X                    break;
  220. X                }
  221. X            }
  222. X            if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0)
  223. X            {
  224. X                if (error > error_in_archive)
  225. X                    error_in_archive = error;
  226. X                if (error > 1) {  /* fatal */
  227. X                    fprintf(stderr, ExtFieldMsg, filename, "central");
  228. X                    members_remaining = 0;
  229. X                    break;
  230. X                }
  231. X            }
  232. X            if ((error = do_string(crec.file_comment_length, SKIP)) != 0) {
  233. X                if (error > error_in_archive)
  234. X                    error_in_archive = error;
  235. X                if (error > 1) {  /* fatal */
  236. X                    fprintf(stderr, "\n%s:  bad file comment length\n",
  237. X                            filename);
  238. X                    members_remaining = 0;
  239. X                    break;
  240. X                }
  241. X            }
  242. X            if (process_all_files) {
  243. X                if (store_info())
  244. X                    ++num_skipped;
  245. X                else
  246. X                    ++j;  /* file is OK: save info[] and continue with next */
  247. X            } else {
  248. X                fnamev = fnv;   /* don't destroy permanent filename pointer */
  249. X                for (--fnamev; *++fnamev;)
  250. X                    if (match(filename, *fnamev)) {
  251. X                        if (store_info())
  252. X                            ++num_skipped;
  253. X                        else
  254. X                            ++j;   /* file is OK */
  255. X                        break;  /* found match for filename, so stop looping */
  256. X                    } /* end if (match), for-loop (fnamev) */
  257. X            } /* end if (process_all_files) */
  258. X
  259. X        } /* end while-loop (adding files to current block) */
  260. X
  261. X        /* save position in central directory so can come back later */
  262. X        cd_bufstart = cur_zipfile_bufstart;
  263. X        cd_inptr = inptr;
  264. X        cd_incnt = incnt;
  265. X
  266. X    /*-----------------------------------------------------------------------
  267. X        Second loop:  process files in current block, extracting or testing
  268. X        each one.
  269. X      -----------------------------------------------------------------------*/
  270. X
  271. X        for (i = 0; i < j; ++i) {
  272. X            filnum = i + blknum*DIR_BLKSIZ;
  273. X            pInfo = &info[i];
  274. X            /*
  275. X             * if the target position is not within the current input buffer
  276. X             * (either haven't yet read far enough, or (maybe) skipping back-
  277. X             * ward) skip to the target position and reset readbuf().
  278. X             */
  279. X            /* LSEEK(pInfo->offset):  */
  280. X            request = pInfo->offset + extra_bytes;
  281. X            inbuf_offset = request % INBUFSIZ;
  282. X            bufstart = request - inbuf_offset;
  283. X
  284. X            if (request < 0) {
  285. X                fprintf(stderr, SeekMsg, ReportMsg);
  286. X                error_in_archive = 3;       /* 3:  severe error in zipfile, */
  287. X                continue;                   /*  but can still go on */
  288. X            } else if (bufstart != cur_zipfile_bufstart) {
  289. X                cur_zipfile_bufstart = lseek(zipfd, bufstart, SEEK_SET);
  290. X                if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) <= 0) {
  291. X                    fprintf(stderr, OffsetMsg, filnum, "lseek");
  292. X                    error_in_archive = 3;   /* 3:  error in zipfile, but */
  293. X                    continue;               /*  can still do next file   */
  294. X                }
  295. X                inptr = inbuf + (int)inbuf_offset;
  296. X                incnt -= (int)inbuf_offset;
  297. X            } else {
  298. X                incnt += (inptr-inbuf) - (int)inbuf_offset;
  299. X                inptr = inbuf + (int)inbuf_offset;
  300. X            }
  301. X
  302. X            /* should be in proper position now, so check for sig */
  303. X            if (readbuf(sig, 4) <= 0) {  /* bad offset */
  304. X                fprintf(stderr, OffsetMsg, filnum, "EOF");
  305. X                error_in_archive = 3;    /* 3:  error in zipfile */
  306. X                continue;       /* but can still try next one */
  307. X            }
  308. X            if (strncmp(sig, local_hdr_sig, 4)) {
  309. X                fprintf(stderr, OffsetMsg, filnum,
  310. X                        "can't find local header sig");   /* bad offset */
  311. X                error_in_archive = 3;
  312. X                continue;
  313. X            }
  314. X            if ((error = process_local_file_hdr()) != 0) {
  315. X                fprintf(stderr, "\nfile #%d:  bad local header\n", filnum);
  316. X                error_in_archive = error;       /* only 51 (EOF) defined */
  317. X                continue;       /* can still try next one */
  318. X            }
  319. X            if ((error = do_string(lrec.filename_length, FILENAME)) != 0) {
  320. X                if (error > error_in_archive)
  321. X                    error_in_archive = error;
  322. X                if (error > 1) {
  323. X                    fprintf(stderr, FilNamMsg, filename, "local");
  324. X                    continue;   /* go on to next one */
  325. X                }
  326. X            }
  327. X            if (extra_field != (byte *)NULL)
  328. X                free(extra_field);
  329. X            extra_field = (byte *)NULL;
  330. X            if ((error = do_string(lrec.extra_field_length, EXTRA_FIELD)) != 0)
  331. X            {
  332. X                if (error > error_in_archive)
  333. X                    error_in_archive = error;
  334. X                if (error > 1) {
  335. X                    fprintf(stderr, ExtFieldMsg, filename, "local");
  336. X                    continue;   /* go on */
  337. X                }
  338. X            }
  339. X
  340. X            /*
  341. X             * just about to extract file:  if extracting to disk, check if
  342. X             * already exists, and if so, take appropriate action according to
  343. X             * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  344. X             * loop because we don't store the possibly renamed filename[] in
  345. X             * info[])
  346. X             */
  347. X            if (!tflag && !cflag) {
  348. X                renamed = FALSE;   /* user hasn't renamed output file yet */
  349. X#ifdef OS2
  350. X                longname = FALSE;  /* no long name has yet been stored */
  351. X#endif
  352. X
  353. Xstartover:
  354. X                query = FALSE;
  355. X#ifdef MACOS
  356. X                macflag = (pInfo->hostnum == MAC_);
  357. X#endif
  358. X                /* mapname can create dirs if not freshening or if renamed */
  359. X                if ((error = mapname(!fflag || renamed)) > 1) {    /* skip */
  360. X                    if ((error > 2) && (error_in_archive < 2))
  361. X                        error_in_archive = 2;   /* (weak) error in zipfile */
  362. X                    continue;   /* go on to next file */
  363. X                }
  364. X
  365. X                switch (check_for_newer(filename)) {
  366. X                    case DOES_NOT_EXIST:
  367. X                        if (fflag && !renamed)  /* don't skip if just renamed */
  368. X                            continue;   /* freshen (no new files):  skip */
  369. X                        break;
  370. X                    case EXISTS_AND_OLDER:
  371. X                        if (overwrite_none)
  372. X                            continue;   /* never overwrite:  skip file */
  373. X                        if (!overwrite_all && !force_flag)
  374. X                            query = TRUE;
  375. X                        break;
  376. X                    case EXISTS_AND_NEWER:             /* (or equal) */
  377. X                        if (overwrite_none || (uflag && !renamed))
  378. X                            continue;  /* skip if update/freshen & orig name */
  379. X                        if (!overwrite_all && !force_flag)
  380. X                            query = TRUE;
  381. X                        break;
  382. X                }
  383. X/*#ifndef VMS*/ /* VMS creates higher version number instead of overwriting
  384. X                 * (will have to modify for VMS-style names with specific
  385. X                 *  version numbers:  just check V_flag?  don't use stat?) */
  386. X                if (query) {
  387. X#ifdef MSWIN
  388. X                    FARPROC lpfnprocReplace;
  389. X                    int ReplaceDlgRetVal;   /* replace dialog return value */
  390. X
  391. X                    ShowCursor(FALSE);      /* turn off cursor */
  392. X                    SetCursor(hSaveCursor); /* restore the cursor */
  393. X                    lpfnprocReplace = MakeProcInstance(ReplaceProc, hInst);
  394. X                    ReplaceDlgRetVal = DialogBoxParam(hInst, "Replace",
  395. X                      hWndMain, lpfnprocReplace, (DWORD)(LPSTR)filename);
  396. X                    FreeProcInstance(lpfnprocReplace);
  397. X                    hSaveCursor = SetCursor(hHourGlass);
  398. X                    ShowCursor(TRUE);
  399. X                    switch (ReplaceDlgRetVal) {
  400. X                        case IDM_REPLACE_RENAME:
  401. X                            renamed = TRUE;
  402. X                            goto startover;   /* sorry for a goto */
  403. X                        case IDM_REPLACE_YES:
  404. X                            break;
  405. X                        case IDM_REPLACE_ALL:
  406. X                            overwrite_all = TRUE;
  407. X                            overwrite_none = FALSE;  /* just to make sure */
  408. X                            break;
  409. X                        case IDM_REPLACE_NONE:
  410. X                            overwrite_none = TRUE;
  411. X                            overwrite_all = FALSE;  /* make sure */
  412. X                            force_flag = FALSE;     /* ditto */
  413. X                            /* FALL THROUGH, skip */
  414. X                        case IDM_REPLACE_NO:
  415. X                            continue;
  416. X                    }
  417. X#else /* !MSWIN */
  418. Xreprompt:
  419. X                    fprintf(stderr,
  420. X                      "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ",
  421. X                      filename);
  422. X                    FFLUSH   /* for Amiga and Mac MPW */
  423. X                    fgets(answerbuf, 9, stdin);
  424. X                    switch (*answerbuf) {
  425. X                        case 'A':   /* dangerous option:  force caps */
  426. X                            overwrite_all = TRUE;
  427. X                            overwrite_none = FALSE;  /* just to make sure */
  428. X                            break;
  429. X                        case 'r':
  430. X                        case 'R':
  431. X                            do {
  432. X                                fprintf(stderr, "new name: ");
  433. X                                FFLUSH   /* for AMIGA and Mac MPW */
  434. X                                fgets(filename, FILNAMSIZ, stdin);
  435. X                                /* usually get \n here:  better check for it */
  436. X                                len = strlen(filename);
  437. X                                if (filename[len-1] == '\n')
  438. X                                    filename[--len] = 0;
  439. X                            } while (len == 0);
  440. X                            renamed = TRUE;
  441. X                            goto startover;   /* sorry for a goto */
  442. X                        case 'y':
  443. X                        case 'Y':
  444. X                            break;
  445. X                        case 'N':
  446. X                            overwrite_none = TRUE;
  447. X                            overwrite_all = FALSE;  /* make sure */
  448. X                            force_flag = FALSE;     /* ditto */
  449. X                            /* FALL THROUGH, skip */
  450. X                        case 'n':
  451. X                            continue;   /* skip file */
  452. X                        default:
  453. X                            fprintf(stderr, "error:  invalid response [%c]\n",
  454. X                              *answerbuf);   /* warn the user */
  455. X                            goto reprompt;   /* why not another goto? */
  456. X                    } /* end switch (*answerbuf) */
  457. X#endif /* ?MSWIN */
  458. X                } /* end if (query) */
  459. X/*#endif*/ /* !VMS */
  460. X            } /* end if (extracting to disk) */
  461. X
  462. X#ifdef CRYPT
  463. X            if (pInfo->encrypted && ((error = decrypt_member()) != 0)) {
  464. X                if (error == 10) {
  465. X                    if (error > error_in_archive)
  466. X                        error_in_archive = error;
  467. X                    fprintf(stderr,
  468. X                      " skipping: %-22s  unable to get password\n", filename);
  469. X                } else {  /* (error == 1) */
  470. X                    fprintf(stderr,
  471. X                      " skipping: %-22s  incorrect password\n", filename);
  472. X                    ++num_bad_pwd;
  473. X                }
  474. X                continue;   /* go on to next file */
  475. X            }
  476. X#endif /* CRYPT */
  477. X            disk_full = 0;
  478. X            if ((error = extract_or_test_member()) != 0) {
  479. X                if (error > error_in_archive)
  480. X                    error_in_archive = error;       /* ...and keep going */
  481. X                if (disk_full > 1)
  482. X                    return error_in_archive;        /* (unless disk full) */
  483. X            }
  484. X        } /* end for-loop (i:  files in current block) */
  485. X
  486. X
  487. X        /*
  488. X         * Jump back to where we were in the central directory, then go and do
  489. X         * the next batch of files.
  490. X         */
  491. X
  492. X        cur_zipfile_bufstart = lseek(zipfd, cd_bufstart, SEEK_SET);
  493. X        read(zipfd, (char *)inbuf, INBUFSIZ);  /* were there b4 ==> no error */
  494. X        inptr = cd_inptr;
  495. X        incnt = cd_incnt;
  496. X        ++blknum;
  497. X
  498. X#ifdef TEST
  499. X        printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
  500. X        printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
  501. X          cur_zipfile_bufstart);
  502. X        printf("inptr-inbuf = %d\n", inptr-inbuf);
  503. X        printf("incnt = %d\n\n", incnt);
  504. X#endif
  505. X
  506. X    } /* end while-loop (blocks of files in central directory) */
  507. X
  508. X/*---------------------------------------------------------------------------
  509. X    Double-check that we're back at the end-of-central-directory record, and
  510. X    print quick summary of results, if we were just testing the archive.  We
  511. X    send the summary to stdout so that people doing the testing in the back-
  512. X    ground and redirecting to a file can just do a "tail" on the output file.
  513. X  ---------------------------------------------------------------------------*/
  514. X
  515. X    readbuf(sig, 4);
  516. X    if (strncmp(sig, end_central_sig, 4)) {     /* just to make sure again */
  517. X        fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig */
  518. X        fprintf(stderr, ReportMsg);  /* check binary transfers */
  519. X        if (!error_in_archive)       /* don't overwrite stronger error */
  520. X            error_in_archive = 1;    /* 1:  warning error */
  521. X    }
  522. X    if (tflag && (quietflg == 1)) {
  523. X        int num=filnum+1 - num_bad_pwd;
  524. X
  525. X        if (error_in_archive)
  526. X            printf("At least one error was detected in %s.\n", zipfn);
  527. X        else if (num == 0)
  528. X            printf("Caution:  zero files tested in %s.\n", zipfn);
  529. X        else if (process_all_files && (num_skipped+num_bad_pwd == 0))
  530. X            printf("No errors detected in %s.\n", zipfn);
  531. X        else
  532. X            printf("No errors detected in %s for the %d file%s tested.\n",
  533. X              zipfn, num, (num==1)? "":"s");
  534. X        if (num_skipped > 0)
  535. X            printf("%d file%s skipped because of unsupported compression or\
  536. X encoding.\n",
  537. X              num_skipped, (num_skipped==1)? "":"s");
  538. X#ifdef CRYPT
  539. X        if (num_bad_pwd > 0)
  540. X            printf("%d file%s skipped because of incorrect password.\n",
  541. X              num_bad_pwd, (num_bad_pwd==1)? "":"s");
  542. X#endif /* CRYPT */
  543. X    }
  544. X    if ((num_skipped > 0) && !error_in_archive)   /* files not tested or  */
  545. X        error_in_archive = 1;                     /*  extracted:  warning */
  546. X#ifdef CRYPT
  547. X    if ((num_bad_pwd > 0) && !error_in_archive)   /* files not tested or  */
  548. X        error_in_archive = 1;                     /*  extracted:  warning */
  549. X#endif /* CRYPT */
  550. X
  551. X    return (error_in_archive);
  552. X
  553. X} /* end function extract_or_test_files() */
  554. X
  555. X
  556. X
  557. X
  558. X
  559. X/***************************/
  560. X/*  Function store_info()  */
  561. X/***************************/
  562. X
  563. Xstatic int store_info()   /* return 1 if skipping, 0 if OK */
  564. X{
  565. X    ULONG tmp;
  566. X
  567. X#define UNKN_COMPR \
  568. X   (crec.compression_method>IMPLODED && crec.compression_method!=DEFLATED)
  569. X#if 0  /* old */
  570. X#  define UNKN_COMPR   (crec.compression_method>IMPLODED)
  571. X#endif
  572. X
  573. X
  574. X/*---------------------------------------------------------------------------
  575. X    Check central directory info for version/compatibility requirements.
  576. X  ---------------------------------------------------------------------------*/
  577. X
  578. X    pInfo->encrypted = crec.general_purpose_bit_flag & 1;    /* bit field */
  579. X    pInfo->ExtLocHdr = (crec.general_purpose_bit_flag & 8) == 8;  /* bit */
  580. X    pInfo->text = crec.internal_file_attributes & 1;         /* bit field */
  581. X    pInfo->crc = crec.crc32;
  582. X    pInfo->compr_size = crec.compressed_size;
  583. X
  584. X    if (crec.version_needed_to_extract[1] == VMS_) {
  585. X        if (crec.version_needed_to_extract[0] > VMS_VERSION) {
  586. X            fprintf(stderr, VersionMsg, filename, "VMS",
  587. X              crec.version_needed_to_extract[0] / 10,
  588. X              crec.version_needed_to_extract[0] % 10,
  589. X              VMS_VERSION / 10, VMS_VERSION % 10);
  590. X            return 1;
  591. X        }
  592. X#ifndef VMS   /* won't be able to use extra field, but still have data */
  593. X        else if (!tflag && !force_flag) {  /* if forcing, extract regardless */
  594. X            fprintf(stderr,
  595. X              "\n%s:  stored in VMS format.  Extract anyway? (y/n) ",
  596. X              filename);
  597. X            FFLUSH   /* for Amiga and Mac MPW */
  598. X            fgets(answerbuf, 9, stdin);
  599. X            if ((*answerbuf != 'y') && (*answerbuf != 'Y'))
  600. X                return 1;
  601. X        }
  602. X#endif /* !VMS */
  603. X    /* usual file type:  don't need VMS to extract */
  604. X    } else if (crec.version_needed_to_extract[0] > UNZIP_VERSION) {
  605. X        fprintf(stderr, VersionMsg, filename, "PK",
  606. X          crec.version_needed_to_extract[0] / 10,
  607. X          crec.version_needed_to_extract[0] % 10,
  608. X          UNZIP_VERSION / 10, UNZIP_VERSION % 10);
  609. X        return 1;
  610. X    }
  611. X
  612. X    if UNKN_COMPR {
  613. X        fprintf(stderr, ComprMsg, filename, crec.compression_method);
  614. X        return 1;
  615. X    }
  616. X#ifndef CRYPT
  617. X    if (pInfo->encrypted) {
  618. X        fprintf(stderr, " skipping: %-22s  encrypted (not supported)\n",
  619. X          filename);
  620. X        return 1;
  621. X    }
  622. X#endif /* !CRYPT */
  623. X
  624. X/*---------------------------------------------------------------------------
  625. X    Store some central-directory information (encryption, file attributes,
  626. X    offsets) for later use.
  627. X  ---------------------------------------------------------------------------*/
  628. X
  629. X    tmp = crec.external_file_attributes;
  630. X
  631. X    pInfo->dos_attr = 32;   /* set archive bit:  file is not backed up */
  632. X    switch (pInfo->hostnum) {
  633. X        case UNIX_:
  634. X        case VMS_:
  635. X            pInfo->unix_attr = (unsigned) (tmp >> 16);
  636. X            break;
  637. X        case DOS_OS2_FAT_:
  638. X        case OS2_HPFS_:
  639. X            pInfo->dos_attr = (unsigned) tmp;
  640. X            tmp = (!(tmp & 1)) << 1;   /* read-only bit */
  641. X            pInfo->unix_attr = (unsigned) (0444 | (tmp<<6) | (tmp<<3) | tmp);
  642. X#ifdef UNIX
  643. X            umask( (int)(tmp=umask(0)) );
  644. X            pInfo->unix_attr &= ~tmp;
  645. X#endif
  646. X            break;
  647. X        case MAC_:
  648. X            pInfo->unix_attr = (unsigned) (tmp & 1);   /* read-only bit */
  649. X            break;
  650. X        default:
  651. X            pInfo->unix_attr = 0666;
  652. X            break;
  653. X    } /* end switch (host-OS-created-by) */
  654. X
  655. X    pInfo->offset = (longint) crec.relative_offset_local_header;
  656. X    return 0;
  657. X
  658. X} /* end function store_info() */
  659. X
  660. X
  661. X
  662. X
  663. X
  664. X/***************************************/
  665. X/*  Function extract_or_test_member()  */
  666. X/***************************************/
  667. X
  668. Xstatic int extract_or_test_member()    /* return PK-type error code */
  669. X{
  670. X#ifdef S_IFLNK
  671. X    int symlnk=FALSE;
  672. X#endif /* S_IFLNK */
  673. X    int error=0;
  674. X    UWORD b;
  675. X
  676. X
  677. X
  678. X/*---------------------------------------------------------------------------
  679. X    Initialize variables, buffers, etc.
  680. X  ---------------------------------------------------------------------------*/
  681. X
  682. X    bits_left = 0;
  683. X    bitbuf = 0L;
  684. X    outpos = 0L;
  685. X    outcnt = 0;
  686. X    outptr = outbuf;
  687. X    zipeof = 0;
  688. X    crc32val = 0xFFFFFFFFL;
  689. X
  690. X#ifdef S_IFLNK
  691. X    if ((pInfo->unix_attr & S_IFMT) == S_IFLNK  &&  (pInfo->hostnum == UNIX_)
  692. X        && !tflag && !cflag)
  693. X        symlnk = TRUE;
  694. X#endif /* S_IFLNK */
  695. X
  696. X    memset(outbuf, 0xaa, OUTBUFSIZ);
  697. X#if (!defined(DOS_OS2) || defined(MSWIN))
  698. X    if (aflag)                  /* if we have a scratchpad, clear it out */
  699. X#ifdef MSWIN
  700. X        _fmemset(outout, 0xaa, OUTBUFSIZ);
  701. X#else /* !MSWIN */
  702. X        memset(outout, 0xaa, OUTBUFSIZ);
  703. X#endif /* ?MSWIN */
  704. X#endif /* !DOS_OS2 || MSWIN */
  705. X
  706. X    if (tflag) {
  707. X        if (!quietflg) {
  708. X            fprintf(stdout, "  Testing: %-22s ", filename);
  709. X            fflush(stdout);
  710. X        }
  711. X    } else {
  712. X        if (cflag) {            /* output to stdout (copy of it) */
  713. X#if (defined(MACOS) || defined(AMIGA))
  714. X            outfd = 1;
  715. X#else /* !(MACOS || AMIGA) */
  716. X            outfd = dup(1);     /* GRR: change this to #define for Mac/Amiga */
  717. X#endif /* ?(MACOS || AMIGA) */
  718. X#ifdef DOS_OS2
  719. X            if (!aflag)
  720. X                setmode(outfd, O_BINARY);
  721. X#endif /* DOS_OS2 */
  722. X#ifdef VMS
  723. X            if (create_output_file())   /* VMS version required for stdout! */
  724. X                return 50;      /* 50:  disk full (?) */
  725. X#endif
  726. X        } else
  727. X#ifdef S_IFLNK
  728. X        if (!symlnk)    /* symlink() takes care of file creation */
  729. X#endif /* !S_IFLNK */
  730. X        {
  731. X            if (create_output_file())
  732. X                return 50;      /* 50:  disk full (?) */
  733. X        }
  734. X    } /* endif (!tflag) */
  735. X
  736. X/*---------------------------------------------------------------------------
  737. X    Unpack the file.
  738. X  ---------------------------------------------------------------------------*/
  739. X
  740. X    switch (lrec.compression_method) {
  741. X
  742. X    case STORED:
  743. X        if (!tflag && (quietflg < 2)) {
  744. X            fprintf(stdout, " Extracting: %-22s ", filename);
  745. X            if (cflag)
  746. X                fprintf(stdout, "\n");
  747. X            fflush(stdout);
  748. X        }
  749. X#ifdef S_IFLNK
  750. X        /*
  751. X         * If file came from Unix and is a symbolic link and we are extracting
  752. X         * to disk, allocate a storage area, put the data in it, and create the
  753. X         * link.  Since we know it's a symbolic link to start with, shouldn't
  754. X         * have to worry about overflowing unsigned ints with unsigned longs.
  755. X         * (This doesn't do anything for compressed symlinks, but that can be
  756. X         * added later...it also doesn't set the time or permissions of the
  757. X         * link, but does anyone really care?)
  758. X         */
  759. X        if (symlnk) {
  760. X#if (defined(MTS) || defined(MACOS))
  761. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  762. X            error = 1;          /* 1:  warning error */
  763. X#else /* !(MTS || MACOS) */
  764. X            char *orig = (char *)malloc((unsigned)lrec.uncompressed_size+1);
  765. X            char *p = orig;
  766. X
  767. X            while (ReadByte(&b))
  768. X                *p++ = b;
  769. X            *p = 0;   /* terminate string */
  770. X            UpdateCRC((unsigned char *)orig, p-orig);
  771. X            if (symlink(orig, filename))
  772. X                if ((errno == EEXIST) && overwrite_all) {  /* OK to overwrite */
  773. X                    unlink(filename);
  774. X                    if (symlink(orig, filename))
  775. X                        perror("symlink error");
  776. X                } else
  777. X                    perror("symlink error");
  778. X            free(orig);
  779. X#endif /* ?(MTS || MACOS) */
  780. X        } else
  781. X#endif /* S_IFLNK */
  782. X        while (ReadByte(&b) && !disk_full)
  783. X            OUTB(b)
  784. X        break;
  785. X
  786. X    case SHRUNK:
  787. X        if (!tflag && (quietflg < 2)) {
  788. X            fprintf(stdout, "UnShrinking: %-22s ", filename);
  789. X            if (cflag)
  790. X                fprintf(stdout, "\n");
  791. X            fflush(stdout);
  792. X        }
  793. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  794. X        if (symlnk) {
  795. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  796. X            error = 1;          /* 1:  warning error */
  797. X        }
  798. X#endif /* S_IFLNK */
  799. X        unShrink();
  800. X        break;
  801. X
  802. X    case REDUCED1:
  803. X    case REDUCED2:
  804. X    case REDUCED3:
  805. X    case REDUCED4:
  806. X        if (!tflag && (quietflg < 2)) {
  807. X            fprintf(stdout, "  Expanding: %-22s ", filename);
  808. X            if (cflag)
  809. X                fprintf(stdout, "\n");
  810. X            fflush(stdout);
  811. X        }
  812. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  813. X        if (symlnk) {
  814. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  815. X            error = 1;          /* 1:  warning error */
  816. X        }
  817. X#endif /* S_IFLNK */
  818. X        unReduce();
  819. X        break;
  820. X
  821. X    case IMPLODED:
  822. X        if (!tflag && (quietflg < 2)) {
  823. X            fprintf(stdout, "  Exploding: %-22s ", filename);
  824. X            if (cflag)
  825. X                fprintf(stdout, "\n");
  826. X            fflush(stdout);
  827. X        }
  828. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  829. X        if (symlnk) {
  830. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  831. X            error = 1;          /* 1:  warning error */
  832. X        }
  833. X#endif /* S_IFLNK */
  834. X        explode();   /* ignore return code for now */
  835. X        break;
  836. X
  837. X    case DEFLATED:
  838. X        if (!tflag && (quietflg < 2)) {
  839. X            fprintf(stdout, "  Inflating: %-22s ", filename);
  840. X            if (cflag)
  841. X                fprintf(stdout, "\n");
  842. X            fflush(stdout);
  843. X        }
  844. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  845. X        if (symlnk) {
  846. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  847. X            error = 1;          /* 1:  warning error */
  848. X        }
  849. X#endif /* S_IFLNK */
  850. X        inflate();
  851. X        break;
  852. X
  853. X    default:   /* should never get to this point */
  854. X        fprintf(stderr, "%s:  unknown compression method\n", filename);
  855. X        /* close and delete file before return? */
  856. X        return 1;               /* 1:  warning error */
  857. X
  858. X    } /* end switch (compression method) */
  859. X
  860. X    if (disk_full) {            /* set by FlushOutput()/OUTB() macro */
  861. X        if (disk_full > 1)
  862. X            return 50;          /* 50:  disk full */
  863. X        error = 1;              /* 1:  warning error */
  864. X    }
  865. X
  866. X/*---------------------------------------------------------------------------
  867. X    Write the last partial buffer, if any; set the file date and time; and
  868. X    close the file (not necessarily in that order).  Then make sure CRC came
  869. X    out OK and print result.
  870. X  ---------------------------------------------------------------------------*/
  871. X
  872. X#ifdef S_IFLNK
  873. X    if (!symlnk) {
  874. X#endif /* S_IFLNK */
  875. X    if (!disk_full && FlushOutput())
  876. X        if (disk_full > 1)
  877. X            return 50;          /* 50:  disk full */
  878. X        else {                  /* disk_full == 1 */
  879. X            fprintf(stderr, "%s:  probably corrupt\n", filename);
  880. X            error = 1;          /* 1:  warning error */
  881. X        }
  882. X
  883. X    if (!tflag)
  884. X#ifdef VMS
  885. X        CloseOutputFile();
  886. X#else /* !VMS */
  887. X#ifdef MTS                      /* MTS can't set file time */
  888. X        close(outfd);
  889. X#else /* !MTS */
  890. X        set_file_time_and_close();
  891. X#endif /* ?MTS */
  892. X#endif /* ?VMS */
  893. X
  894. X#ifdef S_IFLNK
  895. X    } /* endif (!symlnk) */
  896. X#endif /* S_IFLNK */
  897. X
  898. X    /* logical-AND crc32val for 64-bit machines */
  899. X    if ((crc32val = ((~crc32val) & 0xFFFFFFFFL)) != lrec.crc32) {
  900. X        /* if quietflg is set, we haven't output the filename yet:  do it */
  901. X        if (quietflg)
  902. X            printf("%-22s: ", filename);
  903. X        fprintf(stdout, " Bad CRC %08lx  (should be %08lx)\n", crc32val,
  904. X                lrec.crc32);
  905. X        error = 1;              /* 1:  warning error */
  906. X    } else if (tflag) {
  907. X        if (!quietflg)
  908. X            fprintf(stdout, " OK\n");
  909. X    } else {
  910. X        if ((quietflg < 2) && !error)
  911. X            fprintf(stdout, "\n");
  912. X    }
  913. X
  914. X    return error;
  915. X
  916. X}       /* end function extract_or_test_member() */
  917. X
  918. X
  919. X
  920. X
  921. X
  922. X#ifdef CRYPT
  923. X
  924. X/*******************************/
  925. X/*  Function decrypt_member()  */
  926. X/*******************************/
  927. X
  928. Xstatic int decrypt_member()   /* return 10 if out of memory or can't get */
  929. X{                             /*  tty; 1 if password bad; 0 if password OK */
  930. X    UWORD b;
  931. X    int n, r;
  932. X    static int nopwd=FALSE;
  933. X    char *m, *prompt;
  934. X    byte h[12];
  935. X
  936. X
  937. X    /* get header once */
  938. X    for (n = 0; n < 12; n++) {
  939. X        ReadByte(&b);
  940. X        h[n] = (byte) b;
  941. X    }
  942. X
  943. X    /* if have key already, test it; else allocate memory for it */
  944. X    if (key) {
  945. X        if (!testp(h))
  946. X            return 0;      /* existing password OK (else prompt for new) */
  947. X        else if (nopwd)
  948. X            return 1;      /* user indicated no more prompting */
  949. X    } else if ((key = (char *)malloc(PWLEN+1)) == (char *)NULL)
  950. X        return 10;
  951. X
  952. X    if ((prompt = (char *)malloc(FILNAMSIZ+15)) != (char *)NULL) {
  953. X        sprintf(prompt, "%s password: ", filename);
  954. X        m = prompt;
  955. X    } else
  956. X        m = "Enter password: ";
  957. X
  958. X    /* try a few keys */
  959. X    for (r = 0;  r < 3;  ++r) {
  960. X        m = getp(m, key, PWLEN+1);
  961. X        if (prompt != (char *)NULL) {
  962. X            free(prompt);
  963. X            prompt = (char *)NULL;
  964. X        }
  965. X        if (m == (char *)NULL)
  966. X            return 10;
  967. X        if (!testp(h))
  968. X            return 0;
  969. X        if (*key == '\0') {
  970. X            nopwd = TRUE;
  971. X            return 1;
  972. X        }
  973. X        m = "password incorrect--reenter: ";
  974. X    }
  975. X    return 1;
  976. X}
  977. X
  978. X
  979. X
  980. X
  981. X
  982. X/**********************/
  983. X/*  Function testp()  */
  984. X/**********************/
  985. X
  986. Xstatic int testp(h)   /* return -1 if bad password; 0 if OK */
  987. X    byte *h;
  988. X{
  989. X    UWORD b, c;
  990. X    int n, t;
  991. X    byte *p;
  992. X
  993. X    /* set keys */
  994. X    init_keys(key);
  995. X
  996. X    /* check password */
  997. X    for (n = 0; n < 11; n++)
  998. X        c = DECRYPT(h[n]);
  999. X    b = DECRYPT(h[11]);
  1000. X
  1001. X#ifdef CRYPT_DEBUG
  1002. X    printf("   lrec.crc = %08lx  crec.crc = %08lx  pInfo->ExtLocHdr = %s\n",
  1003. X      lrec.crc32, pInfo->crc, pInfo->ExtLocHdr? "true":"false");
  1004. X    printf("   incnt = %d  unzip offset into zipfile = %ld\n", incnt,
  1005. X      cur_zipfile_bufstart+(inptr-inbuf));
  1006. X    printf("   (c | (b<<8)) = %04x  (crc >> 16) = %04x  lrec.time = %04x\n",
  1007. X      (UWORD)(c | (b<<8)), (UWORD)(lrec.crc32 >> 16), lrec.last_mod_file_time);
  1008. X#endif /* CRYPT_DEBUG */
  1009. X
  1010. X    /* same test as in zipbare() in crypt.c: */
  1011. X    if ((UWORD)(c | (b<<8)) != (pInfo->ExtLocHdr? lrec.last_mod_file_time :
  1012. X        (UWORD)(lrec.crc32 >> 16)))
  1013. X        return -1;  /* bad */
  1014. X
  1015. X    /* password OK:  decrypt current buffer contents before leaving */
  1016. X    for (n = (longint)incnt > csize ? (int)csize : incnt, p = inptr; n--; p++)
  1017. X        *p = (byte) DECRYPT(*p);
  1018. X    return 0;       /* OK */
  1019. X
  1020. X} /* end function testp() */
  1021. X
  1022. X#endif /* CRYPT */
  1023. X
  1024. X
  1025. X
  1026. X
  1027. X
  1028. X/*******************************/
  1029. X/*  Function ReadMemoryByte()  */
  1030. X/*******************************/
  1031. X
  1032. Xint ReadMemoryByte(x)   /* return PK-type error code */
  1033. X    UWORD *x;
  1034. X{
  1035. X    if (mem_i_offset < mem_i_size) {
  1036. X        *x = (UWORD) mem_i_buffer[mem_i_offset++];
  1037. X        return 8;
  1038. X    } else
  1039. X        return 0;
  1040. X}
  1041. X
  1042. X
  1043. X
  1044. X
  1045. X
  1046. X/****************************/
  1047. X/*  Function FlushMemory()  */
  1048. X/****************************/
  1049. X
  1050. Xint FlushMemory()   /* return PK-type error code */
  1051. X{
  1052. X    if (outcnt == 0)
  1053. X        return 0;
  1054. X
  1055. X    if (mem_o_offset + outcnt <= mem_o_size) {
  1056. X        memcpy((char *)(mem_o_buffer+mem_o_offset), (char *)outbuf, outcnt);
  1057. X        mem_o_offset += outcnt;
  1058. X        return 0;
  1059. X    } else
  1060. X        return 50;
  1061. X}
  1062. X
  1063. X
  1064. X
  1065. X
  1066. X
  1067. X/***************************/
  1068. X/*  Function memextract()  */   /* extract compressed extra field block */
  1069. X/***************************/
  1070. X
  1071. Xint memextract(tgt, tgtsize, src, srcsize)  /* return 0 if success, 1 if not */
  1072. X    byte *tgt, *src;
  1073. X    ULONG tgtsize, srcsize;
  1074. X{
  1075. X    UWORD method, error = 0;
  1076. X    ULONG crc, oldcrc;
  1077. X
  1078. X    method = makeword(src);
  1079. X    crc = makelong(src+2);
  1080. X
  1081. X    mem_i_buffer = src + 2 + 4;      /* method and crc */
  1082. X    mem_i_size   = srcsize - 2 - 4;
  1083. X    mem_i_offset = 0;
  1084. X  
  1085. X    mem_o_buffer = tgt;
  1086. X    mem_o_size   = tgtsize;
  1087. X    mem_o_offset = 0;
  1088. X
  1089. X    mem_mode = 1;
  1090. X
  1091. X    bits_left = 0;
  1092. X    bitbuf = 0L;
  1093. X    outpos = 0L;
  1094. X    outcnt = 0;
  1095. X    outptr = outbuf;
  1096. X    zipeof = 0;
  1097. X
  1098. X    switch (method) {
  1099. X        case STORED:
  1100. X            memcpy(tgt, src + 2 + 4, (extent) (srcsize - 2 - 4));
  1101. X            break;
  1102. X        case DEFLATED:
  1103. X            inflate();
  1104. X            FlushOutput();
  1105. X            break;
  1106. X        default:
  1107. X            fprintf(stderr,
  1108. X              "warning:  unsupported extra field compression type--skipping\n");
  1109. X            error = 1;   /* GRR:  this should be passed on up via SetEAs() */
  1110. X            break;
  1111. X    }
  1112. X
  1113. X    mem_mode = 0;
  1114. X
  1115. X    if (!error) {
  1116. X        oldcrc = crc32val;
  1117. X        crc32val = 0xFFFFFFFFL;
  1118. X        UpdateCRC((unsigned char *) mem_o_buffer, (int) mem_o_size);
  1119. X        crc32val = (~crc32val) & 0xFFFFFFFFL;
  1120. X
  1121. X        if (crc32val != crc) {
  1122. X            printf("(Bad extra field CRC %08lx, should be %08lx)\n", crc32val,
  1123. X              crc);
  1124. X            error = 1;
  1125. X        }
  1126. X        crc32val = oldcrc; /* grrr ... this ugly kludge should be fixed */
  1127. X    }
  1128. X
  1129. X    return error;
  1130. X}
  1131. END_OF_FILE
  1132.   if test 37529 -ne `wc -c <'extract.c'`; then
  1133.     echo shar: \"'extract.c'\" unpacked with wrong size!
  1134.   fi
  1135.   # end of 'extract.c'
  1136. fi
  1137. if test -f 'mapname.c' -a "${1}" != "-c" ; then 
  1138.   echo shar: Will not clobber existing file \"'mapname.c'\"
  1139. else
  1140.   echo shar: Extracting \"'mapname.c'\" \(15624 characters\)
  1141.   sed "s/^X//" >'mapname.c' <<'END_OF_FILE'
  1142. X/*---------------------------------------------------------------------------
  1143. X
  1144. X  mapname.c
  1145. X
  1146. X  This routine changes DEC-20, VAX/VMS, and DOS-style filenames into normal
  1147. X  Unix names (and vice versa, in some cases); it also creates any necessary 
  1148. X  directories, if the -d switch was specified.
  1149. X
  1150. X  ---------------------------------------------------------------------------
  1151. X
  1152. X  Notes:
  1153. X
  1154. X     - This routine REALLY needs to be rewritten (different routines for
  1155. X       each output OS, with different rules for different parts of the path
  1156. X       name).  If each zip program stores local-format names (like the VMS
  1157. X       one did at one time), it would probably be best to convert to an in-
  1158. X       termediate format first (assuming we're not extracting under the same
  1159. X       OS as that under which the zipfile was created), then from that to
  1160. X       the current operating system's format.
  1161. X     - The strcpy and strcat operations on both cdp and filename may over-
  1162. X       write memory, since they don't check lengths.  With a kilobyte in
  1163. X       which to work, this is probably not that big a deal, but it could
  1164. X       cause problems eventually.
  1165. X
  1166. X  ---------------------------------------------------------------------------*/
  1167. X
  1168. X
  1169. X#include "unzip.h"
  1170. X
  1171. X
  1172. X/*******************/
  1173. X/* Mapname Defines */
  1174. X/*******************/
  1175. X
  1176. X#ifdef VMS
  1177. X#  define PERMS   0
  1178. X#else
  1179. X#  define PERMS   0777
  1180. X#endif
  1181. X
  1182. X#ifndef NO_MKDIR
  1183. X#  if (defined(DOS_OS2) && !defined(__GO32__))
  1184. X#    if (_MSC_VER >= 600)       /* have special MSC mkdir prototype */
  1185. X#      include <direct.h>
  1186. X#    else                       /* own prototype because dir.h conflicts? */
  1187. X       int mkdir(const char *path);
  1188. X#    endif /* ?(MSC 6.0 or later) */
  1189. X#    define MKDIR(path,mode)   mkdir(path)
  1190. X#  else /* !DOS_OS2 || __GO32__ */
  1191. X#    ifdef MACOS
  1192. X#      define MKDIR(path,mode)   macmkdir(path,gnVRefNum,glDirID)
  1193. X#    else /* !MACOS */
  1194. X#      define MKDIR(path,mode)   mkdir(path,mode)
  1195. X#    endif /* ?MACOS */
  1196. X#  endif /* ?(DOS_OS2 && !__GO32__)  */
  1197. X#endif /* !NO_MKDIR */
  1198. X
  1199. X
  1200. X
  1201. X
  1202. X/************************/
  1203. X/*  Function mapname()  */
  1204. X/************************/
  1205. X
  1206. Xint mapname(create_dirs)   /* return 0 if no error, 1 if caution (filename */
  1207. X    int create_dirs;       /*  truncated), 2 if warning (skip file because */
  1208. X{                          /*  dir doesn't exist), 3 if error (skip file) */
  1209. X#ifdef NO_MKDIR
  1210. X    char command[FILNAMSIZ+40]; /* buffer for system() call */
  1211. X#endif
  1212. X#ifdef VMS
  1213. X    int stat_val;               /* temp. holder for stat() return value */
  1214. X    char *dp, *xp;              /* pointers to directory name */
  1215. X    char *np;                   /* pointer into filename */
  1216. X#endif /* VMS */
  1217. X#ifdef DOS_VMS
  1218. X    char *last_dot=NULL;        /* last dot not converted to underscore */
  1219. X#endif /* DOS_VMS */
  1220. X#ifdef OS2
  1221. X    char *last;
  1222. X    extern char longfilename[]; /*  AFTER file created and closed */
  1223. X    extern int longname;        /* used also in file_io.c:  set EAs */
  1224. X    int longdir;
  1225. X#endif /* OS2 */
  1226. X    char name[FILNAMSIZ];       /* file name buffer */
  1227. X    char *pp, *cp, *cdp;        /* character pointers */
  1228. X    char delim = '\0';          /* directory delimiter */
  1229. X    int quote = FALSE;          /* flags */
  1230. X    int indir = FALSE;
  1231. X    int done = FALSE;
  1232. X    int created = FALSE;
  1233. X    register unsigned workch;   /* hold the character being tested */
  1234. X
  1235. X
  1236. X/*---------------------------------------------------------------------------
  1237. X    Initialize various pointers and counters and stuff.
  1238. X  ---------------------------------------------------------------------------*/
  1239. X
  1240. X#ifdef MAP_DEBUG
  1241. X    fprintf(stderr, "%s ", filename);   /* echo name of this file */
  1242. X#endif
  1243. X    cdp = (char *)NULL;
  1244. X    pp = name;                  /* point to translation buffer */
  1245. X    *name = '\0';               /* initialize buffer */
  1246. X    if (!jflag) {               /* -j => junk pathnames */
  1247. X        cdp = (char *)malloc(strlen(filename) + 3);   /* place for holding */
  1248. X        if (cdp == (char *)NULL) {                    /*  directory name */
  1249. X            fprintf(stderr, "mapname:  out of memory [%s]\n", filename);
  1250. X            return 3;
  1251. X        }
  1252. X#ifdef VMS
  1253. X        *cdp++ = '[';
  1254. X        xp = cdp;               /* always points to last non-NULL char */
  1255. X        *cdp++ = '.';
  1256. X#endif /* VMS */
  1257. X#ifdef MACOS
  1258. X        *cdp = ':';             /* the Mac uses ':' as a directory separator */
  1259. X        cdp[1] = '\0';
  1260. X#else /* !MACOS */
  1261. X        *cdp = '\0';
  1262. X#endif /* ?MACOS */
  1263. X    }
  1264. X
  1265. X/*---------------------------------------------------------------------------
  1266. X    Begin main loop through characters in filename.
  1267. X  ---------------------------------------------------------------------------*/
  1268. X
  1269. X    for (cp = filename; (workch = (unsigned char) *cp++) != 0  &&  !done;) {
  1270. X
  1271. X        if (quote) {                 /* if char quoted, */
  1272. X            *pp++ = (char) workch;   /*  include it literally */
  1273. X            quote = FALSE;
  1274. X        } else if (indir) {          /* if in directory name, */
  1275. X            if (workch == (unsigned)delim)  /*  look for end delimiter */
  1276. X                indir = FALSE;
  1277. X        } else
  1278. X            switch (workch) {
  1279. X            case '<':                /* discard DEC-20 directory name */
  1280. X                indir = TRUE;
  1281. X                delim = '>';
  1282. X                break;
  1283. X            case '[':                /* discard VMS directory name */
  1284. X                indir = TRUE;
  1285. X                delim = ']';
  1286. X                break;
  1287. X            case '/':                /* discard Unix path name  */
  1288. X            case '\\':               /*  or MS-DOS path name... */
  1289. X                                     /*  iff -j flag was given  */
  1290. X                /*
  1291. X                 * Special processing case:  if -j flag was not specified on
  1292. X                 * command line and create_dirs is TRUE, create any necessary
  1293. X                 * directories included in the pathname.  Creation of dirs is
  1294. X                 * straightforward on BSD and MS-DOS machines but requires use
  1295. X                 * of the system() command on SysV systems (or any others which
  1296. X                 * don't have mkdir()).  The stat() check is necessary with
  1297. X                 * MSC because it doesn't have an EEXIST errno, and it saves
  1298. X                 * the overhead of multiple system() calls on SysV machines.
  1299. X                 */
  1300. X
  1301. X                if (!jflag) {
  1302. X                    *pp = '\0';
  1303. X#ifdef VMS
  1304. X                    dp = name;
  1305. X                    while (*++xp = *dp++);  /* copy name to cdp */
  1306. X                    last_dot = NULL;        /* dir name:  no dots allowed */
  1307. X                    strcpy(xp, ".dir");     /* add extension for stat check */
  1308. X                    stat_val = stat(cdp, &statbuf);
  1309. X                    *xp = '\0';             /* remove extension for all else */
  1310. X                    if (stat_val) {         /* doesn't exist, so create */
  1311. X#else /* !VMS */
  1312. X#ifdef MSDOS
  1313. X                    if (last_dot != NULL) {  /* one dot in dir name is legal */
  1314. X                        *last_dot = '.';
  1315. X                        last_dot = NULL;
  1316. X                    }
  1317. X#endif /* MSDOS */
  1318. X                    strcat(cdp, name);
  1319. X#ifdef OS2
  1320. X                    if ((longdir = !IsFileNameValid(cdp)) != 0) {
  1321. X                        last = strrchr(cdp, '/');
  1322. X                        strcpy(longfilename, last ? last + 1 : cdp);
  1323. X                        fprintf(stderr, "renaming directory \"%s\"", cdp);
  1324. X                        ChangeNameForFAT(cdp);
  1325. X                        fprintf(stderr, " to \"%s\"\n", cdp);
  1326. X                    }
  1327. X#endif /* OS2 */
  1328. X                    if (stat(cdp, &statbuf)) {  /* doesn't exist, so create */
  1329. X#endif /* ?VMS */
  1330. X                        if (!create_dirs) /* told not to create (freshening) */
  1331. X                            return 2;
  1332. X#ifdef NO_MKDIR
  1333. X                        sprintf(command,
  1334. X                          "IFS=\" \t\n\" /bin/mkdir %s 2>/dev/null", cdp);
  1335. X                        if (system(command)) {
  1336. X#else /* !NO_MKDIR */
  1337. X                        if (MKDIR(cdp, PERMS) == -1) {
  1338. X#endif /* ?NO_MKDIR */
  1339. X                            perror(cdp);
  1340. X                            free(cdp);
  1341. X                            fprintf(stderr, "mapame:  unable to process [%s]\n",
  1342. X                              filename);
  1343. X                            return 3;
  1344. X                        }
  1345. X                        created = TRUE;
  1346. X#ifdef OS2
  1347. X                        if (longdir)
  1348. X                            SetLongNameEA(cdp, longfilename);
  1349. X#endif /* OS2 */
  1350. X                    } else if (!(statbuf.st_mode & S_IFDIR)) {
  1351. X                        fprintf(stderr,
  1352. X                          "mapname:  %s exists but is not a directory\n", cdp);
  1353. X                        free(cdp);
  1354. X                        fprintf(stderr, "mapame:  unable to process [%s]\n",
  1355. X                          filename);
  1356. X                        return 3;
  1357. X                    }
  1358. X#ifdef VMS
  1359. X                    *xp = '/';  /* for now... (mkdir()) */
  1360. X#else /* !VMS */
  1361. X#ifdef MACOS
  1362. X                    strcat(cdp, ":");
  1363. X#else /* !MACOS */
  1364. X                    strcat(cdp, "/");
  1365. X#endif /* ?MACOS */
  1366. X#endif /* ?VMS */
  1367. X                }
  1368. X                pp = name;
  1369. X                break;
  1370. X            case ':':
  1371. X#ifdef UNIX                       /* colon is a valid character in Unix */
  1372. X                *pp++ = workch;   /*  filenames, so keep it; anywhere else, */
  1373. X#else /* !UNIX */                 /*  change it to an underscore (should  */
  1374. X                *pp++ = '_';      /*  NOT have stored drive/node names!!) */
  1375. X#endif /* ?UNIX */
  1376. X             /* pp = name;  (OLD) discard DEC dev: or node:: name */
  1377. X                break;
  1378. X            case '.':                   /* DEC-20 generation number or */
  1379. X#ifdef DOS_VMS                          /*  MS-DOS or VMS separator */
  1380. X                last_dot = pp;          /* point at last dot so far... */
  1381. X                *pp++ = '_';            /* convert dot to underscore */
  1382. X#else /* !DOS_VMS */
  1383. X                *pp++ = workch;
  1384. X#endif /* ?DOS_VMS */
  1385. X                break;
  1386. X            case ';':                   /* VMS generation or DEC-20 attrib */
  1387. X#ifdef MACOS
  1388. X                if (V_flag || macflag)
  1389. X#else /* !MACOS */
  1390. X                if (V_flag)                 /* if requested, save VMS ";##" */
  1391. X#endif /* ?MACOS */                         /*  version info or Macintosh */
  1392. X                    *pp++ = (char) workch;  /*  (?) info; otherwise discard */
  1393. X                else                        /*  everything starting with */
  1394. X                    done = TRUE;            /*  semicolon.  (Worry about */
  1395. X                break;                      /*  DEC-20 later.) */
  1396. X            case '\026':                /* control-V quote for special chars */
  1397. X                quote = TRUE;           /* set flag for next character */
  1398. X                break;
  1399. X            case ' ':
  1400. X#if (defined(VMS) || defined(MTS))
  1401. X                *pp++ = '_';            /* change spaces to underscore */
  1402. X#else /* !(VMS || MTS) */               /*  under VMS and MTS, and under DOS */
  1403. X#ifdef DOS_OS2                          /*  and OS/2 if -s not specified. */
  1404. X                if (!sflag)
  1405. X                    *pp++ = '_';
  1406. X                else
  1407. X#endif /* DOS_OS2 */
  1408. X                *pp++ = (char) workch;  /* otherwise, leave as spaces */
  1409. X#endif /* ?(VMS || MTS) */
  1410. X                break;
  1411. X            default:
  1412. X#ifdef MACOS
  1413. X                if ((macflag && ((unsigned)workch > 0x1F)) || isprint(workch))
  1414. X#else /* !MACOS */
  1415. X#if (defined(DOS_OS2) || (defined(UNIX) && !defined(VMS)))  /* allow non-US */
  1416. X                if (isprint(workch) || (128 <= workch && workch <= 254))
  1417. X#else /* !(DOS_OS2 || UNIX) */
  1418. X                if (isprint(workch))    /* other printable, just keep */
  1419. X#endif /* ?(DOS_OS2 || UNIX) */
  1420. X#endif /* ?MACOS */
  1421. X                    *pp++ = (char) workch;
  1422. X            } /* end switch */
  1423. X    } /* end for loop */
  1424. X    *pp = '\0';                         /* done with name:  terminate it */
  1425. X#ifdef DOS_VMS                          /*  and put a dot back in if VMS */
  1426. X    if (last_dot != NULL)               /*  or MS-DOS */
  1427. X        *last_dot = '.';
  1428. X#endif /* DOS_VMS */
  1429. X
  1430. X/*---------------------------------------------------------------------------
  1431. X    We COULD check for existing names right now, create a "unique" name, etc.
  1432. X    At present, we do this in extract_or_test_files() (immediately after we
  1433. X    return from here).  If conversion went bad, the name'll either be nulled
  1434. X    out (in which case we'll return non-0), or following procedures won't be
  1435. X    able to create the extracted file and other error msgs will result.
  1436. X  ---------------------------------------------------------------------------*/
  1437. X
  1438. X    if (filename[strlen(filename) - 1] == '/') {
  1439. X        /* A directory was extracted. It had a trailing /, 
  1440. X         * don't report the error below. */
  1441. X        if (created) {
  1442. X            printf("   Creating: %s", filename);
  1443. X#ifdef OS2
  1444. X            SetPathInfo(filename, lrec.last_mod_file_date,
  1445. X                                  lrec.last_mod_file_time, -1);
  1446. X            if (extra_field)
  1447. X                SetEAs(filename, extra_field);
  1448. X#endif
  1449. X            printf("\n");
  1450. X        }
  1451. X        return 2; /* but skip file */
  1452. X    }
  1453. X
  1454. X    if (*name == '\0') {
  1455. X        fprintf(stderr, "mapname:  conversion of [%s] failed\n", filename);
  1456. X        return 3;
  1457. X    }
  1458. X
  1459. X#ifdef OS2
  1460. X    if (!longname && ((longname = !IsFileNameValid(name)) != 0)) {
  1461. X        /* in case of second call after user renamed the file, skip this */
  1462. X        last = strrchr(name, '/');      /* THIS time, save for file_io */
  1463. X        last = last ? last + 1 : name;  /* only last component */
  1464. X        strcpy(longfilename, last);
  1465. X        fprintf(stderr, "renaming \"%s\"", name);
  1466. X        ChangeNameForFAT(last);
  1467. X        fprintf(stderr, " to \"%s\"\n", name);
  1468. X    }
  1469. X#endif /* OS2 */
  1470. X
  1471. X#ifdef VMS
  1472. X    /* convert filename to legal VMS one, substituting underscores for
  1473. X     * all invalid characters */
  1474. X    for (np = name;  *np;  ++np)
  1475. X        if (!(isdigit(*np) || isalpha(*np) || (*np == '$') ||
  1476. X            (*np == '-') || (*np == '_') || (*np == '.') || (*np == ';')))
  1477. X            *np = '_';
  1478. X#endif /* VMS */
  1479. X
  1480. X    if (!jflag) {
  1481. X#ifdef VMS
  1482. X        *xp++ = ']';                 /* proper end-of-dir-name delimiter */
  1483. X        if (xp == cdp) {             /* no path-name stuff, so... */
  1484. X            strcpy(filename, name);  /* copy file name into global */
  1485. X            cdp -= 2;                /*   prepare to free malloc'd space */
  1486. X        } else {                     /* we've added path-name stuff... */
  1487. X            *xp = '\0';              /*   so terminate and convert to */
  1488. X            dp = cdp;                /*   VMS subdir separators (skip */
  1489. X            while (*++dp)            /*   first char:  better not be */
  1490. X                if (*dp == '/')      /*   "/"):  change all slashes */
  1491. X                    *dp = '.';       /*   to dots */
  1492. X            cdp -= 2;                /*   include leading bracket and dot */
  1493. X            strcpy(filename, cdp);   /* copy VMS-style path name into global */
  1494. X            strcat(filename, name);  /* concatenate file name to global */
  1495. X        }
  1496. X#else /* !VMS */
  1497. X        strcpy(filename, cdp);       /* either "" or slash-terminated path */
  1498. X        strcat(filename, name);      /* append file name to path name */
  1499. X#endif /* ?VMS */
  1500. X        free(cdp);
  1501. X    } else
  1502. X        strcpy(filename, name);      /* copy converted name into global */
  1503. X
  1504. X#if PATH_MAX < (FILNAMSIZ - 1)
  1505. X    /* check the length of the file name and truncate if necessary */
  1506. X    if (PATH_MAX < strlen(filename)) {
  1507. X        fprintf(stderr, "caution:  truncating filename\n");
  1508. X        filename[PATH_MAX] = '\0';
  1509. X        fprintf(stderr, "[ %s ]\n", filename);
  1510. X        return 1;             /* 1:  warning error */
  1511. X    }
  1512. X#endif
  1513. X
  1514. X    return 0;
  1515. X}
  1516. END_OF_FILE
  1517.   if test 15624 -ne `wc -c <'mapname.c'`; then
  1518.     echo shar: \"'mapname.c'\" unpacked with wrong size!
  1519.   fi
  1520.   # end of 'mapname.c'
  1521. fi
  1522. echo shar: End of archive 2 \(of 14\).
  1523. cp /dev/null ark2isdone
  1524. MISSING=""
  1525. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1526.     if test ! -f ark${I}isdone ; then
  1527.     MISSING="${MISSING} ${I}"
  1528.     fi
  1529. done
  1530. if test "${MISSING}" = "" ; then
  1531.     echo You have unpacked all 14 archives.
  1532.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1533. else
  1534.     echo You still must unpack the following archives:
  1535.     echo "        " ${MISSING}
  1536. fi
  1537. exit 0
  1538. exit 0 # Just in case...
  1539.