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

  1. Newsgroups: comp.sources.misc
  2. From: info-zip@cs.ucla.edu (Info-Zip)
  3. Subject:  v29i033:  unzip - Info-ZIP's portable UnZip v4.2, Part03/12
  4. Message-ID: <1992Apr3.063046.28673@sparky.imd.sterling.com>
  5. X-Md4-Signature: fa7345297a70ab7437f748c167203b96
  6. Date: Fri, 3 Apr 1992 06:30:46 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: info-zip@cs.ucla.edu (Info-Zip)
  10. Posting-number: Volume 29, Issue 33
  11. Archive-name: unzip/part03
  12. Environment: Unix, VMS, OS/2, MS-DOS, Amiga, Macintosh
  13. Supersedes: unzip, Volume 19, Issues 96-101
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  Contents unzip.c
  22. # Wrapped by kent@sparky on Mon Mar 30 01:45:51 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 3 (of 12)."'
  26. if test -f 'Contents' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'Contents'\"
  28. else
  29.   echo shar: Extracting \"'Contents'\" \(4533 characters\)
  30.   sed "s/^X//" >'Contents' <<'END_OF_FILE'
  31. XContents of the UnZip 4.2 main archive (the "sub-archives" may be .arc
  32. Xor .tar.Z instead of .zip, or even sub-directories):
  33. X
  34. X  Contents    this file
  35. X  README    what UnZip is; general information (was unzip##.descr)
  36. X  History.420    new features and fixes in this release
  37. X  ZipRules    Info-ZIP guidelines on (code) contributions to the cause
  38. X  BUGS        known bugs, problems, and (possible) features to be added
  39. X  unzip.1    UnZip manual page, nroff format
  40. X  unzip.man    UnZip manual page, human-readable format
  41. X  zipinfo.1    ZipInfo manual page, nroff format
  42. X  zipinfo.man    ZipInfo manual page, human-readable format
  43. X  CONTRIBS    list of contributors to UnZip
  44. X  COPYING    copyrights and distribution policy
  45. X  crypt.c       NOT INCLUDED:  see notes below
  46. X  extract.c    high-level extraction and decryption code (required)
  47. X  file_io.c    file manipulation and password code (required)
  48. X  mapname.c    code to map filenames between different OS's (required)
  49. X  match.c    pattern-matching code for filename wildcards (required*)
  50. X  misc.c    various support routines (required*)
  51. X  ship.c    utility to encode/split/e-mail binary files (useful/optional)
  52. X  unimplod.c    code for unImploding (required)
  53. X  unreduce.c    code for unReducing (required)
  54. X  unshrink.c    code for unShrinking (required)
  55. X  unzip.c    main UnZip driver code (required)
  56. X  unzip.h    main UnZip header file (required*)
  57. X  zip.h        header for using crypt.c with UnZip (required for decryption)
  58. X  zipinfo.c    zipfile information utility (useful, but optional)
  59. X  Makefile    main Unix and OS/2 makefile for export version (required)
  60. X  Makefile.cr     main Unix and OS/2 makefile for decryption version (see below)
  61. X  AMIGA.zip    support files for compiling on Amiga (LF)
  62. X  ATARI.zip    support files for compiling v4.1 on Atari ST (CR LF)
  63. X  MAC.zip    support files for compiling on Macintosh (LF)
  64. X  MSDOS.zip    support files for compiling under MS-DOS (CR LF)
  65. X  OS2.zip    support files for compiling under OS/2 (CR LF)
  66. X  VMS.zip    support files for compiling under VMS (LF)
  67. X  cray.dif      patch to crypt.c 1.0 (8 Nov 91) to fix bug on 64-bit/Cray
  68. X
  69. XFiles marked "required*" are also needed to compile ZipInfo.  There are
  70. XUnix, OS/2 and MS-DOS targets to make ZipInfo near the bottom of Makefile
  71. X(zipinfo, zi_dos, zi_os2, zi_gcc, zi_icc).  The sub-archives are marked
  72. Xeither "CR LF" or "LF" to indicate the line-endings format of the contained
  73. Xtext files.
  74. X
  75. XThe file ship.c is the stand-alone source file for the ship utility, a 
  76. Xprogram for ASCII-encoding, splitting, e-mailing, and decoding binaries
  77. X(similar to uuencode/uudecode but far more useful).  This is the preferred
  78. Xformat for sending/receiving zipfiles to and from zip-bugs and Info-ZIP.
  79. XInstructions on how to use it are included in the comments near the top
  80. Xof ship.c, and there are Unix, OS/2 and DOS makefile targets in Makefile
  81. X(sorry, we haven't got this fully integrated into all the other sub-
  82. Xarchives).  Ship is more fully supported in the Zip distribution; if
  83. Xyou've already got it from there, you don't need to make it again.
  84. X
  85. XThe Atari ST support is in the form of patches against UnZip 4.1; there
  86. Xare more details in the ATARI sub-archive Contents file.  Amiga support
  87. Xhas not been tested since version 4.1 or earlier (the makefiles, however,
  88. Xhave been updated to reflect the new code structure, and any changes
  89. Xrequired shouldn't be TOO extensive; maybe--dare we say it?--none...).
  90. X
  91. XEncryption and decryption code for both Zip and UnZip (the only file
  92. Xrequired for UnZip is crypt.c) is available from the following sites
  93. X(the filenames may differ slightly, if later versions become available):
  94. X   
  95. X   From the US:
  96. X      pit-manager.mit.edu:/pub/zip/crypt/zipcrypt.shar
  97. X         (mail server at mail-server@pit-manager.mit.edu)
  98. X      wuarchive.wustl.edu:/mirrors3/garbo.uwasa.fi/arcutil/zcrypt10.zip
  99. X   Outside the US:
  100. X      garbo.uwasa.fi:/pc/arcutil/zcrypt10.zip
  101. X      ftp.win.tue.nl:/pub/compression/zip/zcrypt10.zip
  102. X      ftp.inria.fr:/system/arch-compr/zcrypt10.zip
  103. X      ftp.informatik.tu-muenchen.de:/pub/utils/archiver/zcrypt10.zip
  104. X         (mail server at ftp-mailer@ftp.informatik.tu-muenchen.de)
  105. X
  106. XNon-US users, please do NOT ftp from the US site (US regulations and
  107. Xall that).  Likewise, US users, please do not ftp from the European
  108. Xsites (it's not illegal, but it sure is a waste of expensive bandwidth).
  109. XIf someone repackages zipcrypt.shar or zcrypt10.zip as a VMS .share
  110. Xfile and places it on a VMS archive site somewhere, please let us know
  111. X(send e-mail to zip-bugs at the address listed in README).  Likewise 
  112. Xfor Mac- or Atari-specific formats (or any others).
  113. END_OF_FILE
  114.   if test 4533 -ne `wc -c <'Contents'`; then
  115.     echo shar: \"'Contents'\" unpacked with wrong size!
  116.   fi
  117.   # end of 'Contents'
  118. fi
  119. if test -f 'unzip.c' -a "${1}" != "-c" ; then 
  120.   echo shar: Will not clobber existing file \"'unzip.c'\"
  121. else
  122.   echo shar: Extracting \"'unzip.c'\" \(46692 characters\)
  123.   sed "s/^X//" >'unzip.c' <<'END_OF_FILE'
  124. X/*---------------------------------------------------------------------------
  125. X
  126. X  unzip.c
  127. X
  128. X  UnZip - a zipfile extraction utility.  See below for make instructions, or
  129. X  read the comments in Makefile for a more detailed explanation.  To join 
  130. X  Info-ZIP, send a message to info-zip-request@cs.ucla.edu.
  131. X
  132. X  UnZip 4.x is nearly a complete rewrite of version 3.x, mainly to allow 
  133. X  access to zipfiles via the central directory (and hence to the OS bytes, 
  134. X  so we can make intelligent decisions about what to do with the extracted 
  135. X  files).  Based on unzip.c 3.15+ and zipinfo.c 0.90.  For a complete revi-
  136. X  sion history, see UnzpHist.zip at Info-ZIP headquarters (below).  For a 
  137. X  (partial) list of the many (near infinite) contributors, see "CONTRIBS" in
  138. X  the UnZip source distribution.
  139. X
  140. X  ---------------------------------------------------------------------------
  141. X
  142. X  To compile (partial instructions):
  143. X
  144. X     under Unix (cc):  make <system name>
  145. X       (type "make list" for a list of valid names, or read Makefile for 
  146. X        details.  "make unzip" works for most systems.  If you have a NEW
  147. X        system, not covered by any of the existing targets, send FULL infor-
  148. X        mation--hardware, OS, versions, etc.--to zip-bugs@cs.ucla.edu)
  149. X
  150. X     under MS-DOS (TurboC):  make -fMAKEFILE.DOS  for command line compiles
  151. X       (or use the integrated environment and the included files TCCONFIG.TC
  152. X        and UNZIP.PRJ.  Tweak for your environment.)
  153. X
  154. X     under MS-DOS (MSC):  make MAKEFILE.DOS
  155. X       (or use Makefile if you have MSC 6.0:  "nmake msc_dos")
  156. X
  157. X     under OS/2 (MSC):  make MAKEFILE.DOS   (edit appropriately)
  158. X       (or use Makefile if you have MSC 6.0:  "nmake msc_os2")
  159. X
  160. X     under Atari OS:  needs a little work yet...
  161. X
  162. X     under VMS:  DEFINE LNK$LIBRARY SYS$LIBRARY:VAXCRTL.OLB   (see VMSNOTES)
  163. X                 CC UNZIP,FILE_IO,MAPNAME,MATCH,...,UNSHRINK
  164. X                 LINK UNZIP,FILE_IO,MAPNAME,MATCH,...,UNSHRINK
  165. X                 UNZIP :== $DISKNAME:[DIRECTORY]UNZIP.EXE
  166. X
  167. X     under Macintosh OS:   Double click on unzip.make.  Press <Command>-M.
  168. X
  169. X  ---------------------------------------------------------------------------
  170. X
  171. X  Version:  unzip42.{arc | tar.Z | zip | zoo} for Unix, VMS, OS/2, MS-DOS,
  172. X              Mac & Amiga.
  173. X  Source:  valeria.cs.ucla.edu (131.179.64.36) in /pub
  174. X           wuarchive.wustl.edu (128.252.135.4) in /mirrors/misc/unix
  175. X           wsmr-simtel20.army.mil (192.88.110.20) in pd1:[misc.unix]
  176. X  Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
  177. X
  178. X  ---------------------------------------------------------------------------*/
  179. X
  180. X
  181. X
  182. X
  183. X
  184. X#include "unzip.h"              /* includes, defines, and macros */
  185. X
  186. X/* #define VERSION  "v4.20x BETA of 3-20-92"  internal beta level */
  187. X#define VERSION  "v4.2 of 20 March 1992"
  188. X#define PAKFIX   /* temporary solution to PAK-created zipfiles */
  189. X
  190. X
  191. X
  192. X
  193. X
  194. X/**********************/
  195. X/*  Global Variables  */
  196. X/**********************/
  197. X
  198. Xint aflag;            /* -a: do ASCII to EBCDIC translation, or CR-LF  */
  199. X/* int bflag; RESERVED for -b: extract as binary */
  200. Xint cflag;            /* -c: output to stdout */
  201. Xint fflag;            /* -f: "freshen" (extract only newer files) */
  202. Xint jflag;            /* -j: junk pathnames */
  203. Xint overwrite_none;   /* -n: never overwrite files (no prompting) */
  204. Xint overwrite_all;    /* -o: OK to overwrite files without prompting */
  205. Xint force_flag;       /* (shares -o for now): force to override errors, etc. */
  206. Xint quietflg;         /* -q: produce a lot less output */
  207. X#ifdef DOS_OS2          /*    to CR or LF conversion of extracted files */
  208. X   int sflag;         /* -s: allow spaces (blanks) in filenames */
  209. X#endif /* DOS_OS2 */
  210. Xint tflag;            /* -t: test */
  211. Xint uflag;            /* -u: "update" (extract only newer & brand-new files) */
  212. Xstatic int U_flag;    /* -U: leave filenames in upper or mixed case */
  213. Xstatic int vflag;     /* -v: view directory (only used in unzip.c) */
  214. Xint V_flag;           /* -V: don't strip VMS version numbers */
  215. X#ifdef VMS
  216. X   int secinf;        /* -X: keep owner/protection */
  217. X#endif /* VMS */
  218. Xint zflag;            /* -z: display only the archive comment */
  219. Xint process_all_files;
  220. X
  221. Xlongint csize;        /* used by list_files(), ReadByte(): must be signed */
  222. Xlongint ucsize;       /* used by list_files(), unReduce(), unImplode() */
  223. X
  224. Xchar *fnames[2] = {"*", NULL};   /* default filenames vector */
  225. Xchar **fnv = fnames;
  226. Xchar sig[5];
  227. Xchar answerbuf[10];
  228. X
  229. Xmin_info info[DIR_BLKSIZ], *pInfo=info;
  230. X
  231. X#ifdef OS2
  232. X   int longname;           /* used only in mapname.c and file_io.c */
  233. X   char longfilename[FILNAMSIZ];
  234. X#endif /* OS2 */
  235. X
  236. X#ifdef CRYPT
  237. X   char *key = NULL;       /* password with which to decrypt data, or NULL */
  238. X#endif /* CRYPT */
  239. X
  240. X/*---------------------------------------------------------------------------
  241. X    unShrink/unReduce/unImplode working storage:
  242. X  ---------------------------------------------------------------------------*/
  243. X
  244. X/* prefix_of (for unShrink) is biggest storage area, esp. on Crays...space */
  245. X/*  is shared by lit_nodes (unImplode) and followers (unReduce) */
  246. X
  247. Xshort prefix_of[HSIZE + 1];     /* (8193 * sizeof(short)) */
  248. X#ifdef MACOS
  249. X   byte *suffix_of;
  250. X   byte *stack;
  251. X#else
  252. X   byte suffix_of[HSIZE + 1];   /* also s-f length_nodes (smaller) */
  253. X   byte stack[HSIZE + 1];       /* also s-f distance_nodes (smaller) */
  254. X#endif
  255. X
  256. XULONG crc32val;
  257. X
  258. XULONG mask_bits[] =
  259. X{0x00000000L,
  260. X 0x00000001L, 0x00000003L, 0x00000007L, 0x0000000fL,
  261. X 0x0000001fL, 0x0000003fL, 0x0000007fL, 0x000000ffL,
  262. X 0x000001ffL, 0x000003ffL, 0x000007ffL, 0x00000fffL,
  263. X 0x00001fffL, 0x00003fffL, 0x00007fffL, 0x0000ffffL,
  264. X 0x0001ffffL, 0x0003ffffL, 0x0007ffffL, 0x000fffffL,
  265. X 0x001fffffL, 0x003fffffL, 0x007fffffL, 0x00ffffffL,
  266. X 0x01ffffffL, 0x03ffffffL, 0x07ffffffL, 0x0fffffffL,
  267. X 0x1fffffffL, 0x3fffffffL, 0x7fffffffL, 0xffffffffL};
  268. X
  269. X/*---------------------------------------------------------------------------
  270. X    Input file variables:
  271. X  ---------------------------------------------------------------------------*/
  272. X
  273. Xbyte *inbuf, *inptr;     /* input buffer (any size is legal) and pointer */
  274. Xint incnt;
  275. X
  276. XULONG bitbuf;
  277. Xint bits_left;
  278. Xboolean zipeof;
  279. X
  280. Xint zipfd;               /* zipfile file handle */
  281. Xchar zipfn[FILNAMSIZ];
  282. X
  283. Xchar local_hdr_sig[5] = "\120";    /* remaining signature bytes come later   */
  284. Xchar central_hdr_sig[5] = "\120";  /*  (must initialize at runtime so unzip  */
  285. Xchar end_central_sig[5] = "\120";  /*  executable won't look like a zipfile) */
  286. X
  287. Xcdir_file_hdr crec;      /* used in unzip.c, extract.c, misc.c */
  288. Xlocal_file_hdr lrec;     /* used in unzip.c, extract.c */
  289. Xecdir_rec ecrec;         /* used in unzip.c, extract.c */
  290. Xstruct stat statbuf;     /* used by main(), mapped_name(), check_for_newer() */
  291. X
  292. Xlongint extra_bytes = 0;        /* used in unzip.c, misc.c */
  293. Xlongint cur_zipfile_bufstart;   /* extract_or_test_files, readbuf, ReadByte */
  294. X
  295. Xbyte *extra_field = NULL;       /* currently used by VMS version only */
  296. X
  297. X/*---------------------------------------------------------------------------
  298. X    Output stream variables:
  299. X  ---------------------------------------------------------------------------*/
  300. X
  301. Xbyte *outbuf;                   /* buffer for rle look-back */
  302. Xbyte *outptr;
  303. Xbyte *outout;                   /* scratch pad for ASCII-native trans */
  304. Xlongint outpos;                 /* absolute position in outfile */
  305. Xint outcnt;                     /* current position in outbuf */
  306. Xint outfd;
  307. Xint disk_full;
  308. Xchar filename[FILNAMSIZ];
  309. X
  310. X/*---------------------------------------------------------------------------
  311. X    unzip.c static global variables (visible only within this file):
  312. X  ---------------------------------------------------------------------------*/
  313. X
  314. Xstatic byte *hold;
  315. Xstatic char unkn[10];
  316. Xstatic longint ziplen;
  317. Xstatic UWORD methnum;
  318. X
  319. X/*---------------------------------------------------------------------------
  320. X    unzip.c repeated error messages (we use all of these at least twice)
  321. X  ---------------------------------------------------------------------------*/
  322. X
  323. Xchar *EndSigMsg = "\nwarning:\
  324. X  didn't find end-of-central-dir signature at end of central dir.\n";
  325. Xchar *CentSigMsg =
  326. X  "error:  expected central file header signature not found (file #%u).\n";
  327. Xchar *SeekMsg =
  328. X  "error:  attempt to seek before beginning of zipfile\n%s";
  329. X
  330. X#ifdef VMS
  331. Xchar *ReportMsg = "\
  332. X  (please check that you have transferred or created the zipfile in the\n\
  333. X  appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n";
  334. X#else /* !VMS */
  335. Xchar *ReportMsg = "\
  336. X  (please check that you have transferred or created the zipfile in the\n\
  337. X  appropriate BINARY mode and that you have compiled unzip properly)\n";
  338. X#endif /* ?VMS */
  339. X
  340. X
  341. X
  342. X
  343. X/******************/
  344. X/*  Main program  */
  345. X/******************/
  346. X
  347. Xmain(argc, argv)        /* return PK-type error code (except under VMS) */
  348. Xint argc;
  349. Xchar *argv[];
  350. X{
  351. X    char *s;
  352. X    int c, error=FALSE;
  353. X
  354. X
  355. X/*---------------------------------------------------------------------------
  356. X    Macintosh initialization code.
  357. X  ---------------------------------------------------------------------------*/
  358. X
  359. X#ifdef MACOS
  360. X#ifdef THINK_C
  361. X    #include <console.h>
  362. X    static char *argstr[30], args[30*64];
  363. X
  364. X    Point   p;
  365. X    SFTypeList  sfT;
  366. X    int a;
  367. X    EventRecord theEvent;
  368. X    short   eMask;
  369. X    SFReply  fileRep;
  370. X#endif /* THINK_C */
  371. X
  372. X    typedef struct sf_node {        /* node in a true shannon-fano tree */
  373. X        UWORD left;                 /* 0 means leaf node */
  374. X        UWORD right;                /*   or value if leaf node */
  375. X    } sf_node;
  376. X    extern sf_node *lit_nodes, *length_nodes, *distance_nodes;
  377. X
  378. X#ifdef MCH_MACINTOSH
  379. X    defSpin(0x20);
  380. X#endif
  381. X
  382. X    suffix_of = (byte *)calloc(HSIZE+1, sizeof(byte));
  383. X    stack = (byte *)calloc(HSIZE+1, sizeof(byte));
  384. X    length_nodes = (sf_node *) suffix_of;  /* 2*LENVALS nodes */
  385. X    distance_nodes = (sf_node *) stack;    /* 2*DISTVALS nodes */
  386. X
  387. X#ifdef THINK_C   
  388. X    for (a=0; a<30; a+=1)
  389. X        argstr[a] = &args[a*64];
  390. Xstart:
  391. X    tflag=vflag=cflag=aflag=jflag=U_flag=quietflg=fflag=uflag=zflag = 0;
  392. X    local_hdr_sig[1]=central_hdr_sig[1]=end_central_sig[1]='\0';
  393. X
  394. X    argc = ccommand(&argv);
  395. X    SetPt(&p, 40,40);
  396. X
  397. X    SFGetFile(p, "\pSpecify ZIP file:", 0L, -1, sfT, 0L, &fileRep);
  398. X    if (!fileRep.good)
  399. X        exit(1);
  400. X    macfstest(fileRep.vRefNum);
  401. X    SetMacVol(NULL, fileRep.vRefNum);
  402. X    for (a=1; a<argc; a+=1)
  403. X        if (argv[a][0] == '-')
  404. X            BlockMove(argv[a], argstr[a], (strlen(argv[a])>63) ? 64 : strlen(argv[a])+1);
  405. X        else
  406. X            break;
  407. X    PtoCstr((char *)fileRep.fName);
  408. X    strcpy(argstr[a], (char *)fileRep.fName);
  409. X    for (;a<argc; a+=1)
  410. X        BlockMove(argv[a], argstr[a+1], (strlen(argv[a])>63) ? 64 : strlen(argv[a])+1);
  411. X    argc+=1;
  412. X    argv = argstr;
  413. X
  414. X    if (hfsflag == FALSE)   /* can't support directories:  junk pathnames */
  415. X        jflag = 1;
  416. X#endif /* THINK_C */
  417. X#endif /* MACOS */
  418. X
  419. X/*---------------------------------------------------------------------------
  420. X    Debugging info for checking on structure padding:
  421. X  ---------------------------------------------------------------------------*/
  422. X
  423. X#ifdef DEBUG_STRUC
  424. X    printf("local_file_hdr size: %X\n",
  425. X           sizeof(local_file_hdr));
  426. X    printf("local_byte_hdr size: %X\n",
  427. X           sizeof(local_byte_hdr));
  428. X    printf("actual size of local headers: %X\n", LREC_SIZE);
  429. X
  430. X    printf("central directory header size: %X\n",
  431. X           sizeof(cdir_file_hdr));
  432. X    printf("central directory byte header size: %X\n",
  433. X           sizeof(cdir_byte_hdr));
  434. X    printf("actual size of central dir headers: %X\n", CREC_SIZE);
  435. X
  436. X    printf("end central dir record size: %X\n",
  437. X           sizeof(ecdir_rec));
  438. X    printf("end central dir byte record size: %X\n",
  439. X           sizeof(ec_byte_rec));
  440. X    printf("actual size of end-central-dir record: %X\n", ECREC_SIZE);
  441. X#endif /* DEBUG_STRUC */
  442. X
  443. X/*---------------------------------------------------------------------------
  444. X    Rip through any command-line options lurking about...
  445. X  ---------------------------------------------------------------------------*/
  446. X
  447. X    while (--argc > 0 && (*++argv)[0] == '-') {
  448. X        s = argv[0] + 1;
  449. X        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
  450. X            switch (c) {
  451. X            case ('a'):
  452. X                ++aflag;
  453. X                break;
  454. X#if 0
  455. X            case ('s'):
  456. X                ++sflag;
  457. X                break;
  458. X#endif
  459. X            case ('c'):
  460. X                ++cflag;
  461. X#ifdef NATIVE
  462. X                ++aflag;   /* this is so you can read it on the screen */
  463. X#endif
  464. X                break;
  465. X            case ('d'):    /* re-create directory structure (now by default) */
  466. X                break;
  467. X            case ('e'):    /* just ignore -e, -x options (extract) */
  468. X                break;
  469. X            case ('f'):    /* "freshen" (extract only newer files) */
  470. X                ++fflag;
  471. X                ++uflag;
  472. X                break;
  473. X            case ('j'):    /* junk pathnames/directory structure */
  474. X                ++jflag;
  475. X                break;
  476. X         /* case ('l') is below, after fall-through for 'v' */
  477. X            case ('n'):    /* don't overwrite any files */
  478. X                overwrite_none = TRUE;
  479. X                break;
  480. X            case ('o'):    /* OK to overwrite files without prompting */
  481. X                overwrite_all = TRUE;
  482. X                force_flag = TRUE;  /* (share -o for now): force to continue */
  483. X                break;
  484. X            case ('p'):
  485. X                ++cflag;
  486. X#if defined(NATIVE) && !defined(DOS_OS2)
  487. X                ++aflag;
  488. X#endif
  489. X                quietflg += 99;
  490. X                break;
  491. X            case ('q'):
  492. X                ++quietflg;
  493. X                break;
  494. X#ifdef DOS_OS2
  495. X            case ('s'):
  496. X                ++sflag;
  497. X                break;
  498. X#endif
  499. X            case ('t'):
  500. X                ++tflag;
  501. X                break;
  502. X            case ('U'):    /* Uppercase flag (i.e., don't convert to lower) */
  503. X                ++U_flag;
  504. X                break;
  505. X            case ('u'):    /* "update" (extract only new and newer files) */
  506. X                ++uflag;
  507. X                break;
  508. X            case ('V'):    /* Version flag:  retain VMS/DEC-20 file versions */
  509. X                ++V_flag;
  510. X                break;
  511. X            case ('v'):
  512. X                ++vflag;
  513. X                /* fall thru */
  514. X            case ('l'):
  515. X                ++vflag;
  516. X                break;
  517. X#ifdef VMS
  518. X            case ('X'):    /* restore owner/protection info (may need privs) */
  519. X                secinf = TRUE;
  520. X                break;
  521. X#endif /* VMS */
  522. X            case ('x'):    /* extract:  default */
  523. X                break;
  524. X            case ('z'):    /* display only the archive comment */
  525. X                ++zflag;
  526. X                break;
  527. X            default:
  528. X                error = TRUE;
  529. X                break;
  530. X            }
  531. X        }
  532. X    }
  533. X
  534. X/*---------------------------------------------------------------------------
  535. X    Make sure we aren't trying to do too many things here.  [This seems like
  536. X    kind of a brute-force way to do things; but aside from that, isn't the
  537. X    -a option useful when listing the directory (i.e., for reading zipfile
  538. X    comments)?  It's a modifier, not an action in and of itself, so perhaps
  539. X    it should not be included in the test--certainly, in the case of zipfile
  540. X    testing, it can just be ignored.]
  541. X  ---------------------------------------------------------------------------*/
  542. X
  543. X    if ((aflag && tflag) || (aflag && vflag) || (cflag && tflag) ||
  544. X        (cflag && uflag) || (cflag && vflag) || (tflag && uflag) ||
  545. X        (tflag && vflag) || (uflag && vflag) || (fflag && overwrite_none)) {
  546. X        fprintf(stderr, "error:\
  547. X  -at, -av, -ct, -cu, -cv, -fn, -tu, -tv, -uv combinations not allowed\n");
  548. X        error = TRUE;
  549. X    }
  550. X    if (quietflg && zflag)
  551. X        quietflg = 0;
  552. X    if (overwrite_all && overwrite_none) {
  553. X        fprintf(stderr, "caution:  both -n and -o specified; ignoring -o\n");
  554. X        overwrite_all = FALSE;
  555. X    }
  556. X    if ((argc-- == 0) || error)
  557. X        RETURN(usage(error));
  558. X
  559. X/*---------------------------------------------------------------------------
  560. X    Now get the zipfile name from the command line and see if it exists as a
  561. X    regular (non-directory) file.  If not, append the ".zip" suffix.  We don't
  562. X    immediately check to see if this results in a good name, but we will do so
  563. X    later.  In the meantime, see if there are any member filespecs on the com-
  564. X    mand line, and if so, set the filename pointer to point at them.
  565. X  ---------------------------------------------------------------------------*/
  566. X
  567. X    strcpy(zipfn, *argv++);
  568. X    if (stat(zipfn, &statbuf) || (statbuf.st_mode & S_IFMT) == S_IFDIR)
  569. X        strcat(zipfn, ZSUFX);
  570. X#if defined(UNIX) && !defined(VMS)   /* Unix executables have no extension-- */
  571. X    else if (statbuf.st_mode & S_IEXEC)  /* might find zip, not zip.zip; etc */
  572. X        fprintf(stderr, "\nnote:  file [ %s ] may be an executable\n\n", zipfn);
  573. X#endif /* UNIX && !VMS */
  574. X
  575. X    if (stat(zipfn, &statbuf)) {/* try again */
  576. X        fprintf(stderr, "error:  can't find zipfile [ %s ]\n", zipfn);
  577. X        RETURN(9);              /* 9:  file not found */
  578. X    } else
  579. X        ziplen = statbuf.st_size;
  580. X
  581. X    if (argc != 0) {
  582. X        fnv = argv;
  583. X        process_all_files = FALSE;
  584. X    } else
  585. X        process_all_files = TRUE;       /* for speed */
  586. X
  587. X/*---------------------------------------------------------------------------
  588. X    Okey dokey, we have everything we need to get started.  Let's roll.
  589. X  ---------------------------------------------------------------------------*/
  590. X
  591. X    inbuf = (byte *) malloc(INBUFSIZ + 4);     /* 4 extra for hold[] (below) */
  592. X    outbuf = (byte *) malloc(OUTBUFSIZ + 1);   /* 1 extra for string termin. */
  593. X#ifndef DOS_OS2
  594. X    if (aflag)                  /* if need an ascebc scratch, */
  595. X        outout = (byte *) malloc(OUTBUFSIZ);
  596. X    else                        /*  allocate it... */
  597. X#endif /* !DOS_OS2 */
  598. X        outout = outbuf;        /*  else just point to outbuf */
  599. X
  600. X    if ((inbuf == NULL) || (outbuf == NULL) || (outout == NULL)) {
  601. X        fprintf(stderr, "error:  can't allocate unzip buffers\n");
  602. X        RETURN(4);              /* 4-8:  insufficient memory */
  603. X    }
  604. X    hold = &inbuf[INBUFSIZ];    /* to check for boundary-spanning signatures */
  605. X
  606. X#ifdef THINK_C
  607. X    if (!process_zipfile())
  608. X        goto start;
  609. X#else
  610. X    RETURN(process_zipfile());  /* keep passing errors back... */
  611. X#endif
  612. X
  613. X}       /* end main() */
  614. X
  615. X
  616. X
  617. X
  618. X
  619. X/**********************/
  620. X/*  Function usage()  */
  621. X/**********************/
  622. X
  623. Xint usage(error)   /* return PK-type error code */
  624. X    int error;
  625. X{
  626. X#ifdef NATIVE
  627. X#ifdef EBCDIC
  628. X    char *astring = "-a  convert ASCII to EBCDIC";
  629. X#else /* !EBCDIC */
  630. X    char *astring = "-a  convert ASCII to native chars";
  631. X#endif /* ?EBCDIC *?
  632. X/*  char *astring = "-a  convert ASCII to " NATIVE;  (ANSI C concatenation)  */
  633. X    char *loc_str = "";
  634. X#else /* !NATIVE */
  635. X#ifdef DOS_OS2
  636. X    char *astring = "-a  convert text (LF => CR LF)";
  637. X    char *loc_str = "-s  allow spaces in filenames";
  638. X#else /* !DOS_OS2 */
  639. X#ifdef MACOS
  640. X    char *astring = "-a  convert text (CR LF => CR)";
  641. X    char *loc_str = "";
  642. X#else /* !MACOS:  UNIX, VMS */
  643. X    char *astring = "-a  convert text (CR LF => LF)";
  644. X#ifdef VMS
  645. X    char *loc_str = "-X  restore owner/protection info";
  646. X#else /* !VMS */
  647. X    char *loc_str = "";
  648. X#endif /* ?VMS */
  649. X#endif /* ?MACOS */
  650. X#endif /* ?DOS_OS2 */
  651. X#endif /* ?NATIVE */
  652. X    FILE *usagefp;
  653. X
  654. X
  655. X/*---------------------------------------------------------------------------
  656. X    If user requested usage, send it to stdout; else send to stderr.
  657. X  ---------------------------------------------------------------------------*/
  658. X
  659. X    if (error)
  660. X        usagefp = (FILE *) stderr;
  661. X    else
  662. X        usagefp = (FILE *) stdout;
  663. X
  664. X    fprintf(usagefp, "\
  665. XUnZip:  Zipfile Extract %s;  (c) 1989 S.H.Smith and others\n\
  666. XVersions 3.0 and later by Info-ZIP.  Bug reports ONLY to zip-bugs@cs.ucla.edu\
  667. X\n\n", VERSION);
  668. X
  669. X    fprintf(usagefp, "\
  670. XUsage: unzip [ -options[modifiers] ] file[.zip] [filespec...]\n\
  671. X  -x  extract files (default)                -l  list files (short format)\n\
  672. X  -c  extract files to stdout/screen (CRT)   -v  list files (verbose format)\n\
  673. X  -f  freshen existing files, create none    -p  extract to pipe, no messages\n\
  674. X  -u  update files, create if necessary      -t  test archive integrity\n\
  675. X                                             -z  display archive comment\n\
  676. Xmodifiers:\n\
  677. X  -n  never overwrite existing files         %s\n", loc_str);
  678. X    fprintf(usagefp, "\
  679. X  -o  overwrite files WITHOUT prompting      %s\n\
  680. X  -j  junk paths (don't make directories)    -U  don't make names lowercase\n\
  681. X  -q  quiet mode (-qq => quieter)            -V  retain VMS version numbers\
  682. X\n\n\
  683. XExamples: (See manual for more information)\n\
  684. X  unzip data1 Readme   => extracts file Readme from zipfile data1.zip\n\
  685. X  unzip -p foo | more  => send contents of foo.zip via pipe into program more\n\
  686. X  unzip -fo foo        => quietly replace existing files if archive files newer\
  687. X\n", astring);
  688. X
  689. X#ifdef VMS
  690. X    fprintf(usagefp, "\
  691. X  unzip \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS\
  692. X\n");
  693. X#endif
  694. X
  695. X    if (error)
  696. X        return 10;    /* 10:  bad or illegal parameters specified */
  697. X    else
  698. X        return 0;     /* just wanted usage screen: no error */
  699. X
  700. X}       /* end function usage() */
  701. X
  702. X
  703. X
  704. X
  705. X
  706. X/********************************/
  707. X/*  Function process_zipfile()  */
  708. X/********************************/
  709. X
  710. Xint process_zipfile()    /* return PK-type error code */
  711. X{
  712. X    int error=0, error_in_archive;
  713. X    longint real_ecrec_offset, expect_ecrec_offset;
  714. X
  715. X
  716. X/*---------------------------------------------------------------------------
  717. X    Open the zipfile for reading and in BINARY mode to prevent CR/LF trans-
  718. X    lation, which would corrupt the bitstreams.
  719. X  ---------------------------------------------------------------------------*/
  720. X
  721. X#ifdef VMS
  722. X    {
  723. X        int rtype;
  724. X
  725. X        VMSmunch(zipfn, GET_RTYPE, (char *)&rtype);
  726. X        if (rtype == FAT$C_VARIABLE) {
  727. X            fprintf(stderr,
  728. X     "\n     Error:  zipfile is in variable-length record format.  Please\n\
  729. X     run \"bilf l %s\" to convert the zipfile to stream-LF\n\
  730. X     record format.  (Bilf.exe, bilf.c and make_bilf.com are included\n\
  731. X     in the VMS unzip distribution.)\n\n", zipfn);
  732. X            return 2;           /* 2:  error in zipfile */
  733. X        }
  734. X        rtype = FAT$C_STREAMLF; /* Unix I/O loves it */
  735. X        VMSmunch(zipfn, CHANGE_RTYPE, (char *)&rtype);
  736. X    }
  737. X#endif
  738. X    if (open_input_file())      /* this should never happen, given the */
  739. X        return (9);             /*   stat() test in main(), but... */
  740. X
  741. X/*---------------------------------------------------------------------------
  742. X    Reconstruct the various PK signature strings; find and process the cen-
  743. X    tral directory; list, extract or test member files as instructed; and
  744. X    close the zipfile.
  745. X  ---------------------------------------------------------------------------*/
  746. X
  747. X    strcat(local_hdr_sig, LOCAL_HDR_SIG);
  748. X    strcat(central_hdr_sig, CENTRAL_HDR_SIG);
  749. X    strcat(end_central_sig, END_CENTRAL_SIG);
  750. X
  751. X    if (find_end_central_dir()) /* not found; nothing to do */
  752. X        return (2);             /* 2:  error in zipfile */
  753. X
  754. X    real_ecrec_offset = cur_zipfile_bufstart+(inptr-inbuf);
  755. X#ifdef TEST
  756. X    printf("\n  found end-of-central-dir signature at offset %ld (%.8lXh)\n",
  757. X      real_ecrec_offset, real_ecrec_offset);
  758. X    printf("    from beginning of file; offset %d (%.4Xh) within block\n",
  759. X      inptr-inbuf, inptr-inbuf);
  760. X#endif
  761. X
  762. X    if ((error_in_archive = process_end_central_dir()) > 1)
  763. X        return (error_in_archive);
  764. X
  765. X    if (zflag)
  766. X        return (0);
  767. X
  768. X#ifndef PAKFIX
  769. X    if (ecrec.number_this_disk == 0) {
  770. X#else /* PAKFIX */
  771. X    if ((ecrec.number_this_disk == 0)  ||
  772. X        (error = ((ecrec.number_this_disk == 1) &&
  773. X                  (ecrec.num_disk_with_start_central_dir == 1)) )) {
  774. X
  775. X        if (error) {
  776. X            fprintf(stderr,
  777. X     "\n     Warning:  zipfile claims to be disk 2 of a two-part archive;\n\
  778. X     attempting to process anyway.  If no further errors occur, this\n\
  779. X     archive was probably created by PAK v2.5 or earlier.  This bug\n\
  780. X     was reported to NoGate and should have been fixed by mid-1991.\n\n");
  781. X            error_in_archive = 1;  /* 1:  warning */
  782. X        }
  783. X#endif /* ?PAKFIX */
  784. X        expect_ecrec_offset = ecrec.offset_start_central_directory +
  785. X                              ecrec.size_central_directory;
  786. X        if ((extra_bytes = real_ecrec_offset - expect_ecrec_offset) < 0) {
  787. X            fprintf(stderr, "\nerror:  missing %ld bytes in zipfile (\
  788. Xattempting to process anyway)\n\n", -extra_bytes);
  789. X            error_in_archive = 2;       /* 2:  (weak) error in zipfile */
  790. X        } else if (extra_bytes > 0) {
  791. X            if ((ecrec.offset_start_central_directory == 0) &&
  792. X                (ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */
  793. X            {
  794. X                fprintf(stderr, "\nerror:  NULL central directory offset (\
  795. Xattempting to process anyway)\n\n");
  796. X                ecrec.offset_start_central_directory = extra_bytes;
  797. X                extra_bytes = 0;
  798. X                error_in_archive = 2;   /* 2:  (weak) error in zipfile */
  799. X            } else {
  800. X                fprintf(stderr, "\nwarning:  extra %ld bytes at beginning or\
  801. X within zipfile\n          (attempting to process anyway)\n\n", extra_bytes);
  802. X                error_in_archive = 1;   /* 1:  warning error */
  803. X            }
  804. X        }
  805. X        LSEEK( ecrec.offset_start_central_directory )
  806. X        if (vflag)
  807. X            error = list_files();               /* LIST 'EM */
  808. X        else
  809. X            error = extract_or_test_files();    /* EXTRACT OR TEST 'EM */
  810. X        if (error > error_in_archive)   /* don't overwrite stronger error */
  811. X            error_in_archive = error;   /*  with (for example) a warning */
  812. X    } else {
  813. X        fprintf(stderr, "\nerror:  zipfile is part of multi-disk archive \
  814. X(sorry, not supported).\n");
  815. X        fprintf(stderr, "Please report to zip-bugs@cs.ucla.edu\n");
  816. X        error_in_archive = 11;  /* 11:  no files found */
  817. X    }
  818. X
  819. X    close(zipfd);
  820. X#ifdef VMS
  821. X    VMSmunch(zipfn, RESTORE_RTYPE, NULL);
  822. X#endif
  823. X    return (error_in_archive);
  824. X
  825. X}       /* end function process_zipfile() */
  826. X
  827. X
  828. X
  829. X
  830. X
  831. X/************************************/
  832. X/*  Function find_end_central_dir() */
  833. X/************************************/
  834. X
  835. Xint find_end_central_dir()
  836. X/* return 0 if found, 1 otherwise */
  837. X{
  838. X    int i, numblks;
  839. X    longint tail_len;
  840. X
  841. X
  842. X
  843. X/*---------------------------------------------------------------------------
  844. X    Treat case of short zipfile separately.
  845. X  ---------------------------------------------------------------------------*/
  846. X
  847. X    if (ziplen <= INBUFSIZ) {
  848. X        lseek(zipfd, 0L, SEEK_SET);
  849. X        if ((incnt = read(zipfd,(char *)inbuf,(unsigned int)ziplen)) == ziplen)
  850. X
  851. X            /* 'P' must be at least 22 bytes from end of zipfile */
  852. X            for ( inptr = inbuf+ziplen-22  ;  inptr >= inbuf  ;  --inptr )
  853. X                if ( (ascii_to_native(*inptr) == 'P')  &&
  854. X                      !strncmp((char *)inptr, end_central_sig, 4) ) {
  855. X                    incnt -= inptr - inbuf;
  856. X                    return(0);  /* found it! */
  857. X                }               /* ...otherwise fall through & fail */
  858. X
  859. X/*---------------------------------------------------------------------------
  860. X    Zipfile is longer than INBUFSIZ:  may need to loop.  Start with short
  861. X    block at end of zipfile (if not TOO short).
  862. X  ---------------------------------------------------------------------------*/
  863. X
  864. X    } else {
  865. X        if ((tail_len = ziplen % INBUFSIZ) > ECREC_SIZE) {
  866. X            cur_zipfile_bufstart = lseek(zipfd, ziplen-tail_len, SEEK_SET);
  867. X            if ((incnt = read(zipfd,(char *)inbuf,(unsigned int)tail_len)) != tail_len)
  868. X                goto fail;      /* shut up, it's expedient. */
  869. X
  870. X            /* 'P' must be at least 22 bytes from end of zipfile */
  871. X            for ( inptr = inbuf+tail_len-22  ;  inptr >= inbuf  ;  --inptr )
  872. X                if ( (ascii_to_native(*inptr) == 'P')  &&
  873. X                      !strncmp((char *)inptr, end_central_sig, 4) ) {
  874. X                    incnt -= inptr - inbuf;
  875. X                    return(0);  /* found it! */
  876. X                }               /* ...otherwise search next block */
  877. X            strncpy((char *)hold, (char *)inbuf, 3);    /* sig may span block
  878. X                                                           boundary */
  879. X
  880. X        } else {
  881. X            cur_zipfile_bufstart = ziplen - tail_len;
  882. X        }
  883. X
  884. X        /*
  885. X         * Loop through blocks of zipfile data, starting at the end and going
  886. X         * toward the beginning.  Need only check last 65557 bytes of zipfile:
  887. X         * comment may be up to 65535 bytes long, end-of-central-directory rec-
  888. X         * ord is 18 bytes (shouldn't hardcode this number, but what the hell:
  889. X         * already did so above (22=18+4)), and sig itself is 4 bytes.
  890. X         */
  891. X
  892. X        /*          ==amt to search==   ==done==   ==rounding==     =blksiz= */
  893. X        numblks = ( min(ziplen,65557) - tail_len + (INBUFSIZ-1) ) / INBUFSIZ;
  894. X
  895. X        for ( i = 1  ;  i <= numblks  ;  ++i ) {
  896. X            cur_zipfile_bufstart -= INBUFSIZ;
  897. X            lseek(zipfd, cur_zipfile_bufstart, SEEK_SET);
  898. X            if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) != INBUFSIZ)
  899. X                break;          /* fall through and fail */
  900. X
  901. X            for ( inptr = inbuf+INBUFSIZ-1  ;  inptr >= inbuf  ;  --inptr )
  902. X                if ( (ascii_to_native(*inptr) == 'P')  &&
  903. X                      !strncmp((char *)inptr, end_central_sig, 4) ) {
  904. X                    incnt -= inptr - inbuf;
  905. X                    return(0);  /* found it! */
  906. X                }
  907. X            strncpy((char *)hold, (char *)inbuf, 3);    /* sig may span block
  908. X                                                           boundary */
  909. X        }
  910. X
  911. X    } /* end if (ziplen > INBUFSIZ) */
  912. X
  913. X/*---------------------------------------------------------------------------
  914. X    Searched through whole region where signature should be without finding
  915. X    it.  Print informational message and die a horrible death.
  916. X  ---------------------------------------------------------------------------*/
  917. X
  918. Xfail:
  919. X
  920. X    fprintf(stderr, "\nFile:  %s\n\n\
  921. X     End-of-central-directory signature not found.  Either this file is not\n\
  922. X     a zipfile, or it constitutes one disk of a multi-part archive.  In the\n\
  923. X     latter case the central directory and zipfile comment will be found on\n\
  924. X     the last disk(s) of this archive.\n", zipfn);
  925. X    return(1);
  926. X
  927. X}       /* end function find_end_central_dir() */
  928. X
  929. X
  930. X
  931. X
  932. X
  933. X/***************************************/
  934. X/*  Function process_end_central_dir() */
  935. X/***************************************/
  936. X
  937. Xint process_end_central_dir()    /* return PK-type error code */
  938. X{
  939. X    ec_byte_rec byterec;
  940. X    int error=0;
  941. X
  942. X
  943. X/*---------------------------------------------------------------------------
  944. X    Read the end-of-central-directory record and do any necessary machine-
  945. X    type conversions (byte ordering, structure padding compensation) by
  946. X    reading data into character array, then copying to struct.
  947. X  ---------------------------------------------------------------------------*/
  948. X
  949. X    if (readbuf((char *) byterec, ECREC_SIZE+4) <= 0)
  950. X        return (51);
  951. X
  952. X    ecrec.number_this_disk =
  953. X        makeword(&byterec[NUMBER_THIS_DISK]);
  954. X    ecrec.num_disk_with_start_central_dir =
  955. X        makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
  956. X    ecrec.num_entries_centrl_dir_ths_disk =
  957. X        makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
  958. X    ecrec.total_entries_central_dir =
  959. X        makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
  960. X    ecrec.size_central_directory =
  961. X        makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
  962. X    ecrec.offset_start_central_directory =
  963. X        makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
  964. X    ecrec.zipfile_comment_length =
  965. X        makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
  966. X
  967. X/*---------------------------------------------------------------------------
  968. X    Get the zipfile comment, if any, and print it out.  (Comment may be up
  969. X    to 64KB long.  May the fleas of a thousand camels infest the armpits of
  970. X    anyone who actually takes advantage of this fact.)  Then position the
  971. X    file pointer to the beginning of the central directory and fill buffer.
  972. X  ---------------------------------------------------------------------------*/
  973. X
  974. X    if (ecrec.zipfile_comment_length && !quietflg) {
  975. X        if (!zflag)
  976. X          printf("[%s] comment:\n", zipfn);
  977. X        if (do_string(ecrec.zipfile_comment_length,DISPLAY)) {
  978. X            fprintf(stderr, "\ncaution:  zipfile comment truncated\n");
  979. X            error = 1;          /* 1:  warning error */
  980. X        }
  981. X#if 0
  982. X        if (!zflag)
  983. X          printf("\n\n");       /* what the heck is this doing here?! */
  984. X#endif
  985. X    }
  986. X
  987. X    return (error);
  988. X
  989. X}       /* end function process_end_central_dir() */
  990. X
  991. X
  992. X
  993. X
  994. X
  995. X/**************************/
  996. X/*  Function list_files() */
  997. X/**************************/
  998. X
  999. Xint list_files()    /* return PK-type error code */
  1000. X{
  1001. X    char **fnamev;
  1002. X    int do_this_file=FALSE, ratio, error, error_in_archive=0;
  1003. X    int which_hdr=(vflag>1);
  1004. X    UWORD j, yr, mo, dy, hh, mm, members=0;
  1005. X    ULONG tot_csize=0L, tot_ucsize=0L;
  1006. X    min_info info;
  1007. X    static char *method[NUM_METHODS+1] =
  1008. X        {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
  1009. X         "Implode", "Token", "Deflate", unkn};
  1010. X    static char *Headers[][2] = {
  1011. X        {" Length    Date    Time    Name",
  1012. X         " ------    ----    ----    ----"},
  1013. X        {" Length  Method   Size  Ratio   Date    Time   CRC-32     Name",
  1014. X         " ------  ------   ----  -----   ----    ----   ------     ----"}
  1015. X    };
  1016. X
  1017. X
  1018. X
  1019. X/*---------------------------------------------------------------------------
  1020. X    Unlike extract_or_test_files(), this routine confines itself to the cen-
  1021. X    tral directory.  Thus its structure is somewhat simpler, since we can do
  1022. X    just a single loop through the entire directory, listing files as we go.
  1023. X
  1024. X    So to start off, print the heading line and then begin main loop through
  1025. X    the central directory.  The results will look vaguely like the following:
  1026. X
  1027. X  Length  Method   Size  Ratio   Date    Time   CRC-32     Name ("^" ==> case
  1028. X  ------  ------   ----  -----   ----    ----   ------     ----   conversion)
  1029. X   44004  Implode  13041  71%  11-02-89  19:34  8b4207f7   Makefile.UNIX
  1030. X    3438  Shrunk    2209  36%  09-15-90  14:07  a2394fd8  ^dos-file.ext
  1031. X  ---------------------------------------------------------------------------*/
  1032. X
  1033. X    pInfo = &info;
  1034. X
  1035. X    if (quietflg < 2)
  1036. X        if (U_flag)
  1037. X            printf("%s\n%s\n", Headers[which_hdr][0], Headers[which_hdr][1]);
  1038. X        else
  1039. X            printf("%s (\"^\" ==> case\n%s   conversion)\n", 
  1040. X              Headers[which_hdr][0], Headers[which_hdr][1]);
  1041. X
  1042. X    for (j = 0; j < ecrec.total_entries_central_dir; ++j) {
  1043. X
  1044. X        if (readbuf(sig, 4) <= 0)
  1045. X            return (51);        /* 51:  unexpected EOF */
  1046. X        if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
  1047. X            fprintf(stderr, CentSigMsg, j);  /* sig not found */
  1048. X            fprintf(stderr, ReportMsg);   /* check binary transfers */
  1049. X            return (3);         /* 3:  error in zipfile */
  1050. X        }
  1051. X        if ((error = process_cdir_file_hdr()) != 0)  /* (sets pInfo->lcflag) */
  1052. X            return (error);     /* only 51 (EOF) defined */
  1053. X
  1054. X        /*
  1055. X         * We could DISPLAY the filename instead of storing (and possibly trun-
  1056. X         * cating, in the case of a very long name) and printing it, but that
  1057. X         * has the disadvantage of not allowing case conversion--and it's nice
  1058. X         * to be able to see in the listing precisely how you have to type each
  1059. X         * filename in order for unzip to consider it a match.  Speaking of
  1060. X         * which, if member names were specified on the command line, check in
  1061. X         * with match() to see if the current file is one of them, and make a
  1062. X         * note of it if it is.
  1063. X         */
  1064. X
  1065. X        if ((error = do_string(crec.filename_length, FILENAME)) != 0) {
  1066. X            error_in_archive = error;  /*             ^--(uses pInfo->lcflag) */
  1067. X            if (error > 1)      /* fatal:  can't continue */
  1068. X                return (error);
  1069. X        }
  1070. X        if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0) {
  1071. X            error_in_archive = error;  
  1072. X            if (error > 1)      /* fatal:  can't continue */
  1073. X                return (error);
  1074. X        }
  1075. X        if (!process_all_files) {   /* check if specified on command line */
  1076. X            do_this_file = FALSE;
  1077. X            fnamev = fnv;       /* don't destroy permanent filename ptr */
  1078. X            for (--fnamev; *++fnamev;)
  1079. X                if (match(filename, *fnamev)) {
  1080. X                    do_this_file = TRUE;
  1081. X                    break;      /* found match, so stop looping */
  1082. X                }
  1083. X        }
  1084. X        /*
  1085. X         * If current file was specified on command line, or if no names were
  1086. X         * specified, do the listing for this file.  Otherwise, get rid of the
  1087. X         * file comment and go back for the next file.
  1088. X         */
  1089. X
  1090. X        if (process_all_files || do_this_file) {
  1091. X
  1092. X            yr = (((crec.last_mod_file_date >> 9) & 0x7f) + 80) % (unsigned)100;
  1093. X            mo = (crec.last_mod_file_date >> 5) & 0x0f;
  1094. X            dy = crec.last_mod_file_date & 0x1f;
  1095. X
  1096. X            /* twist date so it displays according to national convention */
  1097. X            switch (dateformat()) {
  1098. X                case DF_YMD:
  1099. X                    hh = mo; mo = yr; yr = dy; dy = hh; break;
  1100. X                case DF_DMY:
  1101. X                    hh = mo; mo = dy; dy = hh;
  1102. X            }
  1103. X            hh = (crec.last_mod_file_time >> 11) & 0x1f;
  1104. X            mm = (crec.last_mod_file_time >> 5) & 0x3f;
  1105. X
  1106. X            csize = (longint) crec.compressed_size;
  1107. X            ucsize = (longint) crec.uncompressed_size;
  1108. X            if (crec.general_purpose_bit_flag & 1)
  1109. X                csize -= 12;    /* if encrypted, don't count encrypt hdr */
  1110. X
  1111. X            ratio = (ucsize == 0) ? 0 :   /* .zip can have 0-length members */
  1112. X                ((ucsize > 2000000) ?     /* risk signed overflow if mult. */
  1113. X                (int) ((ucsize-csize) / (ucsize/1000L)) + 5 :   /* big */
  1114. X                (int) ((1000L*(ucsize-csize)) / ucsize) + 5);   /* small */
  1115. X
  1116. X            switch (which_hdr) {
  1117. X                case 0:   /* short form */
  1118. X                    printf("%7ld  %02u-%02u-%02u  %02u:%02u  %c%s\n",
  1119. X                      ucsize, mo, dy, yr, hh, mm, (pInfo->lcflag?'^':' '),
  1120. X                      filename);
  1121. X                    break;
  1122. X                case 1:   /* verbose */
  1123. X                    printf(
  1124. X              "%7ld  %-7s%7ld %3d%%  %02u-%02u-%02u  %02u:%02u  %08lx  %c%s\n",
  1125. X                      ucsize, method[methnum], csize, ratio/10, mo, dy, yr,
  1126. X                      hh, mm, crec.crc32, (pInfo->lcflag?'^':' '), filename);
  1127. X            }
  1128. X
  1129. X            error = do_string(crec.file_comment_length, (QCOND2? DISPLAY:SKIP));
  1130. X            if (error) {
  1131. X                error_in_archive = error;  /* might be just warning */
  1132. X                if (error > 1)  /* fatal */
  1133. X                    return (error);
  1134. X            }
  1135. X            tot_ucsize += (ULONG) ucsize;
  1136. X            tot_csize += (ULONG) csize;
  1137. X            ++members;
  1138. X
  1139. X        } else {        /* not listing this file */
  1140. X            SKIP_(crec.file_comment_length)
  1141. X        }
  1142. X    }                   /* end for-loop (j: files in central directory) */
  1143. X
  1144. X/*---------------------------------------------------------------------------
  1145. X    Print footer line and totals (compressed size, uncompressed size, number
  1146. X    of members in zipfile).
  1147. X  ---------------------------------------------------------------------------*/
  1148. X
  1149. X    ratio = (tot_ucsize == 0) ? 
  1150. X        0 : ((tot_ucsize > 4000000) ?    /* risk unsigned overflow if mult. */
  1151. X        (int) ((tot_ucsize - tot_csize) / (tot_ucsize/1000L)) + 5 :
  1152. X        (int) ((tot_ucsize - tot_csize) * 1000L / tot_ucsize) + 5);
  1153. X
  1154. X    if (quietflg < 2) {
  1155. X        switch (which_hdr) {
  1156. X        case 0:         /* short */
  1157. X            printf("%s\n%7lu                    %-7u\n",
  1158. X                   " ------                    -------",
  1159. X                   tot_ucsize, members);
  1160. X            break;
  1161. X        case 1:         /* verbose */
  1162. X            printf(
  1163. X              "%s\n%7lu         %7lu %3d%%                              %-7u\n",
  1164. X              " ------          ------  ---                              -------",
  1165. X              tot_ucsize, tot_csize, ratio / 10, members);
  1166. X        }
  1167. X    }
  1168. X/*---------------------------------------------------------------------------
  1169. X    Double check that we're back at the end-of-central-directory record.
  1170. X  ---------------------------------------------------------------------------*/
  1171. X
  1172. X    readbuf(sig, 4);
  1173. X    if (strncmp(sig, end_central_sig, 4)) {     /* just to make sure again */
  1174. X        fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig */
  1175. X/*      fprintf(stderr, ReportMsg);   */
  1176. X        error_in_archive = 1;        /* 1:  warning error */
  1177. X    }
  1178. X    return (error_in_archive);
  1179. X
  1180. X}       /* end function list_files() */
  1181. X
  1182. X
  1183. X
  1184. X
  1185. X
  1186. X/**************************************/
  1187. X/*  Function process_cdir_file_hdr()  */
  1188. X/**************************************/
  1189. X
  1190. Xint process_cdir_file_hdr()    /* return PK-type error code */
  1191. X{
  1192. X    cdir_byte_hdr byterec;
  1193. X
  1194. X
  1195. X/*---------------------------------------------------------------------------
  1196. X    Read the next central directory entry and do any necessary machine-type
  1197. X    conversions (byte ordering, structure padding compensation--do so by
  1198. X    copying the data from the array into which it was read (byterec) to the
  1199. X    usable struct (crec)).
  1200. X  ---------------------------------------------------------------------------*/
  1201. X
  1202. X    if (readbuf((char *) byterec, CREC_SIZE) <= 0)
  1203. X        return (51);            /* 51:  unexpected EOF */
  1204. X
  1205. X    crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
  1206. X    crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
  1207. X    crec.version_needed_to_extract[0] = byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
  1208. X    crec.version_needed_to_extract[1] = byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
  1209. X
  1210. X    crec.general_purpose_bit_flag =
  1211. X        makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
  1212. X    crec.compression_method =
  1213. X        makeword(&byterec[C_COMPRESSION_METHOD]);
  1214. X    crec.last_mod_file_time =
  1215. X        makeword(&byterec[C_LAST_MOD_FILE_TIME]);
  1216. X    crec.last_mod_file_date =
  1217. X        makeword(&byterec[C_LAST_MOD_FILE_DATE]);
  1218. X    crec.crc32 =
  1219. X        makelong(&byterec[C_CRC32]);
  1220. X    crec.compressed_size =
  1221. X        makelong(&byterec[C_COMPRESSED_SIZE]);
  1222. X    crec.uncompressed_size =
  1223. X        makelong(&byterec[C_UNCOMPRESSED_SIZE]);
  1224. X    crec.filename_length =
  1225. X        makeword(&byterec[C_FILENAME_LENGTH]);
  1226. X    crec.extra_field_length =
  1227. X        makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
  1228. X    crec.file_comment_length =
  1229. X        makeword(&byterec[C_FILE_COMMENT_LENGTH]);
  1230. X    crec.disk_number_start =
  1231. X        makeword(&byterec[C_DISK_NUMBER_START]);
  1232. X    crec.internal_file_attributes =
  1233. X        makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
  1234. X    crec.external_file_attributes =
  1235. X        makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]);  /* LONG, not word! */
  1236. X    crec.relative_offset_local_header =
  1237. X        makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
  1238. X
  1239. X    pInfo->hostnum = min(crec.version_made_by[1], NUM_HOSTS);
  1240. X/*  extnum = min( crec.version_needed_to_extract[1], NUM_HOSTS ); */
  1241. X    methnum = min(crec.compression_method, NUM_METHODS);
  1242. X    if (methnum == NUM_METHODS)
  1243. X        sprintf(unkn, "Unk:%03d", crec.compression_method);
  1244. X
  1245. X/*---------------------------------------------------------------------------
  1246. X    Set flag for lowercase conversion of filename, depending on which OS the
  1247. X    file is coming from.  This section could be ifdef'd if some people have
  1248. X    come to love DOS uppercase filenames under Unix...but really, guys, get
  1249. X    a life. :)  NOTE THAT ALL SYSTEM NAMES NOW HAVE TRAILING UNDERSCORES!!!
  1250. X    This is to prevent interference with compiler command-line defines such
  1251. X    as -DUNIX, for example, which are then used in "#ifdef UNIX" constructs.
  1252. X  ---------------------------------------------------------------------------*/
  1253. X
  1254. X    pInfo->lcflag = 0;
  1255. X    if (!U_flag)   /* as long as user hasn't specified case-preservation */
  1256. X        switch (pInfo->hostnum) {
  1257. X            case DOS_OS2_FAT_:
  1258. X            case VMS_:
  1259. X            case VM_CMS_:           /* all caps? */
  1260. X            case CPM_:              /* like DOS, right? */
  1261. X        /*  case ATARI_:            ? */
  1262. X        /*  case Z_SYSTEM_:         ? */
  1263. X        /*  case TOPS20_:           (if we had such a thing...) */
  1264. X                pInfo->lcflag = 1;  /* convert filename to lowercase */
  1265. X                break;
  1266. X
  1267. X            default:                /* AMIGA_, UNIX_, (ATARI_), OS2_HPFS_, */
  1268. X                break;              /*   MAC_, (Z_SYSTEM_):  no conversion */
  1269. X        }
  1270. X
  1271. X    return 0;
  1272. X
  1273. X}       /* end function process_cdir_file_hdr() */
  1274. X
  1275. X
  1276. X
  1277. X
  1278. X
  1279. X/***************************************/
  1280. X/*  Function process_local_file_hdr()  */
  1281. X/***************************************/
  1282. X
  1283. Xint process_local_file_hdr()    /* return PK-type error code */
  1284. X{
  1285. X    local_byte_hdr byterec;
  1286. X
  1287. X
  1288. X/*---------------------------------------------------------------------------
  1289. X    Read the next local file header and do any necessary machine-type con-
  1290. X    versions (byte ordering, structure padding compensation--do so by copy-
  1291. X    ing the data from the array into which it was read (byterec) to the
  1292. X    usable struct (lrec)).
  1293. X  ---------------------------------------------------------------------------*/
  1294. X
  1295. X    if (readbuf((char *) byterec, LREC_SIZE) <= 0)
  1296. X        return (51);            /* 51:  unexpected EOF */
  1297. X
  1298. X    lrec.version_needed_to_extract[0] = byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
  1299. X    lrec.version_needed_to_extract[1] = byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
  1300. X
  1301. X    lrec.general_purpose_bit_flag = makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
  1302. X    lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
  1303. X    lrec.last_mod_file_time = makeword(&byterec[L_LAST_MOD_FILE_TIME]);
  1304. X    lrec.last_mod_file_date = makeword(&byterec[L_LAST_MOD_FILE_DATE]);
  1305. X    lrec.crc32 = makelong(&byterec[L_CRC32]);
  1306. X    lrec.compressed_size = makelong(&byterec[L_COMPRESSED_SIZE]);
  1307. X    lrec.uncompressed_size = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
  1308. X    lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
  1309. X    lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
  1310. X
  1311. X    csize = (longint) lrec.compressed_size;
  1312. X    ucsize = (longint) lrec.uncompressed_size;
  1313. X
  1314. X    return (0);                 /* 0:  no error */
  1315. X
  1316. X}       /* end function process_local_file_hdr() */
  1317. END_OF_FILE
  1318.   if test 46692 -ne `wc -c <'unzip.c'`; then
  1319.     echo shar: \"'unzip.c'\" unpacked with wrong size!
  1320.   fi
  1321.   # end of 'unzip.c'
  1322. fi
  1323. echo shar: End of archive 3 \(of 12\).
  1324. cp /dev/null ark3isdone
  1325. MISSING=""
  1326. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1327.     if test ! -f ark${I}isdone ; then
  1328.     MISSING="${MISSING} ${I}"
  1329.     fi
  1330. done
  1331. if test "${MISSING}" = "" ; then
  1332.     echo You have unpacked all 12 archives.
  1333.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1334. else
  1335.     echo You still must unpack the following archives:
  1336.     echo "        " ${MISSING}
  1337. fi
  1338. exit 0
  1339. exit 0 # Just in case...
  1340.