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

  1. Path: sparky!uunet!usc!elroy.jpl.nasa.gov!ames!agate!dog.ee.lbl.gov!network.ucsd.edu!mvb.saic.com!vmsnet-sources
  2. From: goathunter@wkuvx1.bitnet
  3. Newsgroups: vmsnet.sources
  4. Subject: Zip v1.9 & UnZip v5.0, part 10/22
  5. Message-ID: <8009640@MVB.SAIC.COM>
  6. Date: Tue, 01 Sep 1992 22:51:20 GMT
  7. Organization: Western Kentucky University, Bowling Green, KY
  8. Lines: 1369
  9. Approved: Mark.Berryman@Mvb.Saic.Com
  10.  
  11. Submitted-by: goathunter@wkuvx1.bitnet
  12. Posting-number: Volume 3, Issue 132
  13. Archive-name: zip_unzip/part10
  14.  
  15. -+-+-+-+-+-+-+-+ START OF PART 10 -+-+-+-+-+-+-+-+
  16. X    while ((cd < maxcodemax) && (prefix_of`5Bcd`5D != -1))
  17. X        cd++;
  18. X    free_ent = cd;
  19. X`7D
  20. $ CALL UNPACK [.UNZIP50]UNSHRINK.C;1 1162406257
  21. $ create 'f'
  22. X.TH UNZIP 1 "21 Aug 92 (v5.0)"
  23. X.SH NAME
  24. Xunzip \- list/test/extract from a ZIP archive file
  25. X.SH SYNOPSIS
  26. X\fBunzip\fP `5B \-\fBcflptuvxz\fP`5B\fBajnoqUV\fP`5D `5D \fIfile\fP`5B\fI.zi
  27. Vp\fP`5D `5B\fIfilespec\fP\ ...`5D
  28. X.SH ARGUMENTS
  29. X.IP \fIfile\fP`5B\fI.zip\fP`5D \w'`5B\fIfilespec\fP`5D'u+2m
  30. XPath of the ZIP archive.  The suffix
  31. X`60`60\fI.zip\fP'' is applied if the \fIfile\fP specified does not exist.
  32. XNote that self-extracting ZIP files are supported; just specify the
  33. X`60`60\fI.exe\fP'' suffix yourself.
  34. X.IP `5B\fIfilespec\fP`5D
  35. XAn optional list of archive members to be processed.
  36. XExpressions may be used to match multiple members; be sure to quote
  37. Xexpressions that contain characters interpreted by the operating
  38. Xsystem. See DESCRIPTION (below) for more details.
  39. X.SH OPTIONS
  40. X.PD 0
  41. X.IP \-c \w'\-c'u+2m
  42. Xextract files to stdout/screen (`60`60CRT'')
  43. X.IP \-f
  44. Xfreshen existing files (replace if newer); create none
  45. X.IP \-l
  46. Xlist archive files (short format)
  47. X.IP \-p
  48. Xextract files to pipe; no informational messages
  49. X.IP \-t
  50. Xtest archive files
  51. X.IP \-u
  52. Xupdate existing files; create new ones if needed
  53. X.IP \-v
  54. Xlist archive files (verbose format)
  55. X.IP \-x
  56. Xextract files in archive (default)
  57. X.IP \-z
  58. Xdisplay only the archive comment
  59. X.PD
  60. X.SH MODIFIERS
  61. X.PD 0
  62. X.IP \-a \w'\-a'u+2m
  63. Xconvert to MS-DOS textfile format (CR LF), Mac format (CR), Unix/VMS
  64. Xformat (LF), OR from ASCII to EBCDIC, depending on your system (only
  65. Xuse for TEXT files!)
  66. X.IP \-j
  67. Xjunk paths (don't recreate archive's directory structure)
  68. X.IP \-n
  69. Xnever overwrite existing files; don't prompt
  70. X.IP \-o
  71. XOK to overwrite files without prompting
  72. X.IP \-q
  73. Xperform operations quietly (\-qq \(rh even quieter)
  74. X.IP \-s
  75. X`5BOS/2, MS-DOS`5D allow spaces in filenames (e.g., `60`60EA\ DATA.\ SF'')
  76. X.IP \-U
  77. Xleave filenames uppercase if created under MS-DOS, VMS, etc.
  78. X.IP \-V
  79. Xretain (VMS) file version numbers
  80. X.IP \-X
  81. X`5BVMS`5D restore owner/protection info (may require privileges)
  82. X.PD
  83. X.SH DESCRIPTION
  84. X.I UnZip
  85. Xwill list, test, or extract from a ZIP archive, commonly found on MSDOS
  86. Xsystems.
  87. XArchive member extraction is implied by the absence of the \-c, \-p,
  88. X\-t, \-l, \-v or \-z options.  All archive members are processed unless a
  89. X.I filespec
  90. Xis provided to specify a subset of the archive members.  The
  91. X.I filespec
  92. Xis similar to an egrep expression, and may contain:
  93. X.sp 1
  94. X.ta \w'`5B...`5D'u+2m
  95. X*`09matches a sequence of 0 or more characters
  96. X.br
  97. X?`09matches exactly 1 character
  98. X.br
  99. X\\nnn`09matches the character having octal code nnn
  100. X.PD 0
  101. X.IP `5B...`5D \w'`5B...`5D'u+2m
  102. Xmatches any single character found inside the brackets; ranges
  103. Xare specified by a beginning character, a hyphen, and an ending
  104. Xcharacter.  If an exclamation point or a carat (`60!' or `60`5E') follows
  105. Xthe left bracket, then the range of characters matched is complemented
  106. Xwith respect to the ASCII character set (that is, anything except the
  107. Xcharacters inside the brackets is considered a match).
  108. X.PD
  109. X.SH ENVIRONMENT OPTIONS
  110. X\fIUnZip\fP's default behavior may be modified via options placed in
  111. Xan environment variable.  This can be done with any option, but it
  112. Xis probably most useful with the
  113. X\-q, \-o, or \-n modifiers:  in order to make \fIUnZip\fP quieter by`20
  114. Xdefault, or to make it always overwrite or never overwrite files as it
  115. Xextracts them.  For example, to
  116. Xmake \fIUnZip\fP act as quietly as possible, only reporting errors, one woul
  117. Vd
  118. Xuse one of the following commands:
  119. X.ta \w'tabset'u +\w'UNZIP=-qq; export UNZIP'u+4m
  120. X.PP
  121. X.IP "\tsetenv UNZIP -qq\tUnix C shell"
  122. X.br
  123. X.IP "\tUNZIP=-qq; export UNZIP\tUnix Bourne shell"
  124. X.PP
  125. X.IP "\tset UNZIP=-qq\tOS/2 or MS-DOS"
  126. X.PP
  127. X.IP "\tdefine UNZIP_OPTS ""-qq""\tVMS (quotes for LOWERCASE)"
  128. X.PP
  129. XEnvironment options are, in effect, considered to be just like any other
  130. Xcommand-line options, except that they are effectively the first options
  131. Xon the command line.  To override
  132. Xan environment option, one may use the `60`60minus operator'' to remove it.
  133. V  For
  134. Xinstance, to override one of the quiet-flags in the example above, use the
  135. Xcommand
  136. X.PP
  137. X.IP "\t\fIunzip\fP \-\-q`5Bother options`5D zipfile"
  138. X.PP
  139. XThe first hyphen is the normal
  140. Xswitch character, and the second is a minus sign, acting on the q option.
  141. XThus the effect here is to cancel a single quantum of quietness.  To cancel
  142. Xboth quiet flags, two (or more) minuses may be used:
  143. X.PP
  144. X.IP "\t\fIunzip\fP \-x\-\-q zipfile"
  145. X.PP
  146. Xor
  147. X.PP
  148. X.IP "\t\fIunzip\fP \-\-\-qx zipfile"
  149. X.PP
  150. X(the two are equivalent).  This may seem awkward
  151. Xor confusing, but it is reasonably intuitive:  just ignore the first
  152. Xhyphen and go from there.  It is also consistent with the behavior of Unix
  153. Xnice(1).
  154. X.PD
  155. X.SH EXAMPLES
  156. XTo use \fIUnZip\fP to extract all members of the archive letters.zip,
  157. Xcreating any directories as necessary:
  158. X.PP
  159. X.IP "\t\fIunzip\fP letters"
  160. X.PP
  161. XTo extract all members of letters.zip to the current directory:
  162. X.PP
  163. X.IP "\t\fIunzip\fP -j letters"
  164. X.PP
  165. XTo test letters.zip, printing only a summary message indicating
  166. Xwhether the archive is OK or not:
  167. X.PP
  168. X.IP "\t\fIunzip\fP -tq letters"
  169. X.PP
  170. XTo extract to standard output all members of letters.zip whose names end
  171. Xin `60`60.tex'', converting to the local end-of-line convention and piping t
  172. Vhe
  173. Xoutput into more(1):
  174. X.PP
  175. X.IP "\t\fIunzip\fP \-ca letters \e*.tex `7C more"
  176. X.PP
  177. X(The backslash before the asterisk is only required if the shell expands
  178. Xwildcards, as in Unix; double quotes could have been used instead, as in
  179. Xthe source example below.)\ \ To extract the binary file paper1.dvi to`20
  180. Xstandard output and pipe it to a printing program:
  181. X.PP
  182. X.IP "\t\fIunzip\fP \-p articles paper1.dvi `7C dvips"
  183. X.PP
  184. XTo extract all FORTRAN and C source files--*.f, *.c, *.h, Makefile (the
  185. Xdouble quotes are necessary only in Unix and only if globbing is turned on):
  186. X.PP
  187. X.IP "\t\fIunzip\fP source.zip ""*.`5Bfch`5D"" Makefile"
  188. X.PP
  189. XTo extract only newer versions of the files already in the current directory
  190. V,
  191. Xwithout querying (NOTE:  be careful of unzipping in one timezone a zipfile`2
  192. V0
  193. Xcreated in another--ZIP archives contain no timezone information, and a`20
  194. X`60`60newer'' file from an eastern timezone may, in fact, be older):
  195. X.PP
  196. X.IP "\t\fIunzip\fP \-fo sources"
  197. X.PP
  198. XTo extract newer versions of the files already in the current directory and
  199. Xto create any files not already there (same caveat as previous example):
  200. X.PP
  201. X.IP "\t\fIunzip\fP \-uo sources"
  202. X.PP
  203. X.PP
  204. XIn the last five examples, assume that UNZIP or UNZIP_OPTS is set to -q.
  205. XTo do a singly quiet listing:
  206. X.PP
  207. X.IP "\t\fIunzip\fP \-\fIl\fP \fIfile\fP"
  208. X.PP
  209. XTo do a doubly quiet listing:
  210. X.PP
  211. X.IP "\t\fIunzip\fP \-\fIql\fP \fIfile\fP"
  212. X.PP
  213. XTo do a standard listing:
  214. X.PP
  215. X.IP "\t\fIunzip\fP \-\-\fIql\fP \fIfile\fP"
  216. X.PP
  217. Xor
  218. X.PP
  219. X.IP "\t\fIunzip\fP \-\fIl\fP\-\fIq\fP \fIfile\fP"
  220. X.PP
  221. Xor
  222. X.PP
  223. X.IP "\t\fIunzip\fP \-\fIl\fP\-\-\fIq\fP \fIfile\fP"
  224. X.PP
  225. X(extra minuses don't hurt).
  226. X.PD
  227. X.SH TIPS
  228. XThe current maintainer, being a lazy sort, finds it very useful to define
  229. Xan alias `60`60tt'' for `60`60unzip -tq''.  One may then simply type `60`60t
  230. Vt zipfile''
  231. Xto test the archive, something which one ought make a habit of doing.
  232. XWith luck \fIUnZip\fP will report `60`60No errors detected in zipfile.zip,''
  233. Xafter which one may breathe a sigh of relief.
  234. X.PD
  235. X.SH SEE ALSO
  236. Xfunzip(1), zip(1), zipcloak(1), zipinfo(1), zipnote(1), zipsplit(1)
  237. X.PD
  238. X.SH AUTHORS
  239. XSamuel H. Smith, Carl Mascott, David P. Kirschbaum, Greg R. Roelofs, Mark
  240. XAdler, Kai Uwe Rommel, Igor Mandrichenko, Johnny Lee, Jean-loup Gailly; Glen
  241. Vn
  242. XAndrews, Joel Aycock, Allan Bjorklund, James Birdsall, Wim Bonner, John Cowa
  243. Vn,
  244. XFrank da Cruz, Bill Davidsen, Arjan de Vet, James Dugal, Jim Dumser, Mark
  245. XEdwards, David Feinleib, Mike Freeman, Hunter Goatley, Robert Heath, Dave
  246. XHeiland, Larry Jones, Kjetil J`7B\o`7Drgenson, Bob Kemp, J. Kercheval, Alvin
  247. V Koh,
  248. XBo Kullmar, Johnny Lee, Warner Losh, Fulvio Marino, Gene McManus, Joe Meadow
  249. Vs,
  250. XMike O'Carroll, Humberto Ortiz-Zuazaga, Piet W. Plomp, Antonio Querubin Jr.,
  251. XSteve Salisbury, Georg Sassen, Jon Saxton, Hugh Schmidt, Martin Schulz, Char
  252. Vles
  253. XScripter, Chris Seaman, Richard Seay, Alex Sergejew, Cliff Stanford, Onno va
  254. Vn
  255. Xder Linden, Jim Van Zandt, Antoine Verheijen, Paul Wells.
  256. X.PD
  257. X.SH VERSIONS
  258. X.ta \w'vx.x\ \ 'u +\w'fall 1989\ \ 'u
  259. X.PD 0
  260. X.IP "v1.2\t15 Mar 89" \w'\t\t'u
  261. XSamuel H. Smith
  262. X.IP "v2.0\t\ 9 Sep 89"
  263. XSamuel H. Smith
  264. X.IP "v2.x\tfall 1989"
  265. Xmany Usenet contributors
  266. X.IP "v3.0\t\ 1 May 90"
  267. XInfo-ZIP (DPK, consolidator)
  268. X.IP "v3.1\t15 Aug 90"
  269. XInfo-ZIP (DPK, consolidator)
  270. X.IP "v4.0\t\ 1 Dec 90"
  271. XInfo-ZIP (GRR, maintainer)
  272. X.IP "v4.1\t12 May 91"
  273. XInfo-ZIP
  274. X.IP "v4.2\t20 Mar 92"
  275. XInfo-ZIP (zip-bugs subgroup; GRR, maint.)
  276. X.IP "v5.0\t21 Aug 92"
  277. XInfo-ZIP (zip-bugs subgroup; GRR, maint.)
  278. X.PD
  279. $ CALL UNPACK [.UNZIP50]UNZIP.1;1 1882148306
  280. $ create 'f'
  281. X/*--------------------------------------------------------------------------
  282. V-
  283. X
  284. X  unzip.c
  285. X
  286. X  UnZip - a zipfile extraction utility.  See below for make instructions, or
  287. X  read the comments in Makefile and the various Contents files for more de-
  288. X  tailed explanations.  To report a bug, send a *complete* description to
  289. X  zip-bugs@cs.ucla.edu; include machine type, operating system and version,
  290. X  compiler and version, and reasonably detailed error messages or problem
  291. X  report.  To join Info-ZIP, send a message to info-zip-request@cs.ucla.edu.
  292. X
  293. X  UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
  294. X  which in turn was almost a complete rewrite of version 3.x.  For a detaile
  295. Vd
  296. X  revision history, see UnzpHist.zip at Info-ZIP headquarters (below).  For
  297. V a`20
  298. X  (partial) list of the many (near infinite) contributors, see "CONTRIBS" in
  299. X  the UnZip source distribution.
  300. X
  301. X  --------------------------------------------------------------------------
  302. V-
  303. X
  304. X  To compile (partial instructions):
  305. X
  306. X     under Unix (cc):  make <system name>
  307. X       (type "make list" for a list of valid names, or read Makefile for`20
  308. X       details.  "make unzip" works for most systems.  If you have a NEW
  309. X       system, not covered by any of the existing targets, send FULL infor-
  310. X       mation--hardware, OS, versions, etc.--to zip-bugs@cs.ucla.edu)
  311. X
  312. X     under MS-DOS (MSC, Turbo C, or Borland C++):  use the makefiles or
  313. X       project files in the MSDOS sub-archive; edit or otherwise modify
  314. X       as appropriate.  For MSC, use NMAKE.
  315. X
  316. X     under MS Windows 3.x:  get wunz12sr.`7Bzip `7C zoo `7C whatever`7D and
  317. V use
  318. X       the included makefile
  319. X
  320. X     under OS/2 (MSC, gcc, IBM C Set/2, Watcom C):  make -f makefile.os2
  321. X       (from OS2 sub-archive; for MSC, use NMAKE)
  322. X
  323. X     under VMS (VAX C or GNU C):  @make_unzip_vaxc  or  @make_unzip_gcc
  324. X       (from VMS sub-archive; can also use MMS or MAKE/VMS; see VMS.notes)
  325. X
  326. X     under Macintosh OS:  Double click on unzip.make.  Press <Command>-M.
  327. X       (from MAC sub-archive)
  328. X
  329. X     under Windows NT:  use makefile.nt (from NT sub-archive)
  330. X
  331. X     under AmigaDOS:  try one of the makefiles in the AMIGA sub-archive;
  332. X       may need some work yet...
  333. X
  334. X     under Atari TOS:  needs considerable work yet...
  335. X
  336. X  --------------------------------------------------------------------------
  337. V-
  338. X
  339. X  Version:  unzip50.`7Btar.Z `7C zip `7C zoo`7D for Unix, VMS, OS/2, MS-DOS,
  340. V Windows,
  341. X              Windows NT, Macintosh and Amiga.  Decryption requires sources
  342. X              in zcrypt19.zip, and Windows (not NT) support requires sources
  343. X              in wunz12sr.zip.  See accompanying file "Where" in the main
  344. X              source distribution for ftp, uucp and mail-server sites.
  345. X  Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
  346. X
  347. X  --------------------------------------------------------------------------
  348. V-*/
  349. X
  350. X
  351. X
  352. X
  353. X
  354. X#include "unzip.h"               /* includes, defines, and macros */
  355. X#ifdef MSWIN
  356. X#  include "wizunzip.h"          /* see History.500 for version history */
  357. X#endif
  358. X
  359. X#define VERSION  "v5.0 of 21 August 1992"
  360. X/* #define VERSION  "v5.0p BETA of 8-21-92" */   /* internal beta level */
  361. X#define PAKFIX   /* temporary(?) solution to PAK-created zipfiles */
  362. X
  363. X
  364. X
  365. X
  366. X
  367. X/**********************/
  368. X/*  Global Variables  */
  369. X/**********************/
  370. X
  371. Xint aflag=0;          /* -a: do ASCII to EBCDIC translation, or CR-LF  */
  372. X                      /*     to CR or LF conversion of extracted files */
  373. X/* int bflag=0; RESERVED for -b: extract as binary */
  374. Xint cflag=0;          /* -c: output to stdout */
  375. Xint fflag=0;          /* -f: "freshen" (extract only newer files) */
  376. Xint jflag=0;          /* -j: junk pathnames */
  377. Xint overwrite_none=0; /* -n: never overwrite files (no prompting) */
  378. Xint overwrite_all=0;  /* -o: OK to overwrite files without prompting */
  379. Xint force_flag=0;     /* (shares -o for now): force to override errors, etc.
  380. V */
  381. Xint quietflg=0;       /* -q: produce a lot less output */
  382. X#ifdef DOS_OS2
  383. X   int sflag=1;       /* -s: allow spaces (blanks) in filenames */
  384. X#endif /* DOS_OS2 */
  385. Xint tflag=0;          /* -t: test */
  386. Xint uflag=0;          /* -u: "update" (extract only newer & brand-new files)
  387. V */
  388. Xstatic int U_flag=0;  /* -U: leave filenames in upper or mixed case */
  389. Xstatic int vflag=0;   /* -v: view directory (only used in unzip.c) */
  390. Xint V_flag=0;         /* -V: don't strip VMS version numbers */
  391. X#ifdef VMS
  392. X   int secinf=0;      /* -X: keep owner/protection */
  393. X#endif /* VMS */
  394. Xint zflag=0;          /* -z: display only the archive comment */
  395. Xint process_all_files=0;
  396. X
  397. Xlongint csize;        /* used by list_files(), ReadByte(): must be signed */
  398. Xlongint ucsize;       /* used by list_files(), unReduce(), explode() */
  399. X
  400. Xchar *fnames`5B2`5D = `7B"*", NULL`7D;   /* default filenames vector */
  401. Xchar **fnv = fnames;
  402. Xchar sig`5B5`5D;
  403. Xchar answerbuf`5B10`5D;
  404. X
  405. Xmin_info info`5BDIR_BLKSIZ`5D, *pInfo=info;
  406. X
  407. X#ifdef OS2
  408. X   int longname;              /* used in extract.c, mapname.c and file_io.c
  409. V */
  410. X   char longfilename`5BFILNAMSIZ`5D;
  411. X#endif /* OS2 */
  412. X
  413. X#ifdef CRYPT
  414. X   char *key = (char *)NULL;  /* password with which to decrypt data, or NUL
  415. VL */
  416. X#endif /* CRYPT */
  417. X
  418. X/*--------------------------------------------------------------------------
  419. V-
  420. X    unShrink/unReduce/explode/inflate working storage and globals:
  421. X  --------------------------------------------------------------------------
  422. V-*/
  423. X
  424. Xunion work area;              /* see unzip.h for the definition of work */
  425. XULONG crc32val;
  426. X
  427. XUWORD mask_bits`5B`5D = `7B
  428. X    0x0000,
  429. X    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
  430. X    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
  431. X`7D;
  432. X
  433. X/*--------------------------------------------------------------------------
  434. V-
  435. X    Input file variables:
  436. X  --------------------------------------------------------------------------
  437. V-*/
  438. X
  439. Xbyte *inbuf, *inptr;     /* input buffer (any size is legal) and pointer */
  440. Xint incnt;
  441. X
  442. XULONG bitbuf;
  443. Xint bits_left;
  444. Xboolean zipeof;
  445. X
  446. Xint zipfd;               /* zipfile file handle */
  447. X#ifdef MSWIN
  448. X   char *zipfn;
  449. X#else
  450. X   char zipfn`5BFILNAMSIZ`5D;
  451. X#endif
  452. X
  453. Xchar local_hdr_sig`5B5`5D = "\120";    /* remaining signature bytes come lat
  454. Ver   */
  455. Xchar central_hdr_sig`5B5`5D = "\120";  /*  (must initialize at runtime so un
  456. Vzip  */
  457. Xchar end_central_sig`5B5`5D = "\120";  /*  executable won't look like a zipf
  458. Vile) */
  459. X/* char extd_local_sig`5B5`5D = "\120";  NOT USED YET */
  460. X
  461. Xcdir_file_hdr crec;      /* used in unzip.c, extract.c, misc.c */
  462. Xlocal_file_hdr lrec;     /* used in unzip.c, extract.c */
  463. Xecdir_rec ecrec;         /* used in unzip.c, extract.c */
  464. Xstruct stat statbuf;     /* used by main(), mapped_name(), check_for_newer()
  465. V */
  466. X
  467. Xlongint extra_bytes = 0;        /* used in unzip.c, misc.c */
  468. Xlongint cur_zipfile_bufstart;   /* extract_or_test_files, readbuf, ReadByte
  469. V */
  470. X `20
  471. X#ifdef MACOS
  472. X   short  gnVRefNum;
  473. X   long  glDirID;
  474. X   OSType  gostCreator;
  475. X   OSType  gostType;
  476. X   boolean  fMacZipped;
  477. X   boolean  macflag;
  478. X   CursHandle  rghCursor`5B4`5D;    /* status cursors */
  479. X   short  giCursor = 0;
  480. X#endif
  481. X
  482. X/*--------------------------------------------------------------------------
  483. V-
  484. X    Output stream variables:
  485. X  --------------------------------------------------------------------------
  486. V-*/
  487. X
  488. Xbyte *outbuf;                   /* buffer for rle look-back */
  489. Xbyte *outptr;
  490. X#ifdef MSWIN
  491. X   byte __far *outout;
  492. X   char *filename;
  493. X#else /* !MSWIN */
  494. X   byte *outout;                /* scratch pad for ASCII-native trans */
  495. X   char filename`5BFILNAMSIZ`5D;
  496. X#endif /* ?MSWIN */
  497. Xbyte *extra_field = (byte *)NULL;  /* used by VMS, Mac and OS/2 versions */
  498. Xlongint outpos;                 /* absolute position in outfile */
  499. Xint outcnt;                     /* current position in outbuf */
  500. Xint outfd;
  501. Xint mem_mode = 0;
  502. Xint disk_full;
  503. X
  504. X/*--------------------------------------------------------------------------
  505. V-
  506. X    unzip.c static global variables (visible only within this file):
  507. X  --------------------------------------------------------------------------
  508. V-*/
  509. X
  510. Xstatic byte *hold;
  511. Xstatic char unkn`5B10`5D;
  512. Xstatic longint ziplen;
  513. Xstatic UWORD methnum;
  514. X
  515. X/*--------------------------------------------------------------------------
  516. V-
  517. X    unzip.c repeated error messages (we use all of these at least twice)
  518. X  --------------------------------------------------------------------------
  519. V-*/
  520. X
  521. Xchar *EndSigMsg = "\nwarning:\
  522. X  didn't find end-of-central-dir signature at end of central dir.\n";
  523. Xchar *CentSigMsg =
  524. X  "error:  expected central file header signature not found (file #%u).\n";
  525. Xchar *SeekMsg =
  526. X  "error:  attempt to seek before beginning of zipfile\n%s";
  527. X
  528. X#ifdef VMS
  529. Xchar *ReportMsg = "\
  530. X  (please check that you have transferred or created the zipfile in the\n\
  531. X  appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\
  532. Vn";
  533. X#else /* !VMS */
  534. Xchar *ReportMsg = "\
  535. X  (please check that you have transferred or created the zipfile in the\n\
  536. X  appropriate BINARY mode and that you have compiled unzip properly)\n";
  537. X#endif /* ?VMS */
  538. X
  539. X
  540. X#ifdef MSWIN
  541. X/* MS Windows Setup  and Take-Down functions bracket calls to`20
  542. X * process_zipfile().
  543. X * These functions allocate and free the necessary buffers, set and clear
  544. X * any global variables so that  process_zipfile()  can be called multiple
  545. X * times in the same session of WizUnzip. You'll recognize some of the`20
  546. X * code from main() in SetUpToProcessZipFile().
  547. X */
  548. XHANDLE hOutBuf;
  549. XHANDLE hOutOut;   /* added 04/03/92 for version 1.1 */
  550. XHANDLE hInBuf;
  551. XHANDLE hZipFN;
  552. XHANDLE hFileName;
  553. X
  554. XBOOL FSetUpToProcessZipFile(int ncflag, int ntflag, int nvflag, int nUflag,`
  555. V20
  556. X       int nzflag, int ndflag, int noflag, int naflag, int argc,
  557. X       LPSTR lpszZipFN, PSTR *FNV)
  558. X`7B
  559. X    /* clear all global flags -- need to or not. */
  560. X
  561. X    tflag = vflag=cflag=aflag=U_flag=quietflg=zflag = 0;
  562. X    overwrite_all=overwrite_none=0;
  563. X    fnv = &fnames`5B0`5D;       /* assign default file name vector */
  564. X
  565. X    cflag = ncflag ; overwrite_all = noflag;
  566. X    tflag = ntflag ; vflag = nvflag; zflag = nzflag; U_flag = nUflag;
  567. X    aflag = naflag;
  568. X    sflag = 1;
  569. X
  570. X    local_hdr_sig`5B0`5D = central_hdr_sig`5B0`5D = end_central_sig`5B0`5D =
  571. V '\120';
  572. X    local_hdr_sig`5B1`5D = central_hdr_sig`5B1`5D = end_central_sig`5B1`5D =
  573. V '\0';
  574. X
  575. X    if (!(hZipFN = LocalAlloc(LMEM_MOVEABLE, FILNAMSIZ)))
  576. X        return FALSE;
  577. X
  578. X    zipfn = (char *)LocalLock(hZipFN);
  579. X    lstrcpy(zipfn, lpszZipFN);
  580. X    if (stat(zipfn, &statbuf) `7C`7C (statbuf.st_mode & S_IFMT) == S_IFDIR)
  581. X        strcat(zipfn, ZSUFX);
  582. X
  583. X    if (stat(zipfn, &statbuf)) `7B  /* try again */
  584. X        fprintf(stderr, "error:  can't find zipfile `5B %s `5D\n", zipfn);
  585. X        return TRUE;              /* 9:  file not found */
  586. X    `7D else
  587. X        ziplen = statbuf.st_size;
  588. X
  589. X    if (argc != 0) `7B
  590. X        fnv = FNV;
  591. X        process_all_files = FALSE;
  592. X    `7D else
  593. X        process_all_files = TRUE;       /* for speed */
  594. X
  595. X/*--------------------------------------------------------------------------
  596. V-
  597. X    Okey dokey, we have everything we need to get started.  Let's roll.
  598. X  --------------------------------------------------------------------------
  599. V-*/
  600. X
  601. X    if (hInBuf = LocalAlloc(LMEM_MOVEABLE, INBUFSIZ+4)) `7B  /* 4 extra: hol
  602. Vd`5B`5D */
  603. X        inbuf = (byte *) LocalLock(hInBuf);
  604. X        WinAssert(inbuf);
  605. X    `7D
  606. X    if (hOutBuf = LocalAlloc(LMEM_MOVEABLE, OUTBUFSIZ+1)) `7B  /* extra: ASC
  607. VIIZ */
  608. X        outbuf = (byte *)LocalLock(hOutBuf);
  609. X        WinAssert(outbuf);
  610. X        if (aflag) `7B   /* if LF => CR,LF translation */
  611. X            if (hOutOut = GlobalAlloc(GMEM_MOVEABLE,OUTBUFSIZ)) `7B
  612. X                outout = (byte _far *)GlobalLock(hOutOut);
  613. X                WinAssert(outout);
  614. X            `7D
  615. X        `7D else    /* no translation; just re-use output buffer */
  616. X            outout = (byte _far *)outbuf;  /*  point to outbuf */
  617. X    `7D
  618. X    if ( hFileName = LocalAlloc(LMEM_MOVEABLE, FILNAMSIZ)) `7B
  619. X        filename = (char *)LocalLock(hFileName);
  620. X        WinAssert(filename);
  621. X    `7D
  622. X
  623. X    if ((inbuf == NULL) `7C`7C (outbuf == NULL) `7C`7C (outout == NULL) `7C`
  624. V7C
  625. X        (zipfn == NULL) `7C`7C (filename == NULL))
  626. X        return FALSE;
  627. X
  628. X    hold = &inbuf`5BINBUFSIZ`5D;   /* to check for boundary-spanning signatu
  629. Vres */
  630. X
  631. X    return TRUE;    /* set up was OK */
  632. X`7D
  633. X
  634. Xvoid TakeDownFromProcessZipFile(void)
  635. X`7B
  636. X    if (inbuf) `7B
  637. X        LocalUnlock(hInBuf);
  638. X        inbuf = NULL;
  639. X    `7D
  640. X    if (hInBuf)
  641. X        hInBuf = LocalFree(hInBuf);
  642. X
  643. X    if (outbuf) `7B
  644. X        LocalUnlock(hOutBuf);
  645. X        outbuf = NULL;
  646. X    `7D
  647. X    if (hOutBuf)
  648. X        hOutBuf = LocalFree(hOutBuf);
  649. X
  650. X    if (aflag && outout)    /* if doing LF => CR,LF translation */
  651. X        GlobalUnlock(hOutOut);
  652. X    outout = NULL;          /* free now, translation or not     */
  653. X    if (hOutOut)
  654. X        hOutOut = GlobalFree(hOutOut);  /* mark buffer as freed */
  655. X
  656. X    if (zipfn) `7B
  657. X        LocalUnlock(hZipFN);
  658. X        zipfn = NULL;
  659. X    `7D
  660. X    if (hZipFN)
  661. X        hZipFN = LocalFree(hZipFN);
  662. X
  663. X    if (filename) `7B
  664. X        LocalUnlock(hFileName);
  665. X        filename = NULL;
  666. X    `7D
  667. X    if (hFileName)
  668. X        hFileName = LocalFree(hFileName);
  669. X`7D
  670. X
  671. X#else /* !MSWIN */
  672. X
  673. X/******************/
  674. X/*  Main program  */
  675. X/******************/
  676. X
  677. Xint main(argc, argv)   /* return PK-type error code (except under VMS) */
  678. X    int argc;
  679. X    char *argv`5B`5D;
  680. X`7B
  681. X    char *s;
  682. X    int c, error=FALSE, negative=0;
  683. X
  684. X
  685. X/*--------------------------------------------------------------------------
  686. V-
  687. X    Macintosh initialization code.
  688. X  --------------------------------------------------------------------------
  689. V-*/
  690. X
  691. X#ifdef MACOS
  692. X#ifdef THINK_C
  693. X#   include <console.h>
  694. X    static char *argstr`5B30`5D, args`5B30*64`5D;
  695. X    Point p;
  696. X    SFTypeList sfT;
  697. X    EventRecord theEvent;
  698. X    short eMask;
  699. X    SFReply fileRep;
  700. X#endif /* THINK_C */
  701. X    int a;
  702. X
  703. X    for (a = 0;  a < 4;  ++a)
  704. X        rghCursor`5Ba`5D = GetCursor(a+128);
  705. X    giCursor = 0;
  706. X
  707. X    area.Slide = (byte *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char
  708. V));
  709. X    area.shrink.Prefix_of = (short *)area.Slide;
  710. X    area.shrink.Suffix_of = area.Slide + (sizeof(short)*(HSIZE+1));
  711. X    area.shrink.Stack = area.Slide + (sizeof(short) + sizeof(char))*(HSIZE+1
  712. V);
  713. X
  714. X#ifdef THINK_C  `20
  715. X    for (a = 0;  a < 30;  ++a)
  716. X        argstr`5Ba`5D = &args`5Ba*64`5D;
  717. Xstart:
  718. X    tflag=vflag=cflag=aflag=jflag=U_flag=quietflg=fflag=uflag=zflag = 0;
  719. X    local_hdr_sig`5B1`5D = central_hdr_sig`5B1`5D = end_central_sig`5B1`5D =
  720. V '\0';
  721. X/*  extd_local_sig`5B1`5D = '\0';  */
  722. X    error = FALSE;
  723. X
  724. X    argc = ccommand(&argv);
  725. X    SetPt(&p, 40, 40);
  726. X
  727. X    SFGetFile(p, "\pSpecify ZIP file:", 0L, -1, sfT, 0L, &fileRep);
  728. X    if (fileRep.good) `7B
  729. X        macfstest(fileRep.vRefNum);
  730. X        ResolveMacVol(fileRep.vRefNum, &gnVRefNum, &glDirID, NULL);
  731. X        for (a = 1;  a < argc;  ++a)
  732. X            if (argv`5Ba`5D`5B0`5D == '-')
  733. X                BlockMove(argv`5Ba`5D, argstr`5Ba`5D, (strlen(argv`5Ba`5D) >
  734. V 63) ? 64 :
  735. X                   strlen(argv`5Ba`5D)+1);
  736. X            else
  737. X                break;
  738. X        PtoCstr((char *)fileRep.fName);
  739. X        strcpy(argstr`5Ba`5D, (char *)fileRep.fName);
  740. X        for (;  a < argc;  ++a)
  741. X            BlockMove(argv`5Ba`5D, argstr`5Ba+1`5D, (strlen(argv`5Ba`5D) > 6
  742. V3) ? 64 :
  743. X               strlen(argv`5Ba`5D)+1);
  744. X        ++argc;
  745. X        argv = argstr;
  746. X
  747. X        if (hfsflag == FALSE)  /* can't support directories:  junk pathnames
  748. V */
  749. X            jflag = 1;
  750. X    `7D
  751. X#endif /* THINK_C */
  752. X#endif /* MACOS */
  753. X
  754. X/*--------------------------------------------------------------------------
  755. V-
  756. X    Set signal handler for restoring echo, warn of zipfile corruption, etc.
  757. X  --------------------------------------------------------------------------
  758. V-*/
  759. X
  760. X    signal(SIGINT, handler);
  761. X    signal(SIGTERM, handler);
  762. X#ifdef SIGBUS
  763. X    signal(SIGBUS, handler);
  764. X#endif
  765. X#ifdef SIGSEGV
  766. X    signal(SIGSEGV, handler);
  767. X#endif
  768. X
  769. X/*--------------------------------------------------------------------------
  770. V-
  771. X    Debugging info for checking on structure padding:
  772. X  --------------------------------------------------------------------------
  773. V-*/
  774. X
  775. X#ifdef DEBUG_STRUC
  776. X    printf("local_file_hdr size: %X\n",
  777. X           sizeof(local_file_hdr));
  778. X    printf("local_byte_hdr size: %X\n",
  779. X           sizeof(local_byte_hdr));
  780. X    printf("actual size of local headers: %X\n", LREC_SIZE);
  781. X
  782. X    printf("central directory header size: %X\n",
  783. X           sizeof(cdir_file_hdr));
  784. X    printf("central directory byte header size: %X\n",
  785. X           sizeof(cdir_byte_hdr));
  786. X    printf("actual size of central dir headers: %X\n", CREC_SIZE);
  787. X
  788. X    printf("end central dir record size: %X\n",
  789. X           sizeof(ecdir_rec));
  790. X    printf("end central dir byte record size: %X\n",
  791. X           sizeof(ec_byte_rec));
  792. X    printf("actual size of end-central-dir record: %X\n", ECREC_SIZE);
  793. X#endif /* DEBUG_STRUC */
  794. X
  795. X/*--------------------------------------------------------------------------
  796. V-
  797. X    Put environment-variable options into the queue, then rip through any
  798. X    command-line options lurking about...
  799. X  --------------------------------------------------------------------------
  800. V-*/
  801. X
  802. X    envargs(&argc, &argv, ENV_UNZIP);
  803. X
  804. X    while (--argc > 0 && (*++argv)`5B0`5D == '-') `7B
  805. X        s = argv`5B0`5D + 1;
  806. X        while ((c = *s++) != 0) `7B    /* "!= 0":  prevent Turbo C warning *
  807. V/
  808. X            switch (c) `7B
  809. X                case ('-'):
  810. X                    ++negative;
  811. X                    break;
  812. X                case ('a'):
  813. X                    if (negative)
  814. X                        aflag = FALSE, negative = 0;
  815. X                    else
  816. X                        aflag = TRUE;
  817. X                    break;
  818. X#if 0
  819. X                case ('b'):    /* force binary mode */
  820. X                    if (negative)
  821. X                        bflag = FALSE, negative = 0;
  822. X                    else
  823. X                        bflag = TRUE;
  824. X                    break;
  825. X#endif
  826. X                case ('c'):
  827. X                    if (negative) `7B
  828. X                        cflag = FALSE, negative = 0;
  829. X#ifdef NATIVE
  830. X                        aflag = FALSE;
  831. X#endif
  832. X                    `7D else `7B
  833. X                        cflag = TRUE;
  834. X#ifdef NATIVE
  835. X                        aflag = TRUE;  /* so you can read it on the screen *
  836. V/
  837. X#endif
  838. X                    `7D
  839. X                    break;
  840. X                case ('d'):    /* re-create directory structure (default) */
  841. X                    if (negative)
  842. X                        jflag = TRUE, negative = 0;
  843. X                    break;
  844. X                case ('e'):    /* just ignore -e, -x options (extract) */
  845. X                    break;
  846. X                case ('f'):    /* "freshen" (extract only newer files) */
  847. X                    if (negative)
  848. X                        fflag = uflag = FALSE, negative = 0;
  849. X                    else
  850. X                        fflag = uflag = TRUE;
  851. X                    break;
  852. X                case ('j'):    /* junk pathnames/directory structure */
  853. X                    if (negative)
  854. X                        jflag = FALSE, negative = 0;
  855. X                    else
  856. X                        jflag = TRUE;
  857. X                    break;
  858. X                case ('l'):
  859. X                    if (negative) `7B
  860. X                        vflag = MAX(vflag-negative,0);
  861. X                        negative = 0;
  862. X                    `7D else
  863. X                        ++vflag;
  864. X                    break;
  865. X                case ('n'):    /* don't overwrite any files */
  866. X                    if (negative)
  867. X                        overwrite_none = FALSE, negative = 0;
  868. X                    else
  869. X                        overwrite_none = TRUE;
  870. X                    break;
  871. X                case ('o'):    /* OK to overwrite files without prompting */
  872. X                    if (negative) `7B
  873. X                        overwrite_all = MAX(overwrite_all-negative,0);
  874. X                        force_flag = MAX(force_flag-negative,0);
  875. X                        negative = 0;
  876. X                    `7D else `7B
  877. X                        ++overwrite_all;
  878. X                        ++force_flag;  /* (share -o for now) force to cont.
  879. V */
  880. X                    `7D
  881. X                    break;
  882. X                case ('p'):    /* pipes:  stdout, no tranlation, no messages
  883. V */
  884. X                    if (negative) `7B
  885. X                        cflag = FALSE;
  886. X                        quietflg = MAX(quietflg-999,0);
  887. X                        negative = 0;
  888. X                    `7D else `7B
  889. X                        cflag = TRUE;
  890. X                        quietflg += 999;
  891. X                    `7D
  892. X                    break;
  893. X                case ('q'):    /* quiet:  fewer comments/messages */
  894. X                    if (negative) `7B
  895. X                        quietflg = MAX(quietflg-negative,0);
  896. X                        negative = 0;
  897. X                    `7D else
  898. X                        ++quietflg;
  899. X                    break;
  900. X#ifdef DOS_OS2
  901. X                case ('s'):    /* spaces in filenames:  allow by default */
  902. X                    if (negative)
  903. X                        sflag = TRUE, negative = 0;
  904. X                    else
  905. X                        sflag = FALSE;
  906. X                    break;
  907. X#endif
  908. X                case ('t'):
  909. X                    if (negative)
  910. X                        tflag = FALSE, negative = 0;
  911. X                    else
  912. X                        tflag = TRUE;
  913. X                    break;
  914. X                case ('U'):    /* Uppercase (don't convert to all-lower) */
  915. X                    if (negative)
  916. X                        U_flag = FALSE, negative = 0;
  917. X                    else
  918. X                        U_flag = TRUE;
  919. X                    break;
  920. X                case ('u'):    /* update (extract only new and newer files)
  921. V */
  922. X                    if (negative)
  923. X                        uflag = FALSE, negative = 0;
  924. X                    else
  925. X                        uflag = TRUE;
  926. X                    break;
  927. X                case ('V'):    /* Version (retain VMS/DEC-20 file versions)
  928. V */
  929. X                    if (negative)
  930. X                        V_flag = FALSE, negative = 0;
  931. X                    else
  932. X                        V_flag = TRUE;
  933. X                    break;
  934. X                case ('v'):    /* verbose */
  935. X                    if (negative) `7B
  936. X                        vflag = MAX(vflag-negative,0);
  937. X                        negative = 0;
  938. X                    `7D else if (vflag)
  939. X                        ++vflag;
  940. X                    else
  941. X                        vflag = 2;
  942. X                    break;
  943. X#ifdef VMS
  944. X                case ('X'):   /* restore owner/protection info (need privs?)
  945. V */
  946. X                    if (negative)
  947. X                        secinf = FALSE, negative = 0;
  948. X                    else
  949. X                        secinf = TRUE;
  950. X                    break;
  951. X#endif /* VMS */
  952. X                case ('x'):    /* extract:  default */
  953. X                    break;
  954. X                case ('z'):    /* display only the archive comment */
  955. X                    if (negative) `7B
  956. X                        zflag = MAX(zflag-negative,0);
  957. X                        negative = 0;
  958. X                    `7D else
  959. X                        ++zflag;
  960. X                    break;
  961. X                default:
  962. X                    error = TRUE;
  963. X                    break;
  964. X
  965. X            `7D /* end switch */
  966. X        `7D /* end while (not end of argument string) */
  967. X    `7D /* end while (not done with switches) */
  968. X
  969. X/*--------------------------------------------------------------------------
  970. V-
  971. X    Make sure we aren't trying to do too many things here.  `5BThis seems li
  972. Vke
  973. X    kind of a brute-force way to do things; but aside from that, isn't the
  974. X    -a option useful when listing the directory (i.e., for reading zipfile
  975. X    comments)?  It's a modifier, not an action in and of itself, so perhaps
  976. X    it should not be included in the test--certainly, in the case of zipfile
  977. X    testing, it can just be ignored.`5D
  978. X  --------------------------------------------------------------------------
  979. V-*/
  980. X
  981. X    if ((aflag && tflag) `7C`7C (aflag && vflag) `7C`7C (cflag && tflag) `7C
  982. V`7C
  983. X        (cflag && uflag) `7C`7C (cflag && vflag) `7C`7C (tflag && uflag) `7C
  984. V`7C
  985. X        (tflag && vflag) `7C`7C (uflag && vflag) `7C`7C (fflag && overwrite_
  986. Vnone)) `7B
  987. X        fprintf(stderr, "error:\
  988. X  -at, -av, -ct, -cu, -cv, -fn, -tu, -tv, -uv combinations not allowed\n");
  989. X        error = TRUE;
  990. X    `7D
  991. X    if (quietflg && zflag)
  992. X        quietflg = 0;
  993. X    if (overwrite_all && overwrite_none) `7B
  994. X        fprintf(stderr, "caution:  both -n and -o specified; ignoring -o\n")
  995. V;
  996. X        overwrite_all = FALSE;
  997. X    `7D
  998. X    if ((argc-- == 0) `7C`7C error)
  999. X        RETURN(usage(error));
  1000. X
  1001. X/*--------------------------------------------------------------------------
  1002. V-
  1003. X    Now get the zipfile name from the command line and see if it exists as a
  1004. X    regular (non-directory) file.  If not, append the ".zip" suffix.  We don
  1005. V't
  1006. X    immediately check to see if this results in a good name, but we will do
  1007. V so
  1008. X    later.  In the meantime, see if there are any member filespecs on the co
  1009. Vm-
  1010. X    mand line, and if so, set the filename pointer to point at them.
  1011. X  --------------------------------------------------------------------------
  1012. V-*/
  1013. X
  1014. X    strcpy(zipfn, *argv++);
  1015. X    if (stat(zipfn, &statbuf) `7C`7C (statbuf.st_mode & S_IFMT) == S_IFDIR)
  1016. X        strcat(zipfn, ZSUFX);
  1017. X#if (defined(UNIX) && !defined(VMS)) /* Unix executables have no extension--
  1018. V */
  1019. X    else if (statbuf.st_mode & S_IXUSR)  /* might find zip, not zip.zip; etc
  1020. V */
  1021. X        fprintf(stderr, "\nnote:  file `5B %s `5D may be an executable\n\n",
  1022. V zipfn);
  1023. X#endif /* UNIX && !VMS */
  1024. X
  1025. X    if (stat(zipfn, &statbuf)) `7B/* try again */
  1026. X        fprintf(stderr, "error:  can't find zipfile `5B %s `5D\n", zipfn);
  1027. X        RETURN(9);              /* 9:  file not found */
  1028. X    `7D else
  1029. X        ziplen = statbuf.st_size;
  1030. X
  1031. X    if (argc != 0) `7B
  1032. X        fnv = argv;
  1033. X        process_all_files = FALSE;
  1034. X    `7D else
  1035. X        process_all_files = TRUE;       /* for speed */
  1036. X
  1037. X/*--------------------------------------------------------------------------
  1038. V-
  1039. X    Okey dokey, we have everything we need to get started.  Let's roll.
  1040. X  --------------------------------------------------------------------------
  1041. V-*/
  1042. X
  1043. X    inbuf = (byte *) malloc(INBUFSIZ + 4);     /* 4 extra for hold`5B`5D (be
  1044. Vlow) */
  1045. X    outbuf = (byte *) malloc(OUTBUFSIZ + 1);   /* 1 extra for string termin.
  1046. V */
  1047. X#ifndef DOS_OS2
  1048. X    if (aflag)                  /* if need an ascebc scratch, */
  1049. X        outout = (byte *) malloc(OUTBUFSIZ);
  1050. X    else                        /*  allocate it... */
  1051. X#endif /* !DOS_OS2 */
  1052. X        outout = outbuf;        /*  else just point to outbuf */
  1053. X
  1054. X    if ((inbuf == (byte *)NULL) `7C`7C (outbuf == (byte *)NULL) `7C`7C
  1055. X        (outout == (byte *)NULL)) `7B
  1056. X        fprintf(stderr, "error:  can't allocate unzip buffers\n");
  1057. X        RETURN(4);              /* 4-8:  insufficient memory */
  1058. X    `7D
  1059. X    hold = &inbuf`5BINBUFSIZ`5D;    /* to check for boundary-spanning signat
  1060. Vures */
  1061. X
  1062. X    RETURN(process_zipfile());  /* keep passing errors back... */
  1063. X
  1064. X`7D /* end main() */
  1065. X
  1066. X
  1067. X
  1068. X
  1069. X
  1070. X/**********************/
  1071. X/*  Function usage()  */
  1072. X/**********************/
  1073. X
  1074. Xint usage(error)   /* return PK-type error code */
  1075. X    int error;
  1076. X`7B
  1077. X#ifdef NATIVE
  1078. X#ifdef EBCDIC
  1079. X    char *astring = "-a  convert ASCII to EBCDIC";
  1080. X#else /* !EBCDIC */
  1081. X    char *astring = "-a  convert ASCII to native chars";
  1082. X#endif /* ?EBCDIC */
  1083. X/*  char *astring = "-a  convert ASCII to " NATIVE;  (ANSI C concatenation)
  1084. V  */
  1085. X    char *loc_str = "";
  1086. X#else /* !NATIVE */
  1087. X#ifdef DOS_OS2
  1088. X    char *astring = "-a  convert text (LF => CR LF)";
  1089. X    char *loc_str = "-s  spaces in filenames => _";
  1090. X#else /* !DOS_OS2 */
  1091. X#ifdef MACOS
  1092. X    char *astring = "-a  convert text (CR LF => CR)";
  1093. X    char *loc_str = "";
  1094. X#else /* !MACOS:  UNIX, VMS */
  1095. X    char *astring = "-a  convert text (CR LF => LF)";
  1096. X#ifdef VMS
  1097. X    char *loc_str = "-X  restore owner/protection info";
  1098. X#else /* !VMS */
  1099. X    char *loc_str = "";
  1100. X#endif /* ?VMS */
  1101. X#endif /* ?MACOS */
  1102. X#endif /* ?DOS_OS2 */
  1103. X#endif /* ?NATIVE */
  1104. X    FILE *usagefp;
  1105. X
  1106. X
  1107. X/*--------------------------------------------------------------------------
  1108. V-
  1109. X    If user requested usage, send it to stdout; else send to stderr.
  1110. X  --------------------------------------------------------------------------
  1111. V-*/
  1112. X
  1113. X    if (error)
  1114. X        usagefp = (FILE *) stderr;
  1115. X    else
  1116. X        usagefp = (FILE *) stdout;
  1117. X
  1118. X    fprintf(usagefp, "\
  1119. XUnZip:  Zipfile Extract %s;  (c) 1989 S.H.Smith and others\n\
  1120. XVersions 3.0 and later by Info-ZIP.  Bug reports ONLY to zip-bugs@cs.ucla.ed
  1121. Vu\
  1122. X\n\n", VERSION);
  1123. X
  1124. X    fprintf(usagefp, "\
  1125. XUsage: unzip `5B -options`5Bmodifiers`5D `5D file`5B.zip`5D `5Bfilespec...`5
  1126. VD\n\
  1127. X  -x  extract files (default)                -l  list files (short format)\n
  1128. V\
  1129. X  -c  extract files to stdout/screen (CRT)   -v  list files (verbose format)
  1130. V\n\
  1131. X  -f  freshen existing files, create none    -p  extract to pipe, no message
  1132. Vs\n\
  1133. X  -u  update files, create if necessary      -t  test archive integrity\n\
  1134. X                                             -z  display archive comment\n\
  1135. Xmodifiers:\n\
  1136. X  -n  never overwrite existing files         %s\n", loc_str);
  1137. X    fprintf(usagefp, "\
  1138. X  -o  overwrite files WITHOUT prompting      %s\n\
  1139. X  -j  junk paths (don't make directories)    -U  don't make names lowercase\
  1140. Vn\
  1141. X  -q  quiet mode (-qq => quieter)            -V  retain VMS version numbers\
  1142. X\n\n\
  1143. XExamples: (See manual for more information)\n\
  1144. X  unzip data1 Readme   => extracts file Readme from zipfile data1.zip\n\
  1145. X  unzip -p foo `7C more  => send contents of foo.zip via pipe into program m
  1146. Vore\n\
  1147. X  unzip -fo foo        => quietly replace existing files if archive files ne
  1148. Vwer\
  1149. X\n", astring);
  1150. X
  1151. X#ifdef VMS
  1152. X    fprintf(usagefp, "\
  1153. X  unzip \"-V\" foo \"Bar\" => must quote uppercase options and filenames in
  1154. V VMS\
  1155. X\n");
  1156. X#endif
  1157. X
  1158. X    if (error)
  1159. X        return 10;    /* 10:  bad or illegal parameters specified */
  1160. X    else
  1161. X        return 0;     /* just wanted usage screen: no error */
  1162. X
  1163. X`7D /* end function usage() */
  1164. X
  1165. X#endif /* ?MSWIN */
  1166. X
  1167. X
  1168. X
  1169. X
  1170. X/********************************/
  1171. X/*  Function process_zipfile()  */
  1172. X/********************************/
  1173. X
  1174. Xint process_zipfile()    /* return PK-type error code */
  1175. X`7B
  1176. X    int error=0, error_in_archive;
  1177. X    longint real_ecrec_offset, expect_ecrec_offset;
  1178. X
  1179. X
  1180. X/*--------------------------------------------------------------------------
  1181. V-
  1182. X    Open the zipfile for reading and in BINARY mode to prevent CR/LF trans-
  1183. X    lation, which would corrupt the bitstreams.
  1184. X  --------------------------------------------------------------------------
  1185. V-*/
  1186. X
  1187. X#ifdef VMS
  1188. X    if (check_format())         /* check for variable-length format */
  1189. X        return 2;               /* 2:  error in zipfile */
  1190. X#endif /* VMS */
  1191. X
  1192. X    if (open_input_file())      /* this should never happen, given the */
  1193. X        return 9;               /*   stat() test in main(), but... */
  1194. X
  1195. X/*--------------------------------------------------------------------------
  1196. V-
  1197. X    Reconstruct the various PK signature strings, and find and process the
  1198. X    end-of-central-directory header.
  1199. X  --------------------------------------------------------------------------
  1200. V-*/
  1201. X
  1202. X    strcat(local_hdr_sig, LOCAL_HDR_SIG);
  1203. X    strcat(central_hdr_sig, CENTRAL_HDR_SIG);
  1204. X    strcat(end_central_sig, END_CENTRAL_SIG);
  1205. X/*  strcat(extd_local_sig, EXTD_LOCAL_SIG);  */
  1206. X
  1207. X    if (find_end_central_dir()) `7B   /* not found; nothing to do */
  1208. X        close(zipfd);
  1209. X        return 2;                   /* 2:  error in zipfile */
  1210. X    `7D
  1211. X
  1212. X    real_ecrec_offset = cur_zipfile_bufstart+(inptr-inbuf);
  1213. X#ifdef TEST
  1214. X    printf("\n  found end-of-central-dir signature at offset %ld (%.8lXh)\n"
  1215. V,
  1216. X      real_ecrec_offset, real_ecrec_offset);
  1217. X    printf("    from beginning of file; offset %d (%.4Xh) within block\n",
  1218. X      inptr-inbuf, inptr-inbuf);
  1219. X#endif
  1220. X
  1221. X    if ((error_in_archive = process_end_central_dir()) > 1) `7B
  1222. X        close(zipfd);
  1223. X        return error_in_archive;
  1224. X    `7D
  1225. X
  1226. X    if (zflag) `7B
  1227. X        close(zipfd);
  1228. X        return 0;
  1229. X    `7D
  1230. X
  1231. X/*--------------------------------------------------------------------------
  1232. V-
  1233. X    Test the end-of-central-directory info for incompatibilities and incon-
  1234. X    sistencies.
  1235. X  --------------------------------------------------------------------------
  1236. V-*/
  1237. X
  1238. X#ifndef PAKFIX
  1239. X    if (ecrec.number_this_disk == 0) `7B
  1240. X#else /* PAKFIX */
  1241. X    error = ((ecrec.number_this_disk == 1) &&
  1242. X             (ecrec.num_disk_with_start_central_dir == 1));
  1243. X    if ((ecrec.number_this_disk == 0) `7C`7C error) `7B
  1244. X        if (error) `7B
  1245. X            fprintf(stderr,
  1246. X     "\n     Warning:  zipfile claims to be disk 2 of a two-part archive;\n\
  1247. X     attempting to process anyway.  If no further errors occur, this\n\
  1248. X     archive was probably created by PAK v2.51 or earlier.  This bug\n\
  1249. X     was reported to NoGate in March 1991 and was supposed to have been\n\
  1250. X     fixed by mid-1991; as of mid-1992 it still hadn't been.\n\n");
  1251. X            error_in_archive = 1;  /* 1:  warning */
  1252. X        `7D
  1253. X#endif /* ?PAKFIX */
  1254. X        expect_ecrec_offset = ecrec.offset_start_central_directory +
  1255. X                              ecrec.size_central_directory;
  1256. X        if ((extra_bytes = real_ecrec_offset - expect_ecrec_offset) < 0) `7B
  1257. X            fprintf(stderr, "\nerror:  missing %ld bytes in zipfile (\
  1258. Xattempting to process anyway)\n\n", -extra_bytes);
  1259. X            error_in_archive = 2;       /* 2:  (weak) error in zipfile */
  1260. X        `7D else if (extra_bytes > 0) `7B
  1261. X            if ((ecrec.offset_start_central_directory == 0) &&
  1262. X                (ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */
  1263. X            `7B
  1264. X                fprintf(stderr, "\nerror:  NULL central directory offset (\
  1265. Xattempting to process anyway)\n\n");
  1266. X                ecrec.offset_start_central_directory = extra_bytes;
  1267. X                extra_bytes = 0;
  1268. X                error_in_archive = 2;   /* 2:  (weak) error in zipfile */
  1269. X            `7D else `7B
  1270. X                fprintf(stderr, "\nwarning:  extra %ld bytes at beginning or
  1271. V\
  1272. X within zipfile\n          (attempting to process anyway)\n\n", extra_bytes)
  1273. V;
  1274. X                error_in_archive = 1;   /* 1:  warning error */
  1275. X            `7D
  1276. X        `7D
  1277. X
  1278. X    /*----------------------------------------------------------------------
  1279. V-
  1280. X        Check for empty zipfile and exit now if so.
  1281. X      ----------------------------------------------------------------------
  1282. V-*/
  1283. X
  1284. X        if (expect_ecrec_offset == 0L  &&  ecrec.size_central_directory == 0
  1285. V) `7B
  1286. X            fprintf(stderr, "warning:  zipfile is empty\n");
  1287. X            close(zipfd);
  1288. X            return (error_in_archive > 1)? error_in_archive : 1;
  1289. X        `7D
  1290. X
  1291. X    /*----------------------------------------------------------------------
  1292. V-
  1293. X        Compensate for missing or extra bytes, and seek to where the start
  1294. X        of central directory should be.  If header not found, uncompensate
  1295. X        and try again (necessary for at least some Atari archives created
  1296. X        with STZIP, as well as archives created by J.H. Holm's ZIPSPLIT).
  1297. X      ----------------------------------------------------------------------
  1298. V-*/
  1299. X
  1300. X        LSEEK( ecrec.offset_start_central_directory )
  1301. X        if ((readbuf(sig, 4) <= 0) `7C`7C strncmp(sig, central_hdr_sig, 4))
  1302. V `7B
  1303. X            longint tmp = extra_bytes;
  1304. X
  1305. X            extra_bytes = 0;
  1306. X            LSEEK( ecrec.offset_start_central_directory )
  1307. X            if ((readbuf(sig, 4) <= 0) `7C`7C strncmp(sig, central_hdr_sig,
  1308. V 4)) `7B
  1309. X                fprintf(stderr,
  1310. X            "error:  start of central directory not found; zipfile corrupt.\
  1311. Vn");
  1312. X                fprintf(stderr, ReportMsg);
  1313. X                close(zipfd);
  1314. X                return 3;           /* 3:  severe error in zipfile */
  1315. X            `7D
  1316. X            fprintf(stderr, "error:  reported length of central directory is
  1317. V \
  1318. X%d bytes too\n        long (Atari STZIP zipfile?  J.H. Holm ZIPSPLIT zipfile
  1319. V?)\
  1320. X.\n        Compensating...\n\n", -tmp);
  1321. X            error_in_archive = 2;   /* 2:  (weak) error in zipfile */
  1322. X        `7D
  1323. X
  1324. X    /*----------------------------------------------------------------------
  1325. V-
  1326. X        Seek to the start of the central directory one last time, since we
  1327. X        have just read the first entry's signature bytes; then list, extract
  1328. X        or test member files as instructed, and close the zipfile.
  1329. X      ----------------------------------------------------------------------
  1330. V-*/
  1331. X
  1332. X        LSEEK( ecrec.offset_start_central_directory )
  1333. X        if (vflag)
  1334. X            error = list_files();               /* LIST 'EM */
  1335. X        else
  1336. X            error = extract_or_test_files();    /* EXTRACT OR TEST 'EM */
  1337. X        if (error > error_in_archive)   /* don't overwrite stronger error */
  1338. X            error_in_archive = error;   /*  with (for example) a warning */
  1339. X    `7D else `7B
  1340. X        fprintf(stderr, "\nerror:  zipfile is part of multi-disk archive \
  1341. X(sorry, not supported).\n");
  1342. X    /*  fprintf(stderr, "Please report to zip-bugs@cs.ucla.edu\n");  */
  1343. X        error_in_archive = 11;  /* 11:  no files found */
  1344. X    `7D
  1345. X
  1346. X    close(zipfd);
  1347. X    return error_in_archive;
  1348. X
  1349. X`7D /* end function process_zipfile() */
  1350. X
  1351. X
  1352. X
  1353. X
  1354. X
  1355. X/************************************/
  1356. X/*  Function find_end_central_dir() */
  1357. X/************************************/
  1358. X
  1359. Xint find_end_central_dir()   /* return 0 if found, 1 otherwise */
  1360. X`7B
  1361. X    int i, numblks;
  1362. X    longint tail_len;
  1363. X
  1364. X
  1365. X
  1366. X/*--------------------------------------------------------------------------
  1367. V-
  1368. X    Treat case of short zipfile separately.
  1369. X  --------------------------------------------------------------------------
  1370. V-*/
  1371. X
  1372. X    if (ziplen <= INBUFSIZ) `7B
  1373. X        lseek(zipfd, 0L, SEEK_SET);
  1374. X        if ((incnt = read(zipfd,(char *)inbuf,(unsigned int)ziplen)) ==
  1375. X             (int)ziplen)
  1376. X
  1377. X            /* 'P' must be at least 22 bytes from end of zipfile */
  1378. X            for (inptr = inbuf+(int)ziplen-22;  inptr >= inbuf;  --inptr)
  1379. +-+-+-+-+-+-+-+-  END  OF PART 10 +-+-+-+-+-+-+-+-
  1380.