Archive-Unzip-Burst

 view release on metacpan or  search on metacpan

unzip-6.0/process.c  view on Meta::CPAN

/*
  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.

  See the accompanying file LICENSE, version 2009-Jan-02 or later
  (the contents of which are also included in unzip.h) for terms of use.
  If, for some reason, all these files are missing, the Info-ZIP license
  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
*/
/*---------------------------------------------------------------------------

  process.c

  This file contains the top-level routines for processing multiple zipfiles.

  Contains:  process_zipfiles()
             free_G_buffers()
             do_seekable()
             file_size()
             rec_find()
             find_ecrec64()
             find_ecrec()
             process_zip_cmmnt()
             process_cdir_file_hdr()
             get_cdir_ent()
             process_local_file_hdr()
             getZip64Data()
             ef_scan_for_izux()
             getRISCOSexfield()

  ---------------------------------------------------------------------------*/


#define UNZIP_INTERNAL
#include "unzip.h"
#ifdef WINDLL
#  ifdef POCKET_UNZIP
#    include "wince/intrface.h"
#  else
#    include "windll/windll.h"
#  endif
#endif
#if defined(DYNALLOC_CRCTAB) || defined(UNICODE_SUPPORT)
#  include "crc32.h"
#endif

static int    do_seekable        OF((__GPRO__ int lastchance));
#ifdef DO_SAFECHECK_2GB
# ifdef USE_STRM_INPUT
static zoff_t file_size          OF((FILE *file));
# else
static zoff_t file_size          OF((int fh));
# endif
#endif /* DO_SAFECHECK_2GB */
static int    rec_find           OF((__GPRO__ zoff_t, char *, int));
static int    find_ecrec64       OF((__GPRO__ zoff_t searchlen));
static int    find_ecrec         OF((__GPRO__ zoff_t searchlen));
static int    process_zip_cmmnt  OF((__GPRO));
static int    get_cdir_ent       OF((__GPRO));
#ifdef IZ_HAVE_UXUIDGID
static int    read_ux3_value     OF((ZCONST uch *dbuf, unsigned uidgid_sz,
                                     ulg *p_uidgid));
#endif /* IZ_HAVE_UXUIDGID */


static ZCONST char Far CannotAllocateBuffers[] =
  "error:  cannot allocate unzip buffers\n";

#ifdef SFX
   static ZCONST char Far CannotFindMyself[] =
     "unzipsfx:  cannot find myself! [%s]\n";
# ifdef CHEAP_SFX_AUTORUN
   static ZCONST char Far AutorunPrompt[] =
     "\nAuto-run command: %s\nExecute this command? [y/n] ";
   static ZCONST char Far NotAutoRunning[] =
     "Not executing auto-run command.";
# endif

#else /* !SFX */
   /* process_zipfiles() strings */
# if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
     static ZCONST char Far WarnInvalidTZ[] =
       "Warning: TZ environment variable not found, cannot use UTC times!!\n";
# endif
# if !(defined(UNIX) || defined(AMIGA))
   static ZCONST char Far CannotFindWildcardMatch[] =
     "%s:  cannot find any matches for wildcard specification \"%s\".\n";
# endif /* !(UNIX || AMIGA) */
   static ZCONST char Far FilesProcessOK[] =
     "%d archive%s successfully processed.\n";
   static ZCONST char Far ArchiveWarning[] =
     "%d archive%s had warnings but no fatal errors.\n";
   static ZCONST char Far ArchiveFatalError[] =
     "%d archive%s had fatal errors.\n";
   static ZCONST char Far FileHadNoZipfileDir[] =
     "%d file%s had no zipfile directory.\n";
   static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n";
   static ZCONST char Far ManyZipfilesWereDir[] =
     "%d \"zipfiles\" were directories.\n";
   static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n";

   /* do_seekable() strings */
# ifdef UNIX
   static ZCONST char Far CannotFindZipfileDirMsg[] =
     "%s:  cannot find zipfile directory in one of %s or\n\
        %s%s.zip, and cannot find %s, period.\n";
   static ZCONST char Far CannotFindEitherZipfile[] =
     "%s:  cannot find or open %s, %s.zip or %s.\n";
# else /* !UNIX */
   static ZCONST char Far CannotFindZipfileDirMsg[] =
     "%s:  cannot find zipfile directory in %s,\n\
        %sand cannot find %s, period.\n";
# ifdef VMS
   static ZCONST char Far CannotFindEitherZipfile[] =
     "%s:  cannot find %s (%s).\n";
# else /* !VMS */
   static ZCONST char Far CannotFindEitherZipfile[] =
     "%s:  cannot find either %s or %s.\n";
# endif /* ?VMS */
# endif /* ?UNIX */
   extern ZCONST char Far Zipnfo[];       /* in unzip.c */
#ifndef WINDLL

unzip-6.0/process.c  view on Meta::CPAN

  }
  for (wsize = 0; wide_string[wsize] = (zwchar)wc_string[wsize]; wsize++) ;
  wide_string[wsize] = (zwchar) 0;
  free(wc_string);

  return wide_string;
}


/* convert wide string to UTF-8 */
char *wide_to_utf8_string(wide_string)
  ZCONST zwchar *wide_string;
{
  int mbcount;
  char *utf8_string;

  /* get size of utf8 string */
  mbcount = ucs4_string_to_utf8(wide_string, NULL, 0);
  if (mbcount == -1)
    return NULL;
  if ((utf8_string = (char *) malloc(mbcount + 1)) == NULL) {
    return NULL;
  }
  mbcount = ucs4_string_to_utf8(wide_string, utf8_string, mbcount + 1);
  if (mbcount == -1)
    return NULL;

  return utf8_string;
}
#endif /* unused */

/* convert UTF-8 string to wide string */
zwchar *utf8_to_wide_string(utf8_string)
  ZCONST char *utf8_string;
{
  int wcount;
  zwchar *wide_string;

  wcount = utf8_to_ucs4_string(utf8_string, NULL, 0);
  if (wcount == -1)
    return NULL;
  if ((wide_string = (zwchar *) malloc((wcount + 1) * sizeof(zwchar)))
      == NULL) {
    return NULL;
  }
  wcount = utf8_to_ucs4_string(utf8_string, wide_string, wcount + 1);

  return wide_string;
}

#endif /* UNICODE_WCHAR */
#endif /* UNICODE_SUPPORT */





#ifdef USE_EF_UT_TIME

#ifdef IZ_HAVE_UXUIDGID
static int read_ux3_value(dbuf, uidgid_sz, p_uidgid)
    ZCONST uch *dbuf;   /* buffer a uid or gid value */
    unsigned uidgid_sz; /* size of uid/gid value */
    ulg *p_uidgid;      /* return storage: uid or gid value */
{
    zusz_t uidgid64;

    switch (uidgid_sz) {
      case 2:
        *p_uidgid = (ulg)makeword(dbuf);
        break;
      case 4:
        *p_uidgid = (ulg)makelong(dbuf);
        break;
      case 8:
        uidgid64 = makeint64(dbuf);
#ifndef LARGE_FILE_SUPPORT
        if (uidgid64 == (zusz_t)0xffffffffL)
            return FALSE;
#endif
        *p_uidgid = (ulg)uidgid64;
        if ((zusz_t)(*p_uidgid) != uidgid64)
            return FALSE;
        break;
    }
    return TRUE;
}
#endif /* IZ_HAVE_UXUIDGID */


/*******************************/
/* Function ef_scan_for_izux() */
/*******************************/

unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,
                          z_utim, z_uidgid)
    ZCONST uch *ef_buf; /* buffer containing extra field */
    unsigned ef_len;    /* total length of extra field */
    int ef_is_c;        /* flag indicating "is central extra field" */
    ulg dos_mdatetime;  /* last_mod_file_date_time in DOS format */
    iztimes *z_utim;    /* return storage: atime, mtime, ctime */
    ulg *z_uidgid;      /* return storage: uid and gid */
{
    unsigned flags = 0;
    unsigned eb_id;
    unsigned eb_len;
    int have_new_type_eb = 0;
    long i_time;        /* buffer for Unix style 32-bit integer time value */
#ifdef TIME_T_TYPE_DOUBLE
    int ut_in_archive_sgn = 0;
#else
    int ut_zip_unzip_compatible = FALSE;
#endif

/*---------------------------------------------------------------------------
    This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or
    EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's
    access, creation, and modification time.
    If a valid block is found, the time stamps are copied to the iztimes
    structure (provided the z_utim pointer is not NULL).
    If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields,
    and the z_uidgid array pointer is valid (!= NULL), the owner info is
    transfered as well.
    The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all
    data from probably present obsolete EF_IZUNIX blocks.
    If multiple blocks of the same type are found, only the information from
    the last block is used.
    The return value is a combination of the EF_TIME Flags field with an
    additional flag bit indicating the presence of valid UID/GID info,
    or 0 in case of failure.
  ---------------------------------------------------------------------------*/

    if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL))
        return 0;

    TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n",
      ef_len));

    while (ef_len >= EB_HEADSIZE) {
        eb_id = makeword(EB_ID + ef_buf);
        eb_len = makeword(EB_LEN + ef_buf);

        if (eb_len > (ef_len - EB_HEADSIZE)) {
            /* discovered some extra field inconsistency! */
            TTrace((stderr,
              "ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len,
              ef_len - EB_HEADSIZE));
            break;
        }

        switch (eb_id) {
          case EF_TIME:
            flags &= ~0x0ff;    /* ignore previous IZUNIX or EF_TIME fields */
            have_new_type_eb = 1;
            if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {
                unsigned eb_idx = EB_UT_TIME1;
                TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n"));
                flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff);
                if ((flags & EB_UT_FL_MTIME)) {
                    if ((eb_idx+4) <= eb_len) {
                        i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
                        eb_idx += 4;
                        TTrace((stderr,"  UT e.f. modification time = %ld\n",
                                i_time));

#ifdef TIME_T_TYPE_DOUBLE
                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {
                            if (dos_mdatetime == DOSTIME_MINIMUM) {
                              ut_in_archive_sgn = -1;
                              z_utim->mtime =
                                (time_t)((long)i_time | (~(long)0x7fffffffL));
                            } else if (dos_mdatetime >= DOSTIME_2038_01_18) {
                              ut_in_archive_sgn = 1;
                              z_utim->mtime =
                                (time_t)((ulg)i_time & (ulg)0xffffffffL);
                            } else {
                              ut_in_archive_sgn = 0;
                              /* cannot determine sign of mtime;
                                 without modtime: ignore complete UT field */
                              flags &= ~0x0ff;  /* no time_t times available */
                              TTrace((stderr,
                                "  UT modtime range error; ignore e.f.!\n"));
                              break;            /* stop scanning this field */
                            }
                        } else {
                            /* cannot determine, safe assumption is FALSE */
                            ut_in_archive_sgn = 0;
                            z_utim->mtime = (time_t)i_time;
                        }
#else /* !TIME_T_TYPE_DOUBLE */
                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {
                            ut_zip_unzip_compatible =
                              ((time_t)0x80000000L < (time_t)0L)

unzip-6.0/process.c  view on Meta::CPAN

                        if (((ulg)(i_time) & (ulg)(0x80000000L)) &&
                            !ut_zip_unzip_compatible) {
                            flags &= ~EB_UT_FL_ATIME;
                            TTrace((stderr,
                              "  UT access time range error: skip time!\n"));
                        } else {
                            z_utim->atime = (time_t)i_time;
                        }
#endif /* ?TIME_T_TYPE_DOUBLE */
                    } else {
                        flags &= ~EB_UT_FL_ATIME;
                    }
                }
                if (flags & EB_UT_FL_CTIME) {
                    if ((eb_idx+4) <= eb_len) {
                        i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
                        TTrace((stderr,"  UT e.f. creation time = %ld\n",
                                i_time));
#ifdef TIME_T_TYPE_DOUBLE
                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {
                            if (ut_in_archive_sgn == -1)
                              z_utim->ctime =
                                (time_t)((long)i_time | (~(long)0x7fffffffL));
                            } else if (ut_in_archive_sgn == 1) {
                              z_utim->ctime =
                                (time_t)((ulg)i_time & (ulg)0xffffffffL);
                            } else {
                              /* sign of 32-bit time is unknown -> ignore it */
                              flags &= ~EB_UT_FL_CTIME;
                              TTrace((stderr,
                              "  UT creation time range error: skip time!\n"));
                            }
                        } else {
                            z_utim->ctime = (time_t)i_time;
                        }
#else /* !TIME_T_TYPE_DOUBLE */
                        if (((ulg)(i_time) & (ulg)(0x80000000L)) &&
                            !ut_zip_unzip_compatible) {
                            flags &= ~EB_UT_FL_CTIME;
                            TTrace((stderr,
                              "  UT creation time range error: skip time!\n"));
                        } else {
                            z_utim->ctime = (time_t)i_time;
                        }
#endif /* ?TIME_T_TYPE_DOUBLE */
                    } else {
                        flags &= ~EB_UT_FL_CTIME;
                    }
                }
            }
            break;

          case EF_IZUNIX2:
            if (have_new_type_eb == 0) {
                flags &= ~0x0ff;        /* ignore any previous IZUNIX field */
                have_new_type_eb = 1;
            }
#ifdef IZ_HAVE_UXUIDGID
            if (have_new_type_eb > 1)
                break;          /* IZUNIX3 overrides IZUNIX2 e.f. block ! */
            if (eb_len == EB_UX2_MINLEN && z_uidgid != NULL) {
                z_uidgid[0] = (ulg)makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf);
                z_uidgid[1] = (ulg)makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf);
                flags |= EB_UX2_VALID;   /* signal success */
            }
#endif
            break;

          case EF_IZUNIX3:
            /* new 3rd generation Unix ef */
            have_new_type_eb = 2;

        /*
          Version       1 byte      version of this extra field, currently 1
          UIDSize       1 byte      Size of UID field
          UID           Variable    UID for this entry
          GIDSize       1 byte      Size of GID field
          GID           Variable    GID for this entry
        */

#ifdef IZ_HAVE_UXUIDGID
            if (eb_len >= EB_UX3_MINLEN
                && z_uidgid != NULL
                && (*((EB_HEADSIZE + 0) + ef_buf) == 1)
                    /* only know about version 1 */
            {
                uch uid_size;
                uch gid_size;

                uid_size = *((EB_HEADSIZE + 1) + ef_buf);
                gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf);

                flags &= ~0x0ff;      /* ignore any previous UNIX field */

                if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf,
                                    uid_size, z_uidgid[0])
                    &&
                     read_ux3_value((EB_HEADSIZE + uid_size + 3) + ef_buf,
                                    gid_size, z_uidgid[1]) )
                {
                    flags |= EB_UX2_VALID;   /* signal success */
                }
            }
#endif /* IZ_HAVE_UXUIDGID */
            break;

          case EF_IZUNIX:
          case EF_PKUNIX:       /* PKUNIX e.f. layout is identical to IZUNIX */
            if (eb_len >= EB_UX_MINLEN) {
                TTrace((stderr,"ef_scan_for_izux: found %s extra field\n",
                        (eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX")));
                if (have_new_type_eb > 0) {
                    break;      /* Ignore IZUNIX extra field block ! */
                }
                if (z_utim != NULL) {
                    flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
                    i_time = (long)makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf);
                    TTrace((stderr,"  Unix EF modtime = %ld\n", i_time));
#ifdef TIME_T_TYPE_DOUBLE
                    if ((ulg)(i_time) & (ulg)(0x80000000L)) {
                        if (dos_mdatetime == DOSTIME_MINIMUM) {
                            ut_in_archive_sgn = -1;
                            z_utim->mtime =
                              (time_t)((long)i_time | (~(long)0x7fffffffL));
                        } else if (dos_mdatetime >= DOSTIME_2038_01_18) {
                            ut_in_archive_sgn = 1;
                            z_utim->mtime =
                              (time_t)((ulg)i_time & (ulg)0xffffffffL);
                        } else {
                            ut_in_archive_sgn = 0;
                            /* cannot determine sign of mtime;
                               without modtime: ignore complete UT field */
                            flags &= ~0x0ff;    /* no time_t times available */
                            TTrace((stderr,
                                  "  UX modtime range error: ignore e.f.!\n"));
                        }
                    } else {
                        /* cannot determine, safe assumption is FALSE */
                        ut_in_archive_sgn = 0;
                        z_utim->mtime = (time_t)i_time;
                    }
#else /* !TIME_T_TYPE_DOUBLE */
                    if ((ulg)(i_time) & (ulg)(0x80000000L)) {
                        ut_zip_unzip_compatible =
                          ((time_t)0x80000000L < (time_t)0L)
                          ? (dos_mdatetime == DOSTIME_MINIMUM)
                          : (dos_mdatetime >= DOSTIME_2038_01_18);
                        if (!ut_zip_unzip_compatible) {
                            /* UnZip interpretes mtime differently than Zip;
                               without modtime: ignore complete UT field */
                            flags &= ~0x0ff;    /* no time_t times available */
                            TTrace((stderr,
                                  "  UX modtime range error: ignore e.f.!\n"));
                        }
                    } else {
                        /* cannot determine, safe assumption is FALSE */
                        ut_zip_unzip_compatible = FALSE;
                    }
                    z_utim->mtime = (time_t)i_time;
#endif /* ?TIME_T_TYPE_DOUBLE */
                    i_time = (long)makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf);
                    TTrace((stderr,"  Unix EF actime = %ld\n", i_time));
#ifdef TIME_T_TYPE_DOUBLE
                    if ((ulg)(i_time) & (ulg)(0x80000000L)) {
                        if (ut_in_archive_sgn == -1)
                            z_utim->atime =
                              (time_t)((long)i_time | (~(long)0x7fffffffL));
                        } else if (ut_in_archive_sgn == 1) {
                            z_utim->atime =
                              (time_t)((ulg)i_time & (ulg)0xffffffffL);
                        } else if (flags & 0x0ff) {
                            /* sign of 32-bit time is unknown -> ignore it */
                            flags &= ~EB_UT_FL_ATIME;
                            TTrace((stderr,
                                "  UX access time range error: skip time!\n"));
                        }
                    } else {
                        z_utim->atime = (time_t)i_time;
                    }
#else /* !TIME_T_TYPE_DOUBLE */
                    if (((ulg)(i_time) & (ulg)(0x80000000L)) &&
                        !ut_zip_unzip_compatible && (flags & 0x0ff)) {
                        /* atime not in range of UnZip's time_t */
                        flags &= ~EB_UT_FL_ATIME;
                        TTrace((stderr,
                                "  UX access time range error: skip time!\n"));
                    } else {
                        z_utim->atime = (time_t)i_time;
                    }
#endif /* ?TIME_T_TYPE_DOUBLE */
                }
#ifdef IZ_HAVE_UXUIDGID
                if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) {
                    z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf);
                    z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf);
                    flags |= EB_UX2_VALID;
                }
#endif /* IZ_HAVE_UXUIDGID */
            }
            break;

          default:
            break;
        }

        /* Skip this extra field block */
        ef_buf += (eb_len + EB_HEADSIZE);
        ef_len -= (eb_len + EB_HEADSIZE);
    }

    return flags;
}

#endif /* USE_EF_UT_TIME */


#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))

#define SPARKID_2 0x30435241    /* = "ARC0" */

/*******************************/
/* Function getRISCOSexfield() */
/*******************************/

zvoid *getRISCOSexfield(ef_buf, ef_len)
    ZCONST uch *ef_buf; /* buffer containing extra field */
    unsigned ef_len;    /* total length of extra field */
{
    unsigned eb_id;
    unsigned eb_len;

/*---------------------------------------------------------------------------
    This function scans the extra field for a Acorn SPARK filetype ef-block.
    If a valid block is found, the function returns a pointer to the start
    of the SPARK_EF block in the extra field buffer.  Otherwise, a NULL
    pointer is returned.
  ---------------------------------------------------------------------------*/

    if (ef_len == 0 || ef_buf == NULL)
        return NULL;

    Trace((stderr,"\ngetRISCOSexfield: scanning extra field of length %u\n",
      ef_len));

    while (ef_len >= EB_HEADSIZE) {
        eb_id = makeword(EB_ID + ef_buf);
        eb_len = makeword(EB_LEN + ef_buf);

        if (eb_len > (ef_len - EB_HEADSIZE)) {
            /* discovered some extra field inconsistency! */
            Trace((stderr,
              "getRISCOSexfield: block length %u > rest ef_size %u\n", eb_len,
              ef_len - EB_HEADSIZE));
            break;
        }



( run in 0.551 second using v1.01-cache-2.11-cpan-5735350b133 )