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