home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / unzip50 / part02 < prev    next >
Encoding:
Text File  |  1992-08-22  |  58.1 KB  |  1,534 lines

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