]> git.saurik.com Git - wxWidgets.git/blob - utils/Install/packzip/list.c
This is how wxPlotWindow would look like with the
[wxWidgets.git] / utils / Install / packzip / list.c
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() */