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