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

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: zip-bugs@cs.ucla.edu (Info-ZIP group)
  4. Subject:  v31i109:  unzip50 - Info-ZIP portable UnZip, version 5.0, Part06/14
  5. Message-ID: <1992Aug24.025521.24680@sparky.imd.sterling.com>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 2d257ec1bd0a912be20ed43f93069654
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. References: <csm-v31i104=unzip50.215137@sparky.IMD.Sterling.COM>
  11. Date: Mon, 24 Aug 1992 02:55:21 GMT
  12. Approved: kent@sparky.imd.sterling.com
  13. Lines: 1974
  14.  
  15. Submitted-by: zip-bugs@cs.ucla.edu (Info-ZIP group)
  16. Posting-number: Volume 31, Issue 109
  17. Archive-name: unzip50/part06
  18. Supersedes: unzip: Volume 29, Issue 31-42
  19. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT AMIGA?, !ATARI, symlink, SGI, DEC, Cray, Convex, Amdahl, Sun
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then feed it
  23. # into a shell via "sh file" or similar.  To overwrite existing files,
  24. # type "sh file -c".
  25. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  26. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  27. # Contents:  MSDOS/tcc/unzip.prj VMS/vms.c zipinfo.c.B
  28. # Wrapped by kent@sparky on Sun Aug 23 21:09:33 1992
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. echo If this archive is complete, you will see the following message:
  31. echo '          "shar: End of archive 6 (of 14)."'
  32. if test -f 'MSDOS/tcc/unzip.prj' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'MSDOS/tcc/unzip.prj'\"
  34. else
  35.   echo shar: Extracting \"'MSDOS/tcc/unzip.prj'\" \(279 characters\)
  36.   sed "s/^X//" >'MSDOS/tcc/unzip.prj' <<'END_OF_FILE'
  37. Xunzip.c        (unzip.h)
  38. Xexplode.c       (unzip.h)
  39. Xextract.c       (unzip.h)
  40. Xfile_io.c       (unzip.h)
  41. Xinflate.c       (unzip.h)
  42. Xmapname.c       (unzip.h)
  43. Xmatch.c         (unzip.h)
  44. Xmisc.c          (unzip.h)
  45. Xunreduce.c      (unzip.h)
  46. Xunshrink.c      (unzip.h)
  47. Xenvargs.c       (unzip.h)
  48. END_OF_FILE
  49.   if test 279 -ne `wc -c <'MSDOS/tcc/unzip.prj'`; then
  50.     echo shar: \"'MSDOS/tcc/unzip.prj'\" unpacked with wrong size!
  51.   fi
  52.   # end of 'MSDOS/tcc/unzip.prj'
  53. fi
  54. if test -f 'VMS/vms.c' -a "${1}" != "-c" ; then 
  55.   echo shar: Will not clobber existing file \"'VMS/vms.c'\"
  56. else
  57.   echo shar: Extracting \"'VMS/vms.c'\" \(25481 characters\)
  58.   sed "s/^X//" >'VMS/vms.c' <<'END_OF_FILE'
  59. X/*************************************************************************
  60. X *                                                                       *
  61. X * Copyright (C) 1992 Igor Mandrichenko.                                 *
  62. X * Permission is granted to any individual or institution to use, copy,  *
  63. X * or redistribute this software so long as all of the original files    *
  64. X * are included unmodified, that it is not sold for profit, and that     *
  65. X * this copyright notice is retained.                                    *
  66. X *                                                                       *
  67. X *************************************************************************/
  68. X
  69. X/*
  70. X *    vms.c  by Igor Mandrichenko
  71. X *    version 1.2-1
  72. X *
  73. X *    This module contains routines to extract VMS file attributes
  74. X *    from extra field and create file with these attributes.  This
  75. X *    source is mainly based on sources of file_io.c from UNZIP 4.1
  76. X *    by Info-ZIP.  [Info-ZIP note:  very little of this code is from
  77. X *    file_io.c; it has virtually been written from the ground up.
  78. X *    Of the few lines which are from the older code, most are mine
  79. X *    (G. Roelofs) and I make no claims upon them.  On the contrary,
  80. X *    my/our thanks to Igor for his contributions!]
  81. X */
  82. X
  83. X/*
  84. X *      Revision history:
  85. X *      1.0-1   Mandrichenko    16-feb-1992
  86. X *              Recognize -c option
  87. X *      1.0-2   Mandrichenko    17-feb-1992
  88. X *              Do not use ASYnchroneous mode.
  89. X *      1.0-3   Mandrichenko    2-mar-1992
  90. X *              Make code more standard
  91. X *              Use lrec instead of crec -- unzip4.2p does not provide
  92. X *              crec now.
  93. X *      1.1     Mandrichenko    5-mar-1992
  94. X *              Make use of asynchronous output.
  95. X *              Be ready to extract RMS blocks of invalid size (because diff
  96. X *              VMS version used to compress).
  97. X *      1.1-1   Mandrichenko    11-mar-1992
  98. X *              Use internal file attributes saved in pInfo to decide
  99. X *              if the file is text.  [GRR:  temporarily disabled, since
  100. X *              no way to override and force binary extraction]
  101. X *      1.1-2   Mandrichenko    13-mar-1992
  102. X *              Do not restore owner/protection info if -X not specified.
  103. X *      1.1-3   Mandrichenko    30-may-1992
  104. X *              Set revision date/time to creation date/time if none specified
  105. X *              Take quiet flag into account.
  106. X *      1.1-4   Cave Newt       14-jun-1992
  107. X *              Check zipfile for variable-length format (unzip and zipinfo).
  108. X *    1.2    Mandrichenko    21-jun-1992
  109. X *        Use deflation/inflation for compression of extra blocks
  110. X *        Free all allocated space
  111. X *    1.2-1    Mandrichenko    23-jun-1992
  112. X *        Interactively select an action when file exists
  113. X */
  114. X
  115. X#ifdef VMS            /*      VMS only !      */
  116. X
  117. X#ifndef SYI$_VERSION
  118. X#define SYI$_VERSION 4096    /* VMS 5.4 definition */
  119. X#endif
  120. X
  121. X#ifndef VAXC
  122. X                /* This definition may be missed */
  123. Xstruct XAB {
  124. X    unsigned char xab$b_cod;
  125. X    unsigned char xab$b_bln;
  126. X    short int xabdef$$_fill_1;
  127. X    char *xab$l_nxt;
  128. X};
  129. X
  130. X#endif
  131. X
  132. X#include "unzip.h"
  133. X#include <ctype.h>
  134. X#include <descrip.h>
  135. X#include <syidef.h>
  136. X
  137. X#define ERR(s) !((s) & 1)
  138. X
  139. X#define BUFS512 8192*2        /* Must be a multiple of 512 */
  140. X
  141. X/*
  142. X*   Local static storage
  143. X*/
  144. Xstatic struct FAB fileblk;
  145. Xstatic struct XABDAT dattim;
  146. Xstatic struct XABRDT rdt;
  147. Xstatic struct RAB rab;
  148. X
  149. Xstatic struct FAB *outfab = 0;
  150. Xstatic struct RAB *outrab = 0;
  151. Xstatic struct XABFHC *xabfhc = 0;
  152. Xstatic struct XABDAT *xabdat = 0;
  153. Xstatic struct XABRDT *xabrdt = 0;
  154. Xstatic struct XABPRO *xabpro = 0;
  155. Xstatic struct XABKEY *xabkey = 0;
  156. Xstatic struct XABALL *xaball = 0;
  157. Xstruct XAB *first_xab = 0L, *last_xab = 0L;
  158. X
  159. Xstatic char query = 0;
  160. Xstatic int text_file = 0;
  161. X
  162. Xstatic char locbuf[BUFS512];
  163. Xstatic int loccnt = 0;
  164. Xstatic char *locptr;
  165. X
  166. Xstatic int WriteBuffer();
  167. Xstatic int _flush_blocks();
  168. Xstatic int _flush_records();
  169. Xstatic byte *extract_block();
  170. Xstatic void message();
  171. Xstatic int get_vms_version();
  172. Xstatic void free_up();
  173. Xstatic int replace();
  174. X
  175. Xstruct bufdsc
  176. X{
  177. X    struct bufdsc *next;
  178. X    byte *buf;
  179. X    int bufcnt;
  180. X};
  181. X
  182. Xstatic struct bufdsc b1, b2, *curbuf;
  183. Xstatic byte buf1[BUFS512], buf2[BUFS512];
  184. X
  185. X
  186. Xint check_format()        /* return non-0 if format is variable-length */
  187. X{
  188. X    int rtype;
  189. X    struct FAB fab;
  190. X
  191. X    fab = cc$rms_fab;
  192. X    fab.fab$l_fna = zipfn;
  193. X    fab.fab$b_fns = strlen(zipfn);
  194. X    sys$open(&fab);
  195. X    rtype = fab.fab$b_rfm;
  196. X    sys$close(&fab);
  197. X
  198. X    if (rtype == FAB$C_VAR || rtype == FAB$C_VFC)
  199. X    {
  200. X    fprintf(stderr,
  201. X        "\n     Error:  zipfile is in variable-length record format.  Please\n\
  202. X     run \"bilf l %s\" to convert the zipfile to stream-LF\n\
  203. X     record format.  (Bilf.exe, bilf.c and make_bilf.com are included\n\
  204. X     in the VMS UnZip source distribution.)\n\n", zipfn);
  205. X    return 2;        /* 2:  error in zipfile */
  206. X    }
  207. X
  208. X    return 0;
  209. X}
  210. X
  211. X
  212. X#ifndef ZIPINFO
  213. X
  214. Xint create_output_file()
  215. X{                /* return non-0 if sys$create failed */
  216. X    int ierr, yr, mo, dy, hh, mm, ss;
  217. X    char timbuf[24];        /* length = first entry in "stupid" + 1 */
  218. X    int attr_given = 0;        /* =1 if VMS attributes are present in
  219. X                *     extra_field */
  220. X
  221. X    rab = cc$rms_rab;        /* fill FAB & RAB with default values */
  222. X    fileblk = cc$rms_fab;
  223. X
  224. X    text_file =/* pInfo->text || */aflag || cflag;
  225. X
  226. X    if (attr_given = find_vms_attrs())
  227. X    {
  228. X    text_file = 0;
  229. X    if (cflag)
  230. X    {
  231. X        printf("Cannot put VMS file %s to stdout.\n",
  232. X           filename);
  233. X        free_up();
  234. X        return 50;
  235. X    }
  236. X    }
  237. X
  238. X    if (!attr_given)
  239. X    {
  240. X    outfab = &fileblk;
  241. X    outfab->fab$l_xab = 0L;
  242. X    if (text_file)
  243. X    {
  244. X        outfab->fab$b_rfm = FAB$C_VAR;    /* variable length records */
  245. X        outfab->fab$b_rat = FAB$M_CR;    /* carriage-return carriage ctrl */
  246. X    }
  247. X    else
  248. X    {
  249. X        outfab->fab$b_rfm = FAB$C_STMLF;    /* stream-LF record format */
  250. X        outfab->fab$b_rat = FAB$M_CR;    /* carriage-return carriage ctrl */
  251. X    }
  252. X    }
  253. X
  254. X    if (!cflag)
  255. X    outfab->fab$l_fna = filename;
  256. X    else
  257. X    outfab->fab$l_fna = "sys$output:";
  258. X
  259. X    outfab->fab$b_fns = strlen(outfab->fab$l_fna);
  260. X
  261. X    if ((!attr_given) || xabdat == 0 || xabrdt == 0)    /* Use date/time info
  262. X                             *  from zipfile if
  263. X                             *  no attributes given
  264. X                             */
  265. X    {
  266. X    static char *month[] =
  267. X        {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  268. X         "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
  269. X
  270. X    /*  fixed-length string descriptor: */
  271. X    struct dsc$descriptor stupid =
  272. X        {23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
  273. X
  274. X    yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
  275. X    mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
  276. X    dy = (lrec.last_mod_file_date & 0x1f);
  277. X    hh = (lrec.last_mod_file_time >> 11) & 0x1f;
  278. X    mm = (lrec.last_mod_file_time >> 5) & 0x3f;
  279. X    ss = (lrec.last_mod_file_time & 0x1f) * 2;
  280. X
  281. X    dattim = cc$rms_xabdat;    /* fill XABs with default values */
  282. X    rdt = cc$rms_xabrdt;
  283. X    sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
  284. X        hh, mm, ss);
  285. X    sys$bintim(&stupid, &dattim.xab$q_cdt);
  286. X    memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));
  287. X
  288. X    if ((!attr_given) || xabdat == 0L)
  289. X    {
  290. X        dattim.xab$l_nxt = outfab->fab$l_xab;
  291. X        outfab->fab$l_xab = &dattim;
  292. X    }
  293. X    }
  294. X
  295. X    outfab->fab$w_ifi = 0;    /* Clear IFI. It may be nonzero after ZIP */
  296. X
  297. X    ierr = sys$create(outfab);
  298. X    if (ierr == RMS$_FEX)
  299. X    ierr = replace();
  300. X
  301. X    if (ierr == 0)        /* Canceled */
  302. X    return free_up(), 1;
  303. X
  304. X    if (ERR(ierr))
  305. X    {
  306. X    char buf[256];
  307. X
  308. X    sprintf(buf, "[ Cannot create output file %s ]\n", filename);
  309. X    message(buf, ierr);
  310. X    message("", outfab->fab$l_stv);
  311. X    free_up();
  312. X    return (1);
  313. X    }
  314. X
  315. X    if (!text_file && !cflag)    /* Do not reopen text files and stdout
  316. X                *  Just open them in right mode         */
  317. X    {
  318. X    /*
  319. X    *       Reopen file for Block I/O with no XABs.
  320. X    */
  321. X    if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
  322. X    {
  323. X#ifdef DEBUG
  324. X        message("[ create_output_file: sys$close failed ]\n", ierr);
  325. X        message("", outfab->fab$l_stv);
  326. X#endif
  327. X        fprintf(stderr, "Can't create output file:  %s\n", filename);
  328. X        free_up();
  329. X        return (1);
  330. X    }
  331. X
  332. X
  333. X    outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT;    /* Get ready for block
  334. X                             * output */
  335. X    outfab->fab$l_xab = 0L;    /* Unlink all XABs */
  336. X
  337. X    if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
  338. X    {
  339. X        char buf[256];
  340. X
  341. X        sprintf(buf, "[ Cannot open output file %s ]\n", filename);
  342. X        message(buf, ierr);
  343. X        message("", outfab->fab$l_stv);
  344. X        free_up();
  345. X        return (1);
  346. X    }
  347. X    }
  348. X
  349. X    outrab = &rab;
  350. X    rab.rab$l_fab = outfab;
  351. X    if (!text_file) rab.rab$l_rop |= RAB$M_BIO;
  352. X    if (!text_file) rab.rab$l_rop |= RAB$M_ASY;
  353. X    rab.rab$b_rac = RAB$C_SEQ;
  354. X
  355. X    if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
  356. X    {
  357. X#ifdef DEBUG
  358. X    message("create_output_file: sys$connect failed.\n", ierr);
  359. X    message("", outfab->fab$l_stv);
  360. X#endif
  361. X    fprintf(stderr, "Can't create output file:  %s\n", filename);
  362. X    free_up();
  363. X    return (1);
  364. X    }
  365. X
  366. X    locptr = &locbuf[0];
  367. X    loccnt = 0;
  368. X
  369. X    b1.buf = &buf1[0];
  370. X    b1.bufcnt = 0;
  371. X    b1.next = &b2;
  372. X    b2.buf = &buf2[0];
  373. X    b2.bufcnt = 0;
  374. X    b2.next = &b1;
  375. X    curbuf = &b1;
  376. X
  377. X    return (0);
  378. X}
  379. X
  380. Xstatic int replace()
  381. X{                /*
  382. X                *    File exists. Inquire user about futher action.
  383. X                */
  384. X    char answ[10];
  385. X    struct NAM nam;
  386. X    int ierr;
  387. X
  388. X    if (query == 0)
  389. X    {
  390. X    do
  391. X    {
  392. X        fprintf(stderr,
  393. X            "Replace %s : [o]verwrite, new [v]ersion or [c]ancel (O,V,C - all) ? ",
  394. X            filename);
  395. X        fflush(stderr);
  396. X    } while (fgets(answ, 9, stderr) == NULL && !isalpha(answ[0])
  397. X         && tolower(answ[0]) != 'o'
  398. X         && tolower(answ[0]) != 'v'
  399. X         && tolower(answ[0]) != 'c');
  400. X
  401. X    if (isupper(answ[0]))
  402. X        query = answ[0] = tolower(answ[0]);
  403. X    }
  404. X    else
  405. X    answ[0] = query;
  406. X
  407. X    switch (answ[0])
  408. X    {
  409. X    case 'c':
  410. X        ierr = 0;
  411. X        break;
  412. X    case 'v':
  413. X        nam = cc$rms_nam;
  414. X        nam.nam$l_rsa = filename;
  415. X        nam.nam$b_rss = FILNAMSIZ - 1;
  416. X
  417. X        outfab->fab$l_fop |= FAB$M_MXV;
  418. X        outfab->fab$l_nam = &nam;
  419. X
  420. X        ierr = sys$create(outfab);
  421. X        if (!ERR(ierr))
  422. X        {
  423. X        outfab->fab$l_nam = 0L;
  424. X        filename[outfab->fab$b_fns = nam.nam$b_rsl] = 0;
  425. X        }
  426. X        break;
  427. X    case 'o':
  428. X        outfab->fab$l_fop |= FAB$M_SUP;
  429. X        ierr = sys$create(outfab);
  430. X        break;
  431. X    }
  432. X    return ierr;
  433. X}
  434. X
  435. X/*
  436. X*   Extra record format
  437. X*   ===================
  438. X*   signature       (2 bytes)   = 'I','M'
  439. X*   size            (2 bytes)
  440. X*   block signature (4 bytes)
  441. X*   flags           (2 bytes)
  442. X*   uncomprssed size(2 bytes)
  443. X*   reserved        (4 bytes)
  444. X*   data            ((size-12) bytes)
  445. X*   ....
  446. X*/
  447. X
  448. X#define BC_MASK     07    /* 3 bits for compression type */
  449. X#define BC_STORED    0    /* Stored */
  450. X#define BC_00        1    /* 0byte -> 0bit compression */
  451. X#define BC_DEFL        2    /* Deflated */
  452. X
  453. Xstruct extra_block
  454. X{
  455. X    UWORD sig;            /* Extra field block header structure */
  456. X    UWORD size;
  457. X    ULONG bid;
  458. X    UWORD flags;
  459. X    UWORD length;
  460. X    ULONG reserved;
  461. X    byte body[1];
  462. X};
  463. X
  464. X/*
  465. X *   Extra field signature and block signatures
  466. X */
  467. X
  468. X#define SIGNATURE "IM"
  469. X#define FABL    (cc$rms_fab.fab$b_bln)
  470. X#define RABL    (cc$rms_rab.rab$b_bln)
  471. X#define XALLL   (cc$rms_xaball.xab$b_bln)
  472. X#define XDATL   (cc$rms_xabdat.xab$b_bln)
  473. X#define XFHCL   (cc$rms_xabfhc.xab$b_bln)
  474. X#define XKEYL   (cc$rms_xabkey.xab$b_bln)
  475. X#define XPROL   (cc$rms_xabpro.xab$b_bln)
  476. X#define XRDTL   (cc$rms_xabrdt.xab$b_bln)
  477. X#define XSUML   (cc$rms_xabsum.xab$b_bln)
  478. X#define EXTBSL  4        /* Block signature length   */
  479. X#define RESL    8        /* Rserved 8 bytes  */
  480. X#define EXTHL   (4+EXTBSL)
  481. X#define FABSIG  "VFAB"
  482. X#define XALLSIG "VALL"
  483. X#define XFHCSIG "VFHC"
  484. X#define XDATSIG "VDAT"
  485. X#define XRDTSIG "VRDT"
  486. X#define XPROSIG "VPRO"
  487. X#define XKEYSIG "VKEY"
  488. X#define XNAMSIG "VNAM"
  489. X#define VERSIG  "VMSV"
  490. X
  491. X
  492. X
  493. X#define W(p)    (*(unsigned short*)(p))
  494. X#define L(p)    (*(unsigned long*)(p))
  495. X#define EQL_L(a,b)      ( L(a) == L(b) )
  496. X#define EQL_W(a,b)      ( W(a) == W(b) )
  497. X
  498. X/****************************************************************
  499. X * Function find_vms_attrs scans ZIP entry extra field if any   *
  500. X * and looks for VMS attribute records. Returns 0 if either no  *
  501. X * attributes found or no fab given.                            *
  502. X ****************************************************************/
  503. Xint find_vms_attrs()
  504. X{
  505. X    byte *scan = extra_field;
  506. X    struct extra_block *blk;
  507. X    int len;
  508. X
  509. X    outfab = xabfhc = xabdat = xabrdt = xabpro = first_xab = last_xab = 0L;
  510. X
  511. X    if (scan == NULL)
  512. X    return 0;
  513. X    len = lrec.extra_field_length;
  514. X
  515. X#define LINK(p) {    /* Link xaballs and xabkeys into chain */    \
  516. X                if( first_xab == 0L )                   \
  517. X                        first_xab = p;                  \
  518. X                if( last_xab != 0L )                    \
  519. X                        last_xab -> xab$l_nxt = p;      \
  520. X                last_xab = p;                           \
  521. X                p -> xab$l_nxt = 0;                     \
  522. X        }
  523. X    /* End of macro LINK */
  524. X
  525. X    while (len > 0)
  526. X    {
  527. X    blk = (struct block *) scan;
  528. X    if (EQL_W(&blk->sig, SIGNATURE))
  529. X    {
  530. X        byte *block_id;
  531. X
  532. X        block_id = &blk->bid;
  533. X        if (EQL_L(block_id, FABSIG))
  534. X        {
  535. X        outfab = (struct FAB *) extract_block(blk, 0,
  536. X                              &cc$rms_fab, FABL);
  537. X        }
  538. X        else if (EQL_L(block_id, XALLSIG))
  539. X        {
  540. X        xaball = (struct XABALL *) extract_block(blk, 0,
  541. X                             &cc$rms_xaball, XALLL);
  542. X        LINK(xaball);
  543. X        }
  544. X        else if (EQL_L(block_id, XKEYSIG))
  545. X        {
  546. X        xabkey = (struct XABKEY *) extract_block(blk, 0,
  547. X                             &cc$rms_xabkey, XKEYL);
  548. X        LINK(xabkey);
  549. X        }
  550. X        else if (EQL_L(block_id, XFHCSIG))
  551. X        {
  552. X        xabfhc = (struct XABFHC *) extract_block(blk, 0,
  553. X                             &cc$rms_xabfhc, XFHCL);
  554. X        }
  555. X        else if (EQL_L(block_id, XDATSIG))
  556. X        {
  557. X        xabdat = (struct XABDAT *) extract_block(blk, 0,
  558. X                             &cc$rms_xabdat, XDATL);
  559. X        }
  560. X        else if (EQL_L(block_id, XRDTSIG))
  561. X        {
  562. X        xabrdt = (struct XABRDT *) extract_block(blk, 0,
  563. X                             &cc$rms_xabrdt, XRDTL);
  564. X        }
  565. X        else if (EQL_L(block_id, XPROSIG))
  566. X        {
  567. X        xabpro = (struct XABPRO *) extract_block(blk, 0,
  568. X                             &cc$rms_xabpro, XPROL);
  569. X        }
  570. X        else if (EQL_L(block_id, VERSIG))
  571. X        {
  572. X        char verbuf[80];
  573. X        int verlen = 0;
  574. X        byte *vers;
  575. X        char *m;
  576. X
  577. X        get_vms_version(verbuf, 80);
  578. X        vers = extract_block(blk, &verlen, 0, 0);
  579. X        if ((m = strrchr(vers, '-')) != NULL)
  580. X            *m = 0;    /* Cut out release number */
  581. X        if (strcmp(verbuf, vers) && quietflg == 0)
  582. X        {
  583. X            printf("[ Warning: VMS version mismatch.");
  584. X
  585. X            printf("   This version %s --", verbuf);
  586. X            strncpy(verbuf, vers, verlen);
  587. X            verbuf[verlen] = 0;
  588. X            printf(" version made by %s ]\n", verbuf);
  589. X        }
  590. X        free(vers);
  591. X        }
  592. X        else if (quietflg == 0)
  593. X        fprintf(stderr, "[ Warning: Unknown block signature %s ]\n",
  594. X            block_id);
  595. X    }
  596. X    len -= blk->size + 4;
  597. X    scan += blk->size + 4;
  598. X    }
  599. X
  600. X
  601. X    if (outfab != 0)
  602. X    {                /* Do not link XABPRO,XABRDT now. Leave them for sys$close() */
  603. X
  604. X    outfab->fab$l_xab = 0L;
  605. X    if (xabfhc != 0L)
  606. X    {
  607. X        xabfhc->xab$l_nxt = outfab->fab$l_xab;
  608. X        outfab->fab$l_xab = xabfhc;
  609. X    }
  610. X    if (xabdat != 0L)
  611. X    {
  612. X        xabdat->xab$l_nxt = outfab->fab$l_xab;
  613. X        outfab->fab$l_xab = xabdat;
  614. X    }
  615. X    if (first_xab != 0L)    /* Link xaball,xabkey subchain */
  616. X    {
  617. X        last_xab->xab$l_nxt = outfab->fab$l_xab;
  618. X        outfab->fab$l_xab = first_xab;
  619. X    }
  620. X    return 1;
  621. X    }
  622. X    else
  623. X    return 0;
  624. X}
  625. X
  626. Xstatic void free_up()
  627. X{                /*
  628. X                *    Free up all allocated xabs
  629. X                */
  630. X    if (xabdat != 0L) free(xabdat);
  631. X    if (xabpro != 0L) free(xabpro);
  632. X    if (xabrdt != 0L) free(xabrdt);
  633. X    if (xabfhc != 0L) free(xabfhc);
  634. X    while (first_xab != 0L)
  635. X    {
  636. X    struct XAB *x;
  637. X
  638. X    x = first_xab->xab$l_nxt;
  639. X    free(first_xab);
  640. X    first_xab = x;
  641. X    }
  642. X    if (outfab != 0L && outfab != &fileblk)
  643. X    free(outfab);
  644. X}
  645. X
  646. Xstatic int get_vms_version(verbuf, len)
  647. X    char *verbuf;
  648. Xint len;
  649. X{
  650. X    int i = SYI$_VERSION;
  651. X    int verlen = 0;
  652. X    struct dsc$descriptor version;
  653. X    char *m;
  654. X
  655. X    version.dsc$a_pointer = verbuf;
  656. X    version.dsc$w_length = len - 1;
  657. X    version.dsc$b_dtype = DSC$K_DTYPE_B;
  658. X    version.dsc$b_class = DSC$K_CLASS_S;
  659. X
  660. X    if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
  661. X    return 0;
  662. X
  663. X    /* Cut out trailing spaces "V5.4-3   " -> "V5.4-3" */
  664. X    for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)
  665. X    --m;
  666. X    *m = 0;
  667. X
  668. X    /* Cut out release number "V5.4-3" -> "V5.4" */
  669. X    if ((m = strrchr(verbuf, '-')) != NULL)
  670. X    *m = 0;
  671. X    return strlen(verbuf) + 1;    /* Transmit ending 0 too */
  672. X}
  673. X
  674. X/******************************
  675. X *   Function extract_block   *
  676. X ******************************/
  677. X/*
  678. X * Extracts block from p. If resulting length is less then needed, fill
  679. X * extra space with corresponding bytes from 'init'.
  680. X * Currently understands 3 formats of block compression:
  681. X * - Simple storing
  682. X * - Compression of zero bytes to zero bits
  683. X * - Deflation. See memextract() from extract.c
  684. X */
  685. Xstatic byte *extract_block(p, retlen, init, needlen)
  686. X    struct extra_block *p;
  687. Xint *retlen;
  688. Xbyte *init;
  689. Xint needlen;
  690. X{
  691. X    byte *block;        /* Pointer to block allocated */
  692. X    int cmptype;
  693. X    int usiz, csiz, max;
  694. X
  695. X    cmptype = p->flags & BC_MASK;
  696. X    csiz = p->size - EXTBSL - RESL;
  697. X    usiz = (cmptype == BC_STORED ? csiz : p->length);
  698. X
  699. X    if (needlen == 0)
  700. X    needlen = usiz;
  701. X
  702. X    if (retlen)
  703. X    *retlen = usiz;
  704. X
  705. X#ifndef MAX
  706. X#define MAX(a,b)    ( (a) > (b) ? (a) : (b) )
  707. X#endif
  708. X
  709. X    if ((block = (byte *) malloc(MAX(needlen, usiz))) == NULL)
  710. X    return NULL;
  711. X
  712. X    if (init && (usiz < needlen))
  713. X    memcpy(block, init, needlen);
  714. X
  715. X    switch (cmptype)
  716. X    {
  717. X    case BC_STORED:    /* The simplest case */
  718. X        memcpy(block, &(p->body[0]), usiz);
  719. X        break;
  720. X    case BC_00:
  721. X        decompress_bits(block, usiz, &(p->body[0]));
  722. X        break;
  723. X    case BC_DEFL:
  724. X        memextract(block, usiz, &(p->body[0]), csiz);
  725. X        break;
  726. X    default:
  727. X        free(block);
  728. X        block = NULL;
  729. X    }
  730. X    return block;
  731. X}
  732. X
  733. X/*
  734. X *  Simple uncompression routine. The compression uses bit stream.
  735. X *  Compression scheme:
  736. X *
  737. X *  if(byte!=0)
  738. X *      putbit(1),putbyte(byte)
  739. X *  else
  740. X *      putbit(0)
  741. X */
  742. Xstatic void decompress_bits(outptr, needlen, bitptr)
  743. X    byte *bitptr;
  744. X
  745. X/* Pointer into compressed data */
  746. Xbyte *outptr;            /* Pointer into output block */
  747. Xint needlen;            /* Size of uncompressed block */
  748. X{
  749. X    ULONG bitbuf = 0;
  750. X    int bitcnt = 0;
  751. X
  752. X#define _FILL   if(bitcnt+8 <= 32)                      \
  753. X                {       bitbuf |= (*bitptr++) << bitcnt;\
  754. X                        bitcnt += 8;                    \
  755. X                }
  756. X
  757. X    while (needlen--)
  758. X    {
  759. X    if (bitcnt <= 0)
  760. X        _FILL;
  761. X
  762. X    if (bitbuf & 1)
  763. X    {
  764. X        bitbuf >>= 1;
  765. X        if ((bitcnt -= 1) < 8)
  766. X        _FILL;
  767. X        *outptr++ = (byte) bitbuf;
  768. X        bitcnt -= 8;
  769. X        bitbuf >>= 8;
  770. X    }
  771. X    else
  772. X    {
  773. X        *outptr++ = 0;
  774. X        bitcnt -= 1;
  775. X        bitbuf >>= 1;
  776. X    }
  777. X    }
  778. X}
  779. X
  780. X/***************************/
  781. X/*  Function FlushOutput() */
  782. X/***************************/
  783. X
  784. Xint FlushOutput()
  785. X{
  786. X    if (mem_mode)
  787. X    {                /* Hope, mem_mode stays constant during
  788. X                 * extraction */
  789. X    int rc = FlushMemory();    /* For mem_extract() */
  790. X
  791. X    outpos += outcnt;
  792. X    outcnt = 0;
  793. X    outptr = outbuf;
  794. X    return rc;
  795. X    }
  796. X
  797. X    /* return PK-type error code */
  798. X    /* flush contents of output buffer */
  799. X    if (tflag)
  800. X    {                /* Do not output. Update CRC only */
  801. X    UpdateCRC(outbuf, outcnt);
  802. X    outpos += outcnt;
  803. X    outcnt = 0;
  804. X    outptr = outbuf;
  805. X    return 0;
  806. X    }
  807. X    else
  808. X    return text_file ? _flush_records(0) : _flush_blocks(0);
  809. X}
  810. X
  811. Xstatic int _flush_blocks(final_flag)    /* Asynchronous version */
  812. X    int final_flag;
  813. X
  814. X/* 1 if this is the final flushout */
  815. X{
  816. X    int round;
  817. X    int rest;
  818. X    int off = 0;
  819. X    int out_count = outcnt;
  820. X    int status;
  821. X
  822. X    while (out_count > 0)
  823. X    {
  824. X    if (curbuf->bufcnt < BUFS512)
  825. X    {
  826. X        int ncpy;
  827. X
  828. X        ncpy = out_count > (BUFS512 - curbuf->bufcnt) ?
  829. X                BUFS512 - curbuf->bufcnt :
  830. X                out_count;
  831. X        memcpy(curbuf->buf + curbuf->bufcnt, outbuf + off, ncpy);
  832. X        out_count -= ncpy;
  833. X        curbuf->bufcnt += ncpy;
  834. X        off += ncpy;
  835. X    }
  836. X    if (curbuf->bufcnt == BUFS512)
  837. X    {
  838. X        status = WriteBuffer(curbuf->buf, curbuf->bufcnt);
  839. X        if (status)
  840. X        return status;
  841. X        curbuf = curbuf->next;
  842. X        curbuf->bufcnt = 0;
  843. X    }
  844. X    }
  845. X
  846. X    UpdateCRC(outbuf, outcnt);
  847. X    outpos += outcnt;
  848. X    outcnt = 0;
  849. X    outptr = outbuf;
  850. X
  851. X    return (final_flag && (curbuf->bufcnt > 0)) ?
  852. X    WriteBuffer(curbuf->buf, curbuf->bufcnt) :
  853. X    0;
  854. X    /* 0:  no error */
  855. X}
  856. X
  857. X#define RECORD_END(c) ((c) == CR || (c) == LF || (c) == CTRLZ)
  858. X
  859. Xstatic int _flush_records(final_flag)
  860. X    int final_flag;
  861. X
  862. X/* 1 if this is the final flushout */
  863. X{
  864. X    int rest;
  865. X    int end = 0, start = 0;
  866. X    int off = 0;
  867. X
  868. X    if (outcnt == 0 && loccnt == 0)
  869. X    return 0;        /* Nothing to do ... */
  870. X
  871. X    if (loccnt)
  872. X    {
  873. X    for (end = 0; end < outcnt && !RECORD_END(outbuf[end]);)
  874. X        ++end;
  875. X
  876. X    if (end >= outcnt && !final_flag)
  877. X    {
  878. X        if (WriteRecord(locbuf, loccnt))
  879. X        return (50);
  880. X        fprintf(stderr, "[ Warning: Record too long (%d) ]\n",
  881. X            outcnt + loccnt);
  882. X        memcpy(locbuf, outbuf, outcnt);
  883. X        locptr = &locbuf[loccnt = outcnt];
  884. X    }
  885. X    else
  886. X    {
  887. X        memcpy(locptr, outbuf, end);
  888. X        if (WriteRecord(locbuf, loccnt + end))
  889. X        return (50);
  890. X        loccnt = 0;
  891. X        locptr = &locbuf;
  892. X    }
  893. X    start = end + 1;
  894. X
  895. X    if (start < outcnt && outbuf[end] == CR && outbuf[start] == LF)
  896. X        ++start;
  897. X    }
  898. X
  899. X    do
  900. X    {
  901. X    while (start < outcnt && outbuf[start] == CR)    /* Skip CR's at the
  902. X                            *  beginning of rec. */
  903. X        ++start;
  904. X    /* Find record end */
  905. X    for (end = start; end < outcnt && !RECORD_END(outbuf[end]);)
  906. X        ++end;
  907. X
  908. X    if (end < outcnt)
  909. X    {            /* Record end found, write the record */
  910. X        if (WriteRecord(outbuf + start, end - start))
  911. X        return (50);
  912. X        /* Shift to the begining of the next record */
  913. X        start = end + 1;
  914. X    }
  915. X
  916. X    if (start < outcnt && outbuf[end] == CR && outbuf[start] == LF)
  917. X        ++start;
  918. X
  919. X    } while (start < outcnt && end < outcnt);
  920. X
  921. X    rest = outcnt - start;
  922. X
  923. X    if (rest > 0)
  924. X    if (final_flag)
  925. X    {
  926. X        /* This is a final flush. Put out all remaining in
  927. X        *  the buffer                               */
  928. X        if (loccnt && WriteRecord(locbuf, loccnt))
  929. X        return (50);
  930. X    }
  931. X    else
  932. X    {
  933. X        memcpy(locptr, outbuf + start, rest);
  934. X        locptr += rest;
  935. X        loccnt += rest;
  936. X    }
  937. X    UpdateCRC(outbuf, outcnt);
  938. X    outpos += outcnt;
  939. X    outcnt = 0;
  940. X    outptr = outbuf;
  941. X    return (0);            /* 0:  no error */
  942. X}
  943. X
  944. X/***************************/
  945. X/*  Function WriteBuffer() */
  946. X/***************************/
  947. X
  948. Xstatic int WriteBuffer(buf, len)/* return 0 if successful, 1 if not */
  949. X    unsigned char *buf;
  950. Xint len;
  951. X{
  952. X    int status;
  953. X
  954. X    status = sys$wait(outrab);
  955. X#ifdef DEBUG
  956. X    if (ERR(status))
  957. X    {
  958. X    message("[ WriteBuffer: sys$wait failed ]\n", status);
  959. X    message("", outrab->rab$l_stv);
  960. X    }
  961. X#endif
  962. X    outrab->rab$w_rsz = len;
  963. X    outrab->rab$l_rbf = buf;
  964. X
  965. X    if (ERR(status = sys$write(outrab)))
  966. X    {
  967. X    message("[ WriteBuffer: sys$write failed ]\n", status);
  968. X    message("", outrab->rab$l_stv);
  969. X    return 50;
  970. X    }
  971. X    return (0);
  972. X}
  973. X
  974. X/***************************/
  975. X/*  Function WriteRecord() */
  976. X/***************************/
  977. X
  978. Xstatic int WriteRecord(rec, len)/* return 0 if successful, 1 if not */
  979. X    unsigned char *rec;
  980. Xint len;
  981. X{
  982. X    int status;
  983. X
  984. X    sys$wait(outrab);
  985. X#ifdef DEBUG
  986. X    if (ERR(status))
  987. X    {
  988. X    message("[ WriteRecord: sys$wait faled ]\n", status);
  989. X    message("", outrab->rab$l_stv);
  990. X    }
  991. X#endif
  992. X    outrab->rab$w_rsz = len;
  993. X    outrab->rab$l_rbf = rec;
  994. X
  995. X    if (ERR(status = sys$put(outrab)))
  996. X    {
  997. X    message("[ WriteRecord: sys$put failed ]\n", status);
  998. X    message("", outrab->rab$l_stv);
  999. X    return 50;
  1000. X    }
  1001. X    return (0);
  1002. X}
  1003. X
  1004. X/********************************/
  1005. X/*  Function CloseOutputFile()  */
  1006. X/********************************/
  1007. X
  1008. Xint CloseOutputFile()
  1009. X{
  1010. X    int status;
  1011. X
  1012. X    if (text_file) _flush_records(1);
  1013. X    else
  1014. X    _flush_blocks(1);
  1015. X    /* Link XABRDT,XABDAT and optionaly XABPRO */
  1016. X    if (xabrdt != 0L)
  1017. X    {
  1018. X    xabrdt->xab$l_nxt = 0L;
  1019. X    outfab->fab$l_xab = xabrdt;
  1020. X    }
  1021. X    else
  1022. X    {
  1023. X    rdt.xab$l_nxt = 0L;
  1024. X    outfab->fab$l_xab = &rdt;
  1025. X    }
  1026. X    if (xabdat != 0L)
  1027. X    {
  1028. X    xabdat->xab$l_nxt = outfab->fab$l_xab;
  1029. X    outfab->fab$l_xab = xabdat;
  1030. X    }
  1031. X    if (secinf && xabpro != 0L)
  1032. X    {
  1033. X    xabpro->xab$l_nxt = outfab->fab$l_xab;
  1034. X    outfab->fab$l_xab = xabpro;
  1035. X    }
  1036. X
  1037. X    sys$wait(outrab);
  1038. X
  1039. X    status = sys$close(outfab);
  1040. X#ifdef DEBUG
  1041. X    if (ERR(status))
  1042. X    {
  1043. X    message("\r[ Warning: cannot set owner/protection/time attributes ]\n", status);
  1044. X    message("", outfab->fab$l_stv);
  1045. X    }
  1046. X#endif
  1047. X    free_up();
  1048. X}
  1049. X
  1050. X#ifdef DEBUG
  1051. Xdump_rms_block(p)
  1052. X    unsigned char *p;
  1053. X{
  1054. X    unsigned char bid, len;
  1055. X    int err;
  1056. X    char *type;
  1057. X    char buf[132];
  1058. X    int i;
  1059. X
  1060. X    err = 0;
  1061. X    bid = p[0];
  1062. X    len = p[1];
  1063. X    switch (bid)
  1064. X    {
  1065. X    case FAB$C_BID:
  1066. X        type = "FAB";
  1067. X        break;
  1068. X    case XAB$C_ALL:
  1069. X        type = "xabALL";
  1070. X        break;
  1071. X    case XAB$C_KEY:
  1072. X        type = "xabKEY";
  1073. X        break;
  1074. X    case XAB$C_DAT:
  1075. X        type = "xabDAT";
  1076. X        break;
  1077. X    case XAB$C_RDT:
  1078. X        type = "xabRDT";
  1079. X        break;
  1080. X    case XAB$C_FHC:
  1081. X        type = "xabFHC";
  1082. X        break;
  1083. X    case XAB$C_PRO:
  1084. X        type = "xabPRO";
  1085. X        break;
  1086. X    default:
  1087. X        type = "Unknown";
  1088. X        err = 1;
  1089. X        break;
  1090. X    }
  1091. X    printf("Block @%08X of type %s (%d).", p, type, bid);
  1092. X    if (err)
  1093. X    {
  1094. X    printf("\n");
  1095. X    return;
  1096. X    }
  1097. X    printf(" Size = %d\n", len);
  1098. X    printf(" Offset - Hex - Dec\n");
  1099. X    for (i = 0; i < len; i += 8)
  1100. X    {
  1101. X    int j;
  1102. X
  1103. X    printf("%3d - ", i);
  1104. X    for (j = 0; j < 8; j++)
  1105. X        if (i + j < len)
  1106. X        printf("%02X ", p[i + j]);
  1107. X        else
  1108. X        printf("   ");
  1109. X    printf(" - ");
  1110. X    for (j = 0; j < 8; j++)
  1111. X        if (i + j < len)
  1112. X        printf("%03d ", p[i + j]);
  1113. X        else
  1114. X        printf("    ");
  1115. X    printf("\n");
  1116. X    }
  1117. X}
  1118. X
  1119. X#endif                /* DEBUG */
  1120. X
  1121. Xstatic void message(string, status)
  1122. X    int status;
  1123. Xchar *string;
  1124. X{
  1125. X    char msgbuf[256];
  1126. X
  1127. X    $DESCRIPTOR(msgd, msgbuf);
  1128. X    int msglen = 0;
  1129. X
  1130. X    if (ERR(lib$sys_getmsg(&status, &msglen, &msgd, 0, 0)))
  1131. X    fprintf(stderr, "%s[ VMS status = %d ]\n", string, status);
  1132. X    else
  1133. X    {
  1134. X    msgbuf[msglen] = 0;
  1135. X    fprintf(stderr, "%s[ %s ]\n", string, msgbuf);
  1136. X    }
  1137. X}
  1138. X
  1139. X
  1140. X#endif                /* !ZIPINFO */
  1141. X#endif                /* VMS */
  1142. END_OF_FILE
  1143.   if test 25481 -ne `wc -c <'VMS/vms.c'`; then
  1144.     echo shar: \"'VMS/vms.c'\" unpacked with wrong size!
  1145.   fi
  1146.   # end of 'VMS/vms.c'
  1147. fi
  1148. if test -f 'zipinfo.c.B' -a "${1}" != "-c" ; then 
  1149.   echo shar: Will not clobber existing file \"'zipinfo.c.B'\"
  1150. else
  1151.   echo shar: Extracting \"'zipinfo.c.B'\" \(29824 characters\)
  1152.   sed "s/^X//" >'zipinfo.c.B' <<'END_OF_FILE'
  1153. X
  1154. X/************************************/
  1155. X/*  Function process_central_dir()  */
  1156. X/************************************/
  1157. X
  1158. Xint process_central_dir()   /* return PK-type error code */
  1159. X{
  1160. X    char    **fnamev;
  1161. X    int     do_this_file=FALSE, none_found=TRUE, error, error_in_archive=0;
  1162. X    UWORD   j, members=0;
  1163. X    ULONG   c=0L, uc=0L;
  1164. X
  1165. X
  1166. X/*---------------------------------------------------------------------------
  1167. X    Set file pointer to start of central directory, then loop through cen-
  1168. X    tral directory entries.  Check that directory-entry signature bytes are
  1169. X    actually there (just a precaution), then process the entry.  We know
  1170. X    the entire central directory is on this disk:  we wouldn't have any of
  1171. X    this information unless the end-of-central-directory record was on this
  1172. X    disk, and we wouldn't have gotten to this routine unless this is also
  1173. X    the disk on which the central directory starts.  In practice, this had
  1174. X    better be the *only* disk in the archive, but maybe someday we'll add
  1175. X    multi-disk support.
  1176. X  ---------------------------------------------------------------------------*/
  1177. X
  1178. X    pInfo->lcflag = 0;   /* match(), do_string():  never TRUE in zipinfo */
  1179. X
  1180. X    for (j = 0;  j < ecrec.total_entries_central_dir;  ++j) {
  1181. X        if (readbuf(sig, 4) <= 0)
  1182. X            return 51;          /* 51:  unexpected EOF */
  1183. X        if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
  1184. X            fprintf(stderr, CentSigMsg, j);  /* sig not found */
  1185. X            return 3;           /* 3:  error in zipfile */
  1186. X        }
  1187. X        if ((error = process_cdir_file_hdr()) != 0)
  1188. X            return error;       /* only 51 (EOF) defined */
  1189. X        if ((error = do_string(crec.filename_length, FILENAME)) != 0) {
  1190. X          error_in_archive = error;   /* might be warning */
  1191. X          if (error > 1)        /* fatal */
  1192. X              return error;
  1193. X        }
  1194. X
  1195. X        if (!process_all_files) {   /* check if specified on command line */
  1196. X            do_this_file = FALSE;
  1197. X            fnamev = fnv;       /* don't destroy permanent filename ptr */
  1198. X            for (--fnamev;  *++fnamev; )
  1199. X                if (match(filename, *fnamev)) {
  1200. X                    do_this_file = TRUE;
  1201. X                    none_found = FALSE;
  1202. X                    break;      /* found match, so stop looping */
  1203. X                }
  1204. X        }
  1205. X
  1206. X    /*-----------------------------------------------------------------------
  1207. X        If current file was specified on command line, or if no names were
  1208. X        specified, do the listing for this file.  Otherwise, get rid of the
  1209. X        file comment and go back for the next file.
  1210. X      -----------------------------------------------------------------------*/
  1211. X
  1212. X        if (process_all_files || do_this_file) {
  1213. X            switch (lflag) {
  1214. X                case 1:
  1215. X                    printf("%s\n", filename);
  1216. X                    SKIP_(crec.extra_field_length)
  1217. X                    SKIP_(crec.file_comment_length)
  1218. X                    break;
  1219. X
  1220. X                case 3:
  1221. X                case 4:
  1222. X                case 5:
  1223. X                    if ((error = short_info()) != 0) {
  1224. X                        error_in_archive = error;   /* might be warning */
  1225. X                        if (error > 1)              /* fatal */
  1226. X                            return error;
  1227. X                    }
  1228. X                    break;
  1229. X
  1230. X                case 10:
  1231. X#ifdef VMS   /* GRR: FIX THIS (no pipes:  add cbreak-style "more" function) */
  1232. X                    printf("\nCentral directory entry #%d:\n", j);
  1233. X#else /* !VMS */
  1234. X                    /* formfeed/CR for piping to "more": */
  1235. X                    printf("%s\nCentral directory entry #%d:\n", "\014", j);
  1236. X#endif /* ?VMS */
  1237. X                    printf("---------------------------\n\n");
  1238. X
  1239. X                    if ((error = long_info()) != 0) {
  1240. X                      error_in_archive = error;   /* might be warning */
  1241. X                      if (error > 1)              /* fatal */
  1242. X                          return error;
  1243. X                    }
  1244. X                    break;
  1245. X
  1246. X                default:
  1247. X                    SKIP_(crec.extra_field_length)
  1248. X                    SKIP_(crec.file_comment_length)
  1249. X                    break;
  1250. X
  1251. X            } /* end switch (lflag) */
  1252. X
  1253. X            uc += crec.uncompressed_size;
  1254. X            c += crec.compressed_size;
  1255. X            if (crec.general_purpose_bit_flag & 1)
  1256. X                c -= 12;    /* if encrypted, don't count encryption header */
  1257. X            ++members;
  1258. X
  1259. X        } else {   /* not listing */
  1260. X            SKIP_(crec.extra_field_length)
  1261. X            SKIP_(crec.file_comment_length)
  1262. X
  1263. X        } /* end if (list member?) */
  1264. X
  1265. X    } /* end for-loop (j: member files) */
  1266. X
  1267. X/*---------------------------------------------------------------------------
  1268. X    Double check that we're back at the end-of-central-directory record.
  1269. X  ---------------------------------------------------------------------------*/
  1270. X
  1271. X    readbuf(sig, 4);
  1272. X    if (strncmp(sig, end_central_sig, 4)) {     /* just to make sure again */
  1273. X        fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig */
  1274. X        error_in_archive = 1;        /* 1:  warning error */
  1275. X    }
  1276. X
  1277. X/*---------------------------------------------------------------------------
  1278. X    Check that we actually found requested files; if so, print totals.
  1279. X  ---------------------------------------------------------------------------*/
  1280. X
  1281. X    if (none_found && !process_all_files) {
  1282. X        fnamev = fnv;       /* don't destroy permanent filename ptr */
  1283. X        for (--fnamev;  *++fnamev; )
  1284. X            printf("zipinfo:  %s not found in %s\n", *fnamev, zipfn);
  1285. X    } else if (tflag)
  1286. X        printf(
  1287. X          "%d file%s, %lu bytes uncompressed, %lu bytes compressed:  %d%%\n",
  1288. X          members, (members==1)? "":"s", uc, c, (uc==0)? 0 : ((uc>2000000L)?
  1289. X          ((int)((uc-c)/(uc/1000L))+5)/10 : ((int)((1000L*(uc-c))/uc)+5)/10) );
  1290. X
  1291. X    return error_in_archive;
  1292. X
  1293. X} /* end function process_central_dir() */
  1294. X
  1295. X
  1296. X
  1297. X
  1298. X
  1299. X/**************************************/
  1300. X/*  Function process_cdir_file_hdr()  */
  1301. X/**************************************/
  1302. X
  1303. Xint process_cdir_file_hdr()   /* return PK-type error code */
  1304. X{
  1305. X    cdir_byte_hdr   byterec;
  1306. X
  1307. X
  1308. X/*---------------------------------------------------------------------------
  1309. X    Read the next central directory entry and do any necessary machine-type
  1310. X    conversions (byte ordering, structure padding compensation--do so by
  1311. X    copying the data from the array into which it was read (byterec) to the
  1312. X    usable struct (crec)).
  1313. X  ---------------------------------------------------------------------------*/
  1314. X
  1315. X    if (readbuf((char *) byterec, CREC_SIZE) <= 0)
  1316. X        return 51;   /* 51:  unexpected EOF */
  1317. X
  1318. X    crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
  1319. X    crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
  1320. X    crec.version_needed_to_extract[0] = byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
  1321. X    crec.version_needed_to_extract[1] = byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
  1322. X
  1323. X    crec.general_purpose_bit_flag =
  1324. X        makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
  1325. X    crec.compression_method =
  1326. X        makeword(&byterec[C_COMPRESSION_METHOD]);
  1327. X    crec.last_mod_file_time =
  1328. X        makeword(&byterec[C_LAST_MOD_FILE_TIME]);
  1329. X    crec.last_mod_file_date =
  1330. X        makeword(&byterec[C_LAST_MOD_FILE_DATE]);
  1331. X    crec.crc32 =
  1332. X        makelong(&byterec[C_CRC32]);
  1333. X    crec.compressed_size =
  1334. X        makelong(&byterec[C_COMPRESSED_SIZE]);
  1335. X    crec.uncompressed_size =
  1336. X        makelong(&byterec[C_UNCOMPRESSED_SIZE]);
  1337. X    crec.filename_length =
  1338. X        makeword(&byterec[C_FILENAME_LENGTH]);
  1339. X    crec.extra_field_length =
  1340. X        makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
  1341. X    crec.file_comment_length =
  1342. X        makeword(&byterec[C_FILE_COMMENT_LENGTH]);
  1343. X    crec.disk_number_start =
  1344. X        makeword(&byterec[C_DISK_NUMBER_START]);
  1345. X    crec.internal_file_attributes =
  1346. X        makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
  1347. X    crec.external_file_attributes =
  1348. X        makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]); /* LONG, not word! */
  1349. X    crec.relative_offset_local_header =
  1350. X        makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
  1351. X
  1352. X    return 0;
  1353. X
  1354. X} /* end function process_cdir_file_hdr() */
  1355. X
  1356. X
  1357. X
  1358. X
  1359. X/**************************/
  1360. X/*  Function long_info()  */
  1361. X/**************************/
  1362. X
  1363. Xint long_info()   /* return PK-type error code */
  1364. X{
  1365. X    int           error, error_in_archive=0;
  1366. X    UWORD         hostver, extver, xattr;
  1367. X    char          workspace[12], attribs[22];
  1368. X    static char   unkn[16];
  1369. X    static char   *os[NUM_HOSTS+1] = {"MS-DOS or OS/2 FAT", "Amiga", "VAX VMS",
  1370. X                      "Unix", "VM/CMS", "Atari ST", "OS/2 HPFS", "Macintosh",
  1371. X                      "Z-System", "CP/M", "unknown" };
  1372. X    static char   *method[NUM_METHODS+1] = {"none (stored)", "shrunk",
  1373. X                      "reduced (factor 1)", "reduced (factor 2)",
  1374. X                      "reduced (factor 3)", "reduced (factor 4)",
  1375. X                      "imploded", "tokenized", "deflated", unkn};
  1376. X    static char   *dtype[4] = {"normal", "maximum", "fastest", "undefined"};
  1377. X
  1378. X
  1379. X/*---------------------------------------------------------------------------
  1380. X    Print out various interesting things about the compressed file.
  1381. X  ---------------------------------------------------------------------------*/
  1382. X
  1383. X    hostnum = MIN(crec.version_made_by[1], NUM_HOSTS);
  1384. X    hostver = crec.version_made_by[0];
  1385. X    extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS);
  1386. X    extver = crec.version_needed_to_extract[0];
  1387. X    methnum = MIN(crec.compression_method, NUM_METHODS);
  1388. X    if (methnum == NUM_METHODS)
  1389. X        sprintf(unkn, "unknown (%d)", crec.compression_method);
  1390. X
  1391. X    printf("  %s\n", filename);
  1392. X
  1393. X    printf("\n  host operating system (created on):               %s\n",
  1394. X      os[hostnum]);
  1395. X    printf("  version of encoding software:                     %d.%d\n",
  1396. X      hostver/10, hostver%10);
  1397. X    printf("  minimum operating system compatibility required:  %s\n",
  1398. X      os[extnum]);
  1399. X    printf("  minimum software version required to extract:     %d.%d\n",
  1400. X      extver/10, extver%10);
  1401. X    printf("  compression method:                               %s\n",
  1402. X      method[methnum]);
  1403. X    if (methnum == IMPLODED) {
  1404. X        printf("  size of sliding dictionary (implosion):           %cK\n",
  1405. X          (crec.general_purpose_bit_flag & 2)? '8' : '4');
  1406. X        printf("  number of Shannon-Fano trees (implosion):         %c\n",
  1407. X          (crec.general_purpose_bit_flag & 4)? '3' : '2');
  1408. X    } else if (methnum == DEFLATED) {
  1409. X        UWORD  dnum=(crec.general_purpose_bit_flag>>1) & 3;
  1410. X        printf("  compression sub-type (deflation):                 %s\n",
  1411. X          dtype[dnum]);
  1412. X    }
  1413. X    printf("  file security status:                             %sencrypted\n",
  1414. X      (crec.general_purpose_bit_flag & 1)? "" : "not ");
  1415. X    printf("  extended local header:                            %s\n",
  1416. X      (crec.general_purpose_bit_flag & 8)? "yes" : "no");
  1417. X    /* print upper 3 bits for amusement? */
  1418. X    printf("  file last modified on:                            %s\n",
  1419. X      zipinfo_time(&crec.last_mod_file_date, &crec.last_mod_file_time));
  1420. X    printf("  32-bit CRC value (hex):                           %.8lx\n",
  1421. X      crec.crc32);
  1422. X    printf("  compressed size:                                  %lu bytes\n",
  1423. X      crec.compressed_size);
  1424. X    printf("  uncompressed size:                                %lu bytes\n",
  1425. X      crec.uncompressed_size);
  1426. X    printf("  length of filename:                               %u characters\n",
  1427. X      crec.filename_length);
  1428. X    printf("  length of extra field:                            %u bytes\n",
  1429. X      crec.extra_field_length);
  1430. X    printf("  length of file comment:                           %u characters\n",
  1431. X      crec.file_comment_length);
  1432. X    printf("  disk number on which file begins:                 disk %u\n",
  1433. X      crec.disk_number_start);
  1434. X    printf("  apparent file type:                               %s\n",
  1435. X      (crec.internal_file_attributes & 1)? "text" : "binary");
  1436. X/*
  1437. X    printf("  external file attributes (hex):                   %.8lx\n",
  1438. X      crec.external_file_attributes);
  1439. X */
  1440. X    xattr = (UWORD) ((crec.external_file_attributes >> 16) & 0xFFFF);
  1441. X    if (hostnum == VMS_) {
  1442. X        char   *p=attribs, *q=attribs+1;
  1443. X        int    i, j, k;
  1444. X
  1445. X        for (k = 0;  k < 12;  ++k)
  1446. X            workspace[k] = 0;
  1447. X        if (xattr & S_IRUSR)
  1448. X            workspace[0] = 'R';
  1449. X        if (xattr & S_IWUSR) {
  1450. X            workspace[1] = 'W';
  1451. X            workspace[3] = 'D';
  1452. X        }
  1453. X        if (xattr & S_IXUSR)
  1454. X            workspace[2] = 'E';
  1455. X        if (xattr & S_IRGRP)
  1456. X            workspace[4] = 'R';
  1457. X        if (xattr & S_IWGRP) {
  1458. X            workspace[5] = 'W';
  1459. X            workspace[7] = 'D';
  1460. X        }
  1461. X        if (xattr & S_IXGRP)
  1462. X            workspace[6] = 'E';
  1463. X        if (xattr & S_IROTH)
  1464. X            workspace[8] = 'R';
  1465. X        if (xattr & S_IWOTH) {
  1466. X            workspace[9] = 'W';
  1467. X            workspace[11] = 'D';
  1468. X        }
  1469. X        if (xattr & S_IXOTH)
  1470. X            workspace[10] = 'E';
  1471. X
  1472. X        *p++ = '(';
  1473. X        for (k = j = 0;  j < 3;  ++j) {    /* loop over groups of permissions */
  1474. X            for (i = 0;  i < 4;  ++i, ++k)  /* loop over perms within a group */
  1475. X                if (workspace[k])
  1476. X                    *p++ = workspace[k];
  1477. X            *p++ = ',';                      /* group separator */
  1478. X            if (j == 0)
  1479. X                while ((*p++ = *q++) != ','); /* system, owner perms are same */
  1480. X        }
  1481. X        *p-- = 0;
  1482. X        *p = ')';   /* overwrite last comma */
  1483. X        printf("  VMS file attributes (%06o octal):               %s\n",
  1484. X          xattr, attribs);
  1485. X
  1486. X    } else if ((hostnum != DOS_OS2_FAT_) && (hostnum != OS2_HPFS_)) {
  1487. X        /* assume Unix-like */
  1488. X        switch (xattr & S_IFMT) {
  1489. X            case S_IFREG:   attribs[0] = '-';  break;
  1490. X            case S_IFLNK:   attribs[0] = 'l';  break;
  1491. X            case S_IFBLK:   attribs[0] = 'b';  break;
  1492. X            case S_IFCHR:   attribs[0] = 'c';  break;
  1493. X            case S_IFIFO:   attribs[0] = 'p';  break;
  1494. X            case S_IFSOCK:  attribs[0] = 's';  break;
  1495. X            case S_IFDIR:   attribs[0] = 'd';  break;
  1496. X            default:        attribs[0] = '?';  break;
  1497. X        }
  1498. X        if (xattr & S_IRUSR)        /* no read-permission: user */
  1499. X            attribs[1] = 'r';
  1500. X        else
  1501. X            attribs[1] = '-';
  1502. X        if (xattr & S_IWUSR)        /* no write-permission: user */
  1503. X            attribs[2] = 'w';
  1504. X        else
  1505. X            attribs[2] = '-';
  1506. X        if (xattr & S_IXUSR)        /* no execute-permission: user */
  1507. X            if (xattr & S_ISUID)
  1508. X                attribs[3] = 's';
  1509. X            else
  1510. X                attribs[3] = 'x';
  1511. X        else
  1512. X            if (xattr & S_ISUID)
  1513. X                attribs[3] = 'S';   /* undefined state */
  1514. X            else
  1515. X                attribs[3] = '-';
  1516. X        if (xattr & S_IRGRP)        /* no read-permission: group */
  1517. X            attribs[4] = 'r';
  1518. X        else
  1519. X            attribs[4] = '-';
  1520. X        if (xattr & S_IWGRP)        /* no write-permission: group */
  1521. X            attribs[5] = 'w';
  1522. X        else
  1523. X            attribs[5] = '-';
  1524. X        if (xattr & S_IXGRP)        /* no execute-permission: group */
  1525. X            if (xattr & S_ISGID)
  1526. X                attribs[6] = 's';
  1527. X            else
  1528. X                attribs[6] = 'x';
  1529. X        else
  1530. X            if (xattr & S_ISGID)    /* or could use S_ENFMT (same) */
  1531. X                attribs[6] = 'l';
  1532. X            else
  1533. X                attribs[6] = '-';
  1534. X        if (xattr & S_IROTH)        /* no read-permission: other */
  1535. X            attribs[7] = 'r';
  1536. X        else
  1537. X            attribs[7] = '-';
  1538. X        if (xattr & S_IWOTH)        /* no write-permission: other */
  1539. X            attribs[8] = 'w';
  1540. X        else
  1541. X            attribs[8] = '-';
  1542. X        if (xattr & S_IXOTH)        /* no execute-permission: other */
  1543. X            if (xattr & S_ISVTX)    /* "sticky bit" */
  1544. X                attribs[9] = 't';
  1545. X            else
  1546. X                attribs[9] = 'x';
  1547. X        else
  1548. X            if (xattr & S_ISVTX)
  1549. X                attribs[9] = 'T';   /* undefined state */
  1550. X            else
  1551. X                attribs[9] = '-';
  1552. X        attribs[10] = 0;
  1553. X        printf("  Unix file attributes (%06o octal):              %s\n",
  1554. X          xattr, attribs);
  1555. X
  1556. X    } /* endif (hostnum: external attributes format) */
  1557. X
  1558. X    if ((xattr=(UWORD)(crec.external_file_attributes & 0xFF)) == 0)
  1559. X        printf("  MS-DOS file attributes (%02X hex):                  none\n",
  1560. X          xattr);
  1561. X    else if (xattr == 1)
  1562. X        printf(
  1563. X          "  MS-DOS file attributes (%02X hex):                  read-only\n",
  1564. X          xattr);
  1565. X    else
  1566. X        printf(
  1567. X         "  MS-DOS file attributes (%02X hex):                  %s%s%s%s%s%s\n",
  1568. X          xattr, (xattr&1)?"rdo ":"", (xattr&2)?"hid ":"", (xattr&4)?"sys ":"",
  1569. X          (xattr&8)?"lab ":"", (xattr&16)?"dir ":"", (xattr&32)?"arc":"");
  1570. X    printf(
  1571. X     "  offset of local header from start of archive:     %lu (%.8lXh) bytes\n",
  1572. X      crec.relative_offset_local_header, crec.relative_offset_local_header);
  1573. X
  1574. X/*---------------------------------------------------------------------------
  1575. X    Skip the extra field, if any, and print the file comment, if any (the
  1576. X    filename has already been printed, above).  That finishes up this file
  1577. X    entry...
  1578. X  ---------------------------------------------------------------------------*/
  1579. X
  1580. X    if (crec.extra_field_length > 0) {
  1581. X/* #ifdef OS2 */
  1582. X#if TRUE
  1583. X        ULONG ea_size;
  1584. X        if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0) {
  1585. X            error_in_archive = error;
  1586. X            if (error > 1)      /* fatal:  can't continue */
  1587. X                return (error);
  1588. X        }
  1589. X        if ((ea_size = SizeOfEAs(extra_field)) != 0)
  1590. X            printf("\n\
  1591. X  This file has %lu bytes of OS/2 EA's in the local extra field.\n\
  1592. X  (May not match OS/2 \"dir\" amount due to storage method.)\n\n",
  1593. X              ea_size);
  1594. X        else
  1595. X            printf("\n  There is an unknown extra field (skipping).\n");
  1596. X#else
  1597. X        printf("\n  There is an extra field (skipping).\n");
  1598. X        SKIP_(crec.extra_field_length)
  1599. X#endif
  1600. X    } else
  1601. X        printf("\n");
  1602. X
  1603. X    if (!crec.file_comment_length)
  1604. X        printf("  There is no file comment.\n");
  1605. X    else {
  1606. X        printf("\
  1607. X------------------------- file comment begins ----------------------------\n");
  1608. X        if ((error = do_string(crec.file_comment_length, DISPLAY)) != 0) {
  1609. X          error_in_archive = error;   /* might be warning */
  1610. X          if (error > 1)      /* fatal */
  1611. X              return error;
  1612. X        }
  1613. X        printf("\n\
  1614. X-------------------------- file comment ends -----------------------------\n");
  1615. X    }
  1616. X
  1617. X    return error_in_archive;
  1618. X
  1619. X} /* end function long_info() */
  1620. X
  1621. X
  1622. X
  1623. X
  1624. X
  1625. X/**************************/
  1626. X/*  Function SizeOfEAs()  */
  1627. X/**************************/
  1628. X
  1629. XULONG SizeOfEAs(extra_field)   /* Author: Kai Uwe Rommel */
  1630. X    void   *extra_field;
  1631. X{
  1632. X    EAHEADER *pEAblock = (PEAHEADER) extra_field;
  1633. X
  1634. X    if ( extra_field != NULL && pEAblock -> nID == EAID )
  1635. X      return pEAblock -> lSize;
  1636. X
  1637. X    return 0L;
  1638. X}
  1639. X
  1640. X
  1641. X
  1642. X
  1643. X
  1644. X/***************************/
  1645. X/*  Function short_info()  */
  1646. X/***************************/
  1647. X
  1648. Xint short_info()   /* return PK-type error code */
  1649. X{
  1650. X    int           k, error, error_in_archive=0;
  1651. X    UWORD         hostver, xattr;
  1652. X    char          workspace[12], attribs[16];
  1653. X    static char   impl[5]="i#:#", defl[5]="def#", unkn[8];
  1654. X    static char   dtype[5]="NXF?";  /* normal, maximum, fastest, undefined */
  1655. X    static char   *os[NUM_HOSTS+1] = {"dos", "ami", "vms", "unx", "cms",
  1656. X                      "atr", "os2", "mac", "zzz", "cpm", "???" };
  1657. X    static char   *method[NUM_METHODS+1] = {"stor", "shrk", "re:1", "re:2",
  1658. X                      "re:3", "re:4", impl, "tokn", defl, unkn};
  1659. X
  1660. X
  1661. X/*---------------------------------------------------------------------------
  1662. X    Print out various interesting things about the compressed file.
  1663. X  ---------------------------------------------------------------------------*/
  1664. X
  1665. X    methnum = MIN(crec.compression_method, NUM_METHODS);
  1666. X    hostnum = MIN(crec.version_made_by[1], NUM_HOSTS);
  1667. X    hostver = crec.version_made_by[0];
  1668. X/*
  1669. X    extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS);
  1670. X    extver = crec.version_needed_to_extract[0];
  1671. X */
  1672. X
  1673. X    if (methnum == IMPLODED) {
  1674. X        impl[1] = (crec.general_purpose_bit_flag & 2)? '8' : '4';
  1675. X        impl[3] = (crec.general_purpose_bit_flag & 4)? '3' : '2';
  1676. X    } else if (methnum == DEFLATED) {
  1677. X        UWORD  dnum=(crec.general_purpose_bit_flag>>1) & 3;
  1678. X        defl[3] = dtype[dnum];
  1679. X    } else if (methnum == NUM_METHODS) {   /* unknown */
  1680. X        sprintf(unkn, "u%03d", crec.compression_method);
  1681. X    }
  1682. X
  1683. X    for (k = 0;  k < 15;  ++k)
  1684. X        attribs[k] = ' ';
  1685. X    attribs[15] = 0;
  1686. X
  1687. X    xattr = (UWORD) ((crec.external_file_attributes >> 16) & 0xFFFF);
  1688. X    switch (hostnum) {
  1689. X      case VMS_:
  1690. X          {   char   *p=attribs;
  1691. X              int    i, j;
  1692. X
  1693. X              for (k = 0;  k < 12;  ++k)
  1694. X                  workspace[k] = 0;
  1695. X              if (xattr & S_IRUSR)
  1696. X                  workspace[0] = 'R';
  1697. X              if (xattr & S_IWUSR) {
  1698. X                  workspace[1] = 'W';
  1699. X                  workspace[3] = 'D';
  1700. X              }
  1701. X              if (xattr & S_IXUSR)
  1702. X                  workspace[2] = 'E';
  1703. X              if (xattr & S_IRGRP)
  1704. X                  workspace[4] = 'R';
  1705. X              if (xattr & S_IWGRP) {
  1706. X                  workspace[5] = 'W';
  1707. X                  workspace[7] = 'D';
  1708. X              }
  1709. X              if (xattr & S_IXGRP)
  1710. X                workspace[6] = 'E';
  1711. X              if (xattr & S_IROTH)
  1712. X                  workspace[8] = 'R';
  1713. X              if (xattr & S_IWOTH) {
  1714. X                  workspace[9] = 'W';
  1715. X                  workspace[11] = 'D';
  1716. X              }
  1717. X              if (xattr & S_IXOTH)
  1718. X                  workspace[10] = 'E';
  1719. X
  1720. X              for (k = j = 0;  j < 3;  ++j) {     /* groups of permissions */
  1721. X                  for (i = 0;  i < 4;  ++i, ++k)  /* perms within a group */
  1722. X                      if (workspace[k])
  1723. X                          *p++ = workspace[k];
  1724. X                  *p++ = ',';                     /* group separator */
  1725. X              }
  1726. X              *--p = ' ';   /* overwrite last comma */
  1727. X              if ((p - attribs) < 12)
  1728. X                  sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
  1729. X          }
  1730. X          break;
  1731. X
  1732. X      case DOS_OS2_FAT_:
  1733. X      case OS2_HPFS_:
  1734. X          xattr = (UWORD) (crec.external_file_attributes & 0xFF);
  1735. X          sprintf(attribs, "%s,%s,%s,%s", (xattr&32)?"arc":"",
  1736. X            (xattr&2)?"hid":"", (xattr&1)?"rdo":"rw", (xattr&4)?"sys":"");
  1737. X          if ((k = strlen(attribs)) < 15)
  1738. X              attribs[k] = ' ';   /* overwrite '\0' */
  1739. X          if (k < 12)
  1740. X              sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
  1741. X          break;
  1742. X
  1743. X      default:   /* assume Unix-like */
  1744. X          switch (xattr & S_IFMT) {
  1745. X              case S_IFREG:   attribs[0] = '-';  break;
  1746. X              case S_IFLNK:   attribs[0] = 'l';  break;
  1747. X              case S_IFBLK:   attribs[0] = 'b';  break;
  1748. X              case S_IFCHR:   attribs[0] = 'c';  break;
  1749. X              case S_IFIFO:   attribs[0] = 'p';  break;
  1750. X              case S_IFSOCK:  attribs[0] = 's';  break;
  1751. X              case S_IFDIR:   attribs[0] = 'd';  break;
  1752. X              default:        attribs[0] = '?';  break;
  1753. X          }
  1754. X          if (xattr & S_IRUSR)        /* no read-permission: user */
  1755. X              attribs[1] = 'r';
  1756. X          else
  1757. X              attribs[1] = '-';
  1758. X          if (xattr & S_IWUSR)        /* no write-permission: user */
  1759. X              attribs[2] = 'w';
  1760. X          else
  1761. X              attribs[2] = '-';
  1762. X          if (xattr & S_IXUSR)        /* no execute-permission: user */
  1763. X              if (xattr & S_ISUID)
  1764. X                  attribs[3] = 's';
  1765. X              else
  1766. X                  attribs[3] = 'x';
  1767. X          else
  1768. X              if (xattr & S_ISUID)
  1769. X                  attribs[3] = 'S';   /* undefined state */
  1770. X              else
  1771. X                  attribs[3] = '-';
  1772. X          if (xattr & S_IRGRP)        /* no read-permission: group */
  1773. X              attribs[4] = 'r';
  1774. X          else
  1775. X              attribs[4] = '-';
  1776. X          if (xattr & S_IWGRP)        /* no write-permission: group */
  1777. X              attribs[5] = 'w';
  1778. X          else
  1779. X              attribs[5] = '-';
  1780. X          if (xattr & S_IXGRP)        /* no execute-permission: group */
  1781. X              if (xattr & S_ISGID)
  1782. X                  attribs[6] = 's';
  1783. X              else
  1784. X                  attribs[6] = 'x';
  1785. X          else
  1786. X              if (xattr & S_ISGID)    /* or could use S_ENFMT (same) */
  1787. X                  attribs[6] = 'l';
  1788. X              else
  1789. X                  attribs[6] = '-';
  1790. X          if (xattr & S_IROTH)        /* no read-permission: other */
  1791. X              attribs[7] = 'r';
  1792. X          else
  1793. X              attribs[7] = '-';
  1794. X          if (xattr & S_IWOTH)        /* no write-permission: other */
  1795. X              attribs[8] = 'w';
  1796. X          else
  1797. X              attribs[8] = '-';
  1798. X          if (xattr & S_IXOTH)        /* no execute-permission: other */
  1799. X              if (xattr & S_ISVTX)    /* "sticky bit" */
  1800. X                  attribs[9] = 't';
  1801. X              else
  1802. X                  attribs[9] = 'x';
  1803. X          else
  1804. X              if (xattr & S_ISVTX)
  1805. X                  attribs[9] = 'T';   /* undefined state */
  1806. X              else
  1807. X                  attribs[9] = '-';
  1808. X          sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
  1809. X          break;
  1810. X
  1811. X    } /* end switch (hostnum: external attributes format) */
  1812. X
  1813. X    printf("%s %s %7lu %c%c", attribs, os[hostnum], crec.uncompressed_size,
  1814. X      (crec.general_purpose_bit_flag & 1)?
  1815. X      ((crec.internal_file_attributes & 1)? 'T' : 'B') :   /* encrypted */
  1816. X      ((crec.internal_file_attributes & 1)? 't' : 'b'),    /* plaintext */
  1817. X      (crec.general_purpose_bit_flag & 8)? (crec.extra_field_length? 'X' : 'l')
  1818. X                                        : (crec.extra_field_length? 'x' : '-'));
  1819. X    if (lflag == 4) {
  1820. X        longint c = (longint) crec.compressed_size;
  1821. X        longint uc = (longint) crec.uncompressed_size;
  1822. X
  1823. X        if (crec.general_purpose_bit_flag & 1)
  1824. X            c -= 12;    /* if encrypted, don't count encryption header */
  1825. X        /* risk signed overflow if blindly multiply: */
  1826. X        printf("%3d%%", (uc==0)? 0 : ((uc>2000000L)?
  1827. X          ((int)((uc-c)/(uc/1000L))+5)/10 : ((int)((1000L*(uc-c))/uc)+5)/10) );
  1828. X    } else if (lflag == 5)
  1829. X        printf(" %7lu", crec.compressed_size);
  1830. X
  1831. X    printf(" %s %s %s\n", method[methnum],
  1832. X      zipinfo_time(&crec.last_mod_file_date, &crec.last_mod_file_time),
  1833. X      filename);
  1834. X
  1835. X/*---------------------------------------------------------------------------
  1836. X    Skip the extra field and/or the file comment, if any (the filename has
  1837. X    already been printed, above).  That finishes up this file entry...
  1838. X  ---------------------------------------------------------------------------*/
  1839. X
  1840. X    SKIP_(crec.extra_field_length)
  1841. X    SKIP_(crec.file_comment_length)
  1842. X
  1843. X    return error_in_archive;
  1844. X
  1845. X} /* end function short_info() */
  1846. X
  1847. X
  1848. X
  1849. X
  1850. X
  1851. X/*****************************/
  1852. X/*  Function zipinfo_time()  */
  1853. X/*****************************/
  1854. X
  1855. Xchar *zipinfo_time(datez, timez)
  1856. X    UWORD   *datez, *timez;
  1857. X{
  1858. X    UWORD         yr, mo, dy, hh, mm, ss;
  1859. X    static char   d_t_str[21];
  1860. X    static char   *month[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1861. X                                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  1862. X
  1863. X
  1864. X
  1865. X/*---------------------------------------------------------------------------
  1866. X    Convert the file-modification date and time info to a string of the form 
  1867. X    "23 Feb 1990 17:15:00" or "23-Feb-91 17:15," depending on value of lflag.
  1868. X  ---------------------------------------------------------------------------*/
  1869. X
  1870. X    yr = ((*datez >> 9) & 0x7f) + 80;     /* dissect date */
  1871. X    mo = ((*datez >> 5) & 0x0f) - 1;
  1872. X    dy = *datez & 0x1f;
  1873. X
  1874. X    hh = (*timez >> 11) & 0x1f;           /* dissect time */
  1875. X    mm = (*timez >> 5) & 0x3f;
  1876. X    ss = (*timez & 0x1f) * 2;
  1877. X
  1878. X    if ((lflag >= 3) && (lflag <= 5))
  1879. X        sprintf(d_t_str, "%2u-%s-%u %02u:%02u", dy, month[mo], yr, hh, mm);
  1880. X    else if (lflag > 9)  /* verbose listing format */
  1881. X        sprintf(d_t_str, "%u %s %u %02u:%02u:%02u", dy, month[mo], yr+1900,
  1882. X          hh, mm, ss);
  1883. X
  1884. X    return d_t_str;
  1885. X
  1886. X} /* end function zipinfo_time() */
  1887. X
  1888. X
  1889. X
  1890. X
  1891. X
  1892. X/********************************/
  1893. X/*  Function open_input_file()  */
  1894. X/********************************/
  1895. X
  1896. Xint open_input_file()   /* return 1 if open failed */
  1897. X{
  1898. X    /*
  1899. X     *  open the zipfile for reading and in BINARY mode to prevent cr/lf
  1900. X     *  translation, which would corrupt the bitstreams
  1901. X     */
  1902. X
  1903. X#ifdef VMS
  1904. X    zipfd = open(zipfn, O_RDONLY, 0, "ctx=stm");
  1905. X#else /* !VMS */
  1906. X#ifdef UNIX
  1907. X    zipfd = open(zipfn, O_RDONLY);
  1908. X#else /* !UNIX */
  1909. X#ifdef MACOS
  1910. X    zipfd = open(zipfn, 0);
  1911. X#else /* !MACOS */
  1912. X    zipfd = open(zipfn, O_RDONLY | O_BINARY);
  1913. X#endif /* ?MACOS */
  1914. X#endif /* ?UNIX */
  1915. X#endif /* ?VMS */
  1916. X    if (zipfd < 1) {
  1917. X        fprintf(stderr, "error:  can't open zipfile [ %s ]\n", zipfn);
  1918. X        return 1;
  1919. X    }
  1920. X    return 0;
  1921. X
  1922. X} /* end function open_input_file() */
  1923. X
  1924. X
  1925. X
  1926. X
  1927. X
  1928. X/************************/
  1929. X/*  Function readbuf()  */
  1930. X/************************/
  1931. X
  1932. Xint readbuf(buf, size)   /* return number of bytes read into buf */
  1933. X    char *buf;
  1934. X    register unsigned size;
  1935. X{
  1936. X    register int count;
  1937. X    int n;
  1938. X
  1939. X    n = size;
  1940. X    while (size) {
  1941. X        if (incnt == 0) {
  1942. X            if ((incnt = read(zipfd, inbuf, INBUFSIZ)) <= 0)
  1943. X                return (n-size);
  1944. X            /* buffer ALWAYS starts on a block boundary:  */
  1945. X            cur_zipfile_bufstart += INBUFSIZ;
  1946. X            inptr = inbuf;
  1947. X        }
  1948. X        count = MIN(size, (unsigned)incnt);
  1949. X        memcpy(buf, inptr, count);
  1950. X        buf += count;
  1951. X        inptr += count;
  1952. X        incnt -= count;
  1953. X        size -= count;
  1954. X    }
  1955. X    return n;
  1956. X
  1957. X} /* end function readbuf() */
  1958. END_OF_FILE
  1959.  if test 29824 -ne `wc -c <'zipinfo.c.B'`; then
  1960.     echo shar: \"'zipinfo.c.B'\" unpacked with wrong size!
  1961.  elif test -f 'zipinfo.c.A'; then
  1962.     echo shar: Combining  \"'zipinfo.c'\" \(59337 characters\)
  1963.     cat 'zipinfo.c.A' 'zipinfo.c.B' > 'zipinfo.c'
  1964.     if test 59337 -ne `wc -c <'zipinfo.c'`; then
  1965.       echo shar: \"'zipinfo.c'\" combined with wrong size!
  1966.     else
  1967.       rm zipinfo.c.A zipinfo.c.B
  1968.     fi
  1969.   fi
  1970.   # end of 'zipinfo.c.B'
  1971. fi
  1972. echo shar: End of archive 6 \(of 14\).
  1973. cp /dev/null ark6isdone
  1974. MISSING=""
  1975. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1976.     if test ! -f ark${I}isdone ; then
  1977.     MISSING="${MISSING} ${I}"
  1978.     fi
  1979. done
  1980. if test "${MISSING}" = "" ; then
  1981.     echo You have unpacked all 14 archives.
  1982.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1983. else
  1984.     echo You still must unpack the following archives:
  1985.     echo "        " ${MISSING}
  1986. fi
  1987. exit 0
  1988. exit 0 # Just in case...
  1989.