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 )