home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / unzip50 / part06 < prev    next >
Encoding:
Text File  |  1992-08-22  |  59.2 KB  |  1,983 lines

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