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

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: zip-bugs@cs.ucla.edu (Info-ZIP group)
  4. Subject:  v31i112:  unzip50 - Info-ZIP portable UnZip, version 5.0, Part09/14
  5. Message-ID: <1992Aug24.025659.25051@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 6a5e93b9b352571481748a7a0fb1ea7c
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v31i104=unzip50.215137@sparky.IMD.Sterling.COM>
  11. Date: Mon, 24 Aug 1992 02:56:59 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 1517
  14.  
  15. Submitted-by: zip-bugs@cs.ucla.edu (Info-ZIP group)
  16. Posting-number: Volume 31, Issue 112
  17. Archive-name: unzip50/part09
  18. Supersedes: unzip: Volume 29, Issue 31-42
  19. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT AMIGA?, !ATARI, symlink, SGI, DEC, Cray, Convex, Amdahl, Sun
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then feed it
  23. # into a shell via "sh file" or similar.  To overwrite existing files,
  24. # type "sh file -c".
  25. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  26. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  27. # Contents:  MAC/macstat.h VMS/VMS.notes explode.c zipinfo.1
  28. # Wrapped by kent@sparky on Sun Aug 23 21:09:34 1992
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. echo If this archive is complete, you will see the following message:
  31. echo '          "shar: End of archive 9 (of 14)."'
  32. if test -f 'MAC/macstat.h' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'MAC/macstat.h'\"
  34. else
  35.   echo shar: Extracting \"'MAC/macstat.h'\" \(974 characters\)
  36.   sed "s/^X//" >'MAC/macstat.h' <<'END_OF_FILE'
  37. X/*****************************************************************
  38. X *
  39. X *                stat.h
  40. X *
  41. X *****************************************************************/
  42. X
  43. X#include <time.h>
  44. Xextern int macstat(char *path, struct stat *buf, short nVRefNum, long lDirID );
  45. Xtypedef long dev_t;
  46. Xtypedef long ino_t;
  47. Xtypedef long off_t;
  48. X
  49. Xstruct stat {
  50. X    dev_t    st_dev;
  51. X    ino_t    st_ino;
  52. X    unsigned short    st_mode;
  53. X    short    st_nlink;
  54. X    short    st_uid;
  55. X    short    st_gid;
  56. X    dev_t    st_rdev;
  57. X    off_t    st_size;
  58. X    time_t   st_atime, st_mtime, st_ctime;
  59. X    long     st_blksize;
  60. X    long     st_blocks;
  61. X};
  62. X
  63. X#define S_IFMT     0xF000
  64. X#define S_IFIFO    0x1000
  65. X#define S_IFCHR    0x2000
  66. X#define S_IFDIR    0x4000
  67. X#define S_IFBLK    0x6000
  68. X#define S_IFREG    0x8000
  69. X#define S_IFLNK    0xA000
  70. X#define S_IFSOCK   0xC000
  71. X#define S_ISUID    0x800
  72. X#define S_ISGID    0x400
  73. X#define S_ISVTX    0x200
  74. X#define S_IREAD    0x100
  75. X#define S_IWRITE   0x80
  76. X#define S_IEXEC    0x40
  77. END_OF_FILE
  78.   if test 974 -ne `wc -c <'MAC/macstat.h'`; then
  79.     echo shar: \"'MAC/macstat.h'\" unpacked with wrong size!
  80.   fi
  81.   # end of 'MAC/macstat.h'
  82. fi
  83. if test -f 'VMS/VMS.notes' -a "${1}" != "-c" ; then 
  84.   echo shar: Will not clobber existing file \"'VMS/VMS.notes'\"
  85. else
  86.   echo shar: Extracting \"'VMS/VMS.notes'\" \(13719 characters\)
  87.   sed "s/^X//" >'VMS/VMS.notes' <<'END_OF_FILE'
  88. X                     VMS Notes for UnZip 5.0
  89. X                           24 May 1992
  90. X
  91. X
  92. XThe various VMS tweaks to UnZip 5.0 and ZipInfo 0.97 were tested on a 
  93. XVAX 8600 running VMS 5.2 (and, later, VMS 5.4) and VAX C 3.0.  Older 
  94. Xversions were also tested on a VAX 11/785.
  95. X
  96. XTo build UnZip (and its trusty sidekick, ZipInfo), just run one of the 
  97. Xincluded command files MAKE_UNZIP_VAXC.COM or MAKE_UNZIP_GCC.COM, either
  98. Xdecryption or non-decryption versions, depending on whether you have the
  99. Xseparate crypt.c module and whether you use VAX C or GNU C (for example, 
  100. X"@make_unzip_vaxc").  By default, this creates shareable-image executables,
  101. Xwhich are smaller and (supposedly) load faster than the normal type.  They 
  102. Xalso (supposedly) will be better able to take advantage of any bug fixes 
  103. Xor new capabilities that DEC might introduce, since the library code isn't 
  104. Xbuilt into the executable.  The shared executable is about a quarter the 
  105. Xsize of the ordinary type in the case of UnZip.
  106. X
  107. X[Btw, the VMS make utility "MMS" is not compatible enough with Unix make 
  108. Xto use the same makefile.  Antonio Querubin, Jr., sent along an MMS makefile,
  109. Xsubsequently modified by Igor Mandrichenko.  Read the comments at the top 
  110. Xof DESCRIP.MMS for more info.  An alternate Unix-like makefile designed for 
  111. Xuse with Todd Aven's MAKE/VMS is included, as well.  Comments on where to
  112. Xget MAKE/VMS are at the bottom of VMS Contents.]
  113. X
  114. XUnZip is written to return the standard PK-type return codes (or error
  115. Xcodes, or exit codes, or whatever you want to call them).  Unfortunately,
  116. XVMS insists on interpreting the codes in its own lovable way, and this
  117. Xresults in endearing commentary such as "access violation, error mask =
  118. X0005, PC = 00003afc" (or something like that) when you run UnZip with no
  119. Xarguments.  To avoid this I've added a special VMS_return() function which
  120. Xeither ignores the error codes (and exits with normal status) or interprets
  121. Xthem, prints a semi-informative message (enclosed in square [] brackets), 
  122. Xand then exits with a normal error status.  I personally can't stand the 
  123. Xlatter behavior, so by default the error codes are simply ignored.  Tastes
  124. Xvary, however, and some people may actually like semi-informative messages.
  125. XIf you happen to be one of those people, you may enable the messages by 
  126. Xrecompiling misc.c with RETURN_CODES defined.  (This adds a block or two
  127. Xto the executable size, though.)  The syntax is as follows:
  128. X    cc /def=(RETURN_CODES) misc
  129. X
  130. XTo use UnZip in the normal way, define a symbol "unzip" as follows:
  131. X    unzip :== "$diskname:[directory]unzip.exe"
  132. X(substitute for "diskname" and "directory" as appropriate, and DON'T FORGET
  133. XTHE `$'!  It won't work if you omit that.)  In general it's wise to stick 
  134. Xsuch assignments in your LOGIN.COM file and THEN forget about them.  It is 
  135. Xno longer necessary to worry about the record type of the zipfile...er, 
  136. Xwell, most of the time, anyway (see the Kermit section below).
  137. X
  138. XHaving done all this you are ready to roll.  Use the unzip command in
  139. Xthe usual way; as with the Unix, OS/2 and MS-DOS versions, this one uses 
  140. X'-' as a switch character.  If nothing much happens when you do a directory
  141. Xlisting, for example, you're probably trying to specify a filename which
  142. Xhas uppercase letters in it...VMS thoughtfully converts everything on the
  143. Xcommand line to lowercase, so even if you type:
  144. X    unzip -v zipfile Makefile
  145. Xwhat you get is:
  146. X    unzip -v zipfile makefile
  147. Xwhich, in my example here, doesn't match the contents of the zipfile.
  148. XThis is relatively easy to circumvent by enclosing the filespec(s) in 
  149. Xquotes:
  150. X    unzip -tq unzip401 "Makefile" "VMS*" *.c *.h
  151. X[This example also demonstrates the use of wildcards, which act like Unix
  152. Xwildcards, not VMS ones.   In other words, "VMS*" matches files VMSNOTES,
  153. XVMS_MAKE.COM, and VMSSHARE.OPT, whereas the normal VMS behavior would be
  154. Xto match only the first file (since the others have extensions--ordinarily,
  155. Xyou would be required to specify "VMS*.*").]
  156. X
  157. XNote that created files get whatever default permissions you've set, but 
  158. Xcreated directories additionally inherit the (possibly more restrictive) 
  159. Xpermissions of the parent directory.  And, of course, things probably won't 
  160. Xwork too well if you don't have permission to write to whatever directory 
  161. Xinto which you're trying to extract things.  (That made sense; read it 
  162. Xagain if you don't believe me.)
  163. X
  164. XZipInfo, by the way, is an amusing little utility which tells you all sorts
  165. Xof amazingly useless information about zipfiles.  Occasionally it's useful
  166. Xto debug a problem with a corrupted zipfile (for example, we used it to 
  167. Xfind a bug in PAK-created zipfiles, versions 2.5 and earlier).  Feel free
  168. Xto blow it away if you don't need it.  It's about 30 blocks on my system,
  169. Xand I find I actually prefer its listing format to that of UnZip now (hardly
  170. Xsurprising, since I wrote it :-) ).  I also find it useful to use "ii" 
  171. Xrather than "zipinfo" as the symbol for zipinfo, since it's easier to type 
  172. Xthan either "zipinfo" or "unzip -v", and it echoes the common Unix alias 
  173. X"ll" for the similar style of directory listings.  Oh, and the reason it's 
  174. Xstill got a beta version number is that I haven't finished it yet--it would 
  175. Xbe better with an automatic paging function, for example.  Oh well.
  176. X
  177. XRANDOM OTHER NOTES:  (1) Igor Mandrichenko (leader of our fearless Russian 
  178. Xcontingent) rewrote major portions of the VMS file-handling code, with
  179. Xthe result that UnZip is much smarter now about VMS file formats.  For
  180. Xfull VMS compatibility (file attributes, ownership info, etc.), be sure
  181. Xto use the -X option of Zip 1.6 and later.  There are also some notes
  182. Xat the end of this file from Hugh Schmidt and Mike Freeman which give 
  183. Xhints on how to save VMS attributes using Zip 1.0 and UnZip 4.1.  Most of
  184. Xthe information is still valid, but the -X option is much easier if you
  185. Xdon't have to transfer the zipfiles to a Unix or PC system.  (2) Zip 1.0 
  186. Xcannot handle any zipfile that isn't in stream-LF format, so you may need 
  187. Xto use Rahul Dhesi's BILF utility which is included with UnZip.  It will
  188. Xalso be necessary for certain other special occasions, like when you've 
  189. Xforgotten to set the correct Kermit parameters while uploading a zipfile 
  190. X(see Hugh Schmidt's note below for comments about Kermit, too).
  191. X
  192. XGreg Roelofs
  193. X
  194. X====================
  195. X
  196. XFrom INFO-ZIP Digest (Wed, 6 Nov 1991), Volume 91, Issue 290
  197. X
  198. X                VMS attributes and PKZIP compatibility
  199. X                  VMS attributes restored! (2 msgs)
  200. X
  201. X------------------------------
  202. X
  203. XDate: Tue, 5 Nov 91 15:31 CDT
  204. XFrom: Hugh Schmidt <HUGH@macc.wisc.edu>
  205. XSubject: VMS attributes and PKZIP compatibility
  206. XMessage-ID: <21110515313938@vms.macc.wisc.edu>
  207. X
  208. X           ******************************************************
  209. X(1)        *** Retaining VMS attributes - a proposed strategy ***
  210. X           ******************************************************
  211. X
  212. XThis is a proposed strategy for recovering VMS file attributes after
  213. Xzip/unzip:
  214. X
  215. Xa) capture VMS file attributes: VMS ANALYZE/RMS/FDL/OUTPUT=fdlfile vmsfile.ext
  216. Xb) compress files on VMS......: ZIP zipfile vmsfile.ext, fdlfile.fdl
  217. Xc) uncompress files on VMS....: UNZIP zipfile vmsfile.ext, fdlfile.fdl
  218. Xd) recover VMS file attributes: CONVERT/FDL=fdlfile.fdl vmsfile.ext vmsfile.ext
  219. X
  220. XThe wrinkle is that UNZIP creates files which are unreadable by CONVERT
  221. Xdespite a concerted effort to accomodate VMS file management system:
  222. X
  223. Xfile_io.c, line 178: ...creat(filename,0, "rat=cr", "rfm=streamlf")
  224. X
  225. XThese files are unCONVERTABLE because they appear to VMS to contain
  226. Xrecords with 512+ bytes.  Poring over VMS manuals (Programming V-6A, VAX
  227. XC RTL Reference Manual) doesn't readily suggest better alternatives.
  228. XExperimentation with "rat=fix", etc. may help suppress the spurious
  229. Xblock-end delimeters.
  230. X
  231. X          ****************************************************
  232. X(2)       *** VMS ZIP and PKZIP compatibility using KERMIT ***
  233. X          ****************************************************
  234. X
  235. XMany use Procomm's kermit to transfer zipped files between PC and VMS
  236. XVAX.  The following VMS kermit settings make VMS-ZIP compatible with
  237. XPKZIP:
  238. X
  239. X                                             VMS kermit      Procomm kermit
  240. X                                           ---------------   --------------
  241. XUploading PKZIPped file to be UNZIPped:    set fi ty fixed    set fi ty bi
  242. XDownloading ZIPped file to be PKUNZIPped:  set fi ty block    set fi ty bi
  243. X
  244. X"Block I/O lets you bypass the VMS RMS record-processing capabilities
  245. Xentirely", (Guide to VMS file applications, Section 8.5).  The kermit
  246. Xguys must have known this!
  247. X
  248. X         ************************************************
  249. X(3)      *** Making ZIP files compatible with VMS RMS ***
  250. X         ************************************************
  251. X
  252. XIt looks like a crummy patch, but to make VMS RMS happy, I inserted the
  253. Xfollowing near line 570 in the putend() section of zipfile.c:
  254. X
  255. X#ifdef VMS
  256. X fprintf(f,"\n")
  257. X#endif
  258. X
  259. XIt's probably of no consequence, but it satisfies VMS ANALYZE.
  260. X
  261. X------------------------------
  262. X
  263. XDate: Tue, 5 Nov 91 19:40 CDT
  264. XFrom: Hugh Schmidt <HUGH@macc.wisc.edu>
  265. XSubject: VMS attributes restored!
  266. XMessage-ID: <21110519403912@vms.macc.wisc.edu>
  267. X
  268. X           ************************************************************
  269. X           ***   Aha!  It works!  VMS attributes can be restored! *****
  270. X           ***                                                      ***
  271. X           *** Change FAB$C_STMLF to FAB$C_FIX in file_io.c         ***
  272. X           *** ANALYZE => .FDL | CONVERT => original VMS attributes ***
  273. X           ************************************************************
  274. X
  275. X(1) Change line 147 in file_io.c and dropping lines 148-149:
  276. X
  277. X    fileblk.fab$b_rfm = FAB$C_STMLF;    /* stream-LF record format */
  278. X    fileblk.fab$b_rat = FAB$M_CR;       /* carriage-return carriage ctrl */
  279. X    /*                      ^^^^ *NOT* V_CR!!!     */
  280. X
  281. X=>
  282. X
  283. X    fileblk.fab$b_rfm = FAB$C_FIX;    /* fixed record format */
  284. X
  285. X(2) Use VMS ANALYZE to store the VMS attributes for the original file
  286. X    into a file descripion language file.  Save the .FDL file with the
  287. X    original file.
  288. X
  289. X(3) Apply the original attributes to the UNZIPped file using VMS CREATE
  290. X    and the description file (test.fdl).
  291. X
  292. XIn the following example, the original attributes of a SPSSX system
  293. Xformat file were restored.  Later, SPSSX successfully read the UNZIPped/
  294. XCONVERTed file.
  295. X
  296. X!******** Procedure (or method for you ai'ers)
  297. X!********
  298. X!******** Create an .FDL file using ANALYZE
  299. X
  300. X$ analyze/rms/fdl/out=test test.spssxsav;1
  301. X
  302. X!******** ZIP the file and its description file
  303. X
  304. X$ zip test test.spssxsav;1 test.fdl;1
  305. Xadding test.spssxsav (imploded 62%)
  306. Xadding test.fdl (imploded 90%)
  307. X
  308. X!******** When the ZIPPED file is needed, UNZIP it and its description file
  309. X
  310. X$ unzip test
  311. X  Exploding: test.spssxsav
  312. X  Exploding: test.fdl
  313. X
  314. X!******** To restore the original attributes, apply the description file to
  315. X!********  the UNZIPped file using VMS CONVERT
  316. X
  317. X$ convert/fdl=test  test.spssxsav;2 test.spssxsav;3
  318. X
  319. X! ******* The following show that the VMS attributes are restored.
  320. X
  321. X$ analyze/rms/check test.spssxsav;1
  322. X
  323. X    File Spec: PROJDISK5:[322042.CORE]TEST.SPSSXSAV;1
  324. X    File Organization: sequential
  325. X    Record Format: fixed
  326. X    Record Attributes:
  327. X    Maximum Record Size: 4
  328. X    Longest Record: 4
  329. X
  330. XThe analysis uncovered NO errors.
  331. X
  332. X$ analyze/rms/check test.spssxsav;2
  333. X    File Spec: PROJDISK5:[322042.CORE]TEST.SPSSXSAV;2
  334. X    File Organization: sequential
  335. X    Record Format: undefined
  336. X    Record Attributes:
  337. X    Maximum Record Size: 0
  338. X    Longest Record: 512
  339. XThe analysis uncovered NO errors.
  340. X
  341. X$ analyze/rms/check test.spssxsav;3
  342. X    File Spec: PROJDISK5:[322042.CORE]TEST.SPSSXSAV;3
  343. X    File Organization: sequential
  344. X    Record Format: fixed
  345. X    Record Attributes:
  346. X    Maximum Record Size: 4
  347. X    Longest Record: 4
  348. X
  349. XThank you all for your help and comments.  It was very reasurring to
  350. Xknow that I was on the right track.  This is a humble contribution
  351. Xcompared to the great efforts of others in the ZIP project.
  352. X
  353. X------------------------------
  354. X
  355. XDate: Wed, 6 Nov 91 12:49:33 EST
  356. XFrom: Mike Freeman <freeman@watsun.cc.columbia.edu>
  357. XSubject: Re: VMS attributes restored!
  358. XMessage-ID: <CMM.0.90.0.689449773.freeman@watsun.cc.columbia.edu>
  359. X
  360. XHello, all.
  361. X
  362. XHUGH@macc.wisc.edu has come up with a commendable method for saving/
  363. Xrestoring record attributes in Vax/VMS files when ZIPping/UNZIPping.
  364. XThere are a couple of potential problems in his specific implementation,
  365. Xhowever:
  366. X
  367. X(a) It would be better to leave the output file(s) in STREAM_LF format
  368. X    and use Joe Meadows' FILE utility to put them in fixed-record
  369. X    format if CONVERT has trouble reading them.
  370. X
  371. X    Outputting a text file as fixed-record format could be a pain, and
  372. X    one would have to use FILE anyway.
  373. X
  374. X    (Incidentally, I ZIPped up a text file, UNZIPped it and used Hugh's
  375. X    method to restore the attributes.  CONVERT had no trouble with the
  376. X    STREAM_LF format -- it's only a problem with binary files and, as I
  377. X    say, Joe Meadows' FILE will fix this.)
  378. X
  379. X(b) Even if ANALYZE/RMS complains, I do not think one ought to put the
  380. X    "\n" in as Hugh advocates.  This contradicts the ZIP philosophy of
  381. X    byte-for-byte storage/retrieval.
  382. X
  383. X    As Mr. Roelofs has said, there is nothing wrong with the ZIP file;
  384. X    it's just that ANALYZE/RMS expects STREAM_LF files to end in an
  385. X    <LF>.
  386. X
  387. XAnyway, I was able to use Hugh's method without modifying ZIP 1.0.  We
  388. Xreally ought to get the word out about FILE, though -- it's very handy.
  389. X
  390. XMike Freeman, K7UIJ     |       Internet: freeman@watsun.cc.columbia.edu
  391. X301 N.E. 107th Street   |       GEnie: M.FREEMAN11
  392. XVancouvEr, WA 98685 USA |       Confidence is the feeling you have
  393. XTelephone (206)574-8221 |       before you understand the situation.
  394. X
  395. X------------------------------
  396. X
  397. END_OF_FILE
  398.   if test 13719 -ne `wc -c <'VMS/VMS.notes'`; then
  399.     echo shar: \"'VMS/VMS.notes'\" unpacked with wrong size!
  400.   fi
  401.   # end of 'VMS/VMS.notes'
  402. fi
  403. if test -f 'explode.c' -a "${1}" != "-c" ; then 
  404.   echo shar: Will not clobber existing file \"'explode.c'\"
  405. else
  406.   echo shar: Extracting \"'explode.c'\" \(26874 characters\)
  407.   sed "s/^X//" >'explode.c' <<'END_OF_FILE'
  408. X/* explode.c -- Not copyrighted 1992 by Mark Adler
  409. X   version c7, 27 June 1992 */
  410. X
  411. X
  412. X/* You can do whatever you like with this source file, though I would
  413. X   prefer that if you modify it and redistribute it that you include
  414. X   comments to that effect with your name and the date.  Thank you.
  415. X
  416. X   History:
  417. X   vers    date          who           what
  418. X   ----  ---------  --------------  ------------------------------------
  419. X    c1   30 Mar 92  M. Adler        explode that uses huft_build from inflate
  420. X                                    (this gives over a 70% speed improvement
  421. X                                    over the original unimplode.c, which
  422. X                                    decoded a bit at a time)
  423. X    c2    4 Apr 92  M. Adler        fixed bug for file sizes a multiple of 32k.
  424. X    c3   10 Apr 92  M. Adler        added a little memory tracking if DEBUG
  425. X    c4   11 Apr 92  M. Adler        added NOMEMCPY do kill use of memcpy()
  426. X    c5   21 Apr 92  M. Adler        added the WSIZE #define to allow reducing
  427. X                                    the 32K window size for specialized
  428. X                                    applications.
  429. X    c6   31 May 92  M. Adler        added typecasts to eliminate some warnings
  430. X    c7   27 Jun 92  G. Roelofs      added more typecasts
  431. X */
  432. X
  433. X
  434. X/*
  435. X   Explode imploded (PKZIP method 6 compressed) data.  This compression
  436. X   method searches for as much of the current string of bytes (up to a length
  437. X   of ~320) in the previous 4K or 8K bytes.  If it doesn't find any matches
  438. X   (of at least length 2 or 3), it codes the next byte.  Otherwise, it codes
  439. X   the length of the matched string and its distance backwards from the
  440. X   current position.  Single bytes ("literals") are preceded by a one (a
  441. X   single bit) and are either uncoded (the eight bits go directly into the
  442. X   compressed stream for a total of nine bits) or Huffman coded with a
  443. X   supplied literal code tree.  If literals are coded, then the minimum match
  444. X   length is three, otherwise it is two.
  445. X   
  446. X   There are therefore four kinds of imploded streams: 8K search with coded
  447. X   literals (min match = 3), 4K search with coded literals (min match = 3),
  448. X   8K with uncoded literals (min match = 2), and 4K with uncoded literals
  449. X   (min match = 2).  The kind of stream is identified in two bits of a
  450. X   general purpose bit flag that is outside of the compressed stream.
  451. X   
  452. X   Distance-length pairs are always coded.  Distance-length pairs for matched
  453. X   strings are preceded by a zero bit (to distinguish them from literals) and
  454. X   are always coded.  The distance comes first and is either the low six (4K)
  455. X   or low seven (8K) bits of the distance (uncoded), followed by the high six
  456. X   bits of the distance coded.  Then the length is six bits coded (0..63 +
  457. X   min match length), and if the maximum such length is coded, then it's
  458. X   followed by another eight bits (uncoded) to be added to the coded length.
  459. X   This gives a match length range of 2..320 or 3..321 bytes.
  460. X
  461. X   The literal, length, and distance codes are all represented in a slightly
  462. X   compressed form themselves.  What is sent are the lengths of the codes for
  463. X   each value, which is sufficient to construct the codes.  Each byte of the
  464. X   code representation is the code length (the low four bits representing
  465. X   1..16), and the number of values sequentially with that length (the high
  466. X   four bits also representing 1..16).  There are 256 literal code values (if
  467. X   literals are coded), 64 length code values, and 64 distance code values,
  468. X   in that order at the beginning of the compressed stream.  Each set of code
  469. X   values is preceded (redundantly) with a byte indicating how many bytes are
  470. X   in the code description that follows, in the range 1..256.
  471. X
  472. X   The codes themselves are decoded using tables made by huft_build() from
  473. X   the bit lengths.  That routine and its comments are in the inflate.c
  474. X   module.
  475. X */
  476. X
  477. X#include "unzip.h"      /* this must supply the slide[] (byte) array */
  478. X
  479. X#ifndef WSIZE
  480. X#  define WSIZE 0x8000  /* window size--must be a power of two, and at least
  481. X                           8K for zip's implode method */
  482. X#endif /* !WSIZE */
  483. X
  484. X
  485. Xstruct huft {
  486. X  byte e;               /* number of extra bits or operation */
  487. X  byte b;               /* number of bits in this code or subcode */
  488. X  union {
  489. X    UWORD n;            /* literal, length base, or distance base */
  490. X    struct huft *t;     /* pointer to next level of table */
  491. X  } v;
  492. X};
  493. X
  494. X/* Function prototypes */
  495. X/* routines from inflate.c */
  496. Xextern unsigned hufts;
  497. Xint huft_build OF((unsigned *, unsigned, unsigned, UWORD *, UWORD *,
  498. X                   struct huft **, int *));
  499. Xint huft_free OF((struct huft *));
  500. Xvoid flush OF((unsigned));
  501. X
  502. X/* routines here */
  503. Xint get_tree OF((unsigned *, unsigned));
  504. Xint explode_lit8 OF((struct huft *, struct huft *, struct huft *,
  505. X                     int, int, int));
  506. Xint explode_lit4 OF((struct huft *, struct huft *, struct huft *,
  507. X                     int, int, int));
  508. Xint explode_nolit8 OF((struct huft *, struct huft *, int, int));
  509. Xint explode_nolit4 OF((struct huft *, struct huft *, int, int));
  510. Xint explode OF((void));
  511. X
  512. X
  513. X/* The implode algorithm uses a sliding 4K or 8K byte window on the
  514. X   uncompressed stream to find repeated byte strings.  This is implemented
  515. X   here as a circular buffer.  The index is updated simply by incrementing
  516. X   and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1).  Here, the 32K
  517. X   buffer of inflate is used, and it works just as well to always have
  518. X   a 32K circular buffer, so the index is anded with 0x7fff.  This is
  519. X   done to allow the window to also be used as the output buffer. */
  520. X/* This must be supplied in an external module useable like "byte slide[8192];"
  521. X   or "byte *slide;", where the latter would be malloc'ed.  In unzip, slide[]
  522. X   is actually a 32K area for use by inflate, which uses a 32K sliding window.
  523. X */
  524. X
  525. X
  526. X/* Tables for length and distance */
  527. XUWORD cplen2[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
  528. X        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
  529. X        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
  530. X        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65};
  531. XUWORD cplen3[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
  532. X        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
  533. X        36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
  534. X        53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66};
  535. XUWORD extra[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  536. X        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  537. X        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  538. X        8};
  539. XUWORD cpdist4[] = {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,
  540. X        769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,
  541. X        1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,
  542. X        2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,
  543. X        2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,
  544. X        3649, 3713, 3777, 3841, 3905, 3969, 4033};
  545. XUWORD cpdist8[] = {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,
  546. X        1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,
  547. X        2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,
  548. X        4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,
  549. X        5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,
  550. X        7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065};
  551. X
  552. X
  553. X/* Macros for inflate() bit peeking and grabbing.
  554. X   The usage is:
  555. X   
  556. X        NEEDBITS(j)
  557. X        x = b & mask_bits[j];
  558. X        DUMPBITS(j)
  559. X
  560. X   where NEEDBITS makes sure that b has at least j bits in it, and
  561. X   DUMPBITS removes the bits from b.  The macros use the variable k
  562. X   for the number of bits in b.  Normally, b and k are register
  563. X   variables for speed.
  564. X */
  565. X
  566. Xextern UWORD bytebuf;           /* (use the one in inflate.c) */
  567. X#define NEXTBYTE    (ReadByte(&bytebuf), bytebuf)
  568. X#define NEEDBITS(n) {while(k<(n)){b|=((ULONG)NEXTBYTE)<<k;k+=8;}}
  569. X#define DUMPBITS(n) {b>>=(n);k-=(n);}
  570. X
  571. X
  572. X
  573. Xint get_tree(l, n)
  574. Xunsigned *l;            /* bit lengths */
  575. Xunsigned n;             /* number expected */
  576. X/* Get the bit lengths for a code representation from the compressed
  577. X   stream.  If get_tree() returns 4, then there is an error in the data.
  578. X   Otherwise zero is returned. */
  579. X{
  580. X  unsigned i;           /* bytes remaining in list */
  581. X  unsigned k;           /* lengths entered */
  582. X  unsigned j;           /* number of codes */
  583. X  unsigned b;           /* bit length for those codes */ 
  584. X
  585. X
  586. X  /* get bit lengths */
  587. X  ReadByte(&bytebuf);
  588. X  i = bytebuf + 1;                      /* length/count pairs to read */
  589. X  k = 0;                                /* next code */
  590. X  do {
  591. X    ReadByte(&bytebuf);
  592. X    b = ((j = bytebuf) & 0xf) + 1;      /* bits in code (1..16) */
  593. X    j = ((j & 0xf0) >> 4) + 1;          /* codes with those bits (1..16) */
  594. X    if (k + j > n)
  595. X      return 4;                         /* don't overflow l[] */
  596. X    do {
  597. X      l[k++] = b;
  598. X    } while (--j);
  599. X  } while (--i);
  600. X  return k != n ? 4 : 0;                /* should have read n of them */
  601. X}
  602. X
  603. X
  604. X
  605. Xint explode_lit8(tb, tl, td, bb, bl, bd)
  606. Xstruct huft *tb, *tl, *td;      /* literal, length, and distance tables */
  607. Xint bb, bl, bd;                 /* number of bits decoded by those */
  608. X/* Decompress the imploded data using coded literals and an 8K sliding
  609. X   window. */
  610. X{
  611. X  longint s;            /* bytes to decompress */
  612. X  register unsigned e;  /* table entry flag/number of extra bits */
  613. X  unsigned n, d;        /* length and index for copy */
  614. X  unsigned w;           /* current window position */
  615. X  struct huft *t;       /* pointer to table entry */
  616. X  unsigned mb, ml, md;  /* masks for bb, bl, and bd bits */
  617. X  register ULONG b;     /* bit buffer */
  618. X  register unsigned k;  /* number of bits in bit buffer */
  619. X  unsigned u;           /* true if unflushed */
  620. X
  621. X
  622. X  /* explode the coded data */
  623. X  b = k = w = 0;                /* initialize bit buffer, window */
  624. X  u = 1;                        /* buffer unflushed */
  625. X  mb = mask_bits[bb];           /* precompute masks for speed */
  626. X  ml = mask_bits[bl];
  627. X  md = mask_bits[bd];
  628. X  s = ucsize;
  629. X  while (s > 0)                 /* do until ucsize bytes uncompressed */
  630. X  {
  631. X    NEEDBITS(1)
  632. X    if (b & 1)                  /* then literal--decode it */
  633. X    {
  634. X      DUMPBITS(1)
  635. X      s--;
  636. X      NEEDBITS((unsigned)bb)    /* get coded literal */
  637. X      if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
  638. X        do {
  639. X          if (e == 99)
  640. X            return 1;
  641. X          DUMPBITS(t->b)
  642. X          e -= 16;
  643. X          NEEDBITS(e)
  644. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  645. X      DUMPBITS(t->b)
  646. X      slide[w++] = (byte)t->v.n;
  647. X      if (w == WSIZE)
  648. X      {
  649. X        flush(w);
  650. X        w = u = 0;
  651. X      }
  652. X    }
  653. X    else                        /* else distance/length */
  654. X    {
  655. X      DUMPBITS(1)
  656. X      NEEDBITS(7)               /* get distance low bits */
  657. X      d = (unsigned)b & 0x7f;
  658. X      DUMPBITS(7)
  659. X      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
  660. X      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
  661. X        do {
  662. X          if (e == 99)
  663. X            return 1;
  664. X          DUMPBITS(t->b)
  665. X          e -= 16;
  666. X          NEEDBITS(e)
  667. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  668. X      DUMPBITS(t->b)
  669. X      d = w - d - t->v.n;       /* construct offset */
  670. X      NEEDBITS((unsigned)bl)    /* get coded length */
  671. X      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
  672. X        do {
  673. X          if (e == 99)
  674. X            return 1;
  675. X          DUMPBITS(t->b)
  676. X          e -= 16;
  677. X          NEEDBITS(e)
  678. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  679. X      DUMPBITS(t->b)
  680. X      n = t->v.n;
  681. X      if (e)                    /* get length extra bits */
  682. X      {
  683. X        NEEDBITS(8)
  684. X        n += (unsigned)b & 0xff;
  685. X        DUMPBITS(8)
  686. X      }
  687. X
  688. X      /* do the copy */
  689. X      s -= n;
  690. X      do {
  691. X        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
  692. X        if (u && w <= d)
  693. X        {
  694. X          memset(slide + w, 0, e);
  695. X          w += e;
  696. X          d += e;
  697. X        }
  698. X        else
  699. X#ifndef NOMEMCPY
  700. X          if (w - d >= e)       /* (this test assumes unsigned comparison) */
  701. X          {
  702. X            memcpy(slide + w, slide + d, e);
  703. X            w += e;
  704. X            d += e;
  705. X          }
  706. X          else                  /* do it slow to avoid memcpy() overlap */
  707. X#endif /* !NOMEMCPY */
  708. X            do {
  709. X              slide[w++] = slide[d++];
  710. X            } while (--e);
  711. X        if (w == WSIZE)
  712. X        {
  713. X          flush(w);
  714. X          w = u = 0;
  715. X        }
  716. X      } while (n);
  717. X    }
  718. X  }
  719. X
  720. X  /* flush out slide */
  721. X  flush(w);
  722. X  return csize ? 5 : 0;         /* should have read csize bytes */
  723. X}
  724. X
  725. X
  726. X
  727. Xint explode_lit4(tb, tl, td, bb, bl, bd)
  728. Xstruct huft *tb, *tl, *td;      /* literal, length, and distance tables */
  729. Xint bb, bl, bd;                 /* number of bits decoded by those */
  730. X/* Decompress the imploded data using coded literals and a 4K sliding
  731. X   window. */
  732. X{
  733. X  longint s;            /* bytes to decompress */
  734. X  register unsigned e;  /* table entry flag/number of extra bits */
  735. X  unsigned n, d;        /* length and index for copy */
  736. X  unsigned w;           /* current window position */
  737. X  struct huft *t;       /* pointer to table entry */
  738. X  unsigned mb, ml, md;  /* masks for bb, bl, and bd bits */
  739. X  register ULONG b;     /* bit buffer */
  740. X  register unsigned k;  /* number of bits in bit buffer */
  741. X  unsigned u;           /* true if unflushed */
  742. X
  743. X
  744. X  /* explode the coded data */
  745. X  b = k = w = 0;                /* initialize bit buffer, window */
  746. X  u = 1;                        /* buffer unflushed */
  747. X  mb = mask_bits[bb];           /* precompute masks for speed */
  748. X  ml = mask_bits[bl];
  749. X  md = mask_bits[bd];
  750. X  s = ucsize;
  751. X  while (s > 0)                 /* do until ucsize bytes uncompressed */
  752. X  {
  753. X    NEEDBITS(1)
  754. X    if (b & 1)                  /* then literal--decode it */
  755. X    {
  756. X      DUMPBITS(1)
  757. X      s--;
  758. X      NEEDBITS((unsigned)bb)    /* get coded literal */
  759. X      if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
  760. X        do {
  761. X          if (e == 99)
  762. X            return 1;
  763. X          DUMPBITS(t->b)
  764. X          e -= 16;
  765. X          NEEDBITS(e)
  766. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  767. X      DUMPBITS(t->b)
  768. X      slide[w++] = (byte)t->v.n;
  769. X      if (w == WSIZE)
  770. X      {
  771. X        flush(w);
  772. X        w = u = 0;
  773. X      }
  774. X    }
  775. X    else                        /* else distance/length */
  776. X    {
  777. X      DUMPBITS(1)
  778. X      NEEDBITS(6)               /* get distance low bits */
  779. X      d = (unsigned)b & 0x3f;
  780. X      DUMPBITS(6)
  781. X      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
  782. X      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
  783. X        do {
  784. X          if (e == 99)
  785. X            return 1;
  786. X          DUMPBITS(t->b)
  787. X          e -= 16;
  788. X          NEEDBITS(e)
  789. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  790. X      DUMPBITS(t->b)
  791. X      d = w - d - t->v.n;       /* construct offset */
  792. X      NEEDBITS((unsigned)bl)    /* get coded length */
  793. X      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
  794. X        do {
  795. X          if (e == 99)
  796. X            return 1;
  797. X          DUMPBITS(t->b)
  798. X          e -= 16;
  799. X          NEEDBITS(e)
  800. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  801. X      DUMPBITS(t->b)
  802. X      n = t->v.n;
  803. X      if (e)                    /* get length extra bits */
  804. X      {
  805. X        NEEDBITS(8)
  806. X        n += (unsigned)b & 0xff;
  807. X        DUMPBITS(8)
  808. X      }
  809. X
  810. X      /* do the copy */
  811. X      s -= n;
  812. X      do {
  813. X        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
  814. X        if (u && w <= d)
  815. X        {
  816. X          memset(slide + w, 0, e);
  817. X          w += e;
  818. X          d += e;
  819. X        }
  820. X        else
  821. X#ifndef NOMEMCPY
  822. X          if (w - d >= e)       /* (this test assumes unsigned comparison) */
  823. X          {
  824. X            memcpy(slide + w, slide + d, e);
  825. X            w += e;
  826. X            d += e;
  827. X          }
  828. X          else                  /* do it slow to avoid memcpy() overlap */
  829. X#endif /* !NOMEMCPY */
  830. X            do {
  831. X              slide[w++] = slide[d++];
  832. X            } while (--e);
  833. X        if (w == WSIZE)
  834. X        {
  835. X          flush(w);
  836. X          w = u = 0;
  837. X        }
  838. X      } while (n);
  839. X    }
  840. X  }
  841. X
  842. X  /* flush out slide */
  843. X  flush(w);
  844. X  return csize ? 5 : 0;         /* should have read csize bytes */
  845. X}
  846. X
  847. X
  848. X
  849. Xint explode_nolit8(tl, td, bl, bd)
  850. Xstruct huft *tl, *td;   /* length and distance decoder tables */
  851. Xint bl, bd;             /* number of bits decoded by tl[] and td[] */
  852. X/* Decompress the imploded data using uncoded literals and an 8K sliding
  853. X   window. */
  854. X{
  855. X  longint s;            /* bytes to decompress */
  856. X  register unsigned e;  /* table entry flag/number of extra bits */
  857. X  unsigned n, d;        /* length and index for copy */
  858. X  unsigned w;           /* current window position */
  859. X  struct huft *t;       /* pointer to table entry */
  860. X  unsigned ml, md;      /* masks for bl and bd bits */
  861. X  register ULONG b;     /* bit buffer */
  862. X  register unsigned k;  /* number of bits in bit buffer */
  863. X  unsigned u;           /* true if unflushed */
  864. X
  865. X
  866. X  /* explode the coded data */
  867. X  b = k = w = 0;                /* initialize bit buffer, window */
  868. X  u = 1;                        /* buffer unflushed */
  869. X  ml = mask_bits[bl];           /* precompute masks for speed */
  870. X  md = mask_bits[bd];
  871. X  s = ucsize;
  872. X  while (s > 0)                 /* do until ucsize bytes uncompressed */
  873. X  {
  874. X    NEEDBITS(1)
  875. X    if (b & 1)                  /* then literal--get eight bits */
  876. X    {
  877. X      DUMPBITS(1)
  878. X      s--;
  879. X      NEEDBITS(8)
  880. X      slide[w++] = (byte)b;
  881. X      if (w == WSIZE)
  882. X      {
  883. X        flush(w);
  884. X        w = u = 0;
  885. X      }
  886. X      DUMPBITS(8)
  887. X    }
  888. X    else                        /* else distance/length */
  889. X    {
  890. X      DUMPBITS(1)
  891. X      NEEDBITS(7)               /* get distance low bits */
  892. X      d = (unsigned)b & 0x7f;
  893. X      DUMPBITS(7)
  894. X      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
  895. X      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
  896. X        do {
  897. X          if (e == 99)
  898. X            return 1;
  899. X          DUMPBITS(t->b)
  900. X          e -= 16;
  901. X          NEEDBITS(e)
  902. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  903. X      DUMPBITS(t->b)
  904. X      d = w - d - t->v.n;       /* construct offset */
  905. X      NEEDBITS((unsigned)bl)    /* get coded length */
  906. X      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
  907. X        do {
  908. X          if (e == 99)
  909. X            return 1;
  910. X          DUMPBITS(t->b)
  911. X          e -= 16;
  912. X          NEEDBITS(e)
  913. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  914. X      DUMPBITS(t->b)
  915. X      n = t->v.n;
  916. X      if (e)                    /* get length extra bits */
  917. X      {
  918. X        NEEDBITS(8)
  919. X        n += (unsigned)b & 0xff;
  920. X        DUMPBITS(8)
  921. X      }
  922. X
  923. X      /* do the copy */
  924. X      s -= n;
  925. X      do {
  926. X        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
  927. X        if (u && w <= d)
  928. X        {
  929. X          memset(slide + w, 0, e);
  930. X          w += e;
  931. X          d += e;
  932. X        }
  933. X        else
  934. X#ifndef NOMEMCPY
  935. X          if (w - d >= e)       /* (this test assumes unsigned comparison) */
  936. X          {
  937. X            memcpy(slide + w, slide + d, e);
  938. X            w += e;
  939. X            d += e;
  940. X          }
  941. X          else                  /* do it slow to avoid memcpy() overlap */
  942. X#endif /* !NOMEMCPY */
  943. X            do {
  944. X              slide[w++] = slide[d++];
  945. X            } while (--e);
  946. X        if (w == WSIZE)
  947. X        {
  948. X          flush(w);
  949. X          w = u = 0;
  950. X        }
  951. X      } while (n);
  952. X    }
  953. X  }
  954. X
  955. X  /* flush out slide */
  956. X  flush(w);
  957. X  return csize ? 5 : 0;         /* should have read csize bytes */
  958. X}
  959. X
  960. X
  961. X
  962. Xint explode_nolit4(tl, td, bl, bd)
  963. Xstruct huft *tl, *td;   /* length and distance decoder tables */
  964. Xint bl, bd;             /* number of bits decoded by tl[] and td[] */
  965. X/* Decompress the imploded data using uncoded literals and a 4K sliding
  966. X   window. */
  967. X{
  968. X  longint s;            /* bytes to decompress */
  969. X  register unsigned e;  /* table entry flag/number of extra bits */
  970. X  unsigned n, d;        /* length and index for copy */
  971. X  unsigned w;           /* current window position */
  972. X  struct huft *t;       /* pointer to table entry */
  973. X  unsigned ml, md;      /* masks for bl and bd bits */
  974. X  register ULONG b;     /* bit buffer */
  975. X  register unsigned k;  /* number of bits in bit buffer */
  976. X  unsigned u;           /* true if unflushed */
  977. X
  978. X
  979. X  /* explode the coded data */
  980. X  b = k = w = 0;                /* initialize bit buffer, window */
  981. X  u = 1;                        /* buffer unflushed */
  982. X  ml = mask_bits[bl];           /* precompute masks for speed */
  983. X  md = mask_bits[bd];
  984. X  s = ucsize;
  985. X  while (s > 0)                 /* do until ucsize bytes uncompressed */
  986. X  {
  987. X    NEEDBITS(1)
  988. X    if (b & 1)                  /* then literal--get eight bits */
  989. X    {
  990. X      DUMPBITS(1)
  991. X      s--;
  992. X      NEEDBITS(8)
  993. X      slide[w++] = (byte)b;
  994. X      if (w == WSIZE)
  995. X      {
  996. X        flush(w);
  997. X        w = u = 0;
  998. X      }
  999. X      DUMPBITS(8)
  1000. X    }
  1001. X    else                        /* else distance/length */
  1002. X    {
  1003. X      DUMPBITS(1)
  1004. X      NEEDBITS(6)               /* get distance low bits */
  1005. X      d = (unsigned)b & 0x3f;
  1006. X      DUMPBITS(6)
  1007. X      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
  1008. X      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
  1009. X        do {
  1010. X          if (e == 99)
  1011. X            return 1;
  1012. X          DUMPBITS(t->b)
  1013. X          e -= 16;
  1014. X          NEEDBITS(e)
  1015. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  1016. X      DUMPBITS(t->b)
  1017. X      d = w - d - t->v.n;       /* construct offset */
  1018. X      NEEDBITS((unsigned)bl)    /* get coded length */
  1019. X      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
  1020. X        do {
  1021. X          if (e == 99)
  1022. X            return 1;
  1023. X          DUMPBITS(t->b)
  1024. X          e -= 16;
  1025. X          NEEDBITS(e)
  1026. X        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
  1027. X      DUMPBITS(t->b)
  1028. X      n = t->v.n;
  1029. X      if (e)                    /* get length extra bits */
  1030. X      {
  1031. X        NEEDBITS(8)
  1032. X        n += (unsigned)b & 0xff;
  1033. X        DUMPBITS(8)
  1034. X      }
  1035. X
  1036. X      /* do the copy */
  1037. X      s -= n;
  1038. X      do {
  1039. X        n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
  1040. X        if (u && w <= d)
  1041. X        {
  1042. X          memset(slide + w, 0, e);
  1043. X          w += e;
  1044. X          d += e;
  1045. X        }
  1046. X        else
  1047. X#ifndef NOMEMCPY
  1048. X          if (w - d >= e)       /* (this test assumes unsigned comparison) */
  1049. X          {
  1050. X            memcpy(slide + w, slide + d, e);
  1051. X            w += e;
  1052. X            d += e;
  1053. X          }
  1054. X          else                  /* do it slow to avoid memcpy() overlap */
  1055. X#endif /* !NOMEMCPY */
  1056. X            do {
  1057. X              slide[w++] = slide[d++];
  1058. X            } while (--e);
  1059. X        if (w == WSIZE)
  1060. X        {
  1061. X          flush(w);
  1062. X          w = u = 0;
  1063. X        }
  1064. X      } while (n);
  1065. X    }
  1066. X  }
  1067. X
  1068. X  /* flush out slide */
  1069. X  flush(w);
  1070. X  return csize ? 5 : 0;         /* should have read csize bytes */
  1071. X}
  1072. X
  1073. X
  1074. X
  1075. Xint explode()
  1076. X/* Explode an imploded compressed stream.  Based on the general purpose
  1077. X   bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding
  1078. X   window.  Construct the literal (if any), length, and distance codes and
  1079. X   the tables needed to decode them (using huft_build() from inflate.c),
  1080. X   and call the appropriate routine for the type of data in the remainder
  1081. X   of the stream.  The four routines are nearly identical, differing only
  1082. X   in whether the literal is decoded or simply read in, and in how many
  1083. X   bits are read in, uncoded, for the low distance bits. */
  1084. X{
  1085. X  unsigned r;           /* return codes */
  1086. X  struct huft *tb;      /* literal code table */
  1087. X  struct huft *tl;      /* length code table */
  1088. X  struct huft *td;      /* distance code table */
  1089. X  int bb;               /* bits for tb */
  1090. X  int bl;               /* bits for tl */
  1091. X  int bd;               /* bits for td */
  1092. X  unsigned l[256];      /* bit lengths for codes */
  1093. X
  1094. X
  1095. X  /* Tune base table sizes.  Note: I thought that to truly optimize speed,
  1096. X     I would have to select different bl, bd, and bb values for different
  1097. X     compressed file sizes.  I was suprised to find out the the values of
  1098. X     7, 7, and 9 worked best over a very wide range of sizes, except that
  1099. X     bd = 8 worked marginally better for large compressed sizes. */
  1100. X  bl = 7;
  1101. X  bd = csize > 200000L ? 8 : 7;
  1102. X
  1103. X
  1104. X  /* With literal tree--minimum match length is 3 */
  1105. X  hufts = 0;                    /* initialze huft's malloc'ed */
  1106. X  if (lrec.general_purpose_bit_flag & 4)
  1107. X  {
  1108. X    bb = 9;                     /* base table size for literals */
  1109. X    if ((r = get_tree(l, 256)) != 0)
  1110. X      return r;
  1111. X    if ((r = huft_build(l, 256, 256, NULL, NULL, &tb, &bb)) != 0)
  1112. X    {
  1113. X      if (r == 1)
  1114. X        huft_free(tb);
  1115. X      return r;
  1116. X    }
  1117. X    if ((r = get_tree(l, 64)) != 0)
  1118. X      return r;
  1119. X    if ((r = huft_build(l, 64, 0, cplen3, extra, &tl, &bl)) != 0)
  1120. X    {
  1121. X      if (r == 1)
  1122. X        huft_free(tl);
  1123. X      huft_free(tb);
  1124. X      return r;
  1125. X    }
  1126. X    if ((r = get_tree(l, 64)) != 0)
  1127. X      return r;
  1128. X    if (lrec.general_purpose_bit_flag & 2)      /* true if 8K */
  1129. X    {
  1130. X      if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
  1131. X      {
  1132. X        if (r == 1)
  1133. X          huft_free(td);
  1134. X        huft_free(tl);
  1135. X        huft_free(tb);
  1136. X        return r;
  1137. X      }
  1138. X      r = explode_lit8(tb, tl, td, bb, bl, bd);
  1139. X    }
  1140. X    else                                        /* else 4K */
  1141. X    {
  1142. X      if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
  1143. X      {
  1144. X        if (r == 1)
  1145. X          huft_free(td);
  1146. X        huft_free(tl);
  1147. X        huft_free(tb);
  1148. X        return r;
  1149. X      }
  1150. X      r = explode_lit4(tb, tl, td, bb, bl, bd);
  1151. X    }
  1152. X    huft_free(td);
  1153. X    huft_free(tl);
  1154. X    huft_free(tb);
  1155. X  }
  1156. X  else
  1157. X
  1158. X
  1159. X  /* No literal tree--minimum match length is 2 */
  1160. X  {
  1161. X    if ((r = get_tree(l, 64)) != 0)
  1162. X      return r;
  1163. X    if ((r = huft_build(l, 64, 0, cplen2, extra, &tl, &bl)) != 0)
  1164. X    {
  1165. X      if (r == 1)
  1166. X        huft_free(tl);
  1167. X      return r;
  1168. X    }
  1169. X    if ((r = get_tree(l, 64)) != 0)
  1170. X      return r;
  1171. X    if (lrec.general_purpose_bit_flag & 2)      /* true if 8K */
  1172. X    {
  1173. X      if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
  1174. X      {
  1175. X        if (r == 1)
  1176. X          huft_free(td);
  1177. X        huft_free(tl);
  1178. X        return r;
  1179. X      }
  1180. X      r = explode_nolit8(tl, td, bl, bd);
  1181. X    }
  1182. X    else                                        /* else 4K */
  1183. X    {
  1184. X      if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
  1185. X      {
  1186. X        if (r == 1)
  1187. X          huft_free(td);
  1188. X        huft_free(tl);
  1189. X        return r;
  1190. X      }
  1191. X      r = explode_nolit4(tl, td, bl, bd);
  1192. X    }
  1193. X    huft_free(td);
  1194. X    huft_free(tl);
  1195. X  }
  1196. X#ifdef DEBUG
  1197. X  fprintf(stderr, "<%u > ", hufts);
  1198. X#endif /* DEBUG */
  1199. X  return r;
  1200. X}
  1201. END_OF_FILE
  1202.   if test 26874 -ne `wc -c <'explode.c'`; then
  1203.     echo shar: \"'explode.c'\" unpacked with wrong size!
  1204.   fi
  1205.   # end of 'explode.c'
  1206. fi
  1207. if test -f 'zipinfo.1' -a "${1}" != "-c" ; then 
  1208.   echo shar: Will not clobber existing file \"'zipinfo.1'\"
  1209. else
  1210.   echo shar: Extracting \"'zipinfo.1'\" \(13533 characters\)
  1211.   sed "s/^X//" >'zipinfo.1' <<'END_OF_FILE'
  1212. X.de X
  1213. X.nf
  1214. X.ien .ti -5
  1215. X.el \{ .ti +2m
  1216. X.ps -1 \}
  1217. X\&\\$1
  1218. X.ien .ti +5
  1219. X.el \{ .ti -2m
  1220. X.ps +1 \}
  1221. X.fi
  1222. X..
  1223. X.TH ZIPINFO 1 "19 Aug 92 (v1.0)"
  1224. X.SH NAME
  1225. Xzipinfo \- list detailed information about a ZIP archive file
  1226. X.SH SYNOPSIS
  1227. X\fBzipinfo\fP [\-\fB1smlvht\fP] \fRfile\fP[\fR.zip\fP] [\fRfilespec\fP\ ...]
  1228. X.SH ARGUMENTS
  1229. X.IP \fIfile\fP[\fI.zip\fP] \w'[\fIfilespec\fP]'u+2m
  1230. XPath of the ZIP archive.  The suffix ``\fR.zip\fP'' is applied
  1231. Xif the \fRfile\fP specified does not exist.  Note that
  1232. Xself-extracting ZIP files are supported; just specify
  1233. Xthe ``\fR.exe\fP'' suffix yourself.
  1234. X.IP [\fIfilespec\fP]
  1235. XAn optional list of archive members to be processed.
  1236. XExpressions may be used to match multiple members; be sure to quote
  1237. Xexpressions that contain characters interpreted by the Unix shell. See
  1238. XPATTERN MATCHING (below) for more details.
  1239. X.SH OPTIONS
  1240. X.PD 0
  1241. X.IP \-1 \w'\-1'u+2m
  1242. Xlist filenames only, one per line (useful for pipes)
  1243. X.IP \-s
  1244. Xlist zipfile info in short Unix ``ls \-l'' format:  default
  1245. X.IP \-m
  1246. Xlist zipfile info in medium Unix ``ls \-l'' format
  1247. X.IP \-l
  1248. Xlist zipfile info in long Unix ``ls \-l'' format
  1249. X.IP \-v
  1250. Xlist zipfile information in verbose, multi-page format
  1251. X.IP \-h
  1252. Xlist header line
  1253. X.IP \-t
  1254. Xlist totals for files listed or for all files
  1255. X.PD
  1256. X.SH PATTERN MATCHING
  1257. XAll archive members are listed unless a \fIfilespec\fP is provided to 
  1258. Xspecify a subset of the archive members.  The \fIfilespec\fP is similar 
  1259. Xto an \fRegrep\fP expression, and may contain:
  1260. X.PP
  1261. X.ta \w'[...]'u+2m
  1262. X*    matches a sequence of 0 or more characters
  1263. X.br
  1264. X?    matches exactly 1 character
  1265. X.br
  1266. X\\nnn    matches the character having octal code nnn
  1267. X.PD 0
  1268. X.IP [...] \w'[...]'u+2m
  1269. Xmatches any single character found inside the brackets; ranges
  1270. Xare specified by a beginning character, a hyphen, and an ending
  1271. Xcharacter.  If an exclamation point or a carat (`!' or `^') follows
  1272. Xthe left bracket, then the range of characters matched is complemented
  1273. Xwith respect to the ASCII character set (that is, anything except the
  1274. Xcharacters inside the brackets is considered a match).
  1275. X.PD
  1276. X.SH DESCRIPTION
  1277. X.I ZipInfo
  1278. Xlists technical information about a ZIP archive, including information
  1279. Xfile access permissions, encryption status, type of compression, version
  1280. Xand operating system of compressing program, and the like.  The default
  1281. Xoption is to list files in the following format:
  1282. X.PP
  1283. X.X "-rw-rwl---  1.5 unx    2802 t- defX 11-Aug-91 13:48 perms.2660"
  1284. X.PP
  1285. XThe last three fields are clearly the modification date and time of
  1286. Xthe file, and its name.  The case of the filename is respected; thus
  1287. Xfiles which come from MS-DOS PKZIP are always capitalized.  If the file
  1288. Xwas zipped with a stored directory name, that is also displayed as part
  1289. Xof the filename.
  1290. X.PP
  1291. XThe second and third fields indicate that the file was zipped under
  1292. XUnix with version 1.5 of \fRZip\fP (a beta version).  Since it comes
  1293. Xfrom Unix, the file
  1294. Xpermissions at the beginning of the line are printed in Unix format.
  1295. XThe uncompressed file-size (2802 in this example) is the fourth field.
  1296. X.PP
  1297. XThe fifth field consists of two characters, either of which may take
  1298. Xon several values.  The first character may be either `t' or `b', indicating
  1299. Xthat \fRZip\fP believes the file to be text or binary, respectively;
  1300. Xbut if the file is encrypted, \fIZipInfo\fP
  1301. Xnotes this fact by capitalizing the character (`T' or `B').  The second
  1302. Xcharacter may also take on four values, depending on whether there is
  1303. Xan extended local header and/or an ``extra field'' associated with the
  1304. Xfile (explained in PKWare's APPNOTE.TXT).  If neither exists, the character
  1305. Xwill be a hyphen (`\-'); if there is an extended local header but no extra
  1306. Xfield, `l'; if the reverse, `x'; and if both exist, `X'.  Thus the
  1307. Xfile in this example is (apparently) a text file, is not encrypted, and
  1308. Xhas neither an extra field nor an extended local header associated with it.
  1309. XThe example below, on the other hand, is an encrypted binary file with an 
  1310. Xextra field:
  1311. X.PP
  1312. X.X "RWD,R,R     0.9 vms     168 Bx shrk  9-Aug-91 19:15 perms.0644"
  1313. X.PP
  1314. XExtra fields are used by PKWare for authenticity verification(?) and
  1315. Xpossibly other purposes, and by Info-ZIP's \fRZip\fP
  1316. X1.6 and later to store OS/2, Macintosh and VMS file attributes.
  1317. XThis example presumably falls into
  1318. Xthe latter class, then.  Note that the file attributes are listed in
  1319. XVMS format.  Other possibilities for the host operating system include
  1320. XOS/2 with High Performance File System (HPFS), DOS or OS/2 with File 
  1321. XAllocation Table (FAT) file system, and Macintosh, denoted
  1322. Xas follows:
  1323. X.PP
  1324. X.X "arc,,rw,    1.0 os2    5358 Tl i4:3  4-Dec-91 11:33 longfilename.hpfs"
  1325. X.X "arc,hid,rdo,sys dos    4096 b- i4:2 14-Jul-91 12:58 EA DATA. SF"
  1326. X.X "--w-------  1.0 mac   17357 bx i8:2  4-May-92 04:02 unzip.macr"
  1327. X.PP
  1328. XFile attributes in the first two cases are indicated in a DOS-like format,
  1329. Xwhere the file may or may not have its archive bit set; may be hidden or not;
  1330. Xmay be read-write or read-only; and may be a system file or not.  If the
  1331. Xattributes are too long, the version number of the encoding software is
  1332. Xomitted.  (The information is still available in the verbose listing, 
  1333. Xhowever.)  Interpretation of Macintosh file attributes needs some work yet.
  1334. X.PP
  1335. XFinally, the sixth field indicates
  1336. Xthe compression method and possible sub-method used.  There are six methods
  1337. Xknown at present:  storing (no compression), reducing, shrinking, imploding,
  1338. Xtokenizing, and deflating.  In addition, there are four levels of reducing
  1339. X(1 through 4); four types of imploding (4K or 8K sliding dictionary, and
  1340. X2 or 3 Shannon-Fano trees); and three levels of deflating (fast, normal,
  1341. Xmaximum compression).  \fIZipInfo\fP represents these methods and their
  1342. Xsub-methods as follows:  ``stor''; ``re:1,'' ``re:2,'' etc.; ``shrk'';
  1343. X``i4:2,'' ``i8:3,'' etc.; ``tokn''; and ``defF,'' ``defN,'' and ``defX.''
  1344. X.PP
  1345. XThe medium and long listings are almost identical to the
  1346. Xshort format except that they add information on the file's
  1347. Xcompression.  The medium format indicates the file's
  1348. Xcompression factor as a percentage:
  1349. X.PP
  1350. X.X "-rw-rwl---  1.5 unx    2802 t- 81% defX 11-Aug-91 13:48 perms.2660"
  1351. X.PP
  1352. XIn this example, the file has been compressed by more than a factor of
  1353. Xfive; the compressed data are only 19% of the original size.  The long
  1354. Xformat gives the compressed file's size in bytes, instead:
  1355. X.PP
  1356. X.X "-rw-rwl---  1.5 unx    2802 t-     538 defX 11-Aug-91 13:48 perms.2660"
  1357. X.PP
  1358. XIn addition to individual file information, a default zipfile listing
  1359. Xalso includes header and trailer lines:
  1360. X.PP
  1361. X.X "Archive:  OS2.zip   5453 bytes   5 files"
  1362. X.X ",,rw,       1.0 os2     730 b- i4:3 26-Jun-92 23:40 Contents"
  1363. X.X ",,rw,       1.0 os2    3710 b- i4:3 26-Jun-92 23:33 makefile.os2"
  1364. X.X ",,rw,       1.0 os2    8753 b- i8:3 26-Jun-92 15:29 os2unzip.c"
  1365. X.X ",,rw,       1.0 os2      98 b- stor 21-Aug-91 15:34 unzip.def"
  1366. X.X ",,rw,       1.0 os2      95 b- stor 21-Aug-91 17:51 zipinfo.def"
  1367. X.X "5 files, 13386 bytes uncompressed, 4951 bytes compressed:  63%"
  1368. X.PP
  1369. XThe header line gives the name of the archive, its total size, and the
  1370. Xtotal number of files; the trailer gives the number of files listed,
  1371. Xtheir total uncompressed size, and their total compressed size (not
  1372. Xincluding any of \fRZip\fP's internal overhead).  If, however, one or 
  1373. Xmore \fIfilespec\fPs are provided, the header and trailer lines are
  1374. Xnot listed.  This behavior is also similar to that of Unix's ``ls \-l'';
  1375. Xit may be overridden by specifying the \-h and \-t options explicitly.
  1376. XIn such a case the listing format must also be specified explicitly,
  1377. Xsince \-h or \-t (or both) in the absence of other options implies
  1378. Xthat ONLY the header or trailer line (or both) is listed.  See the
  1379. XEXAMPLES section below for a semi-intelligible translation of this
  1380. Xnonsense.
  1381. X.PP
  1382. XThe verbose listing is self-explanatory.  It also lists file
  1383. Xcomments and the zipfile comment, if any, and the number of
  1384. Xbytes of OS/2 extended attributes stored.  Note that the
  1385. Xlatter number will in general NOT match the number given by
  1386. XOS/2's ``dir'' command; OS/2 always reports the number of
  1387. Xbytes required in 16-bit format, whereas \fIZipInfo\fP
  1388. Xalways reports the 32-bit storage.
  1389. X.PD
  1390. X.SH ENVIRONMENT OPTIONS
  1391. XModifying \fIZipInfo\fP's default behavior via options placed in
  1392. Xan environment variable can be a bit complicated to explain, due to
  1393. X\fIZipInfo\fP's attempts to handle various defaults in an intuitive,
  1394. Xyet Unix-like, manner.  Nevertheless, there is some underlying logic.
  1395. XIn brief, 
  1396. Xthere are three ``priority levels'' of options:  the default options;
  1397. Xenvironment options, which can override or add to the defaults; and 
  1398. Xexplicit options given by the user, which can override or add to 
  1399. Xeither of the above.
  1400. X.PP
  1401. XThe default listing format, as noted above, corresponds roughly
  1402. Xto the "zipinfo \-hst" command (except when individual zipfile members
  1403. Xare specified).
  1404. XA user who prefers the long-listing format (\-l) can make use of the
  1405. X\fIZIPINFO\fP environment variable to change this default:
  1406. X.ta \w'tabset'u +\w'ZIPINFO=\-l; export ZIPINFO'u+3m
  1407. X.PP
  1408. X.IP "\tsetenv ZIPINFO \-l\tUnix C shell"
  1409. X.br
  1410. X.IP "\tZIPINFO=\-l; export ZIPINFO\tUnix Bourne shell"
  1411. X.PP
  1412. X.IP "\tset ZIPINFO=\-l\tOS/2 or MS-DOS"
  1413. X.PP
  1414. X.IP "\tdefine ZIPINFO_OPTS ""\-l""\tVMS (quotes for LOWERCASE)"
  1415. X.PP
  1416. XIf, in addition, the user dislikes the trailer line, \fIZipInfo\fP's
  1417. Xconcept of ``negative options'' may be used to override the default
  1418. Xinclusion of the line.  This is accomplished by preceding the undesired
  1419. Xoption with one or more minuses:  e.g., ``\-l\-t'' or ``\-\-tl'', in this
  1420. Xexample.  The first hyphen is the regular switch character, but the one
  1421. Xbefore the `t' is a minus sign.  The dual use of hyphens may seem a little
  1422. Xawkward, but it's reasonably intuitive nonetheless:  simply ignore the
  1423. Xfirst hyphen and go from there.  It is also consistent with the behavior
  1424. Xof the Unix command \fRnice\fP(1).
  1425. X.PD
  1426. X.SH EXAMPLES
  1427. XTo get a basic, short-format listing of the complete contents of a ZIP 
  1428. Xarchive ``storage.zip,'' with both header and totals lines, use only
  1429. Xthe archive name as an argument to zipinfo:
  1430. X.PP
  1431. X.IP "\t\fIzipinfo\fP storage"
  1432. X.PP
  1433. XTo produce a basic, long-format listing (not verbose), including header and
  1434. Xtotals lines, use \-l:
  1435. X.PP
  1436. X.IP "\t\fIzipinfo\fP \-l storage"
  1437. X.PP
  1438. XTo list the complete contents of the archive without header and totals
  1439. Xlines, either negate the \-h and \-t options or else specify the contents
  1440. Xexplicitly:
  1441. X.PP
  1442. X.IP "\t\fIzipinfo\fP \-\-h\-t storage"
  1443. X.IP "\t\fIzipinfo\fP storage \e*"
  1444. X.PP
  1445. X(where the backslash is required only if the shell would otherwise expand
  1446. Xthe `*' wildcard, as in Unix when globbing is turned on--double quotes around
  1447. Xthe asterisk would have worked as well).  To turn off the totals line by
  1448. Xdefault, use the environment variable (C shell is assumed here):
  1449. X.PP
  1450. X.IP "\tsetenv ZIPINFO \-\-t"
  1451. X.IP "\t\fIzipinfo\fP storage"
  1452. X.PP
  1453. XTo get the full, short-format listing of the first example again, given
  1454. Xthat the environment variable is set as in the previous example, it is
  1455. Xnecessary to specify the \-s option explicitly, since the \-t
  1456. Xoption by itself implies that ONLY the footer line is to be printed:
  1457. X.PP
  1458. X.IP "\tsetenv ZIPINFO \-\-t"
  1459. X.IP "\t\fIzipinfo\fP \-t storage\t[only totals line]"
  1460. X.IP "\t\fIzipinfo\fP \-st storage\t[full listing]"
  1461. X.PP
  1462. XThe \-s option, like \-m and \-l, includes headers and footers by default,
  1463. Xunless otherwise specified.  Since the environment variable specified no
  1464. Xfooters and that has a higher precedence than the default behavior of \-s,
  1465. Xan explicit \-t option was necessary to produce the full listing.  Nothing 
  1466. Xwas indicated about the header, however, so the \-s option was sufficient.
  1467. XNote that both the \-h and \-t options, when used by themselves or with
  1468. Xeach other, override any default listing of member files; only the header
  1469. Xand/or footer are printed.  This behavior will be more 
  1470. Xuseful when \fIZipInfo\fP accepts wildcards for the zipfile name; one
  1471. Xmay then summarize the contents of all zipfiles with a single command.
  1472. X.PP
  1473. XTo list information on a single file within the archive, in medium format,
  1474. Xspecify the filename explicitly:
  1475. X.PP
  1476. X.IP "\t\fIzipinfo\fP \-m storage unshrink.c"
  1477. X.PP
  1478. XThe specification of any member file, as in this example, will override
  1479. Xthe default header and totals lines; only the single line of information
  1480. Xabout the requested file will be printed.  This is intuitively what one
  1481. Xwould expect when requesting information about a single file.  For multiple
  1482. Xfiles, it is often useful to know the total compressed and uncompressed
  1483. Xsize; in such cases \-t may be specified explicitly:
  1484. X.PP
  1485. X.IP "\t\fIzipinfo\fP \-mt storage ""*.[ch] Mak\e*"
  1486. X.PP
  1487. XFinally, to get maximal information about the ZIP archive, use the verbose 
  1488. Xoption.  It is usually wise to pipe the output into a filter such as 
  1489. X\fRmore\fP(1):
  1490. X.PP
  1491. X.IP "\t\fIzipinfo\fP \-v storage | more"
  1492. X.PD
  1493. X.SH TIPS
  1494. XThe author finds it convenient to set up an alias ``ii'' for \fIZipInfo\fP
  1495. Xon systems which allow aliases, or else to set up a batch file ``ii.bat''
  1496. Xor to rename the executable to ``ii.exe'' on systems such as MS-DOS which
  1497. Xhave no provision for aliases.  The ``ii'' usage parallels the common
  1498. X``ll'' alias for long listings in Unix, and the similarity between the
  1499. Xoutputs of the two commands was intentional.
  1500. X.PD
  1501. X.SH SEE ALSO
  1502. Xfunzip(1), unzip(1), zip(1), zipcloak(1), zipnote(1), zipsplit(1)
  1503. X.PD
  1504. X.SH AUTHOR
  1505. XGreg Roelofs (also known as Cave Newt).  \fIZipInfo\fP is partly based on
  1506. XS. H. Smith's \fRunzip\fP and contains pattern-matching code by J. Kercheval,
  1507. Xbut mostly it was written from scratch.  The OS/2 extra-field code is by
  1508. XKai Uwe Rommel.
  1509. END_OF_FILE
  1510.   if test 13533 -ne `wc -c <'zipinfo.1'`; then
  1511.     echo shar: \"'zipinfo.1'\" unpacked with wrong size!
  1512.   fi
  1513.   # end of 'zipinfo.1'
  1514. fi
  1515. echo shar: End of archive 9 \(of 14\).
  1516. cp /dev/null ark9isdone
  1517. MISSING=""
  1518. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1519.     if test ! -f ark${I}isdone ; then
  1520.     MISSING="${MISSING} ${I}"
  1521.     fi
  1522. done
  1523. if test "${MISSING}" = "" ; then
  1524.     echo You have unpacked all 14 archives.
  1525.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1526. else
  1527.     echo You still must unpack the following archives:
  1528.     echo "        " ${MISSING}
  1529. fi
  1530. exit 0
  1531. exit 0 # Just in case...
  1532.