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