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