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