1/*
2  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.
3
4  See the accompanying file LICENSE, version 2000-Apr-09 or later
5  (the contents of which are also included in unzip.h) for terms of use.
6  If, for some reason, all these files are missing, the Info-ZIP license
7  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
8*/
9/*---------------------------------------------------------------------------
10
11  zipinfo.c                                              Greg Roelofs et al.
12
13  This file contains all of the ZipInfo-specific listing routines for UnZip.
14
15  Contains:  zi_opts()
16             zi_end_central()
17             zipinfo()
18             zi_long()
19             zi_short()
20             zi_time()
21
22  ---------------------------------------------------------------------------*/
23
24
25#define UNZIP_INTERNAL
26#include "unzip.h"
27
28
29#ifndef NO_ZIPINFO  /* strings use up too much space in small-memory systems */
30
31/* Define OS-specific attributes for use on ALL platforms--the S_xxxx
32 * versions of these are defined differently (or not defined) by different
33 * compilers and operating systems. */
34
35#define UNX_IFMT       0170000     /* Unix file type mask */
36#define UNX_IFREG      0100000     /* Unix regular file */
37#define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */
38#define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */
39#define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */
40#define UNX_IFDIR      0040000     /* Unix directory */
41#define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */
42#define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */
43#define UNX_ISUID      04000       /* Unix set user id on execution */
44#define UNX_ISGID      02000       /* Unix set group id on execution */
45#define UNX_ISVTX      01000       /* Unix directory permissions control */
46#define UNX_ENFMT      UNX_ISGID   /* Unix record locking enforcement flag */
47#define UNX_IRWXU      00700       /* Unix read, write, execute: owner */
48#define UNX_IRUSR      00400       /* Unix read permission: owner */
49#define UNX_IWUSR      00200       /* Unix write permission: owner */
50#define UNX_IXUSR      00100       /* Unix execute permission: owner */
51#define UNX_IRWXG      00070       /* Unix read, write, execute: group */
52#define UNX_IRGRP      00040       /* Unix read permission: group */
53#define UNX_IWGRP      00020       /* Unix write permission: group */
54#define UNX_IXGRP      00010       /* Unix execute permission: group */
55#define UNX_IRWXO      00007       /* Unix read, write, execute: other */
56#define UNX_IROTH      00004       /* Unix read permission: other */
57#define UNX_IWOTH      00002       /* Unix write permission: other */
58#define UNX_IXOTH      00001       /* Unix execute permission: other */
59
60#define VMS_IRUSR      UNX_IRUSR   /* VMS read/owner */
61#define VMS_IWUSR      UNX_IWUSR   /* VMS write/owner */
62#define VMS_IXUSR      UNX_IXUSR   /* VMS execute/owner */
63#define VMS_IRGRP      UNX_IRGRP   /* VMS read/group */
64#define VMS_IWGRP      UNX_IWGRP   /* VMS write/group */
65#define VMS_IXGRP      UNX_IXGRP   /* VMS execute/group */
66#define VMS_IROTH      UNX_IROTH   /* VMS read/other */
67#define VMS_IWOTH      UNX_IWOTH   /* VMS write/other */
68#define VMS_IXOTH      UNX_IXOTH   /* VMS execute/other */
69
70#define AMI_IFMT       06000       /* Amiga file type mask */
71#define AMI_IFDIR      04000       /* Amiga directory */
72#define AMI_IFREG      02000       /* Amiga regular file */
73#define AMI_IHIDDEN    00200       /* to be supported in AmigaDOS 3.x */
74#define AMI_ISCRIPT    00100       /* executable script (text command file) */
75#define AMI_IPURE      00040       /* allow loading into resident memory */
76#define AMI_IARCHIVE   00020       /* not modified since bit was last set */
77#define AMI_IREAD      00010       /* can be opened for reading */
78#define AMI_IWRITE     00004       /* can be opened for writing */
79#define AMI_IEXECUTE   00002       /* executable image, a loadable runfile */
80#define AMI_IDELETE    00001       /* can be deleted */
81
82#define THS_IFMT    0xF000         /* Theos file type mask */
83#define THS_IFIFO   0x1000         /* pipe */
84#define THS_IFCHR   0x2000         /* char device */
85#define THS_IFSOCK  0x3000         /* socket */
86#define THS_IFDIR   0x4000         /* directory */
87#define THS_IFLIB   0x5000         /* library */
88#define THS_IFBLK   0x6000         /* block device */
89#define THS_IFREG   0x8000         /* regular file */
90#define THS_IFREL   0x9000         /* relative (direct) */
91#define THS_IFKEY   0xA000         /* keyed */
92#define THS_IFIND   0xB000         /* indexed */
93#define THS_IFRND   0xC000         /* ???? */
94#define THS_IFR16   0xD000         /* 16 bit real mode program */
95#define THS_IFP16   0xE000         /* 16 bit protected mode prog */
96#define THS_IFP32   0xF000         /* 32 bit protected mode prog */
97#define THS_IMODF   0x0800         /* modified */
98#define THS_INHID   0x0400         /* not hidden */
99#define THS_IEUSR   0x0200         /* erase permission: owner */
100#define THS_IRUSR   0x0100         /* read permission: owner */
101#define THS_IWUSR   0x0080         /* write permission: owner */
102#define THS_IXUSR   0x0040         /* execute permission: owner */
103#define THS_IROTH   0x0004         /* read permission: other */
104#define THS_IWOTH   0x0002         /* write permission: other */
105#define THS_IXOTH   0x0001         /* execute permission: other */
106
107#ifdef OLD_THEOS_EXTRA
108#  include "theos/oldstat.h"
109#endif
110
111#ifndef NSK_UNSTRUCTURED
112# define NSK_UNSTRUCTURED   0
113#endif
114#ifndef NSK_OBJECTFILECODE
115# define NSK_OBJECTFILECODE 100
116#endif
117#ifndef NSK_EDITFILECODE
118# define NSK_EDITFILECODE   101
119#endif
120
121#define LFLAG  3   /* short "ls -l" type listing */
122
123static int   zi_long   OF((__GPRO__ ulg *pEndprev));
124static int   zi_short  OF((__GPRO));
125static void  zi_showMacTypeCreator
126                       OF((__GPRO__ uch *ebfield));
127static char *zi_time   OF((__GPRO__ ZCONST ulg *datetimez,
128                           ZCONST time_t *modtimez, char *d_t_str));
129
130
131/**********************************************/
132/*  Strings used in zipinfo.c (ZipInfo half)  */
133/**********************************************/
134
135static ZCONST char nullStr[] = "";
136static ZCONST char PlurSufx[] = "s";
137
138static ZCONST char Far LongHeader[] = "Archive:  %s   %ld bytes   %u file%s\n";
139static ZCONST char Far ShortHeader[] = "Archive:  %s   %ld   %u\n";
140static ZCONST char Far EndCentDirRec[] = "\nEnd-of-central-directory record:\n";
141static ZCONST char Far LineSeparators[] = "-------------------------------\n\n";
142static ZCONST char Far ActOffsetCentDir[] = "\
143  Actual offset of end-of-central-dir record:   %9ld (%.8lXh)\n\
144  Expected offset of end-of-central-dir record: %9ld (%.8lXh)\n\
145  (based on the length of the central directory and its expected offset)\n\n";
146static ZCONST char Far SinglePartArchive1[] = "\
147  This zipfile constitutes the sole disk of a single-part archive; its\n\
148  central directory contains %u %s.  The central directory is %lu\n\
149  (%.8lXh) bytes long, and its (expected) offset in bytes from the\n";
150static ZCONST char Far SinglePartArchive2[] = "\
151  beginning of the zipfile is %lu (%.8lXh).\n\n";
152static ZCONST char Far MultiPartArchive1[] = "\
153  This zipfile constitutes disk %u of a multi-part archive.  The central\n\
154  directory starts on disk %u; %u of its entries %s contained within\n";
155static ZCONST char Far MultiPartArchive2[] = "\
156  this zipfile, out of a total of %u %s.  The entire central\n\
157  directory is %lu (%.8lXh) bytes long, and its offset in bytes from\n";
158static ZCONST char Far MultiPartArchive3[] = "\
159  the beginning of the zipfile in which it begins is %lu (%.8lXh).\n\n";
160static ZCONST char Far NoZipfileComment[] = "  There is no zipfile comment.\n";
161static ZCONST char Far ZipfileCommentDesc[] =
162  "  The zipfile comment is %u bytes long and contains the following text:\n\n";
163static ZCONST char Far ZipfileCommBegin[] =
164 "======================== zipfile comment begins ==========================\n";
165static ZCONST char Far ZipfileCommEnd[] =
166 "========================= zipfile comment ends ===========================\n";
167static ZCONST char Far ZipfileCommTrunc2[] =
168  "\n  The zipfile comment is truncated.\n";
169static ZCONST char Far ZipfileCommTruncMsg[] =
170  "\ncaution:  zipfile comment truncated\n";
171
172static ZCONST char Far CentralDirEntry[] =
173  "\nCentral directory entry #%lu:\n---------------------------\n\n";
174static ZCONST char Far ZipfileStats[] =
175  "%lu file%s, %lu bytes uncompressed, %lu bytes compressed:  %s%d.%d%%\n";
176
177/* zi_long() strings */
178static ZCONST char Far OS_FAT[] = "MS-DOS, OS/2 or NT FAT";
179static ZCONST char Far OS_Amiga[] = "Amiga";
180static ZCONST char Far OS_VMS[] = "VMS";
181static ZCONST char Far OS_Unix[] = "Unix";
182static ZCONST char Far OS_VMCMS[] = "VM/CMS";
183static ZCONST char Far OS_AtariST[] = "Atari ST";
184static ZCONST char Far OS_HPFS[] = "OS/2 or NT HPFS";
185static ZCONST char Far OS_Macintosh[] = "Macintosh HFS";
186static ZCONST char Far OS_ZSystem[] = "Z-System";
187static ZCONST char Far OS_CPM[] = "CP/M";
188static ZCONST char Far OS_TOPS20[] = "TOPS-20";
189static ZCONST char Far OS_NTFS[] = "NTFS";
190static ZCONST char Far OS_QDOS[] = "SMS/QDOS";
191static ZCONST char Far OS_Acorn[] = "Acorn RISC OS";
192static ZCONST char Far OS_MVS[] = "MVS";
193static ZCONST char Far OS_VFAT[] = "Win32 VFAT";
194static ZCONST char Far OS_BeOS[] = "BeOS";
195static ZCONST char Far OS_Tandem[] = "Tandem NSK";
196static ZCONST char Far OS_Theos[] = "Theos";
197#ifdef OLD_THEOS_EXTRA
198  static ZCONST char Far OS_TheosOld[] = "Theos (Old)";
199#endif /* OLD_THEOS_EXTRA */
200
201static ZCONST char Far MthdNone[] = "none (stored)";
202static ZCONST char Far MthdShrunk[] = "shrunk";
203static ZCONST char Far MthdRedF1[] = "reduced (factor 1)";
204static ZCONST char Far MthdRedF2[] = "reduced (factor 2)";
205static ZCONST char Far MthdRedF3[] = "reduced (factor 3)";
206static ZCONST char Far MthdRedF4[] = "reduced (factor 4)";
207static ZCONST char Far MthdImplode[] = "imploded";
208static ZCONST char Far MthdToken[] = "tokenized";
209static ZCONST char Far MthdDeflate[] = "deflated";
210static ZCONST char Far MthdDeflat64[] = "deflated (enhanced-64k)";
211static ZCONST char Far MthdDCLImplode[] = "imploded (PK DCL)";
212
213static ZCONST char Far DeflNorm[] = "normal";
214static ZCONST char Far DeflMax[] = "maximum";
215static ZCONST char Far DeflFast[] = "fast";
216static ZCONST char Far DeflSFast[] = "superfast";
217
218static ZCONST char Far ExtraBytesPreceding[] =
219  "  There are an extra %ld bytes preceding this file.\n\n";
220
221static ZCONST char Far UnknownNo[] = "unknown (%d)";
222
223static ZCONST char Far LocalHeaderOffset[] =
224  "\n  offset of local header from start of archive:     %lu (%.8lXh) bytes\n";
225static ZCONST char Far HostOS[] =
226  "  file system or operating system of origin:        %s\n";
227static ZCONST char Far EncodeSWVer[] =
228  "  version of encoding software:                     %u.%u\n";
229static ZCONST char Far MinOSCompReq[] =
230  "  minimum file system compatibility required:       %s\n";
231static ZCONST char Far MinSWVerReq[] =
232  "  minimum software version required to extract:     %u.%u\n";
233static ZCONST char Far CompressMethod[] =
234  "  compression method:                               %s\n";
235static ZCONST char Far SlideWindowSizeImplode[] =
236  "  size of sliding dictionary (implosion):           %cK\n";
237static ZCONST char Far ShannonFanoTrees[] =
238  "  number of Shannon-Fano trees (implosion):         %c\n";
239static ZCONST char Far CompressSubtype[] =
240  "  compression sub-type (deflation):                 %s\n";
241static ZCONST char Far FileSecurity[] =
242  "  file security status:                             %sencrypted\n";
243static ZCONST char Far ExtendedLocalHdr[] =
244  "  extended local header:                            %s\n";
245static ZCONST char Far FileModDate[] =
246  "  file last modified on (DOS date/time):            %s\n";
247#ifdef USE_EF_UT_TIME
248  static ZCONST char Far UT_FileModDate[] =
249    "  file last modified on (UT extra field modtime):   %s %s\n";
250  static ZCONST char Far LocalTime[] = "local";
251#ifndef NO_GMTIME
252  static ZCONST char Far GMTime[] = "UTC";
253#endif
254#endif /* USE_EF_UT_TIME */
255static ZCONST char Far CRC32Value[] =
256  "  32-bit CRC value (hex):                           %.8lx\n";
257static ZCONST char Far CompressedFileSize[] =
258  "  compressed size:                                  %lu bytes\n";
259static ZCONST char Far UncompressedFileSize[] =
260  "  uncompressed size:                                %lu bytes\n";
261static ZCONST char Far FilenameLength[] =
262  "  length of filename:                               %u characters\n";
263static ZCONST char Far ExtraFieldLength[] =
264  "  length of extra field:                            %u bytes\n";
265static ZCONST char Far FileCommentLength[] =
266  "  length of file comment:                           %u characters\n";
267static ZCONST char Far FileDiskNum[] =
268  "  disk number on which file begins:                 disk %u\n";
269static ZCONST char Far ApparentFileType[] =
270  "  apparent file type:                               %s\n";
271static ZCONST char Far VMSFileAttributes[] =
272  "  VMS file attributes (%06o octal):               %s\n";
273static ZCONST char Far AmigaFileAttributes[] =
274  "  Amiga file attributes (%06o octal):             %s\n";
275static ZCONST char Far UnixFileAttributes[] =
276  "  Unix file attributes (%06o octal):              %s\n";
277static ZCONST char Far NonMSDOSFileAttributes[] =
278  "  non-MSDOS external file attributes:               %06lX hex\n";
279static ZCONST char Far MSDOSFileAttributes[] =
280  "  MS-DOS file attributes (%02X hex):                  none\n";
281static ZCONST char Far MSDOSFileAttributesRO[] =
282  "  MS-DOS file attributes (%02X hex):                  read-only\n";
283static ZCONST char Far MSDOSFileAttributesAlpha[] =
284  "  MS-DOS file attributes (%02X hex):                  %s%s%s%s%s%s%s%s\n";
285static ZCONST char Far TheosFileAttributes[] =
286  "  Theos file attributes (%04X hex):                 %s\n";
287
288static ZCONST char Far TheosFTypLib[] = "Library     ";
289static ZCONST char Far TheosFTypDir[] = "Directory   ";
290static ZCONST char Far TheosFTypReg[] = "Sequential  ";
291static ZCONST char Far TheosFTypRel[] = "Direct      ";
292static ZCONST char Far TheosFTypKey[] = "Keyed       ";
293static ZCONST char Far TheosFTypInd[] = "Indexed     ";
294static ZCONST char Far TheosFTypR16[] = " 86 program ";
295static ZCONST char Far TheosFTypP16[] = "286 program ";
296static ZCONST char Far TheosFTypP32[] = "386 program ";
297static ZCONST char Far TheosFTypUkn[] = "???         ";
298
299static ZCONST char Far ExtraFieldTrunc[] = "\n\
300  error: EF data block (type 0x%04x) size %u exceeds remaining extra field\n\
301         space %u; block length has been truncated.\n";
302static ZCONST char Far ExtraFields[] = "\n\
303  The central-directory extra field contains:";
304static ZCONST char Far ExtraFieldType[] = "\n\
305  - A subfield with ID 0x%04x (%s) and %u data bytes";
306static ZCONST char Far efPKSZ64[] = "PKWARE 64-bit sizes";
307static ZCONST char Far efAV[] = "PKWARE AV";
308static ZCONST char Far efOS2[] = "OS/2";
309static ZCONST char Far efPKVMS[] = "PKWARE VMS";
310static ZCONST char Far efPKWin32[] = "PKWARE Win32";
311static ZCONST char Far efPKUnix[] = "PKWARE Unix";
312static ZCONST char Far efIZVMS[] = "Info-ZIP VMS";
313static ZCONST char Far efIZUnix[] = "old Info-ZIP Unix/OS2/NT";
314static ZCONST char Far efIZUnix2[] = "Unix UID/GID";
315static ZCONST char Far efTime[] = "universal time";
316static ZCONST char Far efJLMac[] = "old Info-ZIP Macintosh";
317static ZCONST char Far efMac3[] = "new Info-ZIP Macintosh";
318static ZCONST char Far efZipIt[] = "ZipIt Macintosh";
319static ZCONST char Far efSmartZip[] = "SmartZip Macintosh";
320static ZCONST char Far efZipIt2[] = "ZipIt Macintosh (short)";
321static ZCONST char Far efVMCMS[] = "VM/CMS";
322static ZCONST char Far efMVS[] = "MVS";
323static ZCONST char Far efACL[] = "OS/2 ACL";
324static ZCONST char Far efNTSD[] = "Security Descriptor";
325static ZCONST char Far efBeOS[] = "BeOS";
326static ZCONST char Far efQDOS[] = "SMS/QDOS";
327static ZCONST char Far efAOSVS[] = "AOS/VS";
328static ZCONST char Far efSpark[] = "Acorn SparkFS";
329static ZCONST char Far efMD5[] = "Fred Kantor MD5";
330static ZCONST char Far efASiUnix[] = "ASi Unix";
331static ZCONST char Far efTandem[] = "Tandem NSK";
332static ZCONST char Far efTheos[] = "Theos";
333static ZCONST char Far efUnknown[] = "unknown";
334
335static ZCONST char Far OS2EAs[] = ".\n\
336    The local extra field has %lu bytes of OS/2 extended attributes.\n\
337    (May not match OS/2 \"dir\" amount due to storage method)";
338static ZCONST char Far izVMSdata[] = ".  The extra\n\
339    field is %s and has %u bytes of VMS %s information%s";
340static ZCONST char Far izVMSstored[] = "stored";
341static ZCONST char Far izVMSrleenc[] = "run-length encoded";
342static ZCONST char Far izVMSdeflat[] = "deflated";
343static ZCONST char Far izVMScunknw[] = "compressed(?)";
344static ZCONST char Far *izVMScomp[4] =
345  {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw};
346static ZCONST char Far ACLdata[] = ".\n\
347    The local extra field has %lu bytes of access control list information";
348static ZCONST char Far NTSDData[] = ".\n\
349    The local extra field has %lu bytes of NT security descriptor data";
350static ZCONST char Far UTdata[] = ".\n\
351    The local extra field has UTC/GMT %s time%s";
352static ZCONST char Far UTmodification[] = "modification";
353static ZCONST char Far UTaccess[] = "access";
354static ZCONST char Far UTcreation[] = "creation";
355static ZCONST char Far ZipItFname[] = ".\n\
356    The Mac long filename is %s";
357static ZCONST char Far Mac3data[] = ".\n\
358    The local extra field has %lu bytes of %scompressed Macintosh\n\
359    finder attributes";
360 /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */
361static ZCONST char Far MacOSdata[] = ".\n\
362    The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'";
363static ZCONST char Far MacOSdata1[] = ".\n\
364    The associated file has type code `0x%lx' and creator code `0x%lx'";
365static ZCONST char Far MacOSJLEEflags[] = ".\n    File is marked as %s";
366static ZCONST char Far MacOS_RF[] = "Resource-fork";
367static ZCONST char Far MacOS_DF[] = "Data-fork";
368static ZCONST char Far MacOSMAC3flags[] = ".\n\
369    File is marked as %s, File Dates are in %d Bit";
370static ZCONST char Far BeOSdata[] = ".\n\
371    The local extra field has %lu bytes of %scompressed BeOS file attributes";
372 /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'" */
373static ZCONST char Far QDOSdata[] = ".\n\
374    The QDOS extra field subtype is `%c%c%c%c'";
375static ZCONST char Far AOSVSdata[] = ".\n\
376    The AOS/VS extra field revision is %d.%d";
377static ZCONST char Far TandemUnstr[] = "Unstructured";
378static ZCONST char Far TandemRel[]   = "Relative";
379static ZCONST char Far TandemEntry[] = "Entry Sequenced";
380static ZCONST char Far TandemKey[]   = "Key Sequenced";
381static ZCONST char Far TandemEdit[]  = "Edit";
382static ZCONST char Far TandemObj[]  = "Object";
383static ZCONST char Far *TandemFileformat[6] =
384  {TandemUnstr, TandemRel, TandemEntry, TandemKey, TandemEdit, TandemObj};
385static ZCONST char Far Tandemdata[] = ".\n\
386    The file was originally a Tandem %s file, with file code %u";
387static ZCONST char Far MD5data[] = ".\n\
388    The 128-bit MD5 signature is %s";
389#ifdef CMS_MVS
390   static ZCONST char Far VmMvsExtraField[] = ".\n\
391    The stored file open mode (FLDATA TYPE) is \"%s\"";
392   static ZCONST char Far VmMvsInvalid[] = "[invalid]";
393#endif /* CMS_MVS */
394
395static ZCONST char Far First20[] = ".  The first\n    20 are:  ";
396static ZCONST char Far ColonIndent[] = ":\n   ";
397static ZCONST char Far efFormat[] = " %02x";
398
399static ZCONST char Far lExtraFieldType[] = "\n\
400  There %s a local extra field with ID 0x%04x (%s) and\n\
401  %u data bytes (%s).\n";
402static ZCONST char Far efIZuid[] =
403  "GMT modification/access times and Unix UID/GID";
404static ZCONST char Far efIZnouid[] = "GMT modification/access times only";
405
406
407static ZCONST char Far NoFileComment[] = "\n  There is no file comment.\n";
408static ZCONST char Far FileCommBegin[] = "\n\
409------------------------- file comment begins ----------------------------\n";
410static ZCONST char Far FileCommEnd[] = "\
411-------------------------- file comment ends -----------------------------\n";
412
413/* zi_time() strings */
414static ZCONST char Far BogusFmt[] = "%03d";
415static ZCONST char Far DMYHMTime[] = "%2u-%s-%02u %02u:%02u";
416static ZCONST char Far YMDHMSTime[] = "%u %s %u %02u:%02u:%02u";
417static ZCONST char Far DecimalTime[] = "%04u%02u%02u.%02u%02u%02u";
418#ifdef USE_EF_UT_TIME
419  static ZCONST char Far YMDHMSTimeError[] = "???? ??? ?? ??:??:??";
420#endif
421
422
423
424
425
426#ifndef WINDLL
427
428/************************/
429/*  Function zi_opts()  */
430/************************/
431
432int zi_opts(__G__ pargc, pargv)
433    int *pargc;
434    char ***pargv;
435    __GDEF
436{
437    char   **argv, *s;
438    int    argc, c, error=FALSE, negative=0;
439    int    hflag_slmv=TRUE, hflag_2=FALSE;  /* diff options => diff defaults */
440    int    tflag_slm=TRUE, tflag_2v=FALSE;
441    int    explicit_h=FALSE, explicit_t=FALSE;
442
443
444#ifdef MACOS
445    uO.lflag = LFLAG;         /* reset default on each call */
446#endif
447    G.extract_flag = FALSE;   /* zipinfo does not extract to disk */
448    argc = *pargc;
449    argv = *pargv;
450
451    while (--argc > 0 && (*++argv)[0] == '-') {
452        s = argv[0] + 1;
453        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
454            switch (c) {
455                case '-':
456                    ++negative;
457                    break;
458                case '1':      /* shortest listing:  JUST filenames */
459                    if (negative)
460                        uO.lflag = -2, negative = 0;
461                    else
462                        uO.lflag = 1;
463                    break;
464                case '2':      /* just filenames, plus headers if specified */
465                    if (negative)
466                        uO.lflag = -2, negative = 0;
467                    else
468                        uO.lflag = 2;
469                    break;
470#ifndef CMS_MVS
471                case ('C'):    /* -C:  match filenames case-insensitively */
472                    if (negative)
473                        uO.C_flag = FALSE, negative = 0;
474                    else
475                        uO.C_flag = TRUE;
476                    break;
477#endif /* !CMS_MVS */
478                case 'h':      /* header line */
479                    if (negative)
480                        hflag_2 = hflag_slmv = FALSE, negative = 0;
481                    else {
482                        hflag_2 = hflag_slmv = explicit_h = TRUE;
483                        if (uO.lflag == -1)
484                            uO.lflag = 0;
485                    }
486                    break;
487                case 'l':      /* longer form of "ls -l" type listing */
488                    if (negative)
489                        uO.lflag = -2, negative = 0;
490                    else
491                        uO.lflag = 5;
492                    break;
493                case 'm':      /* medium form of "ls -l" type listing */
494                    if (negative)
495                        uO.lflag = -2, negative = 0;
496                    else
497                        uO.lflag = 4;
498                    break;
499#ifdef MORE
500                case 'M':      /* send output through built-in "more" */
501                    if (negative)
502                        G.M_flag = FALSE, negative = 0;
503                    else
504                        G.M_flag = TRUE;
505                    break;
506#endif
507                case 's':      /* default:  shorter "ls -l" type listing */
508                    if (negative)
509                        uO.lflag = -2, negative = 0;
510                    else
511                        uO.lflag = 3;
512                    break;
513                case 't':      /* totals line */
514                    if (negative)
515                        tflag_2v = tflag_slm = FALSE, negative = 0;
516                    else {
517                        tflag_2v = tflag_slm = explicit_t = TRUE;
518                        if (uO.lflag == -1)
519                            uO.lflag = 0;
520                    }
521                    break;
522                case ('T'):    /* use (sortable) decimal time format */
523                    if (negative)
524                        uO.T_flag = FALSE, negative = 0;
525                    else
526                        uO.T_flag = TRUE;
527                    break;
528                case 'v':      /* turbo-verbose listing */
529                    if (negative)
530                        uO.lflag = -2, negative = 0;
531                    else
532                        uO.lflag = 10;
533                    break;
534                case 'z':      /* print zipfile comment */
535                    if (negative)
536                        uO.zflag = negative = 0;
537                    else
538                        uO.zflag = 1;
539                    break;
540                case 'Z':      /* ZipInfo mode:  ignore */
541                    break;
542                default:
543                    error = TRUE;
544                    break;
545            }
546        }
547    }
548    if ((argc-- == 0) || error) {
549        *pargc = argc;
550        *pargv = argv;
551        return USAGE(error);
552    }
553
554#ifdef MORE
555    if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func useless */
556        G.M_flag = 0;
557#endif
558
559    /* if no listing options given (or all negated), or if only -h/-t given
560     * with individual files specified, use default listing format */
561    if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0)))
562        uO.lflag = LFLAG;
563
564    /* set header and totals flags to default or specified values */
565    switch (uO.lflag) {
566        case 0:   /* 0:  can only occur if either -t or -h explicitly given; */
567        case 2:   /*  therefore set both flags equal to normally false value */
568            uO.hflag = hflag_2;
569            uO.tflag = tflag_2v;
570            break;
571        case 1:   /* only filenames, *always* */
572            uO.hflag = FALSE;
573            uO.tflag = FALSE;
574            uO.zflag = FALSE;
575            break;
576        case 3:
577        case 4:
578        case 5:
579            uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv;
580            uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm;
581            break;
582        case 10:
583            uO.hflag = hflag_slmv;
584            uO.tflag = tflag_2v;
585            break;
586    }
587
588    *pargc = argc;
589    *pargv = argv;
590    return 0;
591
592} /* end function zi_opts() */
593
594#endif /* !WINDLL */
595
596
597
598
599
600/*******************************/
601/*  Function zi_end_central()  */
602/*******************************/
603
604int zi_end_central(__G)   /* return PK-type error code */
605    __GDEF
606{
607    int  error = PK_COOL;
608
609
610/*---------------------------------------------------------------------------
611    Print out various interesting things about the zipfile.
612  ---------------------------------------------------------------------------*/
613
614    /* header fits on one line, for anything up to 10GB and 10000 files: */
615    if (uO.hflag)
616        Info(slide, 0, ((char *)slide, ((int)strlen(G.zipfn) < 39)?
617          LoadFarString(LongHeader) : LoadFarString(ShortHeader), G.zipfn,
618          (long)G.ziplen, G.ecrec.total_entries_central_dir,
619          (G.ecrec.total_entries_central_dir==1)?
620          nullStr : PlurSufx));
621
622    /* verbose format */
623    if (uO.lflag > 9) {
624        Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec)));
625        Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators)));
626
627        Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir),
628          (long)G.real_ecrec_offset, (long)G.real_ecrec_offset,
629          (long)G.expect_ecrec_offset, (long)G.expect_ecrec_offset));
630
631        if (G.ecrec.number_this_disk == 0) {
632            Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1),
633              G.ecrec.total_entries_central_dir,
634              (G.ecrec.total_entries_central_dir == 1)? "entry" : "entries",
635              G.ecrec.size_central_directory,
636              G.ecrec.size_central_directory));
637            Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2),
638              G.ecrec.offset_start_central_directory,
639              G.ecrec.offset_start_central_directory));
640        } else {
641            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1),
642              G.ecrec.number_this_disk + 1,
643              G.ecrec.num_disk_start_cdir + 1,
644              G.ecrec.num_entries_centrl_dir_ths_disk,
645              (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are"));
646            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2),
647              G.ecrec.total_entries_central_dir,
648              (G.ecrec.total_entries_central_dir == 1) ? "entry" : "entries",
649              G.ecrec.size_central_directory,
650              G.ecrec.size_central_directory));
651            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3),
652              G.ecrec.offset_start_central_directory,
653              G.ecrec.offset_start_central_directory));
654        }
655
656    /*-----------------------------------------------------------------------
657        Get the zipfile comment, if any, and print it out.  (Comment may be
658        up to 64KB long.  May the fleas of a thousand camels infest the arm-
659        pits of anyone who actually takes advantage of this fact.)
660      -----------------------------------------------------------------------*/
661
662        if (!G.ecrec.zipfile_comment_length)
663            Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment)));
664        else {
665            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc),
666              G.ecrec.zipfile_comment_length));
667            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin)));
668            if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY))
669                error = PK_WARN;
670            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd)));
671            if (error)
672                Info(slide, 0, ((char *)slide,
673                  LoadFarString(ZipfileCommTrunc2)));
674        } /* endif (comment exists) */
675
676    /* non-verbose mode:  print zipfile comment only if requested */
677    } else if (uO.zflag && G.ecrec.zipfile_comment_length) {
678        if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
679            Info(slide, 0x401, ((char *)slide,
680              LoadFarString(ZipfileCommTruncMsg)));
681            error = PK_WARN;
682        }
683    } /* endif (verbose) */
684
685    return error;
686
687} /* end function zi_end_central() */
688
689
690
691
692
693/************************/
694/*  Function zipinfo()  */
695/************************/
696
697int zipinfo(__G)   /* return PK-type error code */
698    __GDEF
699{
700    int do_this_file=FALSE, error, error_in_archive=PK_COOL;
701    int *fn_matched=NULL, *xn_matched=NULL;
702    ulg j, members=0L;
703    ulg tot_csize=0L, tot_ucsize=0L;
704    ulg endprev;   /* buffers end of previous entry for zi_long()'s check
705                    *  of extra bytes */
706
707
708/*---------------------------------------------------------------------------
709    Malloc space for check on unmatched filespecs (no big deal if one or both
710    are NULL).
711  ---------------------------------------------------------------------------*/
712
713    if (G.filespecs > 0  &&
714        (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL)
715        for (j = 0;  j < G.filespecs;  ++j)
716            fn_matched[j] = FALSE;
717
718    if (G.xfilespecs > 0  &&
719        (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL)
720        for (j = 0;  j < G.xfilespecs;  ++j)
721            xn_matched[j] = FALSE;
722
723/*---------------------------------------------------------------------------
724    Set file pointer to start of central directory, then loop through cen-
725    tral directory entries.  Check that directory-entry signature bytes are
726    actually there (just a precaution), then process the entry.  We know
727    the entire central directory is on this disk:  we wouldn't have any of
728    this information unless the end-of-central-directory record was on this
729    disk, and we wouldn't have gotten to this routine unless this is also
730    the disk on which the central directory starts.  In practice, this had
731    better be the *only* disk in the archive, but maybe someday we'll add
732    multi-disk support.
733  ---------------------------------------------------------------------------*/
734
735    uO.L_flag = FALSE;      /* zipinfo mode: never convert name to lowercase */
736    G.pInfo = G.info;       /* (re-)initialize, (just to make sure) */
737    G.pInfo->textmode = 0;  /* so one can read on screen (is this ever used?) */
738
739    /* reset endprev for new zipfile; account for multi-part archives (?) */
740    endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L;
741
742
743    for (j = 1L;; j++) {
744        if (readbuf(__G__ G.sig, 4) == 0)
745            return PK_EOF;
746        if (strncmp(G.sig, central_hdr_sig, 4)) {  /* is it a CentDir entry? */
747            if (((unsigned)(j - 1) & (unsigned)0xFFFF) ==
748                (unsigned)G.ecrec.total_entries_central_dir) {
749                /* "j modulus 64k" matches the reported 16-bit-unsigned
750                 * number of directory entries -> probably, the regular
751                 * end of the central directory has been reached
752                 */
753                break;
754            } else {
755                Info(slide, 0x401,
756                     ((char *)slide, LoadFarString(CentSigMsg), j));
757                Info(slide, 0x401,
758                     ((char *)slide, LoadFarString(ReportMsg)));
759                return PK_BADERR;   /* sig not found */
760            }
761        }
762        /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */
763        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
764            return error;       /* only PK_EOF defined */
765
766        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
767             PK_COOL)
768        {
769          error_in_archive = error;   /* might be warning */
770          if (error > PK_WARN)        /* fatal */
771              return error;
772        }
773
774        if (!G.process_all_files) {   /* check if specified on command line */
775            unsigned i;
776
777            do_this_file = FALSE;
778            for (i = 0; i < G.filespecs; i++)
779                if (match(G.filename, G.pfnames[i], uO.C_flag)) {
780                    do_this_file = TRUE;
781                    if (fn_matched)
782                        fn_matched[i] = TRUE;
783                    break;       /* found match, so stop looping */
784                }
785            if (do_this_file) {  /* check if this is an excluded file */
786                for (i = 0; i < G.xfilespecs; i++)
787                    if (match(G.filename, G.pxnames[i], uO.C_flag)) {
788                        do_this_file = FALSE;  /* ^-- ignore case in match */
789                        if (xn_matched)
790                            xn_matched[i] = TRUE;
791                        break;
792                    }
793            }
794        }
795
796    /*-----------------------------------------------------------------------
797        If current file was specified on command line, or if no names were
798        specified, do the listing for this file.  Otherwise, get rid of the
799        file comment and go back for the next file.
800      -----------------------------------------------------------------------*/
801
802        if (G.process_all_files || do_this_file) {
803
804            switch (uO.lflag) {
805                case 1:
806                case 2:
807                    fnprint(__G);
808                    SKIP_(G.crec.extra_field_length)
809                    SKIP_(G.crec.file_comment_length)
810                    break;
811
812                case 3:
813                case 4:
814                case 5:
815                    if ((error = zi_short(__G)) != PK_COOL) {
816                        error_in_archive = error;   /* might be warning */
817                        if (error > PK_WARN)        /* fatal */
818                            return error;
819                    }
820                    break;
821
822                case 10:
823                    Info(slide, 0, ((char *)slide,
824                      LoadFarString(CentralDirEntry), j));
825                    if ((error = zi_long(__G__ &endprev)) != PK_COOL) {
826                        error_in_archive = error;   /* might be warning */
827                        if (error > PK_WARN)        /* fatal */
828                            return error;
829                    }
830                    break;
831
832                default:
833                    SKIP_(G.crec.extra_field_length)
834                    SKIP_(G.crec.file_comment_length)
835                    break;
836
837            } /* end switch (lflag) */
838
839            tot_csize += G.crec.csize;
840            tot_ucsize += G.crec.ucsize;
841            if (G.crec.general_purpose_bit_flag & 1)
842                tot_csize -= 12;   /* don't count encryption header */
843            ++members;
844
845#ifdef DLL
846            if ((G.statreportcb != NULL) &&
847                (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
848                                  G.filename, (zvoid *)&G.crec.ucsize)) {
849                if (fn_matched)
850                    free((zvoid *)fn_matched);
851                if (xn_matched)
852                    free((zvoid *)xn_matched);
853                return IZ_CTRLC;        /* cancel operation by user request */
854            }
855#endif
856#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
857            UserStop();
858#endif
859
860        } else {        /* not listing this file */
861            SKIP_(G.crec.extra_field_length)
862            SKIP_(G.crec.file_comment_length)
863
864        } /* end if (list member?) */
865
866    } /* end for-loop (j: member files) */
867
868/*---------------------------------------------------------------------------
869    Check that we actually found requested files; if so, print totals.
870  ---------------------------------------------------------------------------*/
871
872    if (uO.tflag) {
873        char *sgn = "";
874        int cfactor = ratio(tot_ucsize, tot_csize);
875
876        if (cfactor < 0) {
877            sgn = "-";
878            cfactor = -cfactor;
879        }
880        Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats),
881          members, (members==1L)? nullStr:PlurSufx, tot_ucsize,
882          tot_csize, sgn, cfactor/10, cfactor%10));
883    }
884
885/*---------------------------------------------------------------------------
886    Check for unmatched filespecs on command line and print warning if any
887    found.
888  ---------------------------------------------------------------------------*/
889
890    if (fn_matched) {
891        for (j = 0;  j < G.filespecs;  ++j)
892            if (!fn_matched[j])
893                Info(slide, 0x401, ((char *)slide,
894                  LoadFarString(FilenameNotMatched), G.pfnames[j]));
895        free((zvoid *)fn_matched);
896    }
897    if (xn_matched) {
898        for (j = 0;  j < G.xfilespecs;  ++j)
899            if (!xn_matched[j])
900                Info(slide, 0x401, ((char *)slide,
901                  LoadFarString(ExclFilenameNotMatched), G.pxnames[j]));
902        free((zvoid *)xn_matched);
903    }
904
905/*---------------------------------------------------------------------------
906    Double check that we're back at the end-of-central-directory record.
907  ---------------------------------------------------------------------------*/
908
909    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure again */
910        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
911        error_in_archive = PK_WARN;   /* didn't find sig */
912    }
913    if (members == 0 && error_in_archive <= PK_WARN)
914        error_in_archive = PK_FIND;
915
916    if (uO.lflag >= 10)
917        (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
918
919    return error_in_archive;
920
921} /* end function zipinfo() */
922
923
924
925
926
927/************************/
928/*  Function zi_long()  */
929/************************/
930
931static int zi_long(__G__ pEndprev)   /* return PK-type error code */
932    __GDEF
933    ulg *pEndprev;                   /* for zi_long() check of extra bytes */
934{
935#ifdef USE_EF_UT_TIME
936    iztimes z_utime;
937#endif
938    int  error, error_in_archive=PK_COOL;
939    unsigned  hostnum, hostver, extnum, extver, methnum, xattr;
940    char workspace[12], attribs[22];
941    ZCONST char *varmsg_str;
942    char unkn[16];
943    static ZCONST char Far *os[NUM_HOSTS] = {
944        OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS,
945        OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS,
946        OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem, OS_Theos
947    };
948    static ZCONST char Far *method[NUM_METHODS] = {
949        MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4,
950        MthdImplode, MthdToken, MthdDeflate, MthdDeflat64, MthdDCLImplode
951    };
952    static ZCONST char Far *dtypelng[4] = {
953        DeflNorm, DeflMax, DeflFast, DeflSFast
954    };
955
956
957/*---------------------------------------------------------------------------
958    Check whether there's any extra space inside the zipfile.  If *pEndprev is
959    zero, it's probably a signal that OS/2 extra fields are involved (with
960    unknown compressed size).  We won't worry about prepended junk here...
961  ---------------------------------------------------------------------------*/
962
963    if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) {
964        /*  GRR DEBUG
965        Info(slide, 0, ((char *)slide,
966          "  [crec.relative_offset_local_header = %lu, endprev = %lu]\n",
967          G.crec.relative_offset_local_header, *pEndprev));
968         */
969        Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding),
970          (long)G.crec.relative_offset_local_header - (long)(*pEndprev)));
971    }
972
973    /* calculate endprev for next time around (problem:  extra fields may
974     * differ in length between local and central-directory records) */
975    *pEndprev = G.crec.relative_offset_local_header + (4L + LREC_SIZE) +
976      G.crec.filename_length + G.crec.extra_field_length + G.crec.csize;
977
978/*---------------------------------------------------------------------------
979    Read the extra field, if any. It may be used to get UNIX style modtime.
980  ---------------------------------------------------------------------------*/
981
982    if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0)
983    {
984        if (G.extra_field != NULL) {
985            free(G.extra_field);
986            G.extra_field = NULL;
987        }
988        error_in_archive = error;
989        /* The premature return in case of a "fatal" error (PK_EOF) is
990         * delayed until we analyze the extra field contents.
991         * This allows us to display all the other info that has been
992         * successfully read in.
993         */
994    }
995
996/*---------------------------------------------------------------------------
997    Print out various interesting things about the compressed file.
998  ---------------------------------------------------------------------------*/
999
1000    hostnum = (unsigned)(G.pInfo->hostnum);
1001    hostver = (unsigned)(G.pInfo->hostver);
1002    extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
1003    extver = (unsigned)G.crec.version_needed_to_extract[0];
1004    methnum = (unsigned)MIN(G.crec.compression_method, NUM_METHODS);
1005
1006    (*G.message)((zvoid *)&G, (uch *)"  ", 2L, 0);  fnprint(__G);
1007
1008    Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset),
1009      G.crec.relative_offset_local_header,
1010      G.crec.relative_offset_local_header));
1011
1012    if (hostnum >= NUM_HOSTS) {
1013        sprintf(unkn, LoadFarString(UnknownNo),
1014                (int)G.crec.version_made_by[1]);
1015        varmsg_str = unkn;
1016    } else {
1017        varmsg_str = LoadFarStringSmall(os[hostnum]);
1018#ifdef OLD_THEOS_EXTRA
1019        if (hostnum == FS_VFAT_ && hostver == 20) {
1020            /* entry made by old non-official THEOS port zip archive */
1021            varmsg_str = LoadFarStringSmall(OS_TheosOld);
1022        }
1023#endif /* OLD_THEOS_EXTRA */
1024    }
1025    Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str));
1026    Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10,
1027      hostver%10));
1028
1029    if (extnum >= NUM_HOSTS) {
1030        sprintf(unkn, LoadFarString(UnknownNo),
1031                (int)G.crec.version_needed_to_extract[1]);
1032        varmsg_str = unkn;
1033    } else {
1034        varmsg_str = LoadFarStringSmall(os[extnum]);
1035    }
1036    Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str));
1037    Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10,
1038      extver%10));
1039
1040    if (methnum >= NUM_METHODS) {
1041        sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method);
1042        varmsg_str = unkn;
1043    } else {
1044        varmsg_str = LoadFarStringSmall(method[methnum]);
1045    }
1046    Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str));
1047    if (methnum == IMPLODED) {
1048        Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode),
1049          (G.crec.general_purpose_bit_flag & 2)? '8' : '4'));
1050        Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees),
1051          (G.crec.general_purpose_bit_flag & 4)? '3' : '2'));
1052    } else if (methnum == DEFLATED || methnum == ENHDEFLATED) {
1053        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
1054
1055        Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype),
1056          LoadFarStringSmall(dtypelng[dnum])));
1057    }
1058
1059    Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity),
1060      (G.crec.general_purpose_bit_flag & 1) ? nullStr : "not "));
1061    Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr),
1062      (G.crec.general_purpose_bit_flag & 8) ? "yes" : "no"));
1063    /* print upper 3 bits for amusement? */
1064
1065    /* For printing of date & time, a "char d_t_buf[21]" is required.
1066     * To save stack space, we reuse the "char attribs[22]" buffer which
1067     * is not used yet.
1068     */
1069#   define d_t_buf attribs
1070
1071    zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf);
1072    Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf));
1073#ifdef USE_EF_UT_TIME
1074    if (G.extra_field &&
1075#ifdef IZ_CHECK_TZ
1076        G.tz_is_valid &&
1077#endif
1078        (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
1079                          G.crec.last_mod_dos_datetime, &z_utime, NULL)
1080         & EB_UT_FL_MTIME))
1081    {
1082        TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0 or Macintosh */
1083        d_t_buf[0] = (char)0;               /* signal "show local time" */
1084        zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);
1085        Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),
1086          d_t_buf, LoadFarStringSmall(LocalTime)));
1087#ifndef NO_GMTIME
1088        d_t_buf[0] = (char)1;           /* signal "show UTC (GMT) time" */
1089        zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);
1090        Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),
1091          d_t_buf, LoadFarStringSmall(GMTime)));
1092#endif /* !NO_GMTIME */
1093    }
1094#endif /* USE_EF_UT_TIME */
1095
1096    Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32));
1097    Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize),
1098      G.crec.csize));
1099    Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize),
1100      G.crec.ucsize));
1101    Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength),
1102      G.crec.filename_length));
1103    Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength),
1104      G.crec.extra_field_length));
1105    Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength),
1106      G.crec.file_comment_length));
1107    Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum),
1108      G.crec.disk_number_start + 1));
1109    Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType),
1110      (G.crec.internal_file_attributes & 1)? "text"
1111         : (G.crec.internal_file_attributes & 2)? "ebcdic"
1112              : "binary"));             /* changed to accept EBCDIC */
1113#ifdef ATARI
1114    printf("  external file attributes (hex):                   %.8lx\n",
1115      G.crec.external_file_attributes);
1116#endif
1117    xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF);
1118    if (hostnum == VMS_) {
1119        char   *p=attribs, *q=attribs+1;
1120        int    i, j, k;
1121
1122        for (k = 0;  k < 12;  ++k)
1123            workspace[k] = 0;
1124        if (xattr & VMS_IRUSR)
1125            workspace[0] = 'R';
1126        if (xattr & VMS_IWUSR) {
1127            workspace[1] = 'W';
1128            workspace[3] = 'D';
1129        }
1130        if (xattr & VMS_IXUSR)
1131            workspace[2] = 'E';
1132        if (xattr & VMS_IRGRP)
1133            workspace[4] = 'R';
1134        if (xattr & VMS_IWGRP) {
1135            workspace[5] = 'W';
1136            workspace[7] = 'D';
1137        }
1138        if (xattr & VMS_IXGRP)
1139            workspace[6] = 'E';
1140        if (xattr & VMS_IROTH)
1141            workspace[8] = 'R';
1142        if (xattr & VMS_IWOTH) {
1143            workspace[9] = 'W';
1144            workspace[11] = 'D';
1145        }
1146        if (xattr & VMS_IXOTH)
1147            workspace[10] = 'E';
1148
1149        *p++ = '(';
1150        for (k = j = 0;  j < 3;  ++j) {    /* loop over groups of permissions */
1151            for (i = 0;  i < 4;  ++i, ++k)  /* loop over perms within a group */
1152                if (workspace[k])
1153                    *p++ = workspace[k];
1154            *p++ = ',';                       /* group separator */
1155            if (j == 0)
1156                while ((*p++ = *q++) != ',')
1157                    ;                         /* system, owner perms are same */
1158        }
1159        *p-- = '\0';
1160        *p = ')';   /* overwrite last comma */
1161        Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr,
1162          attribs));
1163
1164    } else if (hostnum == AMIGA_) {
1165        switch (xattr & AMI_IFMT) {
1166            case AMI_IFDIR:  attribs[0] = 'd';  break;
1167            case AMI_IFREG:  attribs[0] = '-';  break;
1168            default:         attribs[0] = '?';  break;
1169        }
1170        attribs[1] = (xattr & AMI_IHIDDEN)?   'h' : '-';
1171        attribs[2] = (xattr & AMI_ISCRIPT)?   's' : '-';
1172        attribs[3] = (xattr & AMI_IPURE)?     'p' : '-';
1173        attribs[4] = (xattr & AMI_IARCHIVE)?  'a' : '-';
1174        attribs[5] = (xattr & AMI_IREAD)?     'r' : '-';
1175        attribs[6] = (xattr & AMI_IWRITE)?    'w' : '-';
1176        attribs[7] = (xattr & AMI_IEXECUTE)?  'e' : '-';
1177        attribs[8] = (xattr & AMI_IDELETE)?   'd' : '-';
1178        attribs[9] = 0;   /* better dlm the string */
1179        Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes),
1180          xattr, attribs));
1181
1182    } else if (hostnum == THEOS_) {
1183        ZCONST char Far *fpFtyp;
1184
1185        switch (xattr & THS_IFMT) {
1186            case THS_IFLIB:  fpFtyp = TheosFTypLib;  break;
1187            case THS_IFDIR:  fpFtyp = TheosFTypDir;  break;
1188            case THS_IFREG:  fpFtyp = TheosFTypReg;  break;
1189            case THS_IFREL:  fpFtyp = TheosFTypRel;  break;
1190            case THS_IFKEY:  fpFtyp = TheosFTypKey;  break;
1191            case THS_IFIND:  fpFtyp = TheosFTypInd;  break;
1192            case THS_IFR16:  fpFtyp = TheosFTypR16;  break;
1193            case THS_IFP16:  fpFtyp = TheosFTypP16;  break;
1194            case THS_IFP32:  fpFtyp = TheosFTypP32;  break;
1195            default:         fpFtyp = TheosFTypUkn;  break;
1196        }
1197        strcpy(attribs, LoadFarStringSmall(fpFtyp));
1198        attribs[12] = (xattr & THS_INHID) ? '.' : 'H';
1199        attribs[13] = (xattr & THS_IMODF) ? '.' : 'M';
1200        attribs[14] = (xattr & THS_IWOTH) ? '.' : 'W';
1201        attribs[15] = (xattr & THS_IROTH) ? '.' : 'R';
1202        attribs[16] = (xattr & THS_IEUSR) ? '.' : 'E';
1203        attribs[17] = (xattr & THS_IXUSR) ? '.' : 'X';
1204        attribs[18] = (xattr & THS_IWUSR) ? '.' : 'W';
1205        attribs[19] = (xattr & THS_IRUSR) ? '.' : 'R';
1206        attribs[20] = 0;
1207        Info(slide, 0, ((char *)slide, LoadFarString(TheosFileAttributes),
1208          xattr, attribs));
1209
1210#ifdef OLD_THEOS_EXTRA
1211    } else if (hostnum == FS_VFAT_ && hostver == 20) {
1212        /* process old non-official THEOS port zip archive */
1213        ZCONST char Far *fpFtyp;
1214
1215        switch (xattr & _THS_IFMT) {
1216            case _THS_IFLIB:  fpFtyp = TheosFTypLib;  break;
1217            case _THS_IFDIR:  fpFtyp = TheosFTypDir;  break;
1218            case _THS_IFREG:  fpFtyp = TheosFTypReg;  break;
1219            case _THS_IODRC:  fpFtyp = TheosFTypRel;  break;
1220            case _THS_IOKEY:  fpFtyp = TheosFTypKey;  break;
1221            case _THS_IOIND:  fpFtyp = TheosFTypInd;  break;
1222            case _THS_IOPRG:  fpFtyp = TheosFTypR16;  break;
1223            case _THS_IO286:  fpFtyp = TheosFTypP16;  break;
1224            case _THS_IO386:  fpFtyp = TheosFTypP32;  break;
1225            default:         fpFtyp = TheosFTypUkn;  break;
1226        }
1227        strcpy(attribs, LoadFarStringSmall(fpFtyp));
1228        attribs[12] = (xattr & _THS_HIDDN) ? 'H' : '.';
1229        attribs[13] = (xattr & _THS_IXOTH) ? '.' : 'X';
1230        attribs[14] = (xattr & _THS_IWOTH) ? '.' : 'W';
1231        attribs[15] = (xattr & _THS_IROTH) ? '.' : 'R';
1232        attribs[16] = (xattr & _THS_IEUSR) ? '.' : 'E';
1233        attribs[17] = (xattr & _THS_IXUSR) ? '.' : 'X';
1234        attribs[18] = (xattr & _THS_IWUSR) ? '.' : 'W';
1235        attribs[19] = (xattr & _THS_IRUSR) ? '.' : 'R';
1236        attribs[20] = 0;
1237        Info(slide, 0, ((char *)slide, LoadFarString(TheosFileAttributes),
1238          xattr, attribs));
1239#endif /* OLD_THEOS_EXTRA */
1240
1241    } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) &&
1242               (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) &&
1243               (hostnum != ACORN_) &&
1244               (hostnum != VM_CMS_) && (hostnum != MVS_))
1245    {                                 /* assume Unix-like */
1246        switch ((unsigned)(xattr & UNX_IFMT)) {
1247            case (unsigned)UNX_IFDIR:   attribs[0] = 'd';  break;
1248            case (unsigned)UNX_IFREG:   attribs[0] = '-';  break;
1249            case (unsigned)UNX_IFLNK:   attribs[0] = 'l';  break;
1250            case (unsigned)UNX_IFBLK:   attribs[0] = 'b';  break;
1251            case (unsigned)UNX_IFCHR:   attribs[0] = 'c';  break;
1252            case (unsigned)UNX_IFIFO:   attribs[0] = 'p';  break;
1253            case (unsigned)UNX_IFSOCK:  attribs[0] = 's';  break;
1254            default:          attribs[0] = '?';  break;
1255        }
1256        attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';
1257        attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';
1258        attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';
1259
1260        attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';
1261        attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';
1262        attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';
1263
1264        if (xattr & UNX_IXUSR)
1265            attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';
1266        else
1267            attribs[3] = (xattr & UNX_ISUID)? 'S' : '-';   /* S = undefined */
1268        if (xattr & UNX_IXGRP)
1269            attribs[6] = (xattr & UNX_ISGID)? 's' : 'x';   /* == UNX_ENFMT */
1270        else
1271            attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';
1272        if (xattr & UNX_IXOTH)
1273            attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x';   /* "sticky bit" */
1274        else
1275            attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-';   /* T = undefined */
1276        attribs[10] = 0;
1277
1278        Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr,
1279          attribs));
1280
1281    } else {
1282        Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes),
1283            G.crec.external_file_attributes >> 8));
1284
1285    } /* endif (hostnum: external attributes format) */
1286
1287    if ((xattr=(unsigned)(G.crec.external_file_attributes & 0xFF)) == 0)
1288        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes),
1289          xattr));
1290    else if (xattr == 1)
1291        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO),
1292          xattr));
1293    else
1294        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha),
1295          xattr, (xattr&1)? "rdo " : nullStr,
1296          (xattr&2)? "hid " : nullStr,
1297          (xattr&4)? "sys " : nullStr,
1298          (xattr&8)? "lab " : nullStr,
1299          (xattr&16)? "dir " : nullStr,
1300          (xattr&32)? "arc " : nullStr,
1301          (xattr&64)? "lnk " : nullStr,
1302          (xattr&128)? "exe" : nullStr));
1303
1304/*---------------------------------------------------------------------------
1305    Analyze the extra field, if any, and print the file comment, if any (the
1306    filename has already been printed, above).  That finishes up this file
1307    entry...
1308  ---------------------------------------------------------------------------*/
1309
1310    if (G.crec.extra_field_length > 0) {
1311        uch *ef_ptr = G.extra_field;
1312        ush ef_len = G.crec.extra_field_length;
1313        ush eb_id, eb_datalen;
1314        ZCONST char Far *ef_fieldname;
1315
1316        if (error_in_archive > PK_WARN)   /* fatal:  can't continue */
1317            /* delayed "fatal error" return from extra field reading */
1318            return error;
1319        if (G.extra_field == (uch *)NULL)
1320            return PK_ERR;   /* not consistent with crec length */
1321
1322        Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields)));
1323
1324        while (ef_len >= EB_HEADSIZE) {
1325            eb_id = makeword(&ef_ptr[EB_ID]);
1326            eb_datalen = makeword(&ef_ptr[EB_LEN]);
1327            ef_ptr += EB_HEADSIZE;
1328            ef_len -= EB_HEADSIZE;
1329
1330            if (eb_datalen > (ush)ef_len) {
1331                Info(slide, 0x421, ((char *)slide,
1332                  LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len));
1333                eb_datalen = ef_len;
1334            }
1335
1336            switch (eb_id) {
1337                case EF_PKSZ64:
1338                    ef_fieldname = efPKSZ64;
1339                    break;
1340                case EF_AV:
1341                    ef_fieldname = efAV;
1342                    break;
1343                case EF_OS2:
1344                    ef_fieldname = efOS2;
1345                    break;
1346                case EF_ACL:
1347                    ef_fieldname = efACL;
1348                    break;
1349                case EF_NTSD:
1350                    ef_fieldname = efNTSD;
1351                    break;
1352                case EF_PKVMS:
1353                    ef_fieldname = efPKVMS;
1354                    break;
1355                case EF_IZVMS:
1356                    ef_fieldname = efIZVMS;
1357                    break;
1358                case EF_PKW32:
1359                    ef_fieldname = efPKWin32;
1360                    break;
1361                case EF_PKUNIX:
1362                    ef_fieldname = efPKUnix;
1363                    break;
1364                case EF_IZUNIX:
1365                    ef_fieldname = efIZUnix;
1366                    if (hostnum == UNIX_ && *pEndprev > 0L)
1367                        *pEndprev += 4L;  /* also have UID/GID in local copy */
1368                    break;
1369                case EF_IZUNIX2:
1370                    ef_fieldname = efIZUnix2;
1371                    if (*pEndprev > 0L)
1372                        *pEndprev += 4L;  /* 4 byte UID/GID in local copy */
1373                    break;
1374                case EF_TIME:
1375                    ef_fieldname = efTime;
1376                    break;
1377                case EF_MAC3:
1378                    ef_fieldname = efMac3;
1379                    break;
1380                case EF_JLMAC:
1381                    ef_fieldname = efJLMac;
1382                    break;
1383                case EF_ZIPIT:
1384                    ef_fieldname = efZipIt;
1385                    break;
1386                case EF_ZIPIT2:
1387                    ef_fieldname = efZipIt2;
1388                    break;
1389                case EF_VMCMS:
1390                    ef_fieldname = efVMCMS;
1391                    break;
1392                case EF_MVS:
1393                    ef_fieldname = efMVS;
1394                    break;
1395                case EF_BEOS:
1396                    ef_fieldname = efBeOS;
1397                    break;
1398                case EF_QDOS:
1399                    ef_fieldname = efQDOS;
1400                    break;
1401                case EF_AOSVS:
1402                    ef_fieldname = efAOSVS;
1403                    break;
1404                case EF_SPARK:   /* from RISC OS */
1405                    ef_fieldname = efSpark;
1406                    break;
1407                case EF_MD5:
1408                    ef_fieldname = efMD5;
1409                    break;
1410                case EF_ASIUNIX:
1411                    ef_fieldname = efASiUnix;
1412                    break;
1413                case EF_TANDEM:
1414                    ef_fieldname = efTandem;
1415                    break;
1416                case EF_SMARTZIP:
1417                    ef_fieldname = efSmartZip;
1418                    break;
1419                case EF_THEOS:
1420#ifdef OLD_THEOS_EXTRA
1421                case EF_THEOSO:
1422#endif
1423                    ef_fieldname = efTheos;
1424                    break;
1425                default:
1426                    ef_fieldname = efUnknown;
1427                    break;
1428            }
1429            Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType),
1430                 eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen));
1431
1432            /* additional, field-specific information: */
1433            switch (eb_id) {
1434                case EF_OS2:
1435                case EF_ACL:
1436                    if (eb_datalen >= EB_OS2_HLEN) {
1437                        if (eb_id == EF_OS2)
1438                            ef_fieldname = OS2EAs;
1439                        else
1440                            ef_fieldname = ACLdata;
1441                        Info(slide, 0, ((char *)slide,
1442                          LoadFarString(ef_fieldname), makelong(ef_ptr)));
1443                        *pEndprev = 0L;   /* no clue about csize of local */
1444                    }
1445                    break;
1446                case EF_NTSD:
1447                    if (eb_datalen >= EB_NTSD_C_LEN) {
1448                        Info(slide, 0, ((char *)slide, LoadFarString(NTSDData),
1449                          makelong(ef_ptr)));
1450                        *pEndprev = 0L;   /* no clue about csize of local */
1451                    }
1452                    break;
1453                case EF_IZVMS:
1454                    if (eb_datalen >= 8) {
1455                        char *p, q[8];
1456                        unsigned compr = makeword(ef_ptr+EB_IZVMS_FLGS)
1457                                        & EB_IZVMS_BCMASK;
1458
1459                        *q = '\0';
1460                        if (compr > 3)
1461                            compr = 3;
1462                        if (strncmp((char *)ef_ptr, "VFAB", 4) == 0)
1463                            p = "FAB";
1464                        else if (strncmp((char *)ef_ptr, "VALL", 4) == 0)
1465                            p = "XABALL";
1466                        else if (strncmp((char *)ef_ptr, "VFHC", 4) == 0)
1467                            p = "XABFHC";
1468                        else if (strncmp((char *)ef_ptr, "VDAT", 4) == 0)
1469                            p = "XABDAT";
1470                        else if (strncmp((char *)ef_ptr, "VRDT", 4) == 0)
1471                            p = "XABRDT";
1472                        else if (strncmp((char *)ef_ptr, "VPRO", 4) == 0)
1473                            p = "XABPRO";
1474                        else if (strncmp((char *)ef_ptr, "VKEY", 4) == 0)
1475                            p = "XABKEY";
1476                        else if (strncmp((char *)ef_ptr, "VMSV", 4) == 0) {
1477                            p = "version";
1478                            if (eb_datalen >= 16) {
1479                                q[0] = ' ';
1480                                q[1] = '(';
1481                                strncpy(q+2, (char *)ef_ptr+EB_IZVMS_HLEN, 4);
1482                                q[6] = ')';
1483                                q[7] = '\0';
1484                            }
1485                        } else
1486                            p = "unknown";
1487                        Info(slide, 0, ((char *)slide,
1488                          LoadFarString(izVMSdata),
1489                          LoadFarStringSmall(izVMScomp[compr]),
1490                          makeword(ef_ptr+EB_IZVMS_UCSIZ), p, q));
1491                    }
1492                    break;
1493                case EF_TIME:
1494                    if (eb_datalen >= 1) {
1495                        char types[80];
1496                        int num = 0, len;
1497
1498                        *types = '\0';
1499                        if (*ef_ptr & 1) {
1500                            strcpy(types, LoadFarString(UTmodification));
1501                            ++num;
1502                        }
1503                        if (*ef_ptr & 2) {
1504                            len = strlen(types);
1505                            if (num)
1506                                types[len++] = '/';
1507                            strcpy(types+len, LoadFarString(UTaccess));
1508                            ++num;
1509                            if (*pEndprev > 0L)
1510                                *pEndprev += 4L;
1511                        }
1512                        if (*ef_ptr & 4) {
1513                            len = strlen(types);
1514                            if (num)
1515                                types[len++] = '/';
1516                            strcpy(types+len, LoadFarString(UTcreation));
1517                            ++num;
1518                            if (*pEndprev > 0L)
1519                                *pEndprev += 4L;
1520                        }
1521                        if (num > 0)
1522                            Info(slide, 0, ((char *)slide,
1523                              LoadFarString(UTdata), types,
1524                              num == 1? nullStr : PlurSufx));
1525                    }
1526                    break;
1527                case EF_MAC3:
1528                    if (eb_datalen >= EB_MAC3_HLEN) {
1529                        ulg eb_uc = makelong(ef_ptr);
1530                        unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS);
1531                        unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR;
1532
1533                        Info(slide, 0, ((char *)slide, LoadFarString(Mac3data),
1534                          eb_uc, eb_is_uc ? "un" : nullStr));
1535                        if (eb_is_uc) {
1536                            if (*pEndprev > 0L)
1537                                *pEndprev += makelong(ef_ptr);
1538                        } else {
1539                            *pEndprev = 0L; /* no clue about csize of local */
1540                        }
1541
1542                        Info(slide, 0, ((char *)slide,
1543                          LoadFarString(MacOSMAC3flags),
1544                          LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ?
1545                                             MacOS_DF : MacOS_RF),
1546                          (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32)));
1547                        zi_showMacTypeCreator(__G__ &ef_ptr[6]);
1548                    }
1549                    break;
1550                case EF_ZIPIT2:
1551                    if (eb_datalen >= 5 &&
1552                        strncmp((char *)ef_ptr, "ZPIT", 4) == 0) {
1553
1554                        if (eb_datalen >= 12) {
1555                            zi_showMacTypeCreator(__G__ &ef_ptr[4]);
1556                        }
1557                    }
1558                    break;
1559                case EF_ZIPIT:
1560                    if (eb_datalen >= 5 &&
1561                        strncmp((char *)ef_ptr, "ZPIT", 4) == 0) {
1562                        unsigned fnlen = ef_ptr[4];
1563
1564                        if ((unsigned)eb_datalen >= fnlen + (5 + 8)) {
1565                            uch nullchar = ef_ptr[fnlen+5];
1566
1567                            ef_ptr[fnlen+5] = '\0'; /* terminate filename */
1568                            Info(slide, 0, ((char *)slide,
1569                              LoadFarString(ZipItFname), (char *)ef_ptr+5));
1570                            ef_ptr[fnlen+5] = nullchar;
1571                            zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]);
1572                        }
1573                    }
1574                    break;
1575                case EF_JLMAC:
1576                    if (eb_datalen >= 40 &&
1577                        strncmp((char *)ef_ptr, "JLEE", 4) == 0)
1578                    {
1579                        zi_showMacTypeCreator(__G__ &ef_ptr[4]);
1580
1581                        Info(slide, 0, ((char *)slide,
1582                          LoadFarString(MacOSJLEEflags),
1583                          LoadFarStringSmall(ef_ptr[31] & 1 ?
1584                                             MacOS_DF : MacOS_RF)));
1585                    }
1586                    break;
1587                case EF_SMARTZIP:
1588                    if ((eb_datalen == EB_SMARTZIP_HLEN) &&
1589                        strncmp((char *)ef_ptr, "dZip", 4) == 0) {
1590                        char filenameBuf[32];
1591                        zi_showMacTypeCreator(__G__ &ef_ptr[4]);
1592                        memcpy(filenameBuf, &ef_ptr[33], 31);
1593                        filenameBuf[ef_ptr[32]] = '\0';
1594                        Info(slide, 0, ((char *)slide,
1595                             LoadFarString(ZipItFname), filenameBuf));
1596                    }
1597                    break;
1598#ifdef CMS_MVS
1599                case EF_VMCMS:
1600                case EF_MVS:
1601                    {
1602                        char type[100];
1603
1604                        Info(slide, 0, ((char *)slide,
1605                             LoadFarString(VmMvsExtraField),
1606                             (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE,
1607                             (unsigned)eb_datalen) > 0)?
1608                             type : LoadFarStringSmall(VmMvsInvalid)));
1609                    }
1610                    break;
1611#endif /* CMS_MVS */
1612                case EF_BEOS:
1613                    if (eb_datalen >= EB_BEOS_HLEN) {
1614                        ulg eb_uc = makelong(ef_ptr);
1615                        unsigned eb_is_uc =
1616                          *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR;
1617
1618                        Info(slide, 0, ((char *)slide, LoadFarString(BeOSdata),
1619                          eb_uc, eb_is_uc ? "un" : nullStr));
1620                        if (eb_is_uc) {
1621                            if (*pEndprev > 0L)
1622                                *pEndprev += makelong(ef_ptr);
1623                        } else {
1624                            *pEndprev = 0L; /* no clue about csize of local */
1625                        }
1626                    }
1627                    break;
1628                case EF_QDOS:
1629                    if (eb_datalen >= 4) {
1630                        Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata),
1631                          ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3]));
1632                    }
1633                    break;
1634                case EF_AOSVS:
1635                    if (eb_datalen >= 5) {
1636                        Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata),
1637                          ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10));
1638                    }
1639                    break;
1640                case EF_TANDEM:
1641                    if (eb_datalen == 20) {
1642                        unsigned type, code;
1643
1644                        type = (ef_ptr[18] & 0x60) >> 5;
1645                        code = makeword(ef_ptr);
1646                        /* Arrg..., Tandem e.f. uses BigEndian byte-order */
1647                        code = ((code << 8) & 0xff00) | ((code >> 8) & 0x00ff);
1648                        if (type == NSK_UNSTRUCTURED) {
1649                            if (code == NSK_EDITFILECODE)
1650                                type = 4;
1651                            else if (code == NSK_OBJECTFILECODE)
1652                                type = 5;
1653                        }
1654                        Info(slide, 0, ((char *)slide,
1655                          LoadFarString(Tandemdata),
1656                          LoadFarStringSmall(TandemFileformat[type]),
1657                          code));
1658                    }
1659                    break;
1660                case EF_MD5:
1661                    if (eb_datalen >= 19) {
1662                        char md5[33];
1663                        int i;
1664
1665                        for (i = 0;  i < 16;  ++i)
1666                            sprintf(&md5[i<<1], "%02x", ef_ptr[15-i]);
1667                        md5[32] = '\0';
1668                        Info(slide, 0, ((char *)slide, LoadFarString(MD5data),
1669                          md5));
1670                        break;
1671                    }   /* else: fall through !! */
1672                default:
1673                    if (eb_datalen > 0) {
1674                        ush i, n;
1675
1676                        if (eb_datalen <= 24) {
1677                            Info(slide, 0, ((char *)slide,
1678                                 LoadFarString(ColonIndent)));
1679                            n = eb_datalen;
1680                        } else {
1681                            Info(slide, 0, ((char *)slide,
1682                                 LoadFarString(First20)));
1683                            n = 20;
1684                        }
1685                        for (i = 0;  i < n;  ++i)
1686                            Info(slide, 0, ((char *)slide,
1687                                 LoadFarString(efFormat), ef_ptr[i]));
1688                    }
1689                    break;
1690            }
1691            (*G.message)((zvoid *)&G, (uch *)".", 1L, 0);
1692
1693            ef_ptr += eb_datalen;
1694            ef_len -= eb_datalen;
1695        }
1696        (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
1697    }
1698
1699    /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */
1700    if ((xattr = (unsigned)((G.crec.external_file_attributes & 0xC000) >> 12))
1701        & 8)
1702    {
1703        if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)
1704        {
1705            Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),
1706              "is", EF_IZUNIX, LoadFarStringSmall(efIZUnix),
1707              (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid));
1708            if (*pEndprev > 0L)
1709                *pEndprev += (ulg)(xattr&12);
1710        }
1711        else if (hostnum == FS_FAT_ && !(xattr&4))
1712            Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),
1713              "may be", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8,
1714              efIZnouid));
1715    }
1716
1717    if (!G.crec.file_comment_length)
1718        Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment)));
1719    else {
1720        Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin)));
1721        if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) !=
1722            PK_COOL)
1723        {
1724            error_in_archive = error;   /* might be warning */
1725            if (error > PK_WARN)   /* fatal */
1726                return error;
1727        }
1728        Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd)));
1729    }
1730
1731    return error_in_archive;
1732
1733} /* end function zi_long() */
1734
1735
1736
1737
1738
1739/*************************/
1740/*  Function zi_short()  */
1741/*************************/
1742
1743static int zi_short(__G)   /* return PK-type error code */
1744    __GDEF
1745{
1746#ifdef USE_EF_UT_TIME
1747    iztimes     z_utime;
1748    time_t      *z_modtim;
1749#endif
1750    int         k, error, error_in_archive=PK_COOL;
1751    unsigned    hostnum, hostver, methnum, xattr;
1752    char        *p, workspace[12], attribs[16];
1753    char        methbuf[5];
1754    static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */
1755    static ZCONST char Far os[NUM_HOSTS+1][4] = {
1756        "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz",
1757        "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk",
1758        "ths", "???"
1759    };
1760#ifdef OLD_THEOS_EXTRA
1761    static ZCONST char Far os_TheosOld[] = "tho";
1762#endif
1763    static ZCONST char Far method[NUM_METHODS+1][5] = {
1764        "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn",
1765        "def#", "d64#", "dcli", "u###"
1766    };
1767
1768
1769/*---------------------------------------------------------------------------
1770    Print out various interesting things about the compressed file.
1771  ---------------------------------------------------------------------------*/
1772
1773    methnum = (unsigned)MIN(G.crec.compression_method, NUM_METHODS);
1774    hostnum = (unsigned)(G.pInfo->hostnum);
1775    hostver = (unsigned)(G.pInfo->hostver);
1776/*
1777    extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
1778    extver = (unsigned)G.crec.version_needed_to_extract[0];
1779 */
1780
1781    zfstrcpy(methbuf, method[methnum]);
1782    if (methnum == IMPLODED) {
1783        methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4');
1784        methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2');
1785    } else if (methnum == DEFLATED || methnum == ENHDEFLATED) {
1786        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
1787        methbuf[3] = dtype[dnum];
1788    } else if (methnum >= NUM_METHODS) {   /* unknown */
1789        sprintf(&methbuf[1], "%03u", G.crec.compression_method);
1790    }
1791
1792    for (k = 0;  k < 15;  ++k)
1793        attribs[k] = ' ';
1794    attribs[15] = 0;
1795
1796    xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF);
1797    switch (hostnum) {
1798        case VMS_:
1799            {   int    i, j;
1800
1801                for (k = 0;  k < 12;  ++k)
1802                    workspace[k] = 0;
1803                if (xattr & VMS_IRUSR)
1804                    workspace[0] = 'R';
1805                if (xattr & VMS_IWUSR) {
1806                    workspace[1] = 'W';
1807                    workspace[3] = 'D';
1808                }
1809                if (xattr & VMS_IXUSR)
1810                    workspace[2] = 'E';
1811                if (xattr & VMS_IRGRP)
1812                    workspace[4] = 'R';
1813                if (xattr & VMS_IWGRP) {
1814                    workspace[5] = 'W';
1815                    workspace[7] = 'D';
1816                }
1817                if (xattr & VMS_IXGRP)
1818                  workspace[6] = 'E';
1819                if (xattr & VMS_IROTH)
1820                    workspace[8] = 'R';
1821                if (xattr & VMS_IWOTH) {
1822                    workspace[9] = 'W';
1823                    workspace[11] = 'D';
1824                }
1825                if (xattr & VMS_IXOTH)
1826                    workspace[10] = 'E';
1827
1828                p = attribs;
1829                for (k = j = 0;  j < 3;  ++j) {     /* groups of permissions */
1830                    for (i = 0;  i < 4;  ++i, ++k)  /* perms within a group */
1831                        if (workspace[k])
1832                            *p++ = workspace[k];
1833                    *p++ = ',';                     /* group separator */
1834                }
1835                *--p = ' ';   /* overwrite last comma */
1836                if ((p - attribs) < 12)
1837                    sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10);
1838            }
1839            break;
1840
1841        case AMIGA_:
1842            switch (xattr & AMI_IFMT) {
1843                case AMI_IFDIR:  attribs[0] = 'd';  break;
1844                case AMI_IFREG:  attribs[0] = '-';  break;
1845                default:         attribs[0] = '?';  break;
1846            }
1847            attribs[1] = (xattr & AMI_IHIDDEN)?   'h' : '-';
1848            attribs[2] = (xattr & AMI_ISCRIPT)?   's' : '-';
1849            attribs[3] = (xattr & AMI_IPURE)?     'p' : '-';
1850            attribs[4] = (xattr & AMI_IARCHIVE)?  'a' : '-';
1851            attribs[5] = (xattr & AMI_IREAD)?     'r' : '-';
1852            attribs[6] = (xattr & AMI_IWRITE)?    'w' : '-';
1853            attribs[7] = (xattr & AMI_IEXECUTE)?  'e' : '-';
1854            attribs[8] = (xattr & AMI_IDELETE)?   'd' : '-';
1855            sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10);
1856            break;
1857
1858        case THEOS_:
1859            switch (xattr & THS_IFMT) {
1860                case THS_IFLIB: *attribs = 'L'; break;
1861                case THS_IFDIR: *attribs = 'D'; break;
1862                case THS_IFCHR: *attribs = 'C'; break;
1863                case THS_IFREG: *attribs = 'S'; break;
1864                case THS_IFREL: *attribs = 'R'; break;
1865                case THS_IFKEY: *attribs = 'K'; break;
1866                case THS_IFIND: *attribs = 'I'; break;
1867                case THS_IFR16: *attribs = 'P'; break;
1868                case THS_IFP16: *attribs = '2'; break;
1869                case THS_IFP32: *attribs = '3'; break;
1870                default:        *attribs = '?'; break;
1871            }
1872            attribs[1] = (xattr & THS_INHID) ? '.' : 'H';
1873            attribs[2] = (xattr & THS_IMODF) ? '.' : 'M';
1874            attribs[3] = (xattr & THS_IWOTH) ? '.' : 'W';
1875            attribs[4] = (xattr & THS_IROTH) ? '.' : 'R';
1876            attribs[5] = (xattr & THS_IEUSR) ? '.' : 'E';
1877            attribs[6] = (xattr & THS_IXUSR) ? '.' : 'X';
1878            attribs[7] = (xattr & THS_IWUSR) ? '.' : 'W';
1879            attribs[8] = (xattr & THS_IRUSR) ? '.' : 'R';
1880            sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10);
1881            break;
1882
1883        case FS_VFAT_:
1884#ifdef OLD_THEOS_EXTRA
1885            if (hostver == 20) {
1886                switch (xattr & _THS_IFMT) {
1887                    case _THS_IFLIB: *attribs = 'L'; break;
1888                    case _THS_IFDIR: *attribs = 'd'; break;
1889                    case _THS_IFCHR: *attribs = 'c'; break;
1890                    case _THS_IFREG: *attribs = 'S'; break;
1891                    case _THS_IODRC: *attribs = 'D'; break;
1892                    case _THS_IOKEY: *attribs = 'K'; break;
1893                    case _THS_IOIND: *attribs = 'I'; break;
1894                    case _THS_IOPRG: *attribs = 'P'; break;
1895                    case _THS_IO286: *attribs = '2'; break;
1896                    case _THS_IO386: *attribs = '3'; break;
1897                    default:         *attribs = '?'; break;
1898                }
1899                attribs[1] = (xattr & _THS_HIDDN) ? 'H' : '.';
1900                attribs[2] = (xattr & _THS_IXOTH) ? '.' : 'X';
1901                attribs[3] = (xattr & _THS_IWOTH) ? '.' : 'W';
1902                attribs[4] = (xattr & _THS_IROTH) ? '.' : 'R';
1903                attribs[5] = (xattr & _THS_IEUSR) ? '.' : 'E';
1904                attribs[6] = (xattr & _THS_IXUSR) ? '.' : 'X';
1905                attribs[7] = (xattr & _THS_IWUSR) ? '.' : 'W';
1906                attribs[8] = (xattr & _THS_IRUSR) ? '.' : 'R';
1907                sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10);
1908                break;
1909            } /* else: fall through! */
1910#endif /* OLD_THEOS_EXTRA */
1911
1912        case FS_FAT_:
1913        case FS_HPFS_:
1914        case FS_NTFS_:
1915        case VM_CMS_:
1916        case MVS_:
1917        case ACORN_:
1918            if (hostnum != FS_FAT_ ||
1919                (unsigned)(xattr & 0700) !=
1920                 ((unsigned)0400 |
1921                  ((unsigned)!(G.crec.external_file_attributes & 1) << 7) |
1922                  ((unsigned)(G.crec.external_file_attributes & 0x10) << 2))
1923               )
1924            {
1925                xattr = (unsigned)(G.crec.external_file_attributes & 0xFF);
1926                sprintf(attribs, ".r.-...     %u.%u", hostver/10, hostver%10);
1927                attribs[2] = (xattr & 0x01)? '-' : 'w';
1928                attribs[5] = (xattr & 0x02)? 'h' : '-';
1929                attribs[6] = (xattr & 0x04)? 's' : '-';
1930                attribs[4] = (xattr & 0x20)? 'a' : '-';
1931                if (xattr & 0x10) {
1932                    attribs[0] = 'd';
1933                    attribs[3] = 'x';
1934                } else
1935                    attribs[0] = '-';
1936                if (IS_VOLID(xattr))
1937                    attribs[0] = 'V';
1938                else if ((p = MBSRCHR(G.filename, '.')) != (char *)NULL) {
1939                    ++p;
1940                    if (STRNICMP(p, "com", 3) == 0 ||
1941                        STRNICMP(p, "exe", 3) == 0 ||
1942                        STRNICMP(p, "btm", 3) == 0 ||
1943                        STRNICMP(p, "cmd", 3) == 0 ||
1944                        STRNICMP(p, "bat", 3) == 0)
1945                        attribs[3] = 'x';
1946                }
1947                break;
1948            } /* else: fall through! */
1949
1950        default:   /* assume Unix-like */
1951            switch ((unsigned)(xattr & UNX_IFMT)) {
1952                case (unsigned)UNX_IFDIR:   attribs[0] = 'd';  break;
1953                case (unsigned)UNX_IFREG:   attribs[0] = '-';  break;
1954                case (unsigned)UNX_IFLNK:   attribs[0] = 'l';  break;
1955                case (unsigned)UNX_IFBLK:   attribs[0] = 'b';  break;
1956                case (unsigned)UNX_IFCHR:   attribs[0] = 'c';  break;
1957                case (unsigned)UNX_IFIFO:   attribs[0] = 'p';  break;
1958                case (unsigned)UNX_IFSOCK:  attribs[0] = 's';  break;
1959                default:          attribs[0] = '?';  break;
1960            }
1961            attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';
1962            attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';
1963            attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';
1964            attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';
1965            attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';
1966            attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';
1967
1968            if (xattr & UNX_IXUSR)
1969                attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';
1970            else
1971                attribs[3] = (xattr & UNX_ISUID)? 'S' : '-';  /* S==undefined */
1972            if (xattr & UNX_IXGRP)
1973                attribs[6] = (xattr & UNX_ISGID)? 's' : 'x';  /* == UNX_ENFMT */
1974            else
1975                /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';  real 4.3BSD */
1976                attribs[6] = (xattr & UNX_ISGID)? 'S' : '-';  /* SunOS 4.1.x */
1977            if (xattr & UNX_IXOTH)
1978                attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x';  /* "sticky bit" */
1979            else
1980                attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-';  /* T==undefined */
1981
1982            sprintf(&attribs[12], "%u.%u", hostver/10, hostver%10);
1983            break;
1984
1985    } /* end switch (hostnum: external attributes format) */
1986
1987#ifdef OLD_THEOS_EXTRA
1988    Info(slide, 0, ((char *)slide, "%s %s %8lu ", attribs,
1989      LoadFarStringSmall(((hostnum == FS_VFAT_ && hostver == 20) ?
1990                          os_TheosOld :
1991                          os[hostnum])),
1992      G.crec.ucsize));
1993#else
1994    Info(slide, 0, ((char *)slide, "%s %s %8lu ", attribs,
1995      LoadFarStringSmall(os[hostnum]),
1996      G.crec.ucsize));
1997#endif
1998    Info(slide, 0, ((char *)slide, "%c",
1999      (G.crec.general_purpose_bit_flag & 1)?
2000      ((G.crec.internal_file_attributes & 1)? 'T' : 'B') :  /* encrypted */
2001      ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */
2002    k = (G.crec.extra_field_length ||
2003         /* a local-only "UX" (old Unix/OS2/NT GMT times "IZUNIX") e.f.? */
2004         ((G.crec.external_file_attributes & 0x8000) &&
2005          (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)));
2006    Info(slide, 0, ((char *)slide, "%c", k?
2007      ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') :  /* extra field */
2008      ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */
2009      /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */
2010
2011    if (uO.lflag == 4) {
2012        ulg csiz = G.crec.csize;
2013
2014        if (G.crec.general_purpose_bit_flag & 1)
2015            csiz -= 12;    /* if encrypted, don't count encryption header */
2016        Info(slide, 0, ((char *)slide, "%3d%%",
2017          (ratio(G.crec.ucsize,csiz)+5)/10));
2018    } else if (uO.lflag == 5)
2019        Info(slide, 0, ((char *)slide, " %8lu", G.crec.csize));
2020
2021    /* Read the extra field, if any.  The extra field info may be used
2022     * in the file modification time section, below.
2023     */
2024    if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0)
2025    {
2026        if (G.extra_field != NULL) {
2027            free(G.extra_field);
2028            G.extra_field = NULL;
2029        }
2030        error_in_archive = error;
2031        /* We do not return prematurely in case of a "fatal" error (PK_EOF).
2032         * This does not hurt here, because we do not need to read from the
2033         * zipfile again before the end of this function.
2034         */
2035    }
2036
2037    /* For printing of date & time, a "char d_t_buf[16]" is required.
2038     * To save stack space, we reuse the "char attribs[16]" buffer whose
2039     * content is no longer needed.
2040     */
2041#   define d_t_buf attribs
2042#ifdef USE_EF_UT_TIME
2043    z_modtim = G.extra_field &&
2044#ifdef IZ_CHECK_TZ
2045               G.tz_is_valid &&
2046#endif
2047               (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
2048                                 G.crec.last_mod_dos_datetime, &z_utime, NULL)
2049                & EB_UT_FL_MTIME)
2050              ? &z_utime.mtime : NULL;
2051    TIMET_TO_NATIVE(z_utime.mtime)     /* NOP unless MSC 7.0 or Macintosh */
2052    d_t_buf[0] = (char)0;              /* signal "show local time" */
2053#else
2054#   define z_modtim NULL
2055#endif
2056    Info(slide, 0, ((char *)slide, " %s %s ", methbuf,
2057      zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf)));
2058    fnprint(__G);
2059
2060/*---------------------------------------------------------------------------
2061    Skip the file comment, if any (the filename has already been printed,
2062    above).  That finishes up this file entry...
2063  ---------------------------------------------------------------------------*/
2064
2065    SKIP_(G.crec.file_comment_length)
2066
2067    return error_in_archive;
2068
2069} /* end function zi_short() */
2070
2071
2072
2073
2074
2075/**************************************/
2076/*  Function zi_showMacTypeCreator()  */
2077/**************************************/
2078
2079static void zi_showMacTypeCreator(__G__ ebfield)
2080    __GDEF
2081    uch *ebfield;
2082{
2083    /* not every Type / Creator character is printable */
2084    if (isprint(ebfield[0]) && isprint(ebfield[1]) &&
2085        isprint(ebfield[2]) && isprint(ebfield[3]) &&
2086        isprint(ebfield[4]) && isprint(ebfield[5]) &&
2087        isprint(ebfield[6]) && isprint(ebfield[7])) {
2088       Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata),
2089            ebfield[0], ebfield[1], ebfield[2], ebfield[3],
2090            ebfield[4], ebfield[5], ebfield[6], ebfield[7]));
2091    } else {
2092       Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1),
2093            (((ulg)ebfield[0]) << 24) +
2094            (((ulg)ebfield[1]) << 16) +
2095            (((ulg)ebfield[2]) << 8)  +
2096            ((ulg)ebfield[3]),
2097            (((ulg)ebfield[4]) << 24) +
2098            (((ulg)ebfield[5]) << 16) +
2099            (((ulg)ebfield[6]) << 8)  +
2100            ((ulg)ebfield[7])));
2101    }
2102} /* end function zi_showMacTypeCreator() */
2103
2104
2105
2106
2107
2108/************************/
2109/*  Function zi_time()  */
2110/************************/
2111
2112static char *zi_time(__G__ datetimez, modtimez, d_t_str)
2113    __GDEF
2114    ZCONST ulg *datetimez;
2115    ZCONST time_t *modtimez;
2116    char *d_t_str;
2117{
2118    unsigned yr, mo, dy, hh, mm, ss;
2119    char monthbuf[4];
2120    ZCONST char *monthstr;
2121    static ZCONST char Far month[12][4] = {
2122        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
2123        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
2124    };
2125#ifdef USE_EF_UT_TIME
2126    struct tm *t;
2127#endif
2128
2129
2130
2131/*---------------------------------------------------------------------------
2132    Convert the file-modification date and time info to a string of the form
2133    "1991 Feb 23 17:15:00", "23-Feb-91 17:15" or "19910223.171500", depending
2134    on values of lflag and T_flag.  If using Unix-time extra fields, convert
2135    to local time or not, depending on value of first character in d_t_str[].
2136  ---------------------------------------------------------------------------*/
2137
2138#ifdef USE_EF_UT_TIME
2139    if (modtimez != NULL) {
2140#ifndef NO_GMTIME
2141        /* check for our secret message from above... */
2142        t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez);
2143#else
2144        t = localtime(modtimez);
2145#endif
2146        if (uO.lflag > 9 && t == (struct tm *)NULL)
2147            /* time conversion error in verbose listing format,
2148             * return string with '?' instead of data
2149             */
2150            return (strcpy(d_t_str, LoadFarString(YMDHMSTimeError)));
2151    } else
2152        t = (struct tm *)NULL;
2153    if (t != (struct tm *)NULL) {
2154        mo = (unsigned)(t->tm_mon + 1);
2155        dy = (unsigned)(t->tm_mday);
2156        yr = (unsigned)(t->tm_year);
2157
2158        hh = (unsigned)(t->tm_hour);
2159        mm = (unsigned)(t->tm_min);
2160        ss = (unsigned)(t->tm_sec);
2161    } else
2162#endif /* USE_EF_UT_TIME */
2163    {
2164        yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80;
2165        mo = ((unsigned)(*datetimez >> 21) & 0x0f);
2166        dy = ((unsigned)(*datetimez >> 16) & 0x1f);
2167
2168        hh = (((unsigned)*datetimez >> 11) & 0x1f);
2169        mm = (((unsigned)*datetimez >> 5) & 0x3f);
2170        ss = (((unsigned)*datetimez << 1) & 0x3e);
2171    }
2172
2173    if (mo == 0 || mo > 12) {
2174        sprintf(monthbuf, LoadFarString(BogusFmt), mo);
2175        monthstr = monthbuf;
2176    } else
2177        monthstr = LoadFarStringSmall(month[mo-1]);
2178
2179    if (uO.lflag > 9)   /* verbose listing format */
2180        sprintf(d_t_str, LoadFarString(YMDHMSTime), yr+1900, monthstr, dy, hh,
2181          mm, ss);
2182    else if (uO.T_flag)
2183        sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy, hh, mm,
2184          ss);
2185    else   /* was:  if ((uO.lflag >= 3) && (uO.lflag <= 5)) */
2186        sprintf(d_t_str, LoadFarString(DMYHMTime), dy, monthstr, yr%100, hh,
2187          mm);
2188
2189    return d_t_str;
2190
2191} /* end function zi_time() */
2192
2193#endif /* !NO_ZIPINFO */
2194