which included commits to RCS files with non-trunk default branches. git-svn-id: svn://10.65.10.50/trunk@5403 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			636 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			636 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*---------------------------------------------------------------------------
 | 
						|
 | 
						|
  list.c
 | 
						|
 | 
						|
  This file contains the non-ZipInfo-specific listing routines for UnZip.
 | 
						|
 | 
						|
  Contains:  list_files()
 | 
						|
             time_stamp()       [still experimental and Unix-only]
 | 
						|
             ratio()
 | 
						|
             fnprint()
 | 
						|
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
 | 
						|
#define UNZIP_INTERNAL
 | 
						|
#include "unzip.h"
 | 
						|
#ifdef WINDLL
 | 
						|
#  ifdef POCKET_UNZIP
 | 
						|
#    include "wince/intrface.h"
 | 
						|
#  else
 | 
						|
#    include "windll/windll.h"
 | 
						|
#  endif
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
#ifdef TIME_STAMP
 | 
						|
   static int  fn_is_dir   OF((__GPRO));
 | 
						|
#endif
 | 
						|
 | 
						|
/* GRR 970327:  Headers*[] formerly referenced in WinGUI code; no longer? */
 | 
						|
 | 
						|
#ifdef OS2_EAS
 | 
						|
   char Far HeadersS[]  = " Length    EAs   ACLs    Date    Time    Name";
 | 
						|
   char Far HeadersS1[] = " ------    ---   ----    ----    ----    ----";
 | 
						|
#else
 | 
						|
   char Far HeadersS[]  = " Length    Date    Time    Name";
 | 
						|
   char Far HeadersS1[] = " ------    ----    ----    ----";
 | 
						|
#endif
 | 
						|
 | 
						|
static char Far CompFactorStr[] = "%c%d%%";
 | 
						|
static char Far CompFactor100[] = "100%%";
 | 
						|
 | 
						|
#ifndef WINDLL
 | 
						|
   char Far HeadersL[]  =
 | 
						|
     " Length  Method   Size  Ratio   Date    Time   CRC-32     Name";
 | 
						|
   char Far HeadersL1[] =
 | 
						|
     " ------  ------   ----  -----   ----    ----   ------     ----";
 | 
						|
   char Far *Headers[][2] = { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} };
 | 
						|
 | 
						|
   static char Far CaseConversion[] = "%s (\"^\" ==> case\n%s   conversion)\n";
 | 
						|
   static char Far LongHdrStats[] =
 | 
						|
     "%7lu  %-7s%7lu %4s  %02u-%02u-%02u  %02u:%02u  %08lx  %c";
 | 
						|
   static char Far LongFileTrailer[] =
 | 
						|
     " ------          ------  ---                         \
 | 
						|
     -------\n%7lu         %7lu %4s                              %u file%s\n";
 | 
						|
#ifdef OS2_EAS
 | 
						|
   static char Far ShortHdrStats[] =
 | 
						|
     "%7lu %6lu %6lu  %02u-%02u-%02u  %02u:%02u  %c";
 | 
						|
   static char Far ShortFileTrailer[] = " ------  -----  -----        \
 | 
						|
            -------\n%7lu %6lu %6lu                    %u file%s\n";
 | 
						|
   static char Far OS2ExtAttrTrailer[] =
 | 
						|
      "%ld file%s %ld bytes of OS/2 extended attributes attached.\n";
 | 
						|
   static char Far OS2ACLTrailer[] =
 | 
						|
      "%ld file%s %ld bytes of access control lists attached.\n";
 | 
						|
#else
 | 
						|
   static char Far ShortHdrStats[] = "%7lu  %02u-%02u-%02u  %02u:%02u  %c";
 | 
						|
   static char Far ShortFileTrailer[] =
 | 
						|
     " ------                    -------\n%7lu                    %u file%s\n";
 | 
						|
#endif /* ?OS2_EAS */
 | 
						|
#endif /* ?WINDLL */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*************************/
 | 
						|
/* Function list_files() */
 | 
						|
/*************************/
 | 
						|
 | 
						|
int list_files(__G)    /* return PK-type error code */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    char sgn, cfactorstr[10];
 | 
						|
    int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
 | 
						|
#ifndef WINDLL
 | 
						|
    int longhdr=(G.vflag>1);
 | 
						|
#endif
 | 
						|
    int date_format;
 | 
						|
    unsigned methnum;
 | 
						|
#ifdef USE_EF_UT_TIME
 | 
						|
    iztimes z_utime;
 | 
						|
#endif
 | 
						|
    ush j, yr, mo, dy, hh, mm, members=0;
 | 
						|
    ulg csiz, tot_csize=0L, tot_ucsize=0L;
 | 
						|
#ifdef OS2_EAS
 | 
						|
    ulg ea_size, tot_easize=0L, tot_eafiles=0L;
 | 
						|
    ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L;
 | 
						|
#endif
 | 
						|
    min_info info;
 | 
						|
    char methbuf[8];
 | 
						|
    static char dtype[]="NXFS";   /* see zi_short() */
 | 
						|
    static char Far method[NUM_METHODS+1][8] =
 | 
						|
        {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
 | 
						|
         "Implode", "Token", "Defl:#", "EnhDefl", "ImplDCL", "Unk:###"};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Unlike extract_or_test_files(), this routine confines itself to the cen-
 | 
						|
    tral directory.  Thus its structure is somewhat simpler, since we can do
 | 
						|
    just a single loop through the entire directory, listing files as we go.
 | 
						|
 | 
						|
    So to start off, print the heading line and then begin main loop through
 | 
						|
    the central directory.  The results will look vaguely like the following:
 | 
						|
 | 
						|
  Length  Method   Size  Ratio   Date    Time   CRC-32     Name ("^" ==> case
 | 
						|
  ------  ------   ----  -----   ----    ----   ------     ----   conversion)
 | 
						|
   44004  Implode  13041  71%  11-02-89  19:34  8b4207f7   Makefile.UNIX
 | 
						|
    3438  Shrunk    2209  36%  09-15-90  14:07  a2394fd8  ^dos-file.ext
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    G.pInfo = &info;
 | 
						|
    date_format = DATE_FORMAT;
 | 
						|
 | 
						|
#ifndef WINDLL
 | 
						|
    if (G.qflag < 2)
 | 
						|
        if (G.L_flag)
 | 
						|
            Info(slide, 0, ((char *)slide, LoadFarString(CaseConversion),
 | 
						|
              LoadFarStringSmall(Headers[longhdr][0]),
 | 
						|
              LoadFarStringSmall2(Headers[longhdr][1])));
 | 
						|
        else
 | 
						|
            Info(slide, 0, ((char *)slide, "%s\n%s\n",
 | 
						|
               LoadFarString(Headers[longhdr][0]),
 | 
						|
               LoadFarStringSmall(Headers[longhdr][1])));
 | 
						|
#endif /* !WINDLL */
 | 
						|
 | 
						|
    for (j = 0; j < G.ecrec.total_entries_central_dir; ++j) {
 | 
						|
 | 
						|
        if (readbuf(__G__ G.sig, 4) == 0)
 | 
						|
            return PK_EOF;
 | 
						|
        if (strncmp(G.sig, G.central_hdr_sig, 4)) {  /* just to make sure */
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
 | 
						|
            return PK_BADERR;
 | 
						|
        }
 | 
						|
        /* process_cdir_file_hdr() sets pInfo->lcflag: */
 | 
						|
        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
 | 
						|
            return error;       /* only PK_EOF defined */
 | 
						|
 | 
						|
        /*
 | 
						|
         * We could DISPLAY the filename instead of storing (and possibly trun-
 | 
						|
         * cating, in the case of a very long name) and printing it, but that
 | 
						|
         * has the disadvantage of not allowing case conversion--and it's nice
 | 
						|
         * to be able to see in the listing precisely how you have to type each
 | 
						|
         * filename in order for unzip to consider it a match.  Speaking of
 | 
						|
         * which, if member names were specified on the command line, check in
 | 
						|
         * with match() to see if the current file is one of them, and make a
 | 
						|
         * note of it if it is.
 | 
						|
         */
 | 
						|
 | 
						|
        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
 | 
						|
             PK_COOL)   /*  ^--(uses pInfo->lcflag) */
 | 
						|
        {
 | 
						|
            error_in_archive = error;
 | 
						|
            if (error > PK_WARN)   /* fatal:  can't continue */
 | 
						|
                return error;
 | 
						|
        }
 | 
						|
        if (G.extra_field != (uch *)NULL) {
 | 
						|
            free(G.extra_field);
 | 
						|
            G.extra_field = (uch *)NULL;
 | 
						|
        }
 | 
						|
        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
 | 
						|
            != 0)
 | 
						|
        {
 | 
						|
            error_in_archive = error;
 | 
						|
            if (error > PK_WARN)      /* fatal */
 | 
						|
                return error;
 | 
						|
        }
 | 
						|
        if (!G.process_all_files) {   /* check if specified on command line */
 | 
						|
            char **pfn = G.pfnames-1;
 | 
						|
 | 
						|
            do_this_file = FALSE;
 | 
						|
            while (*++pfn)
 | 
						|
                if (match(G.filename, *pfn, G.C_flag)) {
 | 
						|
                    do_this_file = TRUE;
 | 
						|
                    break;       /* found match, so stop looping */
 | 
						|
                }
 | 
						|
            if (do_this_file) {  /* check if this is an excluded file */
 | 
						|
                char **pxn = G.pxnames-1;
 | 
						|
 | 
						|
                while (*++pxn)
 | 
						|
                    if (match(G.filename, *pxn, G.C_flag)) {
 | 
						|
                        do_this_file = FALSE;  /* ^-- ignore case in match */
 | 
						|
                        break;
 | 
						|
                    }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        /*
 | 
						|
         * If current file was specified on command line, or if no names were
 | 
						|
         * specified, do the listing for this file.  Otherwise, get rid of the
 | 
						|
         * file comment and go back for the next file.
 | 
						|
         */
 | 
						|
 | 
						|
        if (G.process_all_files || do_this_file) {
 | 
						|
 | 
						|
#ifdef OS2DLL
 | 
						|
            /* this is used by UzpFileTree() to allow easy processing of lists
 | 
						|
             * of zip directory contents */
 | 
						|
            if (G.processExternally)
 | 
						|
                if ((G.processExternally)(G.filename, &G.crec))
 | 
						|
                    break;
 | 
						|
                else
 | 
						|
                    continue;
 | 
						|
#endif
 | 
						|
#ifdef OS2_EAS
 | 
						|
            {
 | 
						|
                uch *ef_ptr = G.extra_field;
 | 
						|
                int ef_size, ef_len = G.crec.extra_field_length;
 | 
						|
                ea_size = acl_size = 0;
 | 
						|
 | 
						|
                while (ef_len >= EB_HEADSIZE) {
 | 
						|
                    ef_size = makeword(&ef_ptr[EB_LEN]);
 | 
						|
                    switch (makeword(&ef_ptr[EB_ID])) {
 | 
						|
                        case EF_OS2:
 | 
						|
                            ea_size = makelong(&ef_ptr[EB_HEADSIZE]);
 | 
						|
                            break;
 | 
						|
                        case EF_ACL:
 | 
						|
                            acl_size = makelong(&ef_ptr[EB_HEADSIZE]);
 | 
						|
                            break;
 | 
						|
                    }
 | 
						|
                    ef_ptr += (ef_size + EB_HEADSIZE);
 | 
						|
                    ef_len -= (ef_size + EB_HEADSIZE);
 | 
						|
                }
 | 
						|
            }
 | 
						|
#endif
 | 
						|
#ifdef USE_EF_UT_TIME
 | 
						|
            if (G.extra_field &&
 | 
						|
                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
 | 
						|
                                  &z_utime, NULL) & EB_UT_FL_MTIME))
 | 
						|
            {
 | 
						|
                struct tm *t;
 | 
						|
 | 
						|
                TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0, Mac */
 | 
						|
                t = localtime(&(z_utime.mtime));
 | 
						|
                switch (date_format) {
 | 
						|
                    case DF_YMD:
 | 
						|
                        mo = (ush)(t->tm_year);
 | 
						|
                        dy = (ush)(t->tm_mon + 1);
 | 
						|
                        yr = (ush)(t->tm_mday);
 | 
						|
                        break;
 | 
						|
                    case DF_DMY:
 | 
						|
                        mo = (ush)(t->tm_mday);
 | 
						|
                        dy = (ush)(t->tm_mon + 1);
 | 
						|
                        yr = (ush)(t->tm_year);
 | 
						|
                        break;
 | 
						|
                    default:
 | 
						|
                        mo = (ush)(t->tm_mon + 1);
 | 
						|
                        dy = (ush)(t->tm_mday);
 | 
						|
                        yr = (ush)(t->tm_year);
 | 
						|
                }
 | 
						|
                hh = (ush)(t->tm_hour);
 | 
						|
                mm = (ush)(t->tm_min);
 | 
						|
            } else
 | 
						|
#endif /* USE_EF_UT_TIME */
 | 
						|
            {
 | 
						|
                yr = (ush)((((G.crec.last_mod_file_date >> 9) & 0x7f) + 80) %
 | 
						|
                           (unsigned)100);
 | 
						|
                mo = (ush)((G.crec.last_mod_file_date >> 5) & 0x0f);
 | 
						|
                dy = (ush)(G.crec.last_mod_file_date & 0x1f);
 | 
						|
 | 
						|
                /* permute date so it displays according to nat'l convention */
 | 
						|
                switch (date_format) {
 | 
						|
                    case DF_YMD:
 | 
						|
                        hh = mo; mo = yr; yr = dy; dy = hh;
 | 
						|
                        break;
 | 
						|
                    case DF_DMY:
 | 
						|
                        hh = mo; mo = dy; dy = hh;
 | 
						|
                }
 | 
						|
 | 
						|
                hh = (ush)((G.crec.last_mod_file_time >> 11) & 0x1f);
 | 
						|
                mm = (ush)((G.crec.last_mod_file_time >> 5) & 0x3f);
 | 
						|
            }
 | 
						|
 | 
						|
            csiz = G.crec.csize;
 | 
						|
            if (G.crec.general_purpose_bit_flag & 1)
 | 
						|
                csiz -= 12;   /* if encrypted, don't count encryption header */
 | 
						|
            if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) {
 | 
						|
                sgn = '-';
 | 
						|
                cfactor = (-cfactor + 5) / 10;
 | 
						|
            } else {
 | 
						|
                sgn = ' ';
 | 
						|
                cfactor = (cfactor + 5) / 10;
 | 
						|
            }
 | 
						|
            if (cfactor == 100)
 | 
						|
                sprintf(cfactorstr, LoadFarString(CompFactor100));
 | 
						|
            else
 | 
						|
                sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
 | 
						|
 | 
						|
            methnum = MIN(G.crec.compression_method, NUM_METHODS);
 | 
						|
            zfstrcpy(methbuf, method[methnum]);
 | 
						|
            if (methnum == DEFLATED) {
 | 
						|
                methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
 | 
						|
            } else if (methnum >= NUM_METHODS) {
 | 
						|
                sprintf(&methbuf[4], "%03u", G.crec.compression_method);
 | 
						|
            }
 | 
						|
 | 
						|
#if 0       /* GRR/Euro:  add this? */
 | 
						|
#if defined(DOS_OS2_W32) || defined(UNIX)
 | 
						|
            for (p = G.filename;  *p;  ++p)
 | 
						|
                if (!isprint(*p))
 | 
						|
                    *p = '?';  /* change non-printable chars to '?' */
 | 
						|
#endif /* DOS_OS2_W32 || UNIX */
 | 
						|
#endif /* 0 */
 | 
						|
 | 
						|
#ifdef WINDLL
 | 
						|
            /* send data to application for formatting and printing */
 | 
						|
            (*lpUserFunctions->SendApplicationMessage)(G.crec.ucsize, csiz,
 | 
						|
              (ush)cfactor, mo, dy, yr, hh, mm,
 | 
						|
              (char)(G.pInfo->lcflag ? '^' : ' '),
 | 
						|
              fnfilter(G.filename, slide), methbuf, G.crec.crc32,
 | 
						|
              (G.crec.general_purpose_bit_flag & 1)? 'E' : ' ');
 | 
						|
#else /* !WINDLL */
 | 
						|
            if (longhdr)
 | 
						|
                Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
 | 
						|
                  G.crec.ucsize, methbuf, csiz, cfactorstr, mo, dy,
 | 
						|
                  yr, hh, mm, G.crec.crc32, (G.pInfo->lcflag? '^':' ')));
 | 
						|
            else
 | 
						|
#ifdef OS2_EAS
 | 
						|
                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
 | 
						|
                  G.crec.ucsize, ea_size, acl_size,
 | 
						|
                  mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' ')));
 | 
						|
#else
 | 
						|
                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
 | 
						|
                  G.crec.ucsize,
 | 
						|
                  mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' ')));
 | 
						|
#endif
 | 
						|
            fnprint(__G);
 | 
						|
#endif /* ?WINDLL */
 | 
						|
 | 
						|
            if ((error = do_string(__G__ G.crec.file_comment_length,
 | 
						|
                                   QCOND? DISPL_8 : SKIP)) != 0)
 | 
						|
            {
 | 
						|
                error_in_archive = error;  /* might be just warning */
 | 
						|
                if (error > PK_WARN)       /* fatal */
 | 
						|
                    return error;
 | 
						|
            }
 | 
						|
            tot_ucsize += G.crec.ucsize;
 | 
						|
            tot_csize += csiz;
 | 
						|
            ++members;
 | 
						|
#ifdef OS2_EAS
 | 
						|
            if (ea_size) {
 | 
						|
                tot_easize += ea_size;
 | 
						|
                ++tot_eafiles;
 | 
						|
            }
 | 
						|
            if (acl_size) {
 | 
						|
                tot_aclsize += acl_size;
 | 
						|
                ++tot_aclfiles;
 | 
						|
            }
 | 
						|
#endif
 | 
						|
        } else {        /* not listing this file */
 | 
						|
            SKIP_(G.crec.file_comment_length)
 | 
						|
        }
 | 
						|
    } /* end for-loop (j: files in central directory) */
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Print footer line and totals (compressed size, uncompressed size, number
 | 
						|
    of members in zipfile).
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (G.qflag < 2) {
 | 
						|
        if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) {
 | 
						|
            sgn = '-';
 | 
						|
            cfactor = (-cfactor + 5) / 10;
 | 
						|
        } else {
 | 
						|
            sgn = ' ';
 | 
						|
            cfactor = (cfactor + 5) / 10;
 | 
						|
        }
 | 
						|
        if (cfactor == 100)
 | 
						|
            sprintf(cfactorstr, LoadFarString(CompFactor100));
 | 
						|
        else
 | 
						|
            sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
 | 
						|
#ifdef WINDLL
 | 
						|
        /* pass the totals back to the calling application */
 | 
						|
        lpUserFunctions->TotalSizeComp = tot_csize;
 | 
						|
        lpUserFunctions->TotalSize = tot_ucsize;
 | 
						|
        lpUserFunctions->CompFactor = cfactor;
 | 
						|
        lpUserFunctions->NumMembers = members;
 | 
						|
 | 
						|
#else /* !WINDLL */
 | 
						|
        if (longhdr) {
 | 
						|
            Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
 | 
						|
              tot_ucsize, tot_csize, cfactorstr, members, members==1? "":"s"));
 | 
						|
#ifdef OS2_EAS
 | 
						|
            if (tot_easize || tot_aclsize)
 | 
						|
                Info(slide, 0, ((char *)slide, "\n"));
 | 
						|
            if (tot_eafiles && tot_easize)
 | 
						|
                Info(slide, 0, ((char *)slide, LoadFarString(OS2ExtAttrTrailer),
 | 
						|
                  tot_eafiles, tot_eafiles == 1? " has" : "s have a total of",
 | 
						|
                  tot_easize));
 | 
						|
            if (tot_aclfiles && tot_aclsize)
 | 
						|
                Info(slide, 0, ((char *)slide, LoadFarString(OS2ACLTrailer),
 | 
						|
                  tot_aclfiles, tot_aclfiles == 1? " has" : "s have a total of",
 | 
						|
                  tot_aclsize));
 | 
						|
#endif /* OS2_EAs */
 | 
						|
        } else
 | 
						|
#ifdef OS2_EAS
 | 
						|
            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
 | 
						|
              tot_ucsize, tot_easize, tot_aclsize, members, members == 1?
 | 
						|
              "" : "s"));
 | 
						|
#else
 | 
						|
            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
 | 
						|
              tot_ucsize, members, members == 1? "" : "s"));
 | 
						|
#endif /* OS2_EAs */
 | 
						|
#endif /* ?WINDLL */
 | 
						|
    }
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Double check that we're back at the end-of-central-directory record.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (readbuf(__G__ G.sig, 4) == 0)
 | 
						|
        return PK_EOF;
 | 
						|
    if (strncmp(G.sig, G.end_central_sig, 4)) {   /* just to make sure again */
 | 
						|
        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
 | 
						|
        error_in_archive = PK_WARN;
 | 
						|
    }
 | 
						|
    if (members == 0 && error_in_archive <= PK_WARN)
 | 
						|
        error_in_archive = PK_FIND;
 | 
						|
 | 
						|
    return error_in_archive;
 | 
						|
 | 
						|
} /* end function list_files() */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#ifdef TIMESTAMP
 | 
						|
 | 
						|
/************************/
 | 
						|
/* Function fn_is_dir() */
 | 
						|
/************************/
 | 
						|
 | 
						|
static int fn_is_dir(__G)    /* returns TRUE if G.filename is directory */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    extent fn_len = strlen(G.filename);
 | 
						|
    register char   endc;
 | 
						|
 | 
						|
    return  fn_len > 0 &&
 | 
						|
            ((endc = G.filename[fn_len-1]) == '/' ||
 | 
						|
             (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/') &&
 | 
						|
              endc == '\\'));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*************************/
 | 
						|
/* Function time_stamp() */
 | 
						|
/*************************/
 | 
						|
 | 
						|
int time_stamp(__G)    /* return PK-type error code */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    int do_this_file=FALSE, error, error_in_archive=PK_COOL;
 | 
						|
    iztimes z_utime;
 | 
						|
    time_t last_modtime=0L;   /* assuming no zipfile data older than 1970 */
 | 
						|
    ush j, members=0;
 | 
						|
    min_info info;
 | 
						|
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Unlike extract_or_test_files() but like list_files(), this function works
 | 
						|
    on information in the central directory alone.  Thus we have a single,
 | 
						|
    large loop through the entire directory, searching for the latest time
 | 
						|
    stamp.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    G.pInfo = &info;
 | 
						|
 | 
						|
    for (j = 0; j < G.ecrec.total_entries_central_dir; ++j) {
 | 
						|
 | 
						|
        if (readbuf(__G__ G.sig, 4) == 0)
 | 
						|
            return PK_EOF;
 | 
						|
        if (strncmp(G.sig, G.central_hdr_sig, 4)) {  /* just to make sure */
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
 | 
						|
            Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
 | 
						|
            return PK_BADERR;
 | 
						|
        }
 | 
						|
        /* process_cdir_file_hdr() sets pInfo->lcflag: */
 | 
						|
        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
 | 
						|
            return error;       /* only PK_EOF defined */
 | 
						|
        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_OK)
 | 
						|
        {        /*  ^-- (uses pInfo->lcflag) */
 | 
						|
            error_in_archive = error;
 | 
						|
            if (error > PK_WARN)   /* fatal:  can't continue */
 | 
						|
                return error;
 | 
						|
        }
 | 
						|
        if (G.extra_field != (uch *)NULL) {
 | 
						|
            free(G.extra_field);
 | 
						|
            G.extra_field = (uch *)NULL;
 | 
						|
        }
 | 
						|
        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
 | 
						|
            != 0)
 | 
						|
        {
 | 
						|
            error_in_archive = error;
 | 
						|
            if (error > PK_WARN)      /* fatal */
 | 
						|
                return error;
 | 
						|
        }
 | 
						|
        if (!G.process_all_files) {   /* check if specified on command line */
 | 
						|
            char **pfn = G.pfnames-1;
 | 
						|
 | 
						|
            do_this_file = FALSE;
 | 
						|
            while (*++pfn)
 | 
						|
                if (match(G.filename, *pfn, G.C_flag)) {
 | 
						|
                    do_this_file = TRUE;
 | 
						|
                    break;       /* found match, so stop looping */
 | 
						|
                }
 | 
						|
            if (do_this_file) {  /* check if this is an excluded file */
 | 
						|
                char **pxn = G.pxnames-1;
 | 
						|
 | 
						|
                while (*++pxn)
 | 
						|
                    if (match(G.filename, *pxn, G.C_flag)) {
 | 
						|
                        do_this_file = FALSE;  /* ^-- ignore case in match */
 | 
						|
                        break;
 | 
						|
                    }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /* If current file was specified on command line, or if no names were
 | 
						|
         * specified, check the time for this file.  Either way, get rid of the
 | 
						|
         * file comment and go back for the next file.
 | 
						|
         * Directory entries are always ignored, to stay compatible with both
 | 
						|
         * Zip and PKZIP.
 | 
						|
         */
 | 
						|
        if ((G.process_all_files || do_this_file) && !fn_is_dir(__G)) {
 | 
						|
#ifdef USE_EF_UT_TIME
 | 
						|
            if (G.extra_field &&
 | 
						|
                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
 | 
						|
                                  &z_utime, NULL) & EB_UT_FL_MTIME))
 | 
						|
            {
 | 
						|
                if (last_modtime < z_utime.mtime)
 | 
						|
                    last_modtime = z_utime.mtime;
 | 
						|
            } else
 | 
						|
#endif /* USE_EF_UT_TIME */
 | 
						|
            {
 | 
						|
                time_t modtime = dos_to_unix_time(G.crec.last_mod_file_date,
 | 
						|
                                                  G.crec.last_mod_file_time);
 | 
						|
 | 
						|
                if (last_modtime < modtime)
 | 
						|
                    last_modtime = modtime;
 | 
						|
            }
 | 
						|
            ++members;
 | 
						|
        }
 | 
						|
        SKIP_(G.crec.file_comment_length)
 | 
						|
 | 
						|
    } /* end for-loop (j: files in central directory) */
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Set the modification (and access) time on the zipfile, assuming we have
 | 
						|
    a modification time to set.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (members > 0) {
 | 
						|
        z_utime.mtime = z_utime.atime = last_modtime;
 | 
						|
        if (utime(G.zipfn, (ztimbuf *)&z_utime))
 | 
						|
            Info(slide, 0x201, ((char *)slide,
 | 
						|
              "warning:  can't set time for %s\n", G.zipfn));
 | 
						|
    }
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
    Double check that we're back at the end-of-central-directory record.
 | 
						|
  ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
    if (readbuf(__G__ G.sig, 4) == 0)
 | 
						|
        return PK_EOF;
 | 
						|
    if (strncmp(G.sig, G.end_central_sig, 4)) {   /* just to make sure again */
 | 
						|
        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
 | 
						|
        error_in_archive = PK_WARN;
 | 
						|
    }
 | 
						|
    if (members == 0 && error_in_archive <= PK_WARN)
 | 
						|
        error_in_archive = PK_FIND;
 | 
						|
 | 
						|
    return error_in_archive;
 | 
						|
 | 
						|
} /* end function time_stamp() */
 | 
						|
 | 
						|
#endif /* TIMESTAMP */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/********************/
 | 
						|
/* Function ratio() */    /* also used by ZipInfo routines */
 | 
						|
/********************/
 | 
						|
 | 
						|
int ratio(uc, c)
 | 
						|
    ulg uc, c;
 | 
						|
{
 | 
						|
    ulg denom;
 | 
						|
 | 
						|
    if (uc == 0)
 | 
						|
        return 0;
 | 
						|
    if (uc > 2000000L) {    /* risk signed overflow if multiply numerator */
 | 
						|
        denom = uc / 1000L;
 | 
						|
        return ((uc >= c) ?
 | 
						|
            (int) ((uc-c + (denom>>1)) / denom) :
 | 
						|
          -((int) ((c-uc + (denom>>1)) / denom)));
 | 
						|
    } else {             /* ^^^^^^^^ rounding */
 | 
						|
        denom = uc;
 | 
						|
        return ((uc >= c) ?
 | 
						|
            (int) ((1000L*(uc-c) + (denom>>1)) / denom) :
 | 
						|
          -((int) ((1000L*(c-uc) + (denom>>1)) / denom)));
 | 
						|
    }                            /* ^^^^^^^^ rounding */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/************************/
 | 
						|
/*  Function fnprint()  */    /* also used by ZipInfo routines */
 | 
						|
/************************/
 | 
						|
 | 
						|
void fnprint(__G)    /* print filename (after filtering) and newline */
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    char *name = fnfilter(G.filename, slide);
 | 
						|
 | 
						|
    (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0);
 | 
						|
    (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
 | 
						|
 | 
						|
} /* end function fnprint() */
 |