]> git.saurik.com Git - wxWidgets.git/blob - utils/Install/sfxzip/list.c
Menuing and statusbar updates
[wxWidgets.git] / utils / Install / sfxzip / 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
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() */