Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 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 | list.c |
||
12 | |||
13 | This file contains the non-ZipInfo-specific listing routines for UnZip. |
||
14 | |||
15 | Contains: list_files() |
||
16 | get_time_stamp() [optional feature] |
||
17 | ratio() |
||
18 | fnprint() |
||
19 | |||
20 | ---------------------------------------------------------------------------*/ |
||
21 | |||
22 | |||
23 | #define UNZIP_INTERNAL |
||
24 | #include "unzip.h" |
||
25 | #ifdef WINDLL |
||
26 | # ifdef POCKET_UNZIP |
||
27 | # include "wince/intrface.h" |
||
28 | # else |
||
29 | # include "windll/windll.h" |
||
30 | # endif |
||
31 | #endif |
||
32 | |||
33 | |||
34 | #ifdef TIMESTAMP |
||
35 | static int fn_is_dir OF((__GPRO)); |
||
36 | #endif |
||
37 | |||
38 | #ifndef WINDLL |
||
39 | static ZCONST char Far CompFactorStr[] = "%c%d%%"; |
||
40 | static ZCONST char Far CompFactor100[] = "100%%"; |
||
41 | |||
42 | #ifdef OS2_EAS |
||
43 | static ZCONST char Far HeadersS[] = |
||
44 | " Length EAs ACLs Date Time Name"; |
||
45 | static ZCONST char Far HeadersS1[] = |
||
46 | "--------- --- ---- ---------- ----- ----"; |
||
47 | #else |
||
48 | static ZCONST char Far HeadersS[] = |
||
49 | " Length Date Time Name"; |
||
50 | static ZCONST char Far HeadersS1[] = |
||
51 | "--------- ---------- ----- ----"; |
||
52 | #endif |
||
53 | |||
54 | static ZCONST char Far HeadersL[] = |
||
55 | " Length Method Size Cmpr Date Time CRC-32 Name"; |
||
56 | static ZCONST char Far HeadersL1[] = |
||
57 | "-------- ------ ------- ---- ---------- ----- -------- ----"; |
||
58 | static ZCONST char Far *Headers[][2] = |
||
59 | { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} }; |
||
60 | |||
61 | static ZCONST char Far CaseConversion[] = |
||
62 | "%s (\"^\" ==> case\n%s conversion)\n"; |
||
63 | static ZCONST char Far LongHdrStats[] = |
||
64 | "%s %-7s%s %4s %02u%c%02u%c%02u %02u:%02u %08lx %c"; |
||
65 | static ZCONST char Far LongFileTrailer[] = |
||
66 | "-------- ------- --- \ |
||
67 | -------\n%s %s %4s %lu file%s\n"; |
||
68 | #ifdef OS2_EAS |
||
69 | static ZCONST char Far ShortHdrStats[] = |
||
70 | "%s %6lu %6lu %02u%c%02u%c%02u %02u:%02u %c"; |
||
71 | static ZCONST char Far ShortFileTrailer[] = |
||
72 | "--------- ----- ----- \ |
||
73 | -------\n%s %6lu %6lu %lu file%s\n"; |
||
74 | static ZCONST char Far OS2ExtAttrTrailer[] = |
||
75 | "%lu file%s %lu bytes of OS/2 extended attributes attached.\n"; |
||
76 | static ZCONST char Far OS2ACLTrailer[] = |
||
77 | "%lu file%s %lu bytes of access control lists attached.\n"; |
||
78 | #else |
||
79 | static ZCONST char Far ShortHdrStats[] = |
||
80 | "%s %02u%c%02u%c%02u %02u:%02u %c"; |
||
81 | static ZCONST char Far ShortFileTrailer[] = |
||
82 | "--------- -------\n%s\ |
||
83 | %lu file%s\n"; |
||
84 | #endif /* ?OS2_EAS */ |
||
85 | #endif /* !WINDLL */ |
||
86 | |||
87 | |||
88 | |||
89 | |||
90 | |||
91 | /*************************/ |
||
92 | /* Function list_files() */ |
||
93 | /*************************/ |
||
94 | |||
95 | int list_files(__G) /* return PK-type error code */ |
||
96 | __GDEF |
||
97 | { |
||
98 | int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL; |
||
99 | #ifndef WINDLL |
||
100 | char sgn, cfactorstr[10]; |
||
101 | int longhdr=(uO.vflag>1); |
||
102 | #endif |
||
103 | int date_format; |
||
104 | char dt_sepchar; |
||
105 | ulg members=0L; |
||
106 | zusz_t j; |
||
107 | unsigned methnum; |
||
108 | #ifdef USE_EF_UT_TIME |
||
109 | iztimes z_utime; |
||
110 | struct tm *t; |
||
111 | #endif |
||
112 | unsigned yr, mo, dy, hh, mm; |
||
113 | zusz_t csiz, tot_csize=0L, tot_ucsize=0L; |
||
114 | #ifdef OS2_EAS |
||
115 | ulg ea_size, tot_easize=0L, tot_eafiles=0L; |
||
116 | ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L; |
||
117 | #endif |
||
118 | min_info info; |
||
119 | char methbuf[8]; |
||
120 | static ZCONST char dtype[]="NXFS"; /* see zi_short() */ |
||
121 | static ZCONST char Far method[NUM_METHODS+1][8] = |
||
122 | {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4", |
||
123 | "Implode", "Token", "Defl:#", "Def64#", "ImplDCL", "BZip2", |
||
124 | "LZMA", "Terse", "IBMLZ77", "WavPack", "PPMd", "Unk:###"}; |
||
125 | |||
126 | |||
127 | |||
128 | /*--------------------------------------------------------------------------- |
||
129 | Unlike extract_or_test_files(), this routine confines itself to the cen- |
||
130 | tral directory. Thus its structure is somewhat simpler, since we can do |
||
131 | just a single loop through the entire directory, listing files as we go. |
||
132 | |||
133 | So to start off, print the heading line and then begin main loop through |
||
134 | the central directory. The results will look vaguely like the following: |
||
135 | |||
136 | Length Method Size Ratio Date Time CRC-32 Name ("^" ==> case |
||
137 | -------- ------ ------- ----- ---- ---- ------ ---- conversion) |
||
138 | 44004 Implode 13041 71% 11-02-89 19:34 8b4207f7 Makefile.UNIX |
||
139 | 3438 Shrunk 2209 36% 09-15-90 14:07 a2394fd8 ^dos-file.ext |
||
140 | 16717 Defl:X 5252 69% 11-03-97 06:40 1ce0f189 WHERE |
||
141 | -------- ------- --- ------- |
||
142 | 64159 20502 68% 3 files |
||
143 | ---------------------------------------------------------------------------*/ |
||
144 | |||
145 | G.pInfo = &info; |
||
146 | date_format = DATE_FORMAT; |
||
147 | dt_sepchar = DATE_SEPCHAR; |
||
148 | |||
149 | #ifndef WINDLL |
||
150 | if (uO.qflag < 2) { |
||
151 | if (uO.L_flag) |
||
152 | Info(slide, 0, ((char *)slide, LoadFarString(CaseConversion), |
||
153 | LoadFarStringSmall(Headers[longhdr][0]), |
||
154 | LoadFarStringSmall2(Headers[longhdr][1]))); |
||
155 | else |
||
156 | Info(slide, 0, ((char *)slide, "%s\n%s\n", |
||
157 | LoadFarString(Headers[longhdr][0]), |
||
158 | LoadFarStringSmall(Headers[longhdr][1]))); |
||
159 | } |
||
160 | #endif /* !WINDLL */ |
||
161 | |||
162 | for (j = 1L;;j++) { |
||
163 | |||
164 | if (readbuf(__G__ G.sig, 4) == 0) |
||
165 | return PK_EOF; |
||
166 | if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a CentDir entry? */ |
||
167 | /* no new central directory entry |
||
168 | * -> is the number of processed entries compatible with the |
||
169 | * number of entries as stored in the end_central record? |
||
170 | */ |
||
171 | if (((j - 1) & |
||
172 | (ulg)(G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16)) |
||
173 | == (ulg)G.ecrec.total_entries_central_dir) |
||
174 | { |
||
175 | /* "j modulus 4T/64k" matches the reported 64/16-bit-unsigned |
||
176 | * number of directory entries -> probably, the regular |
||
177 | * end of the central directory has been reached |
||
178 | */ |
||
179 | break; |
||
180 | } else { |
||
181 | Info(slide, 0x401, |
||
182 | ((char *)slide, LoadFarString(CentSigMsg), j)); |
||
183 | Info(slide, 0x401, |
||
184 | ((char *)slide, LoadFarString(ReportMsg))); |
||
185 | return PK_BADERR; /* sig not found */ |
||
186 | } |
||
187 | } |
||
188 | /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */ |
||
189 | if ((error = process_cdir_file_hdr(__G)) != PK_COOL) |
||
190 | return error; /* only PK_EOF defined */ |
||
191 | |||
192 | /* |
||
193 | * We could DISPLAY the filename instead of storing (and possibly trun- |
||
194 | * cating, in the case of a very long name) and printing it, but that |
||
195 | * has the disadvantage of not allowing case conversion--and it's nice |
||
196 | * to be able to see in the listing precisely how you have to type each |
||
197 | * filename in order for unzip to consider it a match. Speaking of |
||
198 | * which, if member names were specified on the command line, check in |
||
199 | * with match() to see if the current file is one of them, and make a |
||
200 | * note of it if it is. |
||
201 | */ |
||
202 | |||
203 | if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != |
||
204 | PK_COOL) /* ^--(uses pInfo->lcflag) */ |
||
205 | { |
||
206 | error_in_archive = error; |
||
207 | if (error > PK_WARN) /* fatal: can't continue */ |
||
208 | return error; |
||
209 | } |
||
210 | if (G.extra_field != (uch *)NULL) { |
||
211 | free(G.extra_field); |
||
212 | G.extra_field = (uch *)NULL; |
||
213 | } |
||
214 | if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) |
||
215 | != 0) |
||
216 | { |
||
217 | error_in_archive = error; |
||
218 | if (error > PK_WARN) /* fatal */ |
||
219 | return error; |
||
220 | } |
||
221 | if (!G.process_all_files) { /* check if specified on command line */ |
||
222 | unsigned i; |
||
223 | |||
224 | if (G.filespecs == 0) |
||
225 | do_this_file = TRUE; |
||
226 | else { /* check if this entry matches an `include' argument */ |
||
227 | do_this_file = FALSE; |
||
228 | for (i = 0; i < G.filespecs; i++) |
||
229 | if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { |
||
230 | do_this_file = TRUE; |
||
231 | break; /* found match, so stop looping */ |
||
232 | } |
||
233 | } |
||
234 | if (do_this_file) { /* check if this is an excluded file */ |
||
235 | for (i = 0; i < G.xfilespecs; i++) |
||
236 | if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { |
||
237 | do_this_file = FALSE; /* ^-- ignore case in match */ |
||
238 | break; |
||
239 | } |
||
240 | } |
||
241 | } |
||
242 | /* |
||
243 | * If current file was specified on command line, or if no names were |
||
244 | * specified, do the listing for this file. Otherwise, get rid of the |
||
245 | * file comment and go back for the next file. |
||
246 | */ |
||
247 | |||
248 | if (G.process_all_files || do_this_file) { |
||
249 | |||
250 | #ifdef OS2DLL |
||
251 | /* this is used by UzpFileTree() to allow easy processing of lists |
||
252 | * of zip directory contents */ |
||
253 | if (G.processExternally) { |
||
254 | if ((G.processExternally)(G.filename, &G.crec)) |
||
255 | break; |
||
256 | ++members; |
||
257 | } else { |
||
258 | #endif |
||
259 | #ifdef OS2_EAS |
||
260 | { |
||
261 | uch *ef_ptr = G.extra_field; |
||
262 | int ef_size, ef_len = G.crec.extra_field_length; |
||
263 | ea_size = acl_size = 0; |
||
264 | |||
265 | while (ef_len >= EB_HEADSIZE) { |
||
266 | ef_size = makeword(&ef_ptr[EB_LEN]); |
||
267 | switch (makeword(&ef_ptr[EB_ID])) { |
||
268 | case EF_OS2: |
||
269 | ea_size = makelong(&ef_ptr[EB_HEADSIZE]); |
||
270 | break; |
||
271 | case EF_ACL: |
||
272 | acl_size = makelong(&ef_ptr[EB_HEADSIZE]); |
||
273 | break; |
||
274 | } |
||
275 | ef_ptr += (ef_size + EB_HEADSIZE); |
||
276 | ef_len -= (ef_size + EB_HEADSIZE); |
||
277 | } |
||
278 | } |
||
279 | #endif |
||
280 | #ifdef USE_EF_UT_TIME |
||
281 | if (G.extra_field && |
||
282 | #ifdef IZ_CHECK_TZ |
||
283 | G.tz_is_valid && |
||
284 | #endif |
||
285 | (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1, |
||
286 | G.crec.last_mod_dos_datetime, &z_utime, NULL) |
||
287 | & EB_UT_FL_MTIME)) |
||
288 | { |
||
289 | TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0, Mac */ |
||
290 | t = localtime(&(z_utime.mtime)); |
||
291 | } else |
||
292 | t = (struct tm *)NULL; |
||
293 | if (t != (struct tm *)NULL) { |
||
294 | mo = (unsigned)(t->tm_mon + 1); |
||
295 | dy = (unsigned)(t->tm_mday); |
||
296 | yr = (unsigned)(t->tm_year + 1900); |
||
297 | hh = (unsigned)(t->tm_hour); |
||
298 | mm = (unsigned)(t->tm_min); |
||
299 | } else |
||
300 | #endif /* USE_EF_UT_TIME */ |
||
301 | { |
||
302 | yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f) |
||
303 | + 1980)); |
||
304 | mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f); |
||
305 | dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f); |
||
306 | hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f); |
||
307 | mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f); |
||
308 | } |
||
309 | /* permute date so it displays according to nat'l convention |
||
310 | * ('methnum' is not yet set, it is used as temporary buffer) */ |
||
311 | switch (date_format) { |
||
312 | case DF_YMD: |
||
313 | methnum = mo; |
||
314 | mo = yr; yr = dy; dy = methnum; |
||
315 | break; |
||
316 | case DF_DMY: |
||
317 | methnum = mo; |
||
318 | mo = dy; dy = methnum; |
||
319 | } |
||
320 | |||
321 | csiz = G.crec.csize; |
||
322 | if (G.crec.general_purpose_bit_flag & 1) |
||
323 | csiz -= 12; /* if encrypted, don't count encryption header */ |
||
324 | if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) { |
||
325 | #ifndef WINDLL |
||
326 | sgn = '-'; |
||
327 | #endif |
||
328 | cfactor = (-cfactor + 5) / 10; |
||
329 | } else { |
||
330 | #ifndef WINDLL |
||
331 | sgn = ' '; |
||
332 | #endif |
||
333 | cfactor = (cfactor + 5) / 10; |
||
334 | } |
||
335 | |||
336 | methnum = find_compr_idx(G.crec.compression_method); |
||
337 | zfstrcpy(methbuf, method[methnum]); |
||
338 | if (G.crec.compression_method == DEFLATED || |
||
339 | G.crec.compression_method == ENHDEFLATED) { |
||
340 | methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3]; |
||
341 | } else if (methnum >= NUM_METHODS) { |
||
342 | sprintf(&methbuf[4], "%03u", G.crec.compression_method); |
||
343 | } |
||
344 | |||
345 | #if 0 /* GRR/Euro: add this? */ |
||
346 | #if defined(DOS_FLX_NLM_OS2_W32) || defined(THEOS) || defined(UNIX) |
||
347 | for (p = G.filename; *p; ++p) |
||
348 | if (!isprint(*p)) |
||
349 | *p = '?'; /* change non-printable chars to '?' */ |
||
350 | #endif /* DOS_FLX_NLM_OS2_W32 || THEOS || UNIX */ |
||
351 | #endif /* 0 */ |
||
352 | |||
353 | #ifdef WINDLL |
||
354 | /* send data to application for formatting and printing */ |
||
355 | if (G.lpUserFunctions->SendApplicationMessage != NULL) |
||
356 | (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize, |
||
357 | csiz, (unsigned)cfactor, mo, dy, yr, hh, mm, |
||
358 | (char)(G.pInfo->lcflag ? '^' : ' '), |
||
359 | (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)), |
||
360 | (LPCSTR)methbuf, G.crec.crc32, |
||
361 | (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' ')); |
||
362 | else if (G.lpUserFunctions->SendApplicationMessage_i32 != NULL) { |
||
363 | unsigned long ucsize_lo, csiz_lo; |
||
364 | unsigned long ucsize_hi=0L, csiz_hi=0L; |
||
365 | ucsize_lo = (unsigned long)(G.crec.ucsize); |
||
366 | csiz_lo = (unsigned long)(csiz); |
||
367 | #ifdef ZIP64_SUPPORT |
||
368 | ucsize_hi = (unsigned long)(G.crec.ucsize >> 32); |
||
369 | csiz_hi = (unsigned long)(csiz >> 32); |
||
370 | #endif /* ZIP64_SUPPORT */ |
||
371 | (*G.lpUserFunctions->SendApplicationMessage_i32)(ucsize_lo, |
||
372 | ucsize_hi, csiz_lo, csiz_hi, (unsigned)cfactor, |
||
373 | mo, dy, yr, hh, mm, |
||
374 | (char)(G.pInfo->lcflag ? '^' : ' '), |
||
375 | (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)), |
||
376 | (LPCSTR)methbuf, G.crec.crc32, |
||
377 | (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' ')); |
||
378 | } |
||
379 | #else /* !WINDLL */ |
||
380 | if (cfactor == 100) |
||
381 | sprintf(cfactorstr, LoadFarString(CompFactor100)); |
||
382 | else |
||
383 | sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor); |
||
384 | if (longhdr) |
||
385 | Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats), |
||
386 | FmZofft(G.crec.ucsize, "8", "u"), methbuf, |
||
387 | FmZofft(csiz, "8", "u"), cfactorstr, |
||
388 | mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm, |
||
389 | G.crec.crc32, (G.pInfo->lcflag? '^':' '))); |
||
390 | else |
||
391 | #ifdef OS2_EAS |
||
392 | Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats), |
||
393 | FmZofft(G.crec.ucsize, "9", "u"), ea_size, acl_size, |
||
394 | mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm, |
||
395 | (G.pInfo->lcflag? '^':' '))); |
||
396 | #else |
||
397 | Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats), |
||
398 | FmZofft(G.crec.ucsize, "9", "u"), |
||
399 | mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm, |
||
400 | (G.pInfo->lcflag? '^':' '))); |
||
401 | #endif |
||
402 | fnprint(__G); |
||
403 | #endif /* ?WINDLL */ |
||
404 | |||
405 | if ((error = do_string(__G__ G.crec.file_comment_length, |
||
406 | QCOND? DISPL_8 : SKIP)) != 0) |
||
407 | { |
||
408 | error_in_archive = error; /* might be just warning */ |
||
409 | if (error > PK_WARN) /* fatal */ |
||
410 | return error; |
||
411 | } |
||
412 | tot_ucsize += G.crec.ucsize; |
||
413 | tot_csize += csiz; |
||
414 | ++members; |
||
415 | #ifdef OS2_EAS |
||
416 | if (ea_size) { |
||
417 | tot_easize += ea_size; |
||
418 | ++tot_eafiles; |
||
419 | } |
||
420 | if (acl_size) { |
||
421 | tot_aclsize += acl_size; |
||
422 | ++tot_aclfiles; |
||
423 | } |
||
424 | #endif |
||
425 | #ifdef OS2DLL |
||
426 | } /* end of "if (G.processExternally) {...} else {..." */ |
||
427 | #endif |
||
428 | } else { /* not listing this file */ |
||
429 | SKIP_(G.crec.file_comment_length) |
||
430 | } |
||
431 | } /* end for-loop (j: files in central directory) */ |
||
432 | |||
433 | /*--------------------------------------------------------------------------- |
||
434 | Print footer line and totals (compressed size, uncompressed size, number |
||
435 | of members in zipfile). |
||
436 | ---------------------------------------------------------------------------*/ |
||
437 | |||
438 | if (uO.qflag < 2 |
||
439 | #ifdef OS2DLL |
||
440 | && !G.processExternally |
||
441 | #endif |
||
442 | ) { |
||
443 | if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) { |
||
444 | #ifndef WINDLL |
||
445 | sgn = '-'; |
||
446 | #endif |
||
447 | cfactor = (-cfactor + 5) / 10; |
||
448 | } else { |
||
449 | #ifndef WINDLL |
||
450 | sgn = ' '; |
||
451 | #endif |
||
452 | cfactor = (cfactor + 5) / 10; |
||
453 | } |
||
454 | #ifdef WINDLL |
||
455 | /* pass the totals back to the calling application */ |
||
456 | G.lpUserFunctions->TotalSizeComp = tot_csize; |
||
457 | G.lpUserFunctions->TotalSize = tot_ucsize; |
||
458 | G.lpUserFunctions->CompFactor = (ulg)cfactor; |
||
459 | G.lpUserFunctions->NumMembers = members; |
||
460 | |||
461 | #else /* !WINDLL */ |
||
462 | if (cfactor == 100) |
||
463 | sprintf(cfactorstr, LoadFarString(CompFactor100)); |
||
464 | else |
||
465 | sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor); |
||
466 | if (longhdr) { |
||
467 | Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer), |
||
468 | FmZofft(tot_ucsize, "8", "u"), FmZofft(tot_csize, "8", "u"), |
||
469 | cfactorstr, members, members==1? "":"s")); |
||
470 | #ifdef OS2_EAS |
||
471 | if (tot_easize || tot_aclsize) |
||
472 | Info(slide, 0, ((char *)slide, "\n")); |
||
473 | if (tot_eafiles && tot_easize) |
||
474 | Info(slide, 0, ((char *)slide, LoadFarString(OS2ExtAttrTrailer), |
||
475 | tot_eafiles, tot_eafiles == 1? " has" : "s have a total of", |
||
476 | tot_easize)); |
||
477 | if (tot_aclfiles && tot_aclsize) |
||
478 | Info(slide, 0, ((char *)slide, LoadFarString(OS2ACLTrailer), |
||
479 | tot_aclfiles, |
||
480 | tot_aclfiles == 1 ? " has" : "s have a total of", |
||
481 | tot_aclsize)); |
||
482 | #endif /* OS2_EAS */ |
||
483 | } else |
||
484 | #ifdef OS2_EAS |
||
485 | Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer), |
||
486 | FmZofft(tot_ucsize, "9", "u"), tot_easize, tot_aclsize, |
||
487 | members, members == 1 ? "" : "s")); |
||
488 | #else |
||
489 | Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer), |
||
490 | FmZofft(tot_ucsize, "9", "u"), |
||
491 | members, members == 1 ? "" : "s")); |
||
492 | #endif /* OS2_EAS */ |
||
493 | #endif /* ?WINDLL */ |
||
494 | } |
||
495 | |||
496 | /* Skip the following checks in case of a premature listing break. */ |
||
497 | if (error_in_archive <= PK_WARN) { |
||
498 | |||
499 | /*--------------------------------------------------------------------------- |
||
500 | Double check that we're back at the end-of-central-directory record. |
||
501 | ---------------------------------------------------------------------------*/ |
||
502 | |||
503 | if ( (memcmp(G.sig, |
||
504 | (G.ecrec.have_ecr64 ? |
||
505 | end_central64_sig : end_central_sig), |
||
506 | 4) != 0) |
||
507 | && (!G.ecrec.is_zip64_archive) |
||
508 | && (memcmp(G.sig, end_central_sig, 4) != 0) |
||
509 | ) { /* just to make sure again */ |
||
510 | Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); |
||
511 | error_in_archive = PK_WARN; /* didn't find sig */ |
||
512 | } |
||
513 | |||
514 | /* Set specific return code when no files have been found. */ |
||
515 | if (members == 0L && error_in_archive <= PK_WARN) |
||
516 | error_in_archive = PK_FIND; |
||
517 | |||
518 | } |
||
519 | |||
520 | return error_in_archive; |
||
521 | |||
522 | } /* end function list_files() */ |
||
523 | |||
524 | |||
525 | |||
526 | |||
527 | |||
528 | #ifdef TIMESTAMP |
||
529 | |||
530 | /************************/ |
||
531 | /* Function fn_is_dir() */ |
||
532 | /************************/ |
||
533 | |||
534 | static int fn_is_dir(__G) /* returns TRUE if G.filename is directory */ |
||
535 | __GDEF |
||
536 | { |
||
537 | extent fn_len = strlen(G.filename); |
||
538 | register char endc; |
||
539 | |||
540 | return fn_len > 0 && |
||
541 | ((endc = lastchar(G.filename, fn_len)) == '/' || |
||
542 | (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/') && |
||
543 | endc == '\\')); |
||
544 | } |
||
545 | |||
546 | |||
547 | |||
548 | |||
549 | |||
550 | /*****************************/ |
||
551 | /* Function get_time_stamp() */ |
||
552 | /*****************************/ |
||
553 | |||
554 | int get_time_stamp(__G__ last_modtime, nmember) /* return PK-type error code */ |
||
555 | __GDEF |
||
556 | time_t *last_modtime; |
||
557 | ulg *nmember; |
||
558 | { |
||
559 | int do_this_file=FALSE, error, error_in_archive=PK_COOL; |
||
560 | ulg j; |
||
561 | #ifdef USE_EF_UT_TIME |
||
562 | iztimes z_utime; |
||
563 | #endif |
||
564 | min_info info; |
||
565 | |||
566 | |||
567 | /*--------------------------------------------------------------------------- |
||
568 | Unlike extract_or_test_files() but like list_files(), this function works |
||
569 | on information in the central directory alone. Thus we have a single, |
||
570 | large loop through the entire directory, searching for the latest time |
||
571 | stamp. |
||
572 | ---------------------------------------------------------------------------*/ |
||
573 | |||
574 | *last_modtime = 0L; /* assuming no zipfile data older than 1970 */ |
||
575 | *nmember = 0L; |
||
576 | G.pInfo = &info; |
||
577 | |||
578 | for (j = 1L;; j++) { |
||
579 | |||
580 | if (readbuf(__G__ G.sig, 4) == 0) |
||
581 | return PK_EOF; |
||
582 | if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a CentDir entry? */ |
||
583 | if (((unsigned)(j - 1) & (unsigned)0xFFFF) == |
||
584 | (unsigned)G.ecrec.total_entries_central_dir) { |
||
585 | /* "j modulus 64k" matches the reported 16-bit-unsigned |
||
586 | * number of directory entries -> probably, the regular |
||
587 | * end of the central directory has been reached |
||
588 | */ |
||
589 | break; |
||
590 | } else { |
||
591 | Info(slide, 0x401, |
||
592 | ((char *)slide, LoadFarString(CentSigMsg), j)); |
||
593 | Info(slide, 0x401, |
||
594 | ((char *)slide, LoadFarString(ReportMsg))); |
||
595 | return PK_BADERR; /* sig not found */ |
||
596 | } |
||
597 | } |
||
598 | /* process_cdir_file_hdr() sets pInfo->lcflag: */ |
||
599 | if ((error = process_cdir_file_hdr(__G)) != PK_COOL) |
||
600 | return error; /* only PK_EOF defined */ |
||
601 | if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_OK) |
||
602 | { /* ^-- (uses pInfo->lcflag) */ |
||
603 | error_in_archive = error; |
||
604 | if (error > PK_WARN) /* fatal: can't continue */ |
||
605 | return error; |
||
606 | } |
||
607 | if (G.extra_field != (uch *)NULL) { |
||
608 | free(G.extra_field); |
||
609 | G.extra_field = (uch *)NULL; |
||
610 | } |
||
611 | if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) |
||
612 | != 0) |
||
613 | { |
||
614 | error_in_archive = error; |
||
615 | if (error > PK_WARN) /* fatal */ |
||
616 | return error; |
||
617 | } |
||
618 | if (!G.process_all_files) { /* check if specified on command line */ |
||
619 | unsigned i; |
||
620 | |||
621 | if (G.filespecs == 0) |
||
622 | do_this_file = TRUE; |
||
623 | else { /* check if this entry matches an `include' argument */ |
||
624 | do_this_file = FALSE; |
||
625 | for (i = 0; i < G.filespecs; i++) |
||
626 | if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { |
||
627 | do_this_file = TRUE; |
||
628 | break; /* found match, so stop looping */ |
||
629 | } |
||
630 | } |
||
631 | if (do_this_file) { /* check if this is an excluded file */ |
||
632 | for (i = 0; i < G.xfilespecs; i++) |
||
633 | if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { |
||
634 | do_this_file = FALSE; /* ^-- ignore case in match */ |
||
635 | break; |
||
636 | } |
||
637 | } |
||
638 | } |
||
639 | |||
640 | /* If current file was specified on command line, or if no names were |
||
641 | * specified, check the time for this file. Either way, get rid of the |
||
642 | * file comment and go back for the next file. |
||
643 | * Directory entries are always ignored, to stay compatible with both |
||
644 | * Zip and PKZIP. |
||
645 | */ |
||
646 | if ((G.process_all_files || do_this_file) && !fn_is_dir(__G)) { |
||
647 | #ifdef USE_EF_UT_TIME |
||
648 | if (G.extra_field && |
||
649 | #ifdef IZ_CHECK_TZ |
||
650 | G.tz_is_valid && |
||
651 | #endif |
||
652 | (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1, |
||
653 | G.crec.last_mod_dos_datetime, &z_utime, NULL) |
||
654 | & EB_UT_FL_MTIME)) |
||
655 | { |
||
656 | if (*last_modtime < z_utime.mtime) |
||
657 | *last_modtime = z_utime.mtime; |
||
658 | } else |
||
659 | #endif /* USE_EF_UT_TIME */ |
||
660 | { |
||
661 | time_t modtime = dos_to_unix_time(G.crec.last_mod_dos_datetime); |
||
662 | |||
663 | if (*last_modtime < modtime) |
||
664 | *last_modtime = modtime; |
||
665 | } |
||
666 | ++*nmember; |
||
667 | } |
||
668 | SKIP_(G.crec.file_comment_length) |
||
669 | |||
670 | } /* end for-loop (j: files in central directory) */ |
||
671 | |||
672 | /*--------------------------------------------------------------------------- |
||
673 | Double check that we're back at the end-of-central-directory record. |
||
674 | ---------------------------------------------------------------------------*/ |
||
675 | |||
676 | if (memcmp(G.sig, end_central_sig, 4)) { /* just to make sure again */ |
||
677 | Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); |
||
678 | error_in_archive = PK_WARN; |
||
679 | } |
||
680 | if (*nmember == 0L && error_in_archive <= PK_WARN) |
||
681 | error_in_archive = PK_FIND; |
||
682 | |||
683 | return error_in_archive; |
||
684 | |||
685 | } /* end function get_time_stamp() */ |
||
686 | |||
687 | #endif /* TIMESTAMP */ |
||
688 | |||
689 | |||
690 | |||
691 | |||
692 | |||
693 | /********************/ |
||
694 | /* Function ratio() */ /* also used by ZipInfo routines */ |
||
695 | /********************/ |
||
696 | |||
697 | int ratio(uc, c) |
||
698 | zusz_t uc, c; |
||
699 | { |
||
700 | zusz_t denom; |
||
701 | |||
702 | if (uc == 0) |
||
703 | return 0; |
||
704 | if (uc > 2000000L) { /* risk signed overflow if multiply numerator */ |
||
705 | denom = uc / 1000L; |
||
706 | return ((uc >= c) ? |
||
707 | (int) ((uc-c + (denom>>1)) / denom) : |
||
708 | -((int) ((c-uc + (denom>>1)) / denom))); |
||
709 | } else { /* ^^^^^^^^ rounding */ |
||
710 | denom = uc; |
||
711 | return ((uc >= c) ? |
||
712 | (int) ((1000L*(uc-c) + (denom>>1)) / denom) : |
||
713 | -((int) ((1000L*(c-uc) + (denom>>1)) / denom))); |
||
714 | } /* ^^^^^^^^ rounding */ |
||
715 | } |
||
716 | |||
717 | |||
718 | |||
719 | |||
720 | |||
721 | /************************/ |
||
722 | /* Function fnprint() */ /* also used by ZipInfo routines */ |
||
723 | /************************/ |
||
724 | |||
725 | void fnprint(__G) /* print filename (after filtering) and newline */ |
||
726 | __GDEF |
||
727 | { |
||
728 | char *name = fnfilter(G.filename, slide, (extent)(WSIZE>>1)); |
||
729 | |||
730 | (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0); |
||
731 | (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); |
||
732 | |||
733 | } /* end function fnprint() */=>>>>>=>=>>>>>>> |