home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / unzip / part05 < prev    next >
Encoding:
Text File  |  1992-04-02  |  53.7 KB  |  1,425 lines

  1. Newsgroups: comp.sources.misc
  2. From: info-zip@cs.ucla.edu (Info-Zip)
  3. Subject:  v29i035:  unzip - Info-ZIP's portable UnZip v4.2, Part05/12
  4. Message-ID: <1992Apr3.063155.28823@sparky.imd.sterling.com>
  5. X-Md4-Signature: dc9885c504e2284d5361dd5d2bd0bffa
  6. Date: Fri, 3 Apr 1992 06:31:55 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: info-zip@cs.ucla.edu (Info-Zip)
  10. Posting-number: Volume 29, Issue 35
  11. Archive-name: unzip/part05
  12. Environment: Unix, VMS, OS/2, MS-DOS, Amiga, Macintosh
  13. Supersedes: unzip, Volume 19, Issues 96-101
  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:  VMS/VMS.notes VMS/bilf/bilf.c extract.c
  22. # Wrapped by kent@sparky on Mon Mar 30 01:45:53 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 5 (of 12)."'
  26. if test -f 'VMS/VMS.notes' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'VMS/VMS.notes'\"
  28. else
  29.   echo shar: Extracting \"'VMS/VMS.notes'\" \(13423 characters\)
  30.   sed "s/^X//" >'VMS/VMS.notes' <<'END_OF_FILE'
  31. X                     VMS Notes for UnZip 4.2
  32. X                        28 February 1992
  33. X
  34. X
  35. XThe various VMS tweaks to UnZip 4.2 and ZipInfo 0.96 were tested on a 
  36. XVAX 8600 running VMS 5.2 (and, later, VMS 5.4) and VAX C 3.0.  Older 
  37. Xversions were also tested on a VAX 11/785.
  38. X
  39. XTo build UnZip (and its trusty sidekick, ZipInfo), just run the included 
  40. Xcommand file MAKE_UNZIPINFO.COM (i.e., "@make_unzipinfo").  By default, 
  41. Xthis creates shareable-image executables, which are smaller and (sup-
  42. Xposedly) load faster than the normal type.  They also (supposedly) will 
  43. Xbe better able to take advantage of any bug fixes or new capabilities 
  44. Xthat DEC might introduce, since the library code isn't built into the 
  45. Xexecutable.  The shared executable is about a quarter the size of the 
  46. Xordinary type in the case of UnZip.
  47. X
  48. X[Btw, the VMS make utility "MMS" seems not to be compatible enough with
  49. XUnix make to use the same makefile.  Antonio Querubin, Jr., sent along an 
  50. XMMS makefile, subsequently modified by Igor Mandrichenko.  Read the
  51. Xcomments at the top of DESCRIP.MMS for more info.]
  52. X
  53. XUnZip is written to return the standard PK-type return codes (or error
  54. Xcodes, or exit codes, or whatever you want to call them).  Unfortunately,
  55. XVMS insists on interpreting the codes in its own lovable way, and this
  56. Xresults in endearing commentary such as "access violation, error mask =
  57. X0005, PC = 00003afc" (or something like that) when you run UnZip with no
  58. Xarguments.  To avoid this I've added a special VMS_return() function which
  59. Xeither ignores the error codes (and exits with normal status) or interprets
  60. Xthem, prints a semi-informative message (enclosed in square [] brackets), 
  61. Xand then exits with a normal error status.  I personally can't stand the 
  62. Xlatter behavior, so by default the error codes are simply ignored.  Tastes
  63. Xvary, however, and some people may actually like semi-informative messages.
  64. XIf you happen to be one of those people, you may enable the messages by 
  65. Xrecompiling misc.c with RETURN_CODES defined.  (This adds a block or two
  66. Xto the executable size, though.)  The syntax is as follows:
  67. X    cc /def=(RETURN_CODES) misc
  68. X
  69. XTo use UnZip in the normal way, define a symbol "unzip" as follows:
  70. X    unzip :== "$diskname:[directory]unzip.exe"
  71. X(substitute for "diskname" and "directory" as appropriate, and DON'T FORGET
  72. XTHE `$'!  It won't work if you omit that.)  In general it's wise to stick 
  73. Xsuch assignments in your LOGIN.COM file and THEN forget about them.  It is 
  74. Xno longer necessary to worry about the record type of the zipfile...er, 
  75. Xwell, most of the time, anyway (see the Kermit section below).
  76. X
  77. XHaving done all this you are ready to roll.  Use the unzip command in
  78. Xthe usual way; as with the Unix, OS/2 and MS-DOS versions, this one uses 
  79. X'-' as a switch character.  If nothing much happens when you do a directory
  80. Xlisting, for example, you're probably trying to specify a filename which
  81. Xhas uppercase letters in it...VMS thoughtfully converts everything on the
  82. Xcommand line to lowercase, so even if you type:
  83. X    unzip -v zipfile Makefile
  84. Xwhat you get is:
  85. X    unzip -v zipfile makefile
  86. Xwhich, in my example here, doesn't match the contents of the zipfile.
  87. XThis is relatively easy to circumvent, by enclosing the filespec(s) in 
  88. Xquotes:
  89. X    unzip -tq unzip401 "Makefile" "VMS*" *.c *.h
  90. X[This example also demonstrates the use of wildcards, which act like Unix
  91. Xwildcards, not VMS ones.   In other words, "VMS*" matches files VMSNOTES,
  92. XVMS_MAKE.COM, and VMSSHARE.OPT, whereas the normal VMS behavior would be
  93. Xto match only the first file (since the others have extensions--ordinarily,
  94. Xyou would be required to specify "VMS*.*").]
  95. X
  96. XNote that created files get whatever default permissions you've set, but 
  97. Xcreated directories additionally inherit the (possibly more restrictive) 
  98. Xpermissions of the parent directory.  And, of course, things probably won't 
  99. Xwork too well if you don't have permission to write to whatever directory 
  100. Xinto which you're trying to extract things.  (That made sense; read it 
  101. Xagain if you don't believe me.)
  102. X
  103. XZipInfo, by the way, is an amusing little utility which tells you all sorts
  104. Xof amazingly useless information about zipfiles.  Occasionally it's useful
  105. Xto debug a problem with a corrupted zipfile (for example, we used it to 
  106. Xfind a bug in PAK-created zipfiles, versions 2.5 and earlier).  Feel free
  107. Xto blow it away if you don't need it.  It's about 30 blocks on my system,
  108. Xand I find I actually prefer its listing format to that of UnZip now (hardly
  109. Xsurprising, since I wrote it :-) ).  I also find it useful to use "ii" 
  110. Xrather than "zipinfo" as the symbol for zipinfo, since it's easier to type 
  111. Xthan either "zipinfo" or "unzip -v", and it echoes the common Unix alias 
  112. X"ll" for the similar style of directory listings.  Oh, and the reason it's 
  113. Xstill got a beta version number is that I haven't finished it yet--it would 
  114. Xbe better with an automatic paging function, for example.  Oh well.
  115. X
  116. XRANDOM OTHER NOTES:  (1) Igor Mandrichenko (leader of our fearless Russian 
  117. Xcontingent) rewrote major portions of the VMS file-handling code, with
  118. Xthe result that UnZip is much smarter now about VMS file formats.  He
  119. Xmade a corresponding set of changes to Zip, but those are not yet avail-
  120. Xable.  When they are, however, UnZip will be able handle them.  In the
  121. Xmeantime, the notes at the end of this file from Hugh Schmidt and Mike
  122. XFreeman give hints on how to save VMS attributes using Zip 1.0.  These
  123. Xnotes refer to UnZip 4.1, but they should still hold for this version.
  124. X(2) Zip 1.0 cannot handle any zipfile that isn't in stream-LF format, so 
  125. Xyou may need to use Rahul Dhesi's BILF utility which is included with 
  126. XUnZip.  It may also be necessary for certain other special occasions, like 
  127. Xwhen you've forgotten to set the correct Kermit parameters while uploading
  128. Xa zipfile (see Hugh Schmidt's note below for comments about Kermit, too).
  129. X
  130. XGreg Roelofs,
  131. X not really involved with VMS UnZip anymore, but updating this file one
  132. X last time since it's mine. :-)
  133. X
  134. X====================
  135. X
  136. XFrom INFO-ZIP Digest (Wed, 6 Nov 1991), Volume 91, Issue 290
  137. X
  138. X                VMS attributes and PKZIP compatibility
  139. X                  VMS attributes restored! (2 msgs)
  140. X
  141. X------------------------------
  142. X
  143. XDate: Tue, 5 Nov 91 15:31 CDT
  144. XFrom: Hugh Schmidt <HUGH@macc.wisc.edu>
  145. XSubject: VMS attributes and PKZIP compatibility
  146. XMessage-ID: <21110515313938@vms.macc.wisc.edu>
  147. X
  148. X           ******************************************************
  149. X(1)        *** Retaining VMS attributes - a proposed strategy ***
  150. X           ******************************************************
  151. X
  152. XThis is a proposed strategy for recovering VMS file attributes after
  153. Xzip/unzip:
  154. X
  155. Xa) capture VMS file attributes: VMS ANALYZE/RMS/FDL/OUTPUT=fdlfile vmsfile.ext
  156. Xb) compress files on VMS......: ZIP zipfile vmsfile.ext, fdlfile.fdl
  157. Xc) uncompress files on VMS....: UNZIP zipfile vmsfile.ext, fdlfile.fdl
  158. Xd) recover VMS file attributes: CONVERT/FDL=fdlfile.fdl vmsfile.ext vmsfile.ext
  159. X
  160. XThe wrinkle is that UNZIP creates files which are unreadable by CONVERT
  161. Xdespite a concerted effort to accomodate VMS file management system:
  162. X
  163. Xfile_io.c, line 178: ...creat(filename,0, "rat=cr", "rfm=streamlf")
  164. X
  165. XThese files are unCONVERTABLE because they appear to VMS to contain
  166. Xrecords with 512+ bytes.  Poring over VMS manuals (Programming V-6A, VAX
  167. XC RTL Reference Manual) doesn't readily suggest better alternatives.
  168. XExperimentation with "rat=fix", etc. may help suppress the spurious
  169. Xblock-end delimeters.
  170. X
  171. X          ****************************************************
  172. X(2)       *** VMS ZIP and PKZIP compatibility using KERMIT ***
  173. X          ****************************************************
  174. X
  175. XMany use Procomm's kermit to transfer zipped files between PC and VMS
  176. XVAX.  The following VMS kermit settings make VMS-ZIP compatible with
  177. XPKZIP:
  178. X
  179. X                                             VMS kermit      Procomm kermit
  180. X                                           ---------------   --------------
  181. XUploading PKZIPped file to be UNZIPped:    set fi ty fixed    set fi ty bi
  182. XDownloading ZIPped file to be PKUNZIPped:  set fi ty block    set fi ty bi
  183. X
  184. X"Block I/O lets you bypass the VMS RMS record-processing capabilities
  185. Xentirely", (Guide to VMS file applications, Section 8.5).  The kermit
  186. Xguys must have known this!
  187. X
  188. X         ************************************************
  189. X(3)      *** Making ZIP files compatible with VMS RMS ***
  190. X         ************************************************
  191. X
  192. XIt looks like a crummy patch, but to make VMS RMS happy, I inserted the
  193. Xfollowing near line 570 in the putend() section of zipfile.c:
  194. X
  195. X#ifdef VMS
  196. X fprintf(f,"\n")
  197. X#endif
  198. X
  199. XIt's probably of no consequence, but it satisfies VMS ANALYZE.
  200. X
  201. X------------------------------
  202. X
  203. XDate: Tue, 5 Nov 91 19:40 CDT
  204. XFrom: Hugh Schmidt <HUGH@macc.wisc.edu>
  205. XSubject: VMS attributes restored!
  206. XMessage-ID: <21110519403912@vms.macc.wisc.edu>
  207. X
  208. X           ************************************************************
  209. X           ***   Aha!  It works!  VMS attributes can be restored! *****
  210. X           ***                                                      ***
  211. X           *** Change FAB$C_STMLF to FAB$C_FIX in file_io.c         ***
  212. X           *** ANALYZE => .FDL | CONVERT => original VMS attributes ***
  213. X           ************************************************************
  214. X
  215. X(1) Change line 147 in file_io.c and dropping lines 148-149:
  216. X
  217. X    fileblk.fab$b_rfm = FAB$C_STMLF;    /* stream-LF record format */
  218. X    fileblk.fab$b_rat = FAB$M_CR;       /* carriage-return carriage ctrl */
  219. X    /*                      ^^^^ *NOT* V_CR!!!     */
  220. X
  221. X=>
  222. X
  223. X    fileblk.fab$b_rfm = FAB$C_FIX;    /* fixed record format */
  224. X
  225. X(2) Use VMS ANALYZE to store the VMS attributes for the original file
  226. X    into a file descripion language file.  Save the .FDL file with the
  227. X    original file.
  228. X
  229. X(3) Apply the original attributes to the UNZIPped file using VMS CREATE
  230. X    and the description file (test.fdl).
  231. X
  232. XIn the following example, the original attributes of a SPSSX system
  233. Xformat file were restored.  Later, SPSSX successfully read the UNZIPped/
  234. XCONVERTed file.
  235. X
  236. X!******** Procedure (or method for you ai'ers)
  237. X!********
  238. X!******** Create an .FDL file using ANALYZE
  239. X
  240. X$ analyze/rms/fdl/out=test test.spssxsav;1
  241. X
  242. X!******** ZIP the file and its description file
  243. X
  244. X$ zip test test.spssxsav;1 test.fdl;1
  245. Xadding test.spssxsav (imploded 62%)
  246. Xadding test.fdl (imploded 90%)
  247. X
  248. X!******** When the ZIPPED file is needed, UNZIP it and its description file
  249. X
  250. X$ unzip test
  251. X  Exploding: test.spssxsav
  252. X  Exploding: test.fdl
  253. X
  254. X!******** To restore the original attributes, apply the description file to
  255. X!********  the UNZIPped file using VMS CONVERT
  256. X
  257. X$ convert/fdl=test  test.spssxsav;2 test.spssxsav;3
  258. X
  259. X! ******* The following show that the VMS attributes are restored.
  260. X
  261. X$ analyze/rms/check test.spssxsav;1
  262. X
  263. X    File Spec: PROJDISK5:[322042.CORE]TEST.SPSSXSAV;1
  264. X    File Organization: sequential
  265. X    Record Format: fixed
  266. X    Record Attributes:
  267. X    Maximum Record Size: 4
  268. X    Longest Record: 4
  269. X
  270. XThe analysis uncovered NO errors.
  271. X
  272. X$ analyze/rms/check test.spssxsav;2
  273. X    File Spec: PROJDISK5:[322042.CORE]TEST.SPSSXSAV;2
  274. X    File Organization: sequential
  275. X    Record Format: undefined
  276. X    Record Attributes:
  277. X    Maximum Record Size: 0
  278. X    Longest Record: 512
  279. XThe analysis uncovered NO errors.
  280. X
  281. X$ analyze/rms/check test.spssxsav;3
  282. X    File Spec: PROJDISK5:[322042.CORE]TEST.SPSSXSAV;3
  283. X    File Organization: sequential
  284. X    Record Format: fixed
  285. X    Record Attributes:
  286. X    Maximum Record Size: 4
  287. X    Longest Record: 4
  288. X
  289. XThank you all for your help and comments.  It was very reasurring to
  290. Xknow that I was on the right track.  This is a humble contribution
  291. Xcompared to the great efforts of others in the ZIP project.
  292. X
  293. X------------------------------
  294. X
  295. XDate: Wed, 6 Nov 91 12:49:33 EST
  296. XFrom: Mike Freeman <freeman@watsun.cc.columbia.edu>
  297. XSubject: Re: VMS attributes restored!
  298. XMessage-ID: <CMM.0.90.0.689449773.freeman@watsun.cc.columbia.edu>
  299. X
  300. XHello, all.
  301. X
  302. XHUGH@macc.wisc.edu has come up with a commendable method for saving/
  303. Xrestoring record attributes in Vax/VMS files when ZIPping/UNZIPping.
  304. XThere are a couple of potential problems in his specific implementation,
  305. Xhowever:
  306. X
  307. X(a) It would be better to leave the output file(s) in STREAM_LF format
  308. X    and use Joe Meadows' FILE utility to put them in fixed-record
  309. X    format if CONVERT has trouble reading them.
  310. X
  311. X    Outputting a text file as fixed-record format could be a pain, and
  312. X    one would have to use FILE anyway.
  313. X
  314. X    (Incidentally, I ZIPped up a text file, UNZIPped it and used Hugh's
  315. X    method to restore the attributes.  CONVERT had no trouble with the
  316. X    STREAM_LF format -- it's only a problem with binary files and, as I
  317. X    say, Joe Meadows' FILE will fix this.)
  318. X
  319. X(b) Even if ANALYZE/RMS complains, I do not think one ought to put the
  320. X    "\n" in as Hugh advocates.  This contradicts the ZIP philosophy of
  321. X    byte-for-byte storage/retrieval.
  322. X
  323. X    As Mr. Roelofs has said, there is nothing wrong with the ZIP file;
  324. X    it's just that ANALYZE/RMS expects STREAM_LF files to end in an
  325. X    <LF>.
  326. X
  327. XAnyway, I was able to use Hugh's method without modifying ZIP 1.0.  We
  328. Xreally ought to get the word out about FILE, though -- it's very handy.
  329. X
  330. XMike Freeman, K7UIJ     |       Internet: freeman@watsun.cc.columbia.edu
  331. X301 N.E. 107th Street   |       GEnie: M.FREEMAN11
  332. XVancouvEr, WA 98685 USA |       Confidence is the feeling you have
  333. XTelephone (206)574-8221 |       before you understand the situation.
  334. X
  335. X------------------------------
  336. X
  337. END_OF_FILE
  338.   if test 13423 -ne `wc -c <'VMS/VMS.notes'`; then
  339.     echo shar: \"'VMS/VMS.notes'\" unpacked with wrong size!
  340.   fi
  341.   # end of 'VMS/VMS.notes'
  342. fi
  343. if test -f 'VMS/bilf/bilf.c' -a "${1}" != "-c" ; then 
  344.   echo shar: Will not clobber existing file \"'VMS/bilf/bilf.c'\"
  345. else
  346.   echo shar: Extracting \"'VMS/bilf/bilf.c'\" \(6109 characters\)
  347.   sed "s/^X//" >'VMS/bilf/bilf.c' <<'END_OF_FILE'
  348. X/*
  349. XThis program performs conversion of files between stream-LF format
  350. X(as used by zoo) and fixed-length record binary format (used for Kermit
  351. Xtransfers of zoo archives).
  352. X
  353. XThis program is:
  354. X   (C) Copyright 1987 Rahul Dhesi.
  355. X   All Rights Reserved.
  356. X
  357. XPermission is hereby granted to copy and modify this for any purpose,
  358. Xwhether commercial or noncommercial, provided only that the above
  359. Xcopyright notice and this paragraph be preserved and included
  360. Xin all copies.
  361. X
  362. X                                 -- Rahul Dhesi 1987/07/25
  363. X*/
  364. X
  365. X#include <stdio.h>
  366. X#include <ssdef.h>
  367. X#define STAT_NORM SS$_NORMAL
  368. X#define STAT_ABORT SS$_ABORT
  369. X
  370. Xchar *strrchr();
  371. Xchar *strdup ();
  372. X
  373. Xmain (argc, argv)
  374. Xint argc;
  375. Xchar *argv[];
  376. X{
  377. X   char *inname;
  378. X   char *outname;
  379. X   char *option;
  380. X   int status;
  381. X
  382. X   if (argc < 3 || argc > 4) {
  383. X      printf ("BILF version 1.00 for VAX/VMS by Rahul Dhesi (1987/07/25)\n\n");
  384. X      printf ("(C) Copyright 1987 Rahul Dhesi,  All Rights Reserved\n");
  385. X      printf ("Permission to use and distribute is granted provided this copyright\n"); 
  386. X      printf ("notice is preserved and included in all copies.\n\n");
  387. X      printf ("Usage:  BILF {lb} infile [ outfile ]\n\n");
  388. X      printf ("Choose one character from within braces.  If outfile is not supplied\n");
  389. X      printf ("it has the same name as infile but a higher version number.\n");
  390. X      printf ("Options are:\n\n");
  391. X      printf ("l:  Write output file in stream-LF format.  This is the format that\n");
  392. X      printf ("    zoo expects all zoo archives to be in.  If a zoo archive was\n");
  393. X      printf ("    uploaded to a VAX/VMS system, it will need to be converted to\n");
  394. X      printf ("    stream-LF format before manipulating with zoo.\n\n");
  395. X      printf ("b:  Write output file in fixed-length 512-byte binary record format.  Before\n");
  396. X      printf ("    a zoo archive can be downloaded from a VAX/VMS system to a\n");
  397. X      printf ("    microcomputer using VAX/VMS Kermit, it must be converted to\n");
  398. X      printf ("    this binary format.  Failure to do so will result in a corrupted\n");
  399. X      printf ("    download.\n");
  400. X      exit (STAT_NORM);
  401. X   }
  402. X
  403. X   inname = argv[2];
  404. X   option = argv[1];
  405. X
  406. X   if (argc == 3) {                    /* use same filename for output */
  407. X      char *p;
  408. X      outname = strdup (inname);
  409. X      p = strrchr (outname, ';');      /* strip trailing version field */
  410. X      if (p != NULL)
  411. X         *p = '\0';
  412. X   } else
  413. X      outname = argv[3];
  414. X
  415. X   if (*option == 'l')
  416. X      status = cvtstream (outname, inname);
  417. X   else if (*option == 'b')
  418. X      status = cvtbin (outname, inname);
  419. X   else
  420. X      prterror ('f', "Option %s is invalid\n", option);
  421. X   if (status == -1)
  422. X      prterror ('w', "An error occurred -- output file may be corrupted\n");
  423. X   exit (STAT_NORM);
  424. X}
  425. X
  426. X#define  MYBUFSIZ    8192
  427. X
  428. X/* writes input file to output file in stream format */
  429. Xint cvtstream (outname, inname)
  430. Xchar *outname, *inname;
  431. X{
  432. X   FILE *infile, *outfile;
  433. X   char buffer[MYBUFSIZ];
  434. X   int count;
  435. X
  436. X   infile = fopen (inname, "r");
  437. X   if (infile == NULL)
  438. X      prterror ('f', "Could not open input file %s\n", inname);
  439. X   outfile = fopen (outname, "w");
  440. X   if (outfile == NULL)
  441. X      prterror ('f', "Could not open output file %s\n", outname);
  442. X
  443. X   while ((count = fread (buffer, 1, sizeof (buffer), infile)) > 0)
  444. X      count = fwrite (buffer, 1, count, outfile);
  445. X
  446. X   close (infile); close (outfile);
  447. X   if (count == -1)
  448. X      return (-1);
  449. X   else
  450. X      return (0);
  451. X}
  452. X
  453. X/*
  454. XVMS C doesn't have strdup().
  455. X*/
  456. Xchar *strdup (str)
  457. Xchar *str;
  458. X{
  459. X   char *malloc();
  460. X   char *newstr = malloc (strlen (str) + 1);
  461. X   if (newstr != NULL) {
  462. X      strcpy (newstr, str);
  463. X      return (newstr);
  464. X   } else
  465. X      return ((char *) NULL);
  466. X}
  467. X
  468. X/* BLKSIZ must correspond to block size specified below in creat() */
  469. X#define BLKSIZ 512
  470. X
  471. X/*
  472. XWrites input file to output in fixed-length BLKSIZ-byte record format.
  473. X*/
  474. X
  475. X#if 1
  476. X#include <file.h>
  477. X#else
  478. X#include <fcntl.h>
  479. X#endif
  480. X
  481. Xint convert ();
  482. X
  483. Xint cvtbin (outname, inname)
  484. Xchar *outname, *inname;
  485. X{
  486. X   int status, inhan, outhan;
  487. X   inhan = open (inname, O_RDONLY);
  488. X   if (inhan == -1)
  489. X      prterror ('f', "Could not open input file %s\n", inname);
  490. X   outhan = creat (outname, 0, "rfm=fix", "mrs=512");
  491. X   if (outhan == -1)
  492. X      prterror ('f', "Could not open output file %s\n", outname);
  493. X   status = convert (outhan, inhan);
  494. X   close (inhan);
  495. X   close (outhan);
  496. X   return (status);
  497. X}
  498. X
  499. X/*
  500. XFunction convert() reads from inhan and writes to outhan, always
  501. Xwriting in BLKSIZ-byte blocks, padding with nulls if necessary
  502. X*/
  503. X
  504. Xint convert (outhan, inhan)
  505. Xint inhan, outhan;
  506. X{
  507. X   char junk[BLKSIZ];
  508. X   int count;
  509. X   int done = 0;
  510. X   do {
  511. X      count = vmsread (inhan, junk, BLKSIZ);
  512. X      if (count <= 0)
  513. X         break;
  514. X      if (count < BLKSIZ) {
  515. X         int i;
  516. X         for (i = count; i < BLKSIZ; i++)
  517. X            junk[i] = 0;
  518. X         done++;
  519. X      }
  520. X      count = write (outhan, junk, BLKSIZ);
  521. X      if (count == -1)
  522. X         break;
  523. X   } while (!done);
  524. X   if (count == -1)
  525. X      return (-1);
  526. X   else
  527. X      return (0);
  528. X}
  529. X
  530. X/**** Function vmsread() does a standard read() but gets around bugs
  531. Xin the read() function of VAX/VMS C which make it unable to always
  532. Xread the entire amount requested in a single read() call.
  533. X*/
  534. Xint vmsread (han, buf, amount)
  535. Xint han;
  536. Xchar *buf;
  537. Xint amount;
  538. X{
  539. X   int count;
  540. X   int thiscount;
  541. X   count = 0;
  542. X   while (count != -1 && count < amount) {
  543. X      thiscount = read (han, &buf[count], amount - count);
  544. X      if (thiscount == 0)
  545. X         thiscount = read (han, &buf[count], amount - count);
  546. X      if (thiscount == 0)
  547. X          break;
  548. X      if (thiscount == -1)
  549. X         count = -1;
  550. X      else
  551. X         count += thiscount;
  552. X   }
  553. X   return (count);
  554. X}
  555. X
  556. Xprterror (level, msg1, msg2)
  557. Xchar level;
  558. Xchar *msg1, *msg2;
  559. X{
  560. X   if (level == 'e' || level == 'w' || level == 'f')
  561. X      printf ("BILF: ");
  562. X
  563. X   switch (level) {
  564. X      case 'e': printf ("ERROR: ");    break;
  565. X      case 'w': printf ("WARNING: ");  break;
  566. X      case 'f': printf ("FATAL: ");    break;
  567. X      default:  prterror ('f', "Internal error in prterror()\n");
  568. X   }
  569. X
  570. X   printf (msg1, msg2);
  571. X   if (level == 'f')
  572. X      exit (STAT_ABORT);
  573. X}
  574. END_OF_FILE
  575.   if test 6109 -ne `wc -c <'VMS/bilf/bilf.c'`; then
  576.     echo shar: \"'VMS/bilf/bilf.c'\" unpacked with wrong size!
  577.   fi
  578.   # end of 'VMS/bilf/bilf.c'
  579. fi
  580. if test -f 'extract.c' -a "${1}" != "-c" ; then 
  581.   echo shar: Will not clobber existing file \"'extract.c'\"
  582. else
  583.   echo shar: Extracting \"'extract.c'\" \(31421 characters\)
  584.   sed "s/^X//" >'extract.c' <<'END_OF_FILE'
  585. X/*---------------------------------------------------------------------------
  586. X
  587. X  extract.c
  588. X
  589. X  This file contains the high-level routines ("driver routines") for extrac-
  590. X  ting and testing zipfile members.  It calls the low-level routines in files
  591. X  inflate.c, unimplod.c, unreduce.c and unshrink.c.
  592. X
  593. X  ---------------------------------------------------------------------------*/
  594. X
  595. X
  596. X#include "unzip.h"
  597. X
  598. X
  599. X/************************************/
  600. X/*  Extract Local Prototypes, etc.  */
  601. X/************************************/
  602. X
  603. Xstatic int store_info __((void));
  604. Xstatic int extract_or_test_member __((void));
  605. X#ifdef CRYPT
  606. X   static int decrypt_member __((void));
  607. X#endif
  608. X
  609. Xstatic char *VersionMsg =
  610. X  " skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
  611. Xstatic char *ComprMsg =
  612. X  " skipping: %-22s  compression method %d\n";
  613. Xstatic char *FilNamMsg =
  614. X  "%s:  bad filename length (%s)\n";
  615. Xstatic char *ExtFieldMsg =
  616. X  "%s:  bad extra field length (%s)\n";
  617. Xstatic char *OffsetMsg =
  618. X  "file #%d:  bad zipfile offset (%s)\n";
  619. X
  620. X
  621. X
  622. X
  623. X
  624. X/**************************************/
  625. X/*  Function extract_or_test_files()  */
  626. X/**************************************/
  627. X
  628. Xint extract_or_test_files()    /* return PK-type error code */
  629. X{
  630. X    char **fnamev;
  631. X    byte *cd_inptr;
  632. X    int cd_incnt, error, error_in_archive=0;
  633. X    int renamed, query, len, filnum=(-1), blknum=0;
  634. X    UWORD i, j, members_remaining, num_skipped=0, num_bad_pwd=0;
  635. X    longint cd_bufstart, bufstart, inbuf_offset, request;
  636. X    min_info info[DIR_BLKSIZ];
  637. X
  638. X
  639. X/*---------------------------------------------------------------------------
  640. X    The basic idea of this function is as follows.  Since the central di-
  641. X    rectory lies at the end of the zipfile and the member files lie at the
  642. X    beginning or middle or wherever, it is not very desirable to simply
  643. X    read a central directory entry, jump to the member and extract it, and
  644. X    then jump back to the central directory.  In the case of a large zipfile
  645. X    this would lead to a whole lot of disk-grinding, especially if each mem-
  646. X    ber file is small.  Instead, we read from the central directory the per-
  647. X    tinent information for a block of files, then go extract/test the whole
  648. X    block.  Thus this routine contains two small(er) loops within a very
  649. X    large outer loop:  the first of the small ones reads a block of files
  650. X    from the central directory; the second extracts or tests each file; and
  651. X    the outer one loops over blocks.  There's some file-pointer positioning
  652. X    stuff in between, but that's about it.  Btw, it's because of this jump-
  653. X    ing around that we can afford to be lenient if an error occurs in one of
  654. X    the member files:  we should still be able to go find the other members,
  655. X    since we know the offset of each from the beginning of the zipfile.
  656. X
  657. X    Begin main loop over blocks of member files.  We know the entire central
  658. X    directory is on this disk:  we would not have any of this information un-
  659. X    less the end-of-central-directory record was on this disk, and we would
  660. X    not have gotten to this routine unless this is also the disk on which
  661. X    the central directory starts.  In practice, this had better be the ONLY
  662. X    disk in the archive, but maybe someday we'll add multi-disk support.
  663. X  ---------------------------------------------------------------------------*/
  664. X
  665. X    pInfo = info;
  666. X    members_remaining = ecrec.total_entries_central_dir;
  667. X
  668. X    while (members_remaining) {
  669. X        j = 0;
  670. X
  671. X        /*
  672. X         * Loop through files in central directory, storing offsets, file
  673. X         * attributes, and case-conversion flags until block size is reached.
  674. X         */
  675. X
  676. X        while (members_remaining && (j < DIR_BLKSIZ)) {
  677. X            --members_remaining;
  678. X            pInfo = &info[j];
  679. X
  680. X            if (readbuf(sig, 4) <= 0) {
  681. X                error_in_archive = 51;  /* 51:  unexpected EOF */
  682. X                members_remaining = 0;  /* ...so no more left to do */
  683. X                break;
  684. X            }
  685. X            if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
  686. X                fprintf(stderr, CentSigMsg, j);  /* sig not found */
  687. X                fprintf(stderr, ReportMsg);   /* check binary transfers */
  688. X                error_in_archive = 3;   /* 3:  error in zipfile */
  689. X                members_remaining = 0;  /* ...so no more left to do */
  690. X                break;
  691. X            }
  692. X            /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
  693. X            if ((error = process_cdir_file_hdr()) != 0) {
  694. X                error_in_archive = error;   /* only 51 (EOF) defined */
  695. X                members_remaining = 0;  /* ...so no more left to do */
  696. X                break;
  697. X            }
  698. X            if ((error = do_string(crec.filename_length, FILENAME)) != 0) {
  699. X                if (error > error_in_archive)
  700. X                    error_in_archive = error;
  701. X                if (error > 1) {  /* fatal:  no more left to do */
  702. X                    fprintf(stderr, FilNamMsg, filename, "central");
  703. X                    members_remaining = 0;
  704. X                    break;
  705. X                }
  706. X            }
  707. X            if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0)
  708. X            {
  709. X                if (error > error_in_archive)
  710. X                    error_in_archive = error;
  711. X                if (error > 1) {  /* fatal */
  712. X                    fprintf(stderr, ExtFieldMsg, filename, "central");
  713. X                    members_remaining = 0;
  714. X                    break;
  715. X                }
  716. X            }
  717. X            if ((error = do_string(crec.file_comment_length, SKIP)) != 0) {
  718. X                if (error > error_in_archive)
  719. X                    error_in_archive = error;
  720. X                if (error > 1) {  /* fatal */
  721. X                    fprintf(stderr, "\n%s:  bad file comment length\n",
  722. X                            filename);
  723. X                    members_remaining = 0;
  724. X                    break;
  725. X                }
  726. X            }
  727. X            if (process_all_files) {
  728. X                if (store_info())
  729. X                    ++num_skipped;
  730. X                else
  731. X                    ++j;  /* file is OK: save info[] and continue with next */
  732. X            } else {
  733. X                fnamev = fnv;   /* don't destroy permanent filename pointer */
  734. X                for (--fnamev; *++fnamev;)
  735. X                    if (match(filename, *fnamev)) {
  736. X                        if (store_info())
  737. X                            ++num_skipped;
  738. X                        else
  739. X                            ++j;   /* file is OK */
  740. X                        break;  /* found match for filename, so stop looping */
  741. X                    } /* end if (match), for-loop (fnamev) */
  742. X            } /* end if (process_all_files) */
  743. X
  744. X        } /* end while-loop (adding files to current block) */
  745. X
  746. X        /* save position in central directory so can come back later */
  747. X        cd_bufstart = cur_zipfile_bufstart;
  748. X        cd_inptr = inptr;
  749. X        cd_incnt = incnt;
  750. X
  751. X    /*-----------------------------------------------------------------------
  752. X        Second loop:  process files in current block, extracting or testing
  753. X        each one.
  754. X      -----------------------------------------------------------------------*/
  755. X
  756. X        for (i = 0; i < j; ++i) {
  757. X            filnum = i + blknum*DIR_BLKSIZ;
  758. X            pInfo = &info[i];
  759. X            /*
  760. X             * if the target position is not within the current input buffer
  761. X             * (either haven't yet read far enough, or (maybe) skipping back-
  762. X             * ward) skip to the target position and reset readbuf().
  763. X             */
  764. X            /* LSEEK(pInfo->offset):  */
  765. X            request = pInfo->offset + extra_bytes;
  766. X            inbuf_offset = request % INBUFSIZ;
  767. X            bufstart = request - inbuf_offset;
  768. X
  769. X            if (request < 0) {
  770. X                fprintf(stderr, SeekMsg, ReportMsg);
  771. X                error_in_archive = 3;       /* 3:  severe error in zipfile, */
  772. X                continue;                   /*  but can still go on */
  773. X            } else if (bufstart != cur_zipfile_bufstart) {
  774. X                cur_zipfile_bufstart = lseek(zipfd, bufstart, SEEK_SET);
  775. X                if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) <= 0) {
  776. X                    fprintf(stderr, OffsetMsg, filnum, "lseek");
  777. X                    error_in_archive = 3;   /* 3:  error in zipfile, but */
  778. X                    continue;               /*  can still do next file   */
  779. X                }
  780. X                inptr = inbuf + inbuf_offset;
  781. X                incnt -= inbuf_offset;
  782. X            } else {
  783. X                incnt += (inptr-inbuf) - inbuf_offset;
  784. X                inptr = inbuf + inbuf_offset;
  785. X            }
  786. X
  787. X            /* should be in proper position now, so check for sig */
  788. X            if (readbuf(sig, 4) <= 0) {  /* bad offset */
  789. X                fprintf(stderr, OffsetMsg, filnum, "EOF");
  790. X                error_in_archive = 3;    /* 3:  error in zipfile */
  791. X                continue;       /* but can still try next one */
  792. X            }
  793. X            if (strncmp(sig, local_hdr_sig, 4)) {
  794. X                fprintf(stderr, OffsetMsg, filnum,
  795. X                        "can't find local header sig");   /* bad offset */
  796. X                error_in_archive = 3;
  797. X                continue;
  798. X            }
  799. X            if ((error = process_local_file_hdr()) != 0) {
  800. X                fprintf(stderr, "\nfile #%d:  bad local header\n", filnum);
  801. X                error_in_archive = error;       /* only 51 (EOF) defined */
  802. X                continue;       /* can still try next one */
  803. X            }
  804. X            if ((error = do_string(lrec.filename_length, FILENAME)) != 0) {
  805. X                if (error > error_in_archive)
  806. X                    error_in_archive = error;
  807. X                if (error > 1) {
  808. X                    fprintf(stderr, FilNamMsg, filename, "local");
  809. X                    continue;   /* go on to next one */
  810. X                }
  811. X            }
  812. X            if ((error = do_string(lrec.extra_field_length, EXTRA_FIELD)) != 0)
  813. X            {
  814. X                if (error > error_in_archive)
  815. X                    error_in_archive = error;
  816. X                if (error > 1) {
  817. X                    fprintf(stderr, ExtFieldMsg, filename, "local");
  818. X                    continue;   /* go on */
  819. X                }
  820. X            }
  821. X
  822. X            /*
  823. X             * just about to extract file:  if extracting to disk, check if
  824. X             * already exists, and if so, take appropriate action according to
  825. X             * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
  826. X             * loop because we don't store the possibly renamed filename[] in
  827. X             * info[])
  828. X             */
  829. X            if (!tflag && !cflag) {
  830. X                renamed = FALSE;   /* user hasn't renamed output file yet */
  831. Xstartover:
  832. X                query = FALSE;
  833. X                /* mapname can create dirs if not freshening or if renamed */
  834. X                if ((error = mapname(!fflag || renamed)) > 1) {    /* skip */
  835. X                    if ((error > 2) && (error_in_archive < 2))
  836. X                        error_in_archive = 2;   /* (weak) error in zipfile */
  837. X                    continue;   /* go on to next file */
  838. X                }
  839. X
  840. X                switch (check_for_newer(filename)) {
  841. X                    case DOES_NOT_EXIST:
  842. X                        if (fflag && !renamed)  /* don't skip if just renamed */
  843. X                            continue;   /* freshen (no new files):  skip */
  844. X                        break;
  845. X                    case EXISTS_AND_OLDER:
  846. X                        if (overwrite_none)
  847. X                            continue;   /* never overwrite:  skip file */
  848. X                        if (!overwrite_all && !force_flag)
  849. X                            query = TRUE;
  850. X                        break;
  851. X                    case EXISTS_AND_NEWER:             /* (or equal) */
  852. X                        if (overwrite_none || (uflag && !renamed))
  853. X                            continue;  /* skip if update/freshen & orig name */
  854. X                        if (!overwrite_all && !force_flag)
  855. X                            query = TRUE;
  856. X                        break;
  857. X                }
  858. X#ifndef VMS     /* VMS creates higher version number instead of overwriting
  859. X                 * (will have to modify for VMS-style names with specific
  860. X                 *  version numbers:  just check V_flag?  don't use stat?) */
  861. X                if (query) {
  862. X                    fprintf(stderr,
  863. X                      "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ",
  864. X                      filename);
  865. X                    FFLUSH   /* for Amiga and Mac MPW */
  866. X                    fgets(answerbuf, 9, stdin);
  867. X                    switch (*answerbuf) {
  868. X                        case 'A':   /* dangerous option:  force caps */
  869. X                            overwrite_all = TRUE;
  870. X                            overwrite_none = FALSE;  /* just to make sure */
  871. X                            break;
  872. X                        case 'r':
  873. X                        case 'R':
  874. X                            do {
  875. X                                fprintf(stderr, "new name: ");
  876. X                                FFLUSH   /* for AMIGA and Mac MPW */
  877. X                                fgets(filename, FILNAMSIZ, stdin);
  878. X                                /* usually get \n here: better check for it */
  879. X                                len = strlen(filename);
  880. X                                if (filename[len-1] == '\n')
  881. X                                    filename[--len] = 0;
  882. X                            } while (len == 0);
  883. X                            renamed = TRUE;
  884. X                            goto startover;   /* sorry for a goto */
  885. X                        /*  break;   (never reached--dpk) */
  886. X                        case 'y':
  887. X                        case 'Y':
  888. X                            break;
  889. X                        case 'N':
  890. X                            overwrite_none = TRUE;
  891. X                            overwrite_all = FALSE;  /* make sure */
  892. X                            force_flag = FALSE;     /* ditto */
  893. X                            /* FALL THROUGH, skip */
  894. X                        case 'n':
  895. X                        default:
  896. X                            continue;   /* skip file */
  897. X                    } /* end switch (*answerbuf) */
  898. X                } /* end if (query) */
  899. X#endif /* !VMS */
  900. X            } /* end if (extracting to disk) */
  901. X
  902. X#ifdef CRYPT
  903. X            if (pInfo->encrypted && ((error = decrypt_member()) != 0)) {
  904. X                fprintf(stderr, " skipping: %-22s  incorrect password\n",
  905. X                  filename);
  906. X                ++num_bad_pwd;
  907. X            /*  if (error > error_in_archive)   >>until fix up error return<<
  908. X                    error_in_archive = error;    unable to test file... */
  909. X                continue;   /* go on to next file */
  910. X                /* GRR:  add loop here (2 or 3 times) for bad passwords */
  911. X            }
  912. X#endif /* CRYPT */
  913. X            disk_full = 0;
  914. X            if ((error = extract_or_test_member()) != 0) {
  915. X                if (error > error_in_archive)
  916. X                    error_in_archive = error;       /* ...and keep going */
  917. X                if (disk_full > 1)
  918. X                    return error_in_archive;        /* (unless disk full) */
  919. X            }
  920. X        } /* end for-loop (i:  files in current block) */
  921. X
  922. X
  923. X        /*
  924. X         * Jump back to where we were in the central directory, then go and do
  925. X         * the next batch of files.
  926. X         */
  927. X
  928. X        cur_zipfile_bufstart = lseek(zipfd, cd_bufstart, SEEK_SET);
  929. X        read(zipfd, (char *)inbuf, INBUFSIZ);  /* were there b4 ==> no error */
  930. X        inptr = cd_inptr;
  931. X        incnt = cd_incnt;
  932. X        ++blknum;
  933. X
  934. X#ifdef TEST
  935. X        printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
  936. X        printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
  937. X          cur_zipfile_bufstart);
  938. X        printf("inptr-inbuf = %d\n", inptr-inbuf);
  939. X        printf("incnt = %d\n\n", incnt);
  940. X#endif
  941. X
  942. X    } /* end while-loop (blocks of files in central directory) */
  943. X
  944. X/*---------------------------------------------------------------------------
  945. X    Double-check that we're back at the end-of-central-directory record, and
  946. X    print quick summary of results, if we were just testing the archive.  We
  947. X    send the summary to stdout so that people doing the testing in the back-
  948. X    ground and redirecting to a file can just do a "tail" on the output file.
  949. X  ---------------------------------------------------------------------------*/
  950. X
  951. X    readbuf(sig, 4);
  952. X    if (strncmp(sig, end_central_sig, 4)) {     /* just to make sure again */
  953. X        fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig */
  954. X        fprintf(stderr, ReportMsg);  /* check binary transfers */
  955. X        if (!error_in_archive)       /* don't overwrite stronger error */
  956. X            error_in_archive = 1;    /* 1:  warning error */
  957. X    }
  958. X    if (tflag && (quietflg == 1)) {
  959. X        int num=filnum+1 - num_bad_pwd;
  960. X
  961. X        if (error_in_archive)
  962. X            printf("At least one error was detected in %s.\n", zipfn);
  963. X        else if (num == 0)
  964. X            printf("Caution:  zero files tested in %s.\n", zipfn);
  965. X        else if (process_all_files && (num_skipped+num_bad_pwd == 0))
  966. X            printf("No errors detected in %s.\n", zipfn);
  967. X        else
  968. X            printf("No errors detected in %s for the %d file%s tested.\n",
  969. X              zipfn, num, (num==1)? "":"s");
  970. X        if (num_skipped > 0)
  971. X            printf("%d file%s skipped because of unsupported compression or\
  972. X encoding.\n",
  973. X              num_skipped, (num_skipped==1)? "":"s");
  974. X#ifdef CRYPT
  975. X        if (num_bad_pwd > 0)
  976. X            printf("%d file%s skipped because of incorrect password.\n",
  977. X              num_bad_pwd, (num_bad_pwd==1)? "":"s");
  978. X#endif /* CRYPT */
  979. X    }
  980. X    if ((num_skipped > 0) && !error_in_archive)   /* files not tested or  */
  981. X        error_in_archive = 1;                     /*  extracted:  warning */
  982. X#ifdef CRYPT
  983. X    if ((num_bad_pwd > 0) && !error_in_archive)   /* files not tested or  */
  984. X        error_in_archive = 1;                     /*  extracted:  warning */
  985. X#endif /* CRYPT */
  986. X
  987. X    return (error_in_archive);
  988. X
  989. X} /* end function extract_or_test_files() */
  990. X
  991. X
  992. X
  993. X
  994. X
  995. X/***************************/
  996. X/*  Function store_info()  */
  997. X/***************************/
  998. X
  999. Xstatic int store_info()   /* return 1 if skipping, 0 if OK */
  1000. X{
  1001. X    ULONG tmp;
  1002. X
  1003. X#ifdef INFLATE
  1004. X#  define UNKN_COMPR \
  1005. X   (crec.compression_method>IMPLODED && crec.compression_method!=DEFLATED)
  1006. X#else
  1007. X#  define UNKN_COMPR   (crec.compression_method>IMPLODED)
  1008. X#endif
  1009. X
  1010. X
  1011. X/*---------------------------------------------------------------------------
  1012. X    Check central directory info for version/compatibility requirements.
  1013. X  ---------------------------------------------------------------------------*/
  1014. X
  1015. X    pInfo->encrypted = crec.general_purpose_bit_flag & 1;    /* bit field */
  1016. X    pInfo->ExtLocHdr = (crec.general_purpose_bit_flag & 8) == 8;  /* bit */
  1017. X    pInfo->text = crec.internal_file_attributes & 1;         /* bit field */
  1018. X/*  pInfo->crc = crec.crc32;  (no longer used) */
  1019. X
  1020. X    if (crec.version_needed_to_extract[1] == VMS_) {
  1021. X        if (crec.version_needed_to_extract[0] > VMS_VERSION) {
  1022. X            fprintf(stderr, VersionMsg, filename, "VMS",
  1023. X              crec.version_needed_to_extract[0] / 10,
  1024. X              crec.version_needed_to_extract[0] % 10,
  1025. X              VMS_VERSION / 10, VMS_VERSION % 10);
  1026. X            return 1;
  1027. X        }
  1028. X#ifndef VMS   /* won't be able to use extra field, but still have data */
  1029. X        else if (!tflag && !force_flag) {  /* if forcing, extract regardless */
  1030. X            fprintf(stderr,
  1031. X              "\n%s:  stored in VMS format.  Extract anyway? (y/n) ",
  1032. X              filename);
  1033. X            FFLUSH   /* for Amiga and Mac MPW */
  1034. X            fgets(answerbuf, 9, stdin);
  1035. X            if ((*answerbuf != 'y') && (*answerbuf != 'Y'))
  1036. X                return 1;
  1037. X        }
  1038. X#endif /* !VMS */
  1039. X    /* usual file type:  don't need VMS to extract */
  1040. X    } else if (crec.version_needed_to_extract[0] > UNZIP_VERSION) {
  1041. X        fprintf(stderr, VersionMsg, filename, "PK",
  1042. X          crec.version_needed_to_extract[0] / 10,
  1043. X          crec.version_needed_to_extract[0] % 10,
  1044. X          UNZIP_VERSION / 10, UNZIP_VERSION % 10);
  1045. X        return 1;
  1046. X    }
  1047. X
  1048. X    if UNKN_COMPR {
  1049. X        fprintf(stderr, ComprMsg, filename, crec.compression_method);
  1050. X        return 1;
  1051. X    }
  1052. X#ifndef CRYPT
  1053. X    if (pInfo->encrypted) {
  1054. X        fprintf(stderr, " skipping: %-22s  encrypted (not supported)\n",
  1055. X          filename);
  1056. X        return 1;
  1057. X    }
  1058. X#endif /* !CRYPT */
  1059. X
  1060. X/*---------------------------------------------------------------------------
  1061. X    Store some central-directory information (encryption, file attributes,
  1062. X    offsets) for later use.
  1063. X  ---------------------------------------------------------------------------*/
  1064. X
  1065. X    tmp = crec.external_file_attributes;
  1066. X
  1067. X    pInfo->dos_attr = 32;   /* set archive bit:  file is not backed up */
  1068. X    switch (pInfo->hostnum) {
  1069. X        case UNIX_:
  1070. X        case VMS_:
  1071. X            pInfo->unix_attr = tmp >> 16;
  1072. X            break;
  1073. X        case DOS_OS2_FAT_:
  1074. X        case OS2_HPFS_:
  1075. X            pInfo->dos_attr = (unsigned) tmp;
  1076. X            tmp = (!(tmp & 1)) << 1;   /* read-only bit */
  1077. X            pInfo->unix_attr = 0444 | (tmp<<6) | (tmp<<3) | tmp;
  1078. X#ifdef UNIX
  1079. X            umask( (int)(tmp=umask(0)) );
  1080. X            pInfo->unix_attr &= ~tmp;
  1081. X#endif
  1082. X            break;
  1083. X        case MAC_:
  1084. X            tmp &= 1;   /* read-only bit */
  1085. X            pInfo->unix_attr = tmp;
  1086. X            break;
  1087. X        default:
  1088. X            pInfo->unix_attr = 0666;
  1089. X            break;
  1090. X    } /* end switch (host-OS-created-by) */
  1091. X
  1092. X    pInfo->offset = (longint) crec.relative_offset_local_header;
  1093. X    return 0;
  1094. X
  1095. X} /* end function store_info() */
  1096. X
  1097. X
  1098. X
  1099. X
  1100. X
  1101. X/***************************************/
  1102. X/*  Function extract_or_test_member()  */
  1103. X/***************************************/
  1104. X
  1105. Xstatic int extract_or_test_member()    /* return PK-type error code */
  1106. X{
  1107. X#ifdef S_IFLNK
  1108. X    int symlnk=FALSE;
  1109. X#endif /* S_IFLNK */
  1110. X    int error=0;
  1111. X    UWORD b;
  1112. X
  1113. X
  1114. X
  1115. X/*---------------------------------------------------------------------------
  1116. X    Initialize variables, buffers, etc.
  1117. X  ---------------------------------------------------------------------------*/
  1118. X
  1119. X    bits_left = 0;
  1120. X    bitbuf = 0L;
  1121. X    outpos = 0L;
  1122. X    outcnt = 0;
  1123. X    outptr = outbuf;
  1124. X    zipeof = 0;
  1125. X    crc32val = 0xFFFFFFFFL;
  1126. X
  1127. X#ifdef S_IFLNK
  1128. X    if ((pInfo->unix_attr & S_IFMT) == S_IFLNK  &&  (pInfo->hostnum == UNIX_)
  1129. X        && !tflag && !cflag)
  1130. X        symlnk = TRUE;
  1131. X#endif /* S_IFLNK */
  1132. X
  1133. X    memset(outbuf, 0, OUTBUFSIZ);
  1134. X#ifndef DOS_OS2
  1135. X    if (aflag)                  /* if we have a scratchpad, clear it out */
  1136. X        memset(outout, 0, OUTBUFSIZ);
  1137. X#endif /* !DOS_OS2 */
  1138. X
  1139. X    if (tflag) {
  1140. X        if (!quietflg) {
  1141. X            fprintf(stdout, "  Testing: %-22s ", filename);
  1142. X            fflush(stdout);
  1143. X        }
  1144. X    } else {
  1145. X        if (cflag) {            /* output to stdout (copy of it) */
  1146. X#if defined(MACOS) || defined(AMIGA)
  1147. X            outfd = 1;
  1148. X#else /* !(MACOS || AMIGA) */
  1149. X            outfd = dup(1);     /* GRR: change this to #define for Mac/Amiga */
  1150. X#endif /* ?(MACOS || AMIGA) */
  1151. X#ifdef DOS_OS2
  1152. X            if (!aflag)
  1153. X                setmode(outfd, O_BINARY);
  1154. X#endif /* DOS_OS2 */
  1155. X#ifdef VMS
  1156. X            if (create_output_file())   /* VMS version required for stdout! */
  1157. X                return 50;      /* 50:  disk full (?) */
  1158. X#endif
  1159. X        } else
  1160. X#ifdef S_IFLNK
  1161. X        if (!symlnk)    /* symlink() takes care of file creation */
  1162. X#endif /* !S_IFLNK */
  1163. X        {
  1164. X            if (create_output_file())
  1165. X                return 50;      /* 50:  disk full (?) */
  1166. X        }
  1167. X    } /* endif (!tflag) */
  1168. X
  1169. X/*---------------------------------------------------------------------------
  1170. X    Unpack the file.
  1171. X  ---------------------------------------------------------------------------*/
  1172. X
  1173. X    switch (lrec.compression_method) {
  1174. X
  1175. X    case STORED:
  1176. X        if (!tflag && QCOND) {
  1177. X            fprintf(stdout, " Extracting: %-22s ", filename);
  1178. X            if (cflag)
  1179. X                fprintf(stdout, "\n");
  1180. X            fflush(stdout);
  1181. X        }
  1182. X#ifdef S_IFLNK
  1183. X        /*
  1184. X         * If file came from Unix and is a symbolic link and we are extracting
  1185. X         * to disk, allocate a storage area, put the data in it, and create the
  1186. X         * link.  Since we know it's a symbolic link to start with, shouldn't
  1187. X         * have to worry about overflowing unsigned ints with unsigned longs.
  1188. X         * (This doesn't do anything for compressed symlinks, but that can be
  1189. X         * added later...it also doesn't set the time or permissions of the
  1190. X         * link, but does anyone really care?)
  1191. X         */
  1192. X        if (symlnk) {
  1193. X#if defined(MTS) || defined(MACOS)
  1194. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1195. X            error = 1;          /* 1:  warning error */
  1196. X#else /* !(MTS || MACOS) */
  1197. X            char *orig = (char *)malloc((unsigned)lrec.uncompressed_size+1);
  1198. X            char *p = orig;
  1199. X
  1200. X            while (ReadByte(&b))
  1201. X                *p++ = b;
  1202. X            *p = 0;   /* terminate string */
  1203. X            UpdateCRC((unsigned char *)orig, p-orig);
  1204. X            if (symlink(orig, filename))
  1205. X                if ((errno == EEXIST) && overwrite_all) {  /* OK to overwrite */
  1206. X                    unlink(filename);
  1207. X                    if (symlink(orig, filename))
  1208. X                        perror("symlink error");
  1209. X                } else
  1210. X                    perror("symlink error");
  1211. X            free(orig);
  1212. X#endif /* ?(MTS || MACOS) */
  1213. X        } else
  1214. X#endif /* S_IFLNK */
  1215. X        while (ReadByte(&b) && !disk_full)
  1216. X            OUTB(b)
  1217. X        break;
  1218. X
  1219. X    case SHRUNK:
  1220. X        if (!tflag && QCOND) {
  1221. X            fprintf(stdout, "UnShrinking: %-22s ", filename);
  1222. X            if (cflag)
  1223. X                fprintf(stdout, "\n");
  1224. X            fflush(stdout);
  1225. X        }
  1226. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  1227. X        if (symlnk) {
  1228. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1229. X            error = 1;          /* 1:  warning error */
  1230. X        }
  1231. X#endif /* S_IFLNK */
  1232. X        unShrink();
  1233. X        break;
  1234. X
  1235. X    case REDUCED1:
  1236. X    case REDUCED2:
  1237. X    case REDUCED3:
  1238. X    case REDUCED4:
  1239. X        if (!tflag && QCOND) {
  1240. X            fprintf(stdout, "  Expanding: %-22s ", filename);
  1241. X            if (cflag)
  1242. X                fprintf(stdout, "\n");
  1243. X            fflush(stdout);
  1244. X        }
  1245. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  1246. X        if (symlnk) {
  1247. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1248. X            error = 1;          /* 1:  warning error */
  1249. X        }
  1250. X#endif /* S_IFLNK */
  1251. X        unReduce();
  1252. X        break;
  1253. X
  1254. X    case IMPLODED:
  1255. X        if (!tflag && QCOND) {
  1256. X            fprintf(stdout, "  Exploding: %-22s ", filename);
  1257. X            if (cflag)
  1258. X                fprintf(stdout, "\n");
  1259. X            fflush(stdout);
  1260. X        }
  1261. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  1262. X        if (symlnk) {
  1263. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1264. X            error = 1;          /* 1:  warning error */
  1265. X        }
  1266. X#endif /* S_IFLNK */
  1267. X        unImplode();
  1268. X        break;
  1269. X
  1270. X#ifdef INFLATE
  1271. X    case DEFLATED:
  1272. X        if (!tflag && QCOND) {
  1273. X            fprintf(stdout, "  Deflating: %-22s ", filename);
  1274. X            if (cflag)
  1275. X                fprintf(stdout, "\n");
  1276. X            fflush(stdout);
  1277. X        }
  1278. X#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
  1279. X        if (symlnk) {
  1280. X            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
  1281. X            error = 1;          /* 1:  warning error */
  1282. X        }
  1283. X#endif /* S_IFLNK */
  1284. X        inflate();
  1285. X        break;
  1286. X#endif /* INFLATE */
  1287. X
  1288. X    default:   /* should never get to this point */
  1289. X        fprintf(stderr, "%s:  unknown compression method\n", filename);
  1290. X        /* close and delete file before return? */
  1291. X        return 1;               /* 1:  warning error */
  1292. X
  1293. X    } /* end switch (compression method) */
  1294. X
  1295. X    if (disk_full) {            /* set by FlushOutput()/OUTB() macro */
  1296. X        if (disk_full > 1)
  1297. X            return 50;          /* 50:  disk full */
  1298. X        error = 1;              /* 1:  warning error */
  1299. X    }
  1300. X
  1301. X/*---------------------------------------------------------------------------
  1302. X    Write the last partial buffer, if any; set the file date and time; and
  1303. X    close the file (not necessarily in that order).  Then make sure CRC came
  1304. X    out OK and print result.  [Note:  crc32val must be logical-ANDed with
  1305. X    32 bits of 1's, or else machines whose longs are bigger than 32 bits will
  1306. X    report bad CRCs (because of the upper bits being filled with 1's instead
  1307. X    of 0's).]
  1308. X  ---------------------------------------------------------------------------*/
  1309. X
  1310. X#ifdef S_IFLNK
  1311. X    if (!symlnk) {
  1312. X#endif /* S_IFLNK */
  1313. X    if (!disk_full && FlushOutput())
  1314. X        if (disk_full > 1)
  1315. X            return 50;          /* 50:  disk full */
  1316. X        else {                  /* disk_full == 1 */
  1317. X            fprintf(stderr, "%s:  probably corrupt\n", filename);
  1318. X            error = 1;          /* 1:  warning error */
  1319. X        }
  1320. X
  1321. X    if (!tflag)
  1322. X#ifdef VMS
  1323. X        CloseOutputFile();
  1324. X#else /* !VMS */
  1325. X#ifdef MTS                      /* MTS can't set file time */
  1326. X        close(outfd);
  1327. X#else /* !MTS */
  1328. X        set_file_time_and_close();
  1329. X#endif /* ?MTS */
  1330. X#endif /* ?VMS */
  1331. X
  1332. X#ifdef S_IFLNK
  1333. X    } /* endif (!symlnk) */
  1334. X#endif /* S_IFLNK */
  1335. X
  1336. X    if ((crc32val = ((~crc32val) & 0xFFFFFFFFL)) != lrec.crc32) {
  1337. X        /* if quietflg is set, we haven't output the filename yet:  do it */
  1338. X        if (quietflg)
  1339. X            printf("%-22s: ", filename);
  1340. X        fprintf(stdout, " Bad CRC %08lx  (should be %08lx)\n", crc32val,
  1341. X                lrec.crc32);
  1342. X        error = 1;              /* 1:  warning error */
  1343. X    } else if (tflag) {
  1344. X        if (!quietflg)
  1345. X            fprintf(stdout, " OK\n");
  1346. X    } else {
  1347. X        if (QCOND && !error)
  1348. X            fprintf(stdout, "\n");
  1349. X    }
  1350. X
  1351. X    return error;
  1352. X
  1353. X}       /* end function extract_or_test_member() */
  1354. X
  1355. X
  1356. X
  1357. X
  1358. X
  1359. X#ifdef CRYPT
  1360. X
  1361. X/*******************************/
  1362. X/*  Function decrypt_member()  */
  1363. X/*******************************/
  1364. X
  1365. Xstatic int decrypt_member()   /* return 10 if out of memory or can't get */
  1366. X{                             /*  tty; -1 if bad password; 0 if checks out */
  1367. X    UWORD b, c;
  1368. X    byte *p;
  1369. X    int n, t;
  1370. X
  1371. X    /* set keys */
  1372. X    if (key == NULL && ((key = malloc(PWLEN+1)) == NULL ||
  1373. X         getp("Enter password: ", key, PWLEN+1) == NULL))
  1374. X        return 10;        /* what to return here? */
  1375. X    init_keys(key);
  1376. X
  1377. X    /* decrypt current buffer contents, set flag to re-read if necessary */
  1378. X    for (n = incnt > csize ? (int)csize : incnt, p = inptr; n--; p++)
  1379. X        *p = DECRYPT(*p);
  1380. X
  1381. X    /* decrypt header */
  1382. X    for (c = 0; c < 10; c++)
  1383. X        ReadByte(&b);
  1384. X    ReadByte(&c);
  1385. X    ReadByte(&b);
  1386. X#ifdef CRYPT_DEBUG
  1387. X    printf("   lrec.crc = %08lx   crec.crc = [ ? ]   pInfo->ExtLocHdr = %s\n",
  1388. X      lrec.crc32, /* pInfo->crc, */ pInfo->ExtLocHdr? "true":"false");
  1389. X    printf("   incnt = %d   unzip offset into zipfile = %ld\n", incnt,
  1390. X      cur_zipfile_bufstart+(inptr-inbuf));
  1391. X    printf("   (c | (b<<8)) = %04x   (crc >> 16) = %04x   lrec.time = %04x\n",
  1392. X      (UWORD)(c | (b<<8)), (UWORD)(lrec.crc32 >> 16), lrec.last_mod_file_time);
  1393. X#endif /* CRYPT_DEBUG */
  1394. X    /* same test as in zipbare() in crypt.c */
  1395. X    if ((UWORD)(c | (b<<8)) != (pInfo->ExtLocHdr? lrec.last_mod_file_time :
  1396. X        (UWORD)(lrec.crc32 >> 16)))
  1397. X        return -1;
  1398. X    return 0;
  1399. X}
  1400. X
  1401. X#endif /* CRYPT */
  1402. END_OF_FILE
  1403.   if test 31421 -ne `wc -c <'extract.c'`; then
  1404.     echo shar: \"'extract.c'\" unpacked with wrong size!
  1405.   fi
  1406.   # end of 'extract.c'
  1407. fi
  1408. echo shar: End of archive 5 \(of 12\).
  1409. cp /dev/null ark5isdone
  1410. MISSING=""
  1411. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1412.     if test ! -f ark${I}isdone ; then
  1413.     MISSING="${MISSING} ${I}"
  1414.     fi
  1415. done
  1416. if test "${MISSING}" = "" ; then
  1417.     echo You have unpacked all 12 archives.
  1418.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1419. else
  1420.     echo You still must unpack the following archives:
  1421.     echo "        " ${MISSING}
  1422. fi
  1423. exit 0
  1424. exit 0 # Just in case...
  1425.