16714 lines
597 KiB
Diff
16714 lines
597 KiB
Diff
Submitted By: Ken Moffat <ken at linuxfromscratch dot org>
|
|
Date: 2019-12-03
|
|
Initial Package Version: 6.0
|
|
Upstream Status: Some from upstream, but that now appears to be defunct.
|
|
Origin: Found at fedora (omitting their manpage and symlinks patches)
|
|
Description:
|
|
|
|
1. Allow it to use system libbz2.so, this allows unzip and zipinfo to
|
|
deal with archives which contain bz2 compressed members.
|
|
|
|
2. Locale fixes to handle non-latin non-unicode filenames,
|
|
originally from Arch but updated by Canonical to fix buffer overflow
|
|
and to print them (apparently from fedora or redhat) - not tested!
|
|
|
|
3. A large number of security fixes, including for CVE-2014-81{39..41},
|
|
CVE-2016-9844, CVE-2018-18384, CVE-2018-1000035 as well as several
|
|
similar overflow fixes not labelled with CVE numbers and a few general
|
|
fixes.
|
|
|
|
diff -Naur a/crc_i386.S b/crc_i386.S
|
|
--- a/crc_i386.S 2007-01-07 05:02:58.000000000 +0000
|
|
+++ b/crc_i386.S 2019-12-01 23:48:05.278335299 +0000
|
|
@@ -302,3 +302,6 @@
|
|
#endif /* i386 || _i386 || _I386 || __i386 */
|
|
|
|
#endif /* !USE_ZLIB && !CRC_TABLE_ONLY */
|
|
+
|
|
+.section .note.GNU-stack, "", @progbits
|
|
+.previous
|
|
diff -Naur a/crypt.c b/crypt.c
|
|
--- a/crypt.c 2007-01-05 15:47:36.000000000 +0000
|
|
+++ b/crypt.c 2019-12-02 00:37:13.921788251 +0000
|
|
@@ -465,7 +465,17 @@
|
|
GLOBAL(pInfo->encrypted) = FALSE;
|
|
defer_leftover_input(__G);
|
|
for (n = 0; n < RAND_HEAD_LEN; n++) {
|
|
- b = NEXTBYTE;
|
|
+ /* 2012-11-23 SMS. (OUSPG report.)
|
|
+ * Quit early if compressed size < HEAD_LEN. The resulting
|
|
+ * error message ("unable to get password") could be improved,
|
|
+ * but it's better than trying to read nonexistent data, and
|
|
+ * then continuing with a negative G.csize. (See
|
|
+ * fileio.c:readbyte()).
|
|
+ */
|
|
+ if ((b = NEXTBYTE) == (ush)EOF)
|
|
+ {
|
|
+ return PK_ERR;
|
|
+ }
|
|
h[n] = (uch)b;
|
|
Trace((stdout, " (%02x)", h[n]));
|
|
}
|
|
diff -Naur a/extract.c b/extract.c
|
|
--- a/extract.c 2009-03-14 01:32:52.000000000 +0000
|
|
+++ b/extract.c 2019-12-02 01:05:52.857702371 +0000
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
|
|
+ Copyright (c) 1990-2014 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.
|
|
@@ -298,6 +298,8 @@
|
|
#ifndef SFX
|
|
static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
|
|
EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
|
|
+ static ZCONST char Far TooSmallEBlength[] = "bad extra-field entry:\n \
|
|
+ EF block length (%u bytes) invalid (< %d)\n";
|
|
static ZCONST char Far InvalidComprDataEAs[] =
|
|
" invalid compressed data for EAs\n";
|
|
# if (defined(WIN32) && defined(NTSD_EAS))
|
|
@@ -472,8 +474,8 @@
|
|
*/
|
|
Info(slide, 0x401, ((char *)slide,
|
|
LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1));
|
|
- Info(slide, 0x401, ((char *)slide,
|
|
- LoadFarString(ReportMsg)));
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
error_in_archive = PK_BADERR;
|
|
}
|
|
reached_end = TRUE; /* ...so no more left to do */
|
|
@@ -752,8 +754,8 @@
|
|
|
|
#ifndef SFX
|
|
if (no_endsig_found) { /* just to make sure */
|
|
- Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
|
|
- Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
|
|
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(EndSigMsg)));
|
|
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
if (!error_in_archive) /* don't overwrite stronger error */
|
|
error_in_archive = PK_WARN;
|
|
}
|
|
@@ -1255,8 +1257,17 @@
|
|
if (G.lrec.compression_method == STORED) {
|
|
zusz_t csiz_decrypted = G.lrec.csize;
|
|
|
|
- if (G.pInfo->encrypted)
|
|
+ if (G.pInfo->encrypted) {
|
|
+ if (csiz_decrypted < 12) {
|
|
+ /* handle the error now to prevent unsigned overflow */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipNoFile),
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Inflate)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
csiz_decrypted -= 12;
|
|
+ }
|
|
if (G.lrec.ucsize != csiz_decrypted) {
|
|
Info(slide, 0x401, ((char *)slide,
|
|
LoadFarStringSmall2(WrnStorUCSizCSizDiff),
|
|
@@ -1924,24 +1935,21 @@
|
|
|
|
#ifdef VMS /* VMS: required even for stdout! (final flush) */
|
|
if (!uO.tflag) /* don't close NULL file */
|
|
- close_outfile(__G);
|
|
+ error = close_outfile(__G);
|
|
#else
|
|
#ifdef DLL
|
|
if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
|
|
if (G.redirect_data)
|
|
FINISH_REDIRECT();
|
|
else
|
|
- close_outfile(__G);
|
|
+ error = close_outfile(__G);
|
|
}
|
|
#else
|
|
if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */
|
|
- close_outfile(__G);
|
|
+ error = close_outfile(__G);
|
|
#endif
|
|
#endif /* VMS */
|
|
|
|
- /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */
|
|
-
|
|
-
|
|
if (G.disk_full) { /* set by flush() */
|
|
if (G.disk_full > 1) {
|
|
#if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
|
|
@@ -2023,7 +2031,8 @@
|
|
ebID = makeword(ef);
|
|
ebLen = (unsigned)makeword(ef+EB_LEN);
|
|
|
|
- if (ebLen > (ef_len - EB_HEADSIZE)) {
|
|
+ if (ebLen > (ef_len - EB_HEADSIZE))
|
|
+ {
|
|
/* Discovered some extra field inconsistency! */
|
|
if (uO.qflag)
|
|
Info(slide, 1, ((char *)slide, "%-22s ",
|
|
@@ -2158,11 +2167,29 @@
|
|
}
|
|
break;
|
|
case EF_PKVMS:
|
|
- if (makelong(ef+EB_HEADSIZE) !=
|
|
- crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4),
|
|
- (extent)(ebLen-4)))
|
|
- Info(slide, 1, ((char *)slide,
|
|
- LoadFarString(BadCRC_EAs)));
|
|
+ /* 2015-01-30 SMS. Added sufficient-bytes test/message
|
|
+ * here. (Removed defective ebLen test above.)
|
|
+ *
|
|
+ * If sufficient bytes (EB_PKVMS_MINLEN) are available,
|
|
+ * then compare the stored CRC value with the calculated
|
|
+ * CRC for the remainder of the data (and complain about
|
|
+ * a mismatch).
|
|
+ */
|
|
+ if (ebLen < EB_PKVMS_MINLEN)
|
|
+ {
|
|
+ /* Insufficient bytes available. */
|
|
+ Info( slide, 1,
|
|
+ ((char *)slide, LoadFarString( TooSmallEBlength),
|
|
+ ebLen, EB_PKVMS_MINLEN));
|
|
+ }
|
|
+ else if (makelong(ef+ EB_HEADSIZE) !=
|
|
+ crc32(CRCVAL_INITIAL,
|
|
+ (ef+ EB_HEADSIZE+ EB_PKVMS_MINLEN),
|
|
+ (extent)(ebLen- EB_PKVMS_MINLEN)))
|
|
+ {
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(BadCRC_EAs)));
|
|
+ }
|
|
break;
|
|
case EF_PKW32:
|
|
case EF_PKUNIX:
|
|
@@ -2217,14 +2244,28 @@
|
|
ulg eb_ucsize;
|
|
uch *eb_ucptr;
|
|
int r;
|
|
+ ush method;
|
|
|
|
if (compr_offset < 4) /* field is not compressed: */
|
|
return PK_OK; /* do nothing and signal OK */
|
|
|
|
+ /* Return no/bad-data error status if any problem is found:
|
|
+ * 1. eb_size is too small to hold the uncompressed size
|
|
+ * (eb_ucsize). (Else extract eb_ucsize.)
|
|
+ * 2. eb_ucsize is zero (invalid). 2014-12-04 SMS.
|
|
+ * 3. eb_ucsize is positive, but eb_size is too small to hold
|
|
+ * the compressed data header.
|
|
+ */
|
|
if ((eb_size < (EB_UCSIZE_P + 4)) ||
|
|
- ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
|
|
- eb_size <= (compr_offset + EB_CMPRHEADLEN)))
|
|
- return IZ_EF_TRUNC; /* no compressed data! */
|
|
+ ((eb_ucsize = makelong( eb+ (EB_HEADSIZE+ EB_UCSIZE_P))) == 0L) ||
|
|
+ ((eb_ucsize > 0L) && (eb_size <= (compr_offset + EB_CMPRHEADLEN))))
|
|
+ return IZ_EF_TRUNC; /* no/bad compressed data! */
|
|
+
|
|
+ method = makeword(eb + (EB_HEADSIZE + compr_offset));
|
|
+ if ((method == STORED) && (eb_size != compr_offset + EB_CMPRHEADLEN + eb_ucsize))
|
|
+ return PK_ERR; /* compressed & uncompressed
|
|
+ * should match in STORED
|
|
+ * method */
|
|
|
|
if (
|
|
#ifdef INT_16BIT
|
|
@@ -2542,8 +2583,21 @@
|
|
} /* end function set_deferred_symlink() */
|
|
#endif /* SYMLINKS */
|
|
|
|
+/*
|
|
+ * If Unicode is supported, assume we have what we need to do this
|
|
+ * check using wide characters, avoiding MBCS issues.
|
|
+ */
|
|
|
|
-
|
|
+#ifndef UZ_FNFILTER_REPLACECHAR
|
|
+ /* A convenient choice for the replacement of unprintable char codes is
|
|
+ * the "single char wildcard", as this character is quite unlikely to
|
|
+ * appear in filenames by itself. The following default definition
|
|
+ * sets the replacement char to a question mark as the most common
|
|
+ * "single char wildcard"; this setting should be overridden in the
|
|
+ * appropiate system-specific configuration header when needed.
|
|
+ */
|
|
+# define UZ_FNFILTER_REPLACECHAR '?'
|
|
+#endif
|
|
|
|
/*************************/
|
|
/* Function fnfilter() */ /* here instead of in list.c for SFX */
|
|
@@ -2555,48 +2609,168 @@
|
|
extent size;
|
|
{
|
|
#ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */
|
|
- ZCONST uch *r=(ZCONST uch *)raw;
|
|
+ ZCONST uch *r; // =(ZCONST uch *)raw;
|
|
uch *s=space;
|
|
uch *slim=NULL;
|
|
uch *se=NULL;
|
|
int have_overflow = FALSE;
|
|
|
|
- if (size > 0) {
|
|
- slim = space + size
|
|
-#ifdef _MBCS
|
|
- - (MB_CUR_MAX - 1)
|
|
-#endif
|
|
- - 4;
|
|
+# if defined( UNICODE_SUPPORT) && defined( _MBCS)
|
|
+/* If Unicode support is enabled, and we have multi-byte characters,
|
|
+ * then do the isprint() checks by first converting to wide characters
|
|
+ * and checking those. This avoids our having to parse multi-byte
|
|
+ * characters for ourselves. After the wide-char replacements have been
|
|
+ * made, the wide string is converted back to the local character set.
|
|
+ */
|
|
+ wchar_t *wstring; /* wchar_t version of raw */
|
|
+ size_t wslen; /* length of wstring */
|
|
+ wchar_t *wostring; /* wchar_t version of output string */
|
|
+ size_t woslen; /* length of wostring */
|
|
+ char *newraw; /* new raw */
|
|
+
|
|
+ /* 2012-11-06 SMS.
|
|
+ * Changed to check the value returned by mbstowcs(), and bypass the
|
|
+ * Unicode processing if it fails. This seems to fix a problem
|
|
+ * reported in the SourceForge forum, but it's not clear that we
|
|
+ * should be doing any Unicode processing without some evidence that
|
|
+ * the name actually is Unicode. (Check bit 11 in the flags before
|
|
+ * coming here?)
|
|
+ * http://sourceforge.net/p/infozip/bugs/40/
|
|
+ */
|
|
+
|
|
+ if (MB_CUR_MAX <= 1)
|
|
+ {
|
|
+ /* There's no point to converting multi-byte chars if there are
|
|
+ * no multi-byte chars.
|
|
+ */
|
|
+ wslen = (size_t)-1;
|
|
}
|
|
- while (*r) {
|
|
- if (size > 0 && s >= slim && se == NULL) {
|
|
- se = s;
|
|
- }
|
|
-#ifdef QDOS
|
|
- if (qlflag & 2) {
|
|
- if (*r == '/' || *r == '.') {
|
|
+ else
|
|
+ {
|
|
+ /* Get Unicode wide character count (for storage allocation). */
|
|
+ wslen = mbstowcs( NULL, raw, 0);
|
|
+ }
|
|
+
|
|
+ if (wslen != (size_t)-1)
|
|
+ {
|
|
+ /* Apparently valid Unicode. Allocate wide-char storage. */
|
|
+ wstring = (wchar_t *)malloc((wslen + 1) * sizeof(wchar_t));
|
|
+ if (wstring == NULL) {
|
|
+ strcpy( (char *)space, raw);
|
|
+ return (char *)space;
|
|
+ }
|
|
+ wostring = (wchar_t *)malloc(2 * (wslen + 1) * sizeof(wchar_t));
|
|
+ if (wostring == NULL) {
|
|
+ free(wstring);
|
|
+ strcpy( (char *)space, raw);
|
|
+ return (char *)space;
|
|
+ }
|
|
+
|
|
+ /* Convert the multi-byte Unicode to wide chars. */
|
|
+ wslen = mbstowcs(wstring, raw, wslen + 1);
|
|
+
|
|
+ /* Filter the wide-character string. */
|
|
+ fnfilterw( wstring, wostring, (2 * (wslen + 1) * sizeof(wchar_t)));
|
|
+
|
|
+ /* Convert filtered wide chars back to multi-byte. */
|
|
+ woslen = wcstombs( NULL, wostring, 0);
|
|
+ if ((newraw = malloc(woslen + 1)) == NULL) {
|
|
+ free(wstring);
|
|
+ free(wostring);
|
|
+ strcpy( (char *)space, raw);
|
|
+ return (char *)space;
|
|
+ }
|
|
+ woslen = wcstombs( newraw, wostring, (woslen * MB_CUR_MAX) + 1);
|
|
+
|
|
+ if (size > 0) {
|
|
+ slim = space + size - 4;
|
|
+ }
|
|
+ r = (ZCONST uch *)newraw;
|
|
+ while (*r) {
|
|
+ if (size > 0 && s >= slim && se == NULL) {
|
|
+ se = s;
|
|
+ }
|
|
+# ifdef QDOS
|
|
+ if (qlflag & 2) {
|
|
+ if (*r == '/' || *r == '.') {
|
|
+ if (se != NULL && (s > (space + (size-3)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ ++r;
|
|
+ *s++ = '_';
|
|
+ continue;
|
|
+ }
|
|
+ } else
|
|
+# endif
|
|
+ {
|
|
if (se != NULL && (s > (space + (size-3)))) {
|
|
have_overflow = TRUE;
|
|
break;
|
|
}
|
|
- ++r;
|
|
- *s++ = '_';
|
|
- continue;
|
|
+ *s++ = *r++;
|
|
}
|
|
- } else
|
|
+ }
|
|
+ if (have_overflow) {
|
|
+ strcpy((char *)se, "...");
|
|
+ } else {
|
|
+ *s = '\0';
|
|
+ }
|
|
+
|
|
+ free(wstring);
|
|
+ free(wostring);
|
|
+ free(newraw);
|
|
+ }
|
|
+ else
|
|
+# endif /* defined( UNICODE_SUPPORT) && defined( _MBCS) */
|
|
+ {
|
|
+ /* No Unicode support, or apparently invalid Unicode. */
|
|
+ r = (ZCONST uch *)raw;
|
|
+
|
|
+ if (size > 0) {
|
|
+ slim = space + size
|
|
+#ifdef _MBCS
|
|
+ - (MB_CUR_MAX - 1)
|
|
+#endif
|
|
+ - 4;
|
|
+ }
|
|
+ while (*r) {
|
|
+ if (size > 0 && s >= slim && se == NULL) {
|
|
+ se = s;
|
|
+ }
|
|
+#ifdef QDOS
|
|
+ if (qlflag & 2) {
|
|
+ if (*r == '/' || *r == '.') {
|
|
+ if (se != NULL && (s > (space + (size-3)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ ++r;
|
|
+ *s++ = '_';
|
|
+ continue;
|
|
+ }
|
|
+ } else
|
|
#endif
|
|
#ifdef HAVE_WORKING_ISPRINT
|
|
-# ifndef UZ_FNFILTER_REPLACECHAR
|
|
- /* A convenient choice for the replacement of unprintable char codes is
|
|
- * the "single char wildcard", as this character is quite unlikely to
|
|
- * appear in filenames by itself. The following default definition
|
|
- * sets the replacement char to a question mark as the most common
|
|
- * "single char wildcard"; this setting should be overridden in the
|
|
- * appropiate system-specific configuration header when needed.
|
|
- */
|
|
-# define UZ_FNFILTER_REPLACECHAR '?'
|
|
-# endif
|
|
- if (!isprint(*r)) {
|
|
+ if (!isprint(*r)) {
|
|
+ if (*r < 32) {
|
|
+ /* ASCII control codes are escaped as "^{letter}". */
|
|
+ if (se != NULL && (s > (space + (size-4)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ *s++ = '^', *s++ = (uch)(64 + *r++);
|
|
+ } else {
|
|
+ /* Other unprintable codes are replaced by the
|
|
+ * placeholder character. */
|
|
+ if (se != NULL && (s > (space + (size-3)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ *s++ = UZ_FNFILTER_REPLACECHAR;
|
|
+ INCSTR(r);
|
|
+ }
|
|
+#else /* !HAVE_WORKING_ISPRINT */
|
|
if (*r < 32) {
|
|
/* ASCII control codes are escaped as "^{letter}". */
|
|
if (se != NULL && (s > (space + (size-4)))) {
|
|
@@ -2604,47 +2778,30 @@
|
|
break;
|
|
}
|
|
*s++ = '^', *s++ = (uch)(64 + *r++);
|
|
+#endif /* ?HAVE_WORKING_ISPRINT */
|
|
} else {
|
|
- /* Other unprintable codes are replaced by the
|
|
- * placeholder character. */
|
|
+#ifdef _MBCS
|
|
+ unsigned i = CLEN(r);
|
|
+ if (se != NULL && (s > (space + (size-i-2)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ for (; i > 0; i--)
|
|
+ *s++ = *r++;
|
|
+#else
|
|
if (se != NULL && (s > (space + (size-3)))) {
|
|
have_overflow = TRUE;
|
|
break;
|
|
}
|
|
- *s++ = UZ_FNFILTER_REPLACECHAR;
|
|
- INCSTR(r);
|
|
- }
|
|
-#else /* !HAVE_WORKING_ISPRINT */
|
|
- if (*r < 32) {
|
|
- /* ASCII control codes are escaped as "^{letter}". */
|
|
- if (se != NULL && (s > (space + (size-4)))) {
|
|
- have_overflow = TRUE;
|
|
- break;
|
|
- }
|
|
- *s++ = '^', *s++ = (uch)(64 + *r++);
|
|
-#endif /* ?HAVE_WORKING_ISPRINT */
|
|
- } else {
|
|
-#ifdef _MBCS
|
|
- unsigned i = CLEN(r);
|
|
- if (se != NULL && (s > (space + (size-i-2)))) {
|
|
- have_overflow = TRUE;
|
|
- break;
|
|
- }
|
|
- for (; i > 0; i--)
|
|
*s++ = *r++;
|
|
-#else
|
|
- if (se != NULL && (s > (space + (size-3)))) {
|
|
- have_overflow = TRUE;
|
|
- break;
|
|
- }
|
|
- *s++ = *r++;
|
|
#endif
|
|
- }
|
|
- }
|
|
- if (have_overflow) {
|
|
- strcpy((char *)se, "...");
|
|
- } else {
|
|
- *s = '\0';
|
|
+ }
|
|
+ }
|
|
+ if (have_overflow) {
|
|
+ strcpy((char *)se, "...");
|
|
+ } else {
|
|
+ *s = '\0';
|
|
+ }
|
|
}
|
|
|
|
#ifdef WINDLL
|
|
@@ -2666,6 +2823,53 @@
|
|
} /* end function fnfilter() */
|
|
|
|
|
|
+#if defined( UNICODE_SUPPORT) && defined( _MBCS)
|
|
+
|
|
+/****************************/
|
|
+/* Function fnfilter[w]() */ /* (Here instead of in list.c for SFX.) */
|
|
+/****************************/
|
|
+
|
|
+/* fnfilterw() - Convert wide name to safely printable form. */
|
|
+
|
|
+/* fnfilterw() - Convert wide-character name to safely printable form. */
|
|
+
|
|
+wchar_t *fnfilterw( src, dst, siz)
|
|
+ ZCONST wchar_t *src; /* Pointer to source char (string). */
|
|
+ wchar_t *dst; /* Pointer to destination char (string). */
|
|
+ extent siz; /* Not used (!). */
|
|
+{
|
|
+ wchar_t *dsx = dst;
|
|
+
|
|
+ /* Filter the wide chars. */
|
|
+ while (*src)
|
|
+ {
|
|
+ if (iswprint( *src))
|
|
+ {
|
|
+ /* Printable code. Copy it. */
|
|
+ *dst++ = *src;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* Unprintable code. Substitute something printable for it. */
|
|
+ if (*src < 32)
|
|
+ {
|
|
+ /* Replace ASCII control code with "^{letter}". */
|
|
+ *dst++ = (wchar_t)'^';
|
|
+ *dst++ = (wchar_t)(64 + *src);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* Replace other unprintable code with the placeholder. */
|
|
+ *dst++ = (wchar_t)UZ_FNFILTER_REPLACECHAR;
|
|
+ }
|
|
+ }
|
|
+ src++;
|
|
+ }
|
|
+ *dst = (wchar_t)0; /* NUL-terminate the destination string. */
|
|
+ return dsx;
|
|
+} /* fnfilterw(). */
|
|
+
|
|
+#endif /* defined( UNICODE_SUPPORT) && defined( _MBCS) */
|
|
|
|
|
|
#ifdef SET_DIR_ATTRIB
|
|
@@ -2701,6 +2905,12 @@
|
|
int repeated_buf_err;
|
|
bz_stream bstrm;
|
|
|
|
+ if (G.incnt <= 0 && G.csize <= 0L) {
|
|
+ /* avoid an infinite loop */
|
|
+ Trace((stderr, "UZbunzip2() got empty input\n"));
|
|
+ return 2;
|
|
+ }
|
|
+
|
|
#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
|
if (G.redirect_slide)
|
|
wsize = G.redirect_size, redirSlide = G.redirect_buffer;
|
|
diff -Naur a/extract.c.orig b/extract.c.orig
|
|
--- a/extract.c.orig 1970-01-01 01:00:00.000000000 +0100
|
|
+++ b/extract.c.orig 2019-12-02 00:37:13.921788251 +0000
|
|
@@ -0,0 +1,2867 @@
|
|
+/*
|
|
+ Copyright (c) 1990-2014 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
|
|
+*/
|
|
+/*---------------------------------------------------------------------------
|
|
+
|
|
+ extract.c
|
|
+
|
|
+ This file contains the high-level routines ("driver routines") for extrac-
|
|
+ ting and testing zipfile members. It calls the low-level routines in files
|
|
+ explode.c, inflate.c, unreduce.c and unshrink.c.
|
|
+
|
|
+ Contains: extract_or_test_files()
|
|
+ store_info()
|
|
+ find_compr_idx()
|
|
+ extract_or_test_entrylist()
|
|
+ extract_or_test_member()
|
|
+ TestExtraField()
|
|
+ test_compr_eb()
|
|
+ memextract()
|
|
+ memflush()
|
|
+ extract_izvms_block() (VMS or VMS_TEXT_CONV)
|
|
+ set_deferred_symlink() (SYMLINKS only)
|
|
+ fnfilter()
|
|
+ dircomp() (SET_DIR_ATTRIB only)
|
|
+ UZbunzip2() (USE_BZIP2 only)
|
|
+
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+
|
|
+#define __EXTRACT_C /* identifies this source module */
|
|
+#define UNZIP_INTERNAL
|
|
+#include "unzip.h"
|
|
+#ifdef WINDLL
|
|
+# ifdef POCKET_UNZIP
|
|
+# include "wince/intrface.h"
|
|
+# else
|
|
+# include "windll/windll.h"
|
|
+# endif
|
|
+#endif
|
|
+#include "crc32.h"
|
|
+#include "crypt.h"
|
|
+
|
|
+#define GRRDUMP(buf,len) { \
|
|
+ int i, j; \
|
|
+ \
|
|
+ for (j = 0; j < (len)/16; ++j) { \
|
|
+ printf(" "); \
|
|
+ for (i = 0; i < 16; ++i) \
|
|
+ printf("%02x ", (uch)(buf)[i+(j<<4)]); \
|
|
+ printf("\n "); \
|
|
+ for (i = 0; i < 16; ++i) { \
|
|
+ char c = (char)(buf)[i+(j<<4)]; \
|
|
+ \
|
|
+ if (c == '\n') \
|
|
+ printf("\\n "); \
|
|
+ else if (c == '\r') \
|
|
+ printf("\\r "); \
|
|
+ else \
|
|
+ printf(" %c ", c); \
|
|
+ } \
|
|
+ printf("\n"); \
|
|
+ } \
|
|
+ if ((len) % 16) { \
|
|
+ printf(" "); \
|
|
+ for (i = j<<4; i < (len); ++i) \
|
|
+ printf("%02x ", (uch)(buf)[i]); \
|
|
+ printf("\n "); \
|
|
+ for (i = j<<4; i < (len); ++i) { \
|
|
+ char c = (char)(buf)[i]; \
|
|
+ \
|
|
+ if (c == '\n') \
|
|
+ printf("\\n "); \
|
|
+ else if (c == '\r') \
|
|
+ printf("\\r "); \
|
|
+ else \
|
|
+ printf(" %c ", c); \
|
|
+ } \
|
|
+ printf("\n"); \
|
|
+ } \
|
|
+}
|
|
+
|
|
+static int store_info OF((__GPRO));
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,
|
|
+ ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,
|
|
+ unsigned *pnum_dirs, direntry **pdirlist,
|
|
+ int error_in_archive));
|
|
+#else
|
|
+static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,
|
|
+ ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,
|
|
+ int error_in_archive));
|
|
+#endif
|
|
+static int extract_or_test_member OF((__GPRO));
|
|
+#ifndef SFX
|
|
+ static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));
|
|
+ static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,
|
|
+ unsigned compr_offset,
|
|
+ int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
|
|
+ uch *eb_ucptr, ulg eb_ucsize)));
|
|
+#endif
|
|
+#if (defined(VMS) || defined(VMS_TEXT_CONV))
|
|
+ static void decompress_bits OF((uch *outptr, unsigned needlen,
|
|
+ ZCONST uch *bitptr));
|
|
+#endif
|
|
+#ifdef SYMLINKS
|
|
+ static void set_deferred_symlink OF((__GPRO__ slinkentry *slnk_entry));
|
|
+#endif
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
|
|
+#endif
|
|
+
|
|
+
|
|
+
|
|
+/*******************************/
|
|
+/* Strings used in extract.c */
|
|
+/*******************************/
|
|
+
|
|
+static ZCONST char Far VersionMsg[] =
|
|
+ " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n";
|
|
+static ZCONST char Far ComprMsgNum[] =
|
|
+ " skipping: %-22s unsupported compression method %u\n";
|
|
+#ifndef SFX
|
|
+ static ZCONST char Far ComprMsgName[] =
|
|
+ " skipping: %-22s `%s' method not supported\n";
|
|
+ static ZCONST char Far CmprNone[] = "store";
|
|
+ static ZCONST char Far CmprShrink[] = "shrink";
|
|
+ static ZCONST char Far CmprReduce[] = "reduce";
|
|
+ static ZCONST char Far CmprImplode[] = "implode";
|
|
+ static ZCONST char Far CmprTokenize[] = "tokenize";
|
|
+ static ZCONST char Far CmprDeflate[] = "deflate";
|
|
+ static ZCONST char Far CmprDeflat64[] = "deflate64";
|
|
+ static ZCONST char Far CmprDCLImplode[] = "DCL implode";
|
|
+ static ZCONST char Far CmprBzip[] = "bzip2";
|
|
+ static ZCONST char Far CmprLZMA[] = "LZMA";
|
|
+ static ZCONST char Far CmprIBMTerse[] = "IBM/Terse";
|
|
+ static ZCONST char Far CmprIBMLZ77[] = "IBM LZ77";
|
|
+ static ZCONST char Far CmprWavPack[] = "WavPack";
|
|
+ static ZCONST char Far CmprPPMd[] = "PPMd";
|
|
+ static ZCONST char Far *ComprNames[NUM_METHODS] = {
|
|
+ CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
|
|
+ CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode,
|
|
+ CmprBzip, CmprLZMA, CmprIBMTerse, CmprIBMLZ77, CmprWavPack, CmprPPMd
|
|
+ };
|
|
+ static ZCONST unsigned ComprIDs[NUM_METHODS] = {
|
|
+ STORED, SHRUNK, REDUCED1, REDUCED2, REDUCED3, REDUCED4,
|
|
+ IMPLODED, TOKENIZED, DEFLATED, ENHDEFLATED, DCLIMPLODED,
|
|
+ BZIPPED, LZMAED, IBMTERSED, IBMLZ77ED, WAVPACKED, PPMDED
|
|
+ };
|
|
+#endif /* !SFX */
|
|
+static ZCONST char Far FilNamMsg[] =
|
|
+ "%s: bad filename length (%s)\n";
|
|
+#ifndef SFX
|
|
+ static ZCONST char Far WarnNoMemCFName[] =
|
|
+ "%s: warning, no memory for comparison with local header\n";
|
|
+ static ZCONST char Far LvsCFNamMsg[] =
|
|
+ "%s: mismatching \"local\" filename (%s),\n\
|
|
+ continuing with \"central\" filename version\n";
|
|
+#endif /* !SFX */
|
|
+#if (!defined(SFX) && defined(UNICODE_SUPPORT))
|
|
+ static ZCONST char Far GP11FlagsDiffer[] =
|
|
+ "file #%lu (%s):\n\
|
|
+ mismatch between local and central GPF bit 11 (\"UTF-8\"),\n\
|
|
+ continuing with central flag (IsUTF8 = %d)\n";
|
|
+#endif /* !SFX && UNICODE_SUPPORT */
|
|
+static ZCONST char Far WrnStorUCSizCSizDiff[] =
|
|
+ "%s: ucsize %s <> csize %s for STORED entry\n\
|
|
+ continuing with \"compressed\" size value\n";
|
|
+static ZCONST char Far ExtFieldMsg[] =
|
|
+ "%s: bad extra field length (%s)\n";
|
|
+static ZCONST char Far OffsetMsg[] =
|
|
+ "file #%lu: bad zipfile offset (%s): %ld\n";
|
|
+static ZCONST char Far ExtractMsg[] =
|
|
+ "%8sing: %-22s %s%s";
|
|
+#ifndef SFX
|
|
+ static ZCONST char Far LengthMsg[] =
|
|
+ "%s %s: %s bytes required to uncompress to %s bytes;\n %s\
|
|
+ supposed to require %s bytes%s%s%s\n";
|
|
+#endif
|
|
+
|
|
+static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n";
|
|
+static ZCONST char Far LocalHdrSig[] = "local header sig";
|
|
+static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n";
|
|
+static ZCONST char Far AttemptRecompensate[] =
|
|
+ " (attempting to re-compensate)\n";
|
|
+#ifndef SFX
|
|
+ static ZCONST char Far BackslashPathSep[] =
|
|
+ "warning: %s appears to use backslashes as path separators\n";
|
|
+#endif
|
|
+static ZCONST char Far AbsolutePathWarning[] =
|
|
+ "warning: stripped absolute path spec from %s\n";
|
|
+static ZCONST char Far SkipVolumeLabel[] =
|
|
+ " skipping: %-22s %svolume label\n";
|
|
+
|
|
+#ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */
|
|
+ static ZCONST char Far DirlistEntryNoMem[] =
|
|
+ "warning: cannot alloc memory for dir times/permissions/UID/GID\n";
|
|
+ static ZCONST char Far DirlistSortNoMem[] =
|
|
+ "warning: cannot alloc memory to sort dir times/perms/etc.\n";
|
|
+ static ZCONST char Far DirlistSetAttrFailed[] =
|
|
+ "warning: set times/attribs failed for %s\n";
|
|
+ static ZCONST char Far DirlistFailAttrSum[] =
|
|
+ " failed setting times/attribs for %lu dir entries";
|
|
+#endif
|
|
+
|
|
+#ifdef SYMLINKS /* messages of the deferred symlinks handler */
|
|
+ static ZCONST char Far SymLnkWarnNoMem[] =
|
|
+ "warning: deferred symlink (%s) failed:\n\
|
|
+ out of memory\n";
|
|
+ static ZCONST char Far SymLnkWarnInvalid[] =
|
|
+ "warning: deferred symlink (%s) failed:\n\
|
|
+ invalid placeholder file\n";
|
|
+ static ZCONST char Far SymLnkDeferred[] =
|
|
+ "finishing deferred symbolic links:\n";
|
|
+ static ZCONST char Far SymLnkFinish[] =
|
|
+ " %-22s -> %s\n";
|
|
+#endif
|
|
+
|
|
+#ifndef WINDLL
|
|
+ static ZCONST char Far ReplaceQuery[] =
|
|
+# ifdef VMS
|
|
+ "new version of %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
|
|
+# else
|
|
+ "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
|
|
+# endif
|
|
+ static ZCONST char Far AssumeNone[] =
|
|
+ " NULL\n(EOF or read error, treating as \"[N]one\" ...)\n";
|
|
+ static ZCONST char Far NewNameQuery[] = "new name: ";
|
|
+ static ZCONST char Far InvalidResponse[] =
|
|
+ "error: invalid response [%s]\n";
|
|
+#endif /* !WINDLL */
|
|
+
|
|
+static ZCONST char Far ErrorInArchive[] =
|
|
+ "At least one %serror was detected in %s.\n";
|
|
+static ZCONST char Far ZeroFilesTested[] =
|
|
+ "Caution: zero files tested in %s.\n";
|
|
+
|
|
+#ifndef VMS
|
|
+ static ZCONST char Far VMSFormatQuery[] =
|
|
+ "\n%s: stored in VMS format. Extract anyway? (y/n) ";
|
|
+#endif
|
|
+
|
|
+#if CRYPT
|
|
+ static ZCONST char Far SkipCannotGetPasswd[] =
|
|
+ " skipping: %-22s unable to get password\n";
|
|
+ static ZCONST char Far SkipIncorrectPasswd[] =
|
|
+ " skipping: %-22s incorrect password\n";
|
|
+ static ZCONST char Far FilesSkipBadPasswd[] =
|
|
+ "%lu file%s skipped because of incorrect password.\n";
|
|
+ static ZCONST char Far MaybeBadPasswd[] =
|
|
+ " (may instead be incorrect password)\n";
|
|
+#else
|
|
+ static ZCONST char Far SkipEncrypted[] =
|
|
+ " skipping: %-22s encrypted (not supported)\n";
|
|
+#endif
|
|
+
|
|
+static ZCONST char Far NoErrInCompData[] =
|
|
+ "No errors detected in compressed data of %s.\n";
|
|
+static ZCONST char Far NoErrInTestedFiles[] =
|
|
+ "No errors detected in %s for the %lu file%s tested.\n";
|
|
+static ZCONST char Far FilesSkipped[] =
|
|
+ "%lu file%s skipped because of unsupported compression or encoding.\n";
|
|
+
|
|
+static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n";
|
|
+static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n";
|
|
+static ZCONST char Far NotEnoughMem[] = "not enough memory to ";
|
|
+static ZCONST char Far InvalidComprData[] = "invalid compressed data to ";
|
|
+static ZCONST char Far Inflate[] = "inflate";
|
|
+#ifdef USE_BZIP2
|
|
+ static ZCONST char Far BUnzip[] = "bunzip";
|
|
+#endif
|
|
+
|
|
+#ifndef SFX
|
|
+ static ZCONST char Far Explode[] = "explode";
|
|
+#ifndef LZW_CLEAN
|
|
+ static ZCONST char Far Unshrink[] = "unshrink";
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+#if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
|
|
+ static ZCONST char Far FileTruncated[] =
|
|
+ "warning: %s is probably truncated\n";
|
|
+#endif
|
|
+
|
|
+static ZCONST char Far FileUnknownCompMethod[] =
|
|
+ "%s: unknown compression method\n";
|
|
+static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n";
|
|
+
|
|
+ /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
|
|
+char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";
|
|
+char ZCONST Far TruncNTSD[] =
|
|
+ " compressed WinNT security data missing (%d bytes)%s";
|
|
+
|
|
+#ifndef SFX
|
|
+ static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
|
|
+ EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
|
|
+ static ZCONST char Far TooSmallEBlength[] = "bad extra-field entry:\n \
|
|
+ EF block length (%u bytes) invalid (< %d)\n";
|
|
+ static ZCONST char Far InvalidComprDataEAs[] =
|
|
+ " invalid compressed data for EAs\n";
|
|
+# if (defined(WIN32) && defined(NTSD_EAS))
|
|
+ static ZCONST char Far InvalidSecurityEAs[] =
|
|
+ " EAs fail security check\n";
|
|
+# endif
|
|
+ static ZCONST char Far UnsuppNTSDVersEAs[] =
|
|
+ " unsupported NTSD EAs version %d\n";
|
|
+ static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n";
|
|
+ static ZCONST char Far UnknComprMethodEAs[] =
|
|
+ " unknown compression method for EAs (%u)\n";
|
|
+ static ZCONST char Far NotEnoughMemEAs[] =
|
|
+ " out of memory while inflating EAs\n";
|
|
+ static ZCONST char Far UnknErrorEAs[] =
|
|
+ " unknown error on extended attributes\n";
|
|
+#endif /* !SFX */
|
|
+
|
|
+static ZCONST char Far UnsupportedExtraField[] =
|
|
+ "\nerror: unsupported extra-field compression type (%u)--skipping\n";
|
|
+static ZCONST char Far BadExtraFieldCRC[] =
|
|
+ "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n";
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/**************************************/
|
|
+/* Function extract_or_test_files() */
|
|
+/**************************************/
|
|
+
|
|
+int extract_or_test_files(__G) /* return PK-type error code */
|
|
+ __GDEF
|
|
+{
|
|
+ unsigned i, j;
|
|
+ zoff_t cd_bufstart;
|
|
+ uch *cd_inptr;
|
|
+ int cd_incnt;
|
|
+ ulg filnum=0L, blknum=0L;
|
|
+ int reached_end;
|
|
+#ifndef SFX
|
|
+ int no_endsig_found;
|
|
+#endif
|
|
+ int error, error_in_archive=PK_COOL;
|
|
+ int *fn_matched=NULL, *xn_matched=NULL;
|
|
+ zucn_t members_processed;
|
|
+ ulg num_skipped=0L, num_bad_pwd=0L;
|
|
+ zoff_t old_extra_bytes = 0L;
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ unsigned num_dirs=0;
|
|
+ direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL;
|
|
+#endif
|
|
+
|
|
+ /*
|
|
+ * First, two general initializations are applied. These have been moved
|
|
+ * here from process_zipfiles() because they are only needed for accessing
|
|
+ * and/or extracting the data content of the zip archive.
|
|
+ */
|
|
+
|
|
+ /* a) initialize the CRC table pointer (once) */
|
|
+ if (CRC_32_TAB == NULL) {
|
|
+ if ((CRC_32_TAB = get_crc_table()) == NULL) {
|
|
+ return PK_MEM;
|
|
+ }
|
|
+ }
|
|
+
|
|
+#if (!defined(SFX) || defined(SFX_EXDIR))
|
|
+ /* b) check out if specified extraction root directory exists */
|
|
+ if (uO.exdir != (char *)NULL && G.extract_flag) {
|
|
+ G.create_dirs = !uO.fflag;
|
|
+ if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {
|
|
+ /* out of memory, or file in way */
|
|
+ return (error == MPN_NOMEM ? PK_MEM : PK_ERR);
|
|
+ }
|
|
+ }
|
|
+#endif /* !SFX || SFX_EXDIR */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ The basic idea of this function is as follows. Since the central di-
|
|
+ rectory lies at the end of the zipfile and the member files lie at the
|
|
+ beginning or middle or wherever, it is not very desirable to simply
|
|
+ read a central directory entry, jump to the member and extract it, and
|
|
+ then jump back to the central directory. In the case of a large zipfile
|
|
+ this would lead to a whole lot of disk-grinding, especially if each mem-
|
|
+ ber file is small. Instead, we read from the central directory the per-
|
|
+ tinent information for a block of files, then go extract/test the whole
|
|
+ block. Thus this routine contains two small(er) loops within a very
|
|
+ large outer loop: the first of the small ones reads a block of files
|
|
+ from the central directory; the second extracts or tests each file; and
|
|
+ the outer one loops over blocks. There's some file-pointer positioning
|
|
+ stuff in between, but that's about it. Btw, it's because of this jump-
|
|
+ ing around that we can afford to be lenient if an error occurs in one of
|
|
+ the member files: we should still be able to go find the other members,
|
|
+ since we know the offset of each from the beginning of the zipfile.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ G.pInfo = G.info;
|
|
+
|
|
+#if CRYPT
|
|
+ G.newzip = TRUE;
|
|
+#endif
|
|
+#ifndef SFX
|
|
+ G.reported_backslash = FALSE;
|
|
+#endif
|
|
+
|
|
+ /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
|
|
+ if (G.filespecs > 0 &&
|
|
+ (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
|
|
+ for (i = 0; i < G.filespecs; ++i)
|
|
+ fn_matched[i] = FALSE;
|
|
+ if (G.xfilespecs > 0 &&
|
|
+ (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
|
|
+ for (i = 0; i < G.xfilespecs; ++i)
|
|
+ xn_matched[i] = FALSE;
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Begin main loop over blocks of member files. We know the entire central
|
|
+ directory is on this disk: we would not have any of this information un-
|
|
+ less the end-of-central-directory record was on this disk, and we would
|
|
+ not have gotten to this routine unless this is also the disk on which
|
|
+ the central directory starts. In practice, this had better be the ONLY
|
|
+ disk in the archive, but we'll add multi-disk support soon.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ members_processed = 0;
|
|
+#ifndef SFX
|
|
+ no_endsig_found = FALSE;
|
|
+#endif
|
|
+ reached_end = FALSE;
|
|
+ while (!reached_end) {
|
|
+ j = 0;
|
|
+#ifdef AMIGA
|
|
+ memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
|
|
+#endif
|
|
+
|
|
+ /*
|
|
+ * Loop through files in central directory, storing offsets, file
|
|
+ * attributes, case-conversion and text-conversion flags until block
|
|
+ * size is reached.
|
|
+ */
|
|
+
|
|
+ while ((j < DIR_BLKSIZ)) {
|
|
+ G.pInfo = &G.info[j];
|
|
+
|
|
+ if (readbuf(__G__ G.sig, 4) == 0) {
|
|
+ error_in_archive = PK_EOF;
|
|
+ reached_end = TRUE; /* ...so no more left to do */
|
|
+ break;
|
|
+ }
|
|
+ if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a new entry? */
|
|
+ /* no new central directory entry
|
|
+ * -> is the number of processed entries compatible with the
|
|
+ * number of entries as stored in the end_central record?
|
|
+ */
|
|
+ if ((members_processed
|
|
+ & (G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16))
|
|
+ == G.ecrec.total_entries_central_dir) {
|
|
+#ifndef SFX
|
|
+ /* yes, so look if we ARE back at the end_central record
|
|
+ */
|
|
+ no_endsig_found =
|
|
+ ( (memcmp(G.sig,
|
|
+ (G.ecrec.have_ecr64 ?
|
|
+ end_central64_sig : end_central_sig),
|
|
+ 4) != 0)
|
|
+ && (!G.ecrec.is_zip64_archive)
|
|
+ && (memcmp(G.sig, end_central_sig, 4) != 0)
|
|
+ );
|
|
+#endif /* !SFX */
|
|
+ } else {
|
|
+ /* no; we have found an error in the central directory
|
|
+ * -> report it and stop searching for more Zip entries
|
|
+ */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1));
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
+ error_in_archive = PK_BADERR;
|
|
+ }
|
|
+ reached_end = TRUE; /* ...so no more left to do */
|
|
+ break;
|
|
+ }
|
|
+ /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
|
|
+ if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
|
|
+ error_in_archive = error; /* only PK_EOF defined */
|
|
+ reached_end = TRUE; /* ...so no more left to do */
|
|
+ break;
|
|
+ }
|
|
+ if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
|
|
+ PK_COOL)
|
|
+ {
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+ if (error > PK_WARN) { /* fatal: no more left to do */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(FilNamMsg),
|
|
+ FnFilter1(G.filename), "central"));
|
|
+ reached_end = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if ((error = do_string(__G__ G.crec.extra_field_length,
|
|
+ EXTRA_FIELD)) != 0)
|
|
+ {
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+ if (error > PK_WARN) { /* fatal */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(ExtFieldMsg),
|
|
+ FnFilter1(G.filename), "central"));
|
|
+ reached_end = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+#ifdef AMIGA
|
|
+ G.filenote_slot = j;
|
|
+ if ((error = do_string(__G__ G.crec.file_comment_length,
|
|
+ uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)
|
|
+#else
|
|
+ if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
|
|
+ != PK_COOL)
|
|
+#endif
|
|
+ {
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+ if (error > PK_WARN) { /* fatal */
|
|
+ Info(slide, 0x421, ((char *)slide,
|
|
+ LoadFarString(BadFileCommLength),
|
|
+ FnFilter1(G.filename)));
|
|
+ reached_end = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (G.process_all_files) {
|
|
+ if (store_info(__G))
|
|
+ ++j; /* file is OK; info[] stored; continue with next */
|
|
+ else
|
|
+ ++num_skipped;
|
|
+ } else {
|
|
+ int do_this_file;
|
|
+
|
|
+ if (G.filespecs == 0)
|
|
+ do_this_file = TRUE;
|
|
+ else { /* check if this entry matches an `include' argument */
|
|
+ do_this_file = FALSE;
|
|
+ for (i = 0; i < G.filespecs; i++)
|
|
+ if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {
|
|
+ do_this_file = TRUE; /* ^-- ignore case or not? */
|
|
+ if (fn_matched)
|
|
+ fn_matched[i] = TRUE;
|
|
+ break; /* found match, so stop looping */
|
|
+ }
|
|
+ }
|
|
+ if (do_this_file) { /* check if this is an excluded file */
|
|
+ for (i = 0; i < G.xfilespecs; i++)
|
|
+ if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {
|
|
+ do_this_file = FALSE; /* ^-- ignore case or not? */
|
|
+ if (xn_matched)
|
|
+ xn_matched[i] = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (do_this_file) {
|
|
+ if (store_info(__G))
|
|
+ ++j; /* file is OK */
|
|
+ else
|
|
+ ++num_skipped; /* unsupp. compression or encryption */
|
|
+ }
|
|
+ } /* end if (process_all_files) */
|
|
+
|
|
+ members_processed++;
|
|
+
|
|
+ } /* end while-loop (adding files to current block) */
|
|
+
|
|
+ /* save position in central directory so can come back later */
|
|
+ cd_bufstart = G.cur_zipfile_bufstart;
|
|
+ cd_inptr = G.inptr;
|
|
+ cd_incnt = G.incnt;
|
|
+
|
|
+ /*-----------------------------------------------------------------------
|
|
+ Second loop: process files in current block, extracting or testing
|
|
+ each one.
|
|
+ -----------------------------------------------------------------------*/
|
|
+
|
|
+ error = extract_or_test_entrylist(__G__ j,
|
|
+ &filnum, &num_bad_pwd, &old_extra_bytes,
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ &num_dirs, &dirlist,
|
|
+#endif
|
|
+ error_in_archive);
|
|
+ if (error != PK_COOL) {
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+ /* ...and keep going (unless disk full or user break) */
|
|
+ if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
|
|
+ /* clear reached_end to signal premature stop ... */
|
|
+ reached_end = FALSE;
|
|
+ /* ... and cancel scanning the central directory */
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
+ /*
|
|
+ * Jump back to where we were in the central directory, then go and do
|
|
+ * the next batch of files.
|
|
+ */
|
|
+
|
|
+#ifdef USE_STRM_INPUT
|
|
+ zfseeko(G.zipfd, cd_bufstart, SEEK_SET);
|
|
+ G.cur_zipfile_bufstart = zftello(G.zipfd);
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ G.cur_zipfile_bufstart =
|
|
+ zlseek(G.zipfd, cd_bufstart, SEEK_SET);
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+ read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */
|
|
+ G.inptr = cd_inptr;
|
|
+ G.incnt = cd_incnt;
|
|
+ ++blknum;
|
|
+
|
|
+#ifdef TEST
|
|
+ printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
|
|
+ printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
|
|
+ cur_zipfile_bufstart);
|
|
+ printf("inptr-inbuf = %d\n", G.inptr-G.inbuf);
|
|
+ printf("incnt = %d\n\n", G.incnt);
|
|
+#endif
|
|
+
|
|
+ } /* end while-loop (blocks of files in central directory) */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Process the list of deferred symlink extractions and finish up
|
|
+ the symbolic links.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef SYMLINKS
|
|
+ if (G.slink_last != NULL) {
|
|
+ if (QCOND2)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(SymLnkDeferred)));
|
|
+ while (G.slink_head != NULL) {
|
|
+ set_deferred_symlink(__G__ G.slink_head);
|
|
+ /* remove the processed entry from the chain and free its memory */
|
|
+ G.slink_last = G.slink_head;
|
|
+ G.slink_head = G.slink_last->next;
|
|
+ free(G.slink_last);
|
|
+ }
|
|
+ G.slink_last = NULL;
|
|
+ }
|
|
+#endif /* SYMLINKS */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Go back through saved list of directories, sort and set times/perms/UIDs
|
|
+ and GIDs from the deepest level on up.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ if (num_dirs > 0) {
|
|
+ sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *));
|
|
+ if (sorted_dirlist == (direntry **)NULL) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(DirlistSortNoMem)));
|
|
+ while (dirlist != (direntry *)NULL) {
|
|
+ direntry *d = dirlist;
|
|
+
|
|
+ dirlist = dirlist->next;
|
|
+ free(d);
|
|
+ }
|
|
+ } else {
|
|
+ ulg ndirs_fail = 0;
|
|
+
|
|
+ if (num_dirs == 1)
|
|
+ sorted_dirlist[0] = dirlist;
|
|
+ else {
|
|
+ for (i = 0; i < num_dirs; ++i) {
|
|
+ sorted_dirlist[i] = dirlist;
|
|
+ dirlist = dirlist->next;
|
|
+ }
|
|
+ qsort((char *)sorted_dirlist, num_dirs, sizeof(direntry *),
|
|
+ dircomp);
|
|
+ }
|
|
+
|
|
+ Trace((stderr, "setting directory times/perms/attributes\n"));
|
|
+ for (i = 0; i < num_dirs; ++i) {
|
|
+ direntry *d = sorted_dirlist[i];
|
|
+
|
|
+ Trace((stderr, "dir = %s\n", d->fn));
|
|
+ if ((error = set_direc_attribs(__G__ d)) != PK_OK) {
|
|
+ ndirs_fail++;
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ LoadFarString(DirlistSetAttrFailed), d->fn));
|
|
+ if (!error_in_archive)
|
|
+ error_in_archive = error;
|
|
+ }
|
|
+ free(d);
|
|
+ }
|
|
+ free(sorted_dirlist);
|
|
+ if (!uO.tflag && QCOND2) {
|
|
+ if (ndirs_fail > 0)
|
|
+ Info(slide, 0, ((char *)slide,
|
|
+ LoadFarString(DirlistFailAttrSum), ndirs_fail));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+#endif /* SET_DIR_ATTRIB */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Check for unmatched filespecs on command line and print warning if any
|
|
+ found. Free allocated memory. (But suppress check when central dir
|
|
+ scan was interrupted prematurely.)
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (fn_matched) {
|
|
+ if (reached_end) for (i = 0; i < G.filespecs; ++i)
|
|
+ if (!fn_matched[i]) {
|
|
+#ifdef DLL
|
|
+ if (!G.redirect_data && !G.redirect_text)
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(FilenameNotMatched), G.pfnames[i]));
|
|
+ else
|
|
+ setFileNotFound(__G);
|
|
+#else
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(FilenameNotMatched), G.pfnames[i]));
|
|
+#endif
|
|
+ if (error_in_archive <= PK_WARN)
|
|
+ error_in_archive = PK_FIND; /* some files not found */
|
|
+ }
|
|
+ free((zvoid *)fn_matched);
|
|
+ }
|
|
+ if (xn_matched) {
|
|
+ if (reached_end) for (i = 0; i < G.xfilespecs; ++i)
|
|
+ if (!xn_matched[i])
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
|
|
+ free((zvoid *)xn_matched);
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Now, all locally allocated memory has been released. When the central
|
|
+ directory processing has been interrupted prematurely, it is safe to
|
|
+ return immediately. All completeness checks and summary messages are
|
|
+ skipped in this case.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+ if (!reached_end)
|
|
+ return error_in_archive;
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Double-check that we're back at the end-of-central-directory record, and
|
|
+ print quick summary of results, if we were just testing the archive. We
|
|
+ send the summary to stdout so that people doing the testing in the back-
|
|
+ ground and redirecting to a file can just do a "tail" on the output file.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifndef SFX
|
|
+ if (no_endsig_found) { /* just to make sure */
|
|
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(EndSigMsg)));
|
|
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
+ if (!error_in_archive) /* don't overwrite stronger error */
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+#endif /* !SFX */
|
|
+ if (uO.tflag) {
|
|
+ ulg num = filnum - num_bad_pwd;
|
|
+
|
|
+ if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */
|
|
+ if (error_in_archive)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
|
|
+ (error_in_archive == PK_WARN)? "warning-" : "", G.zipfn));
|
|
+ else if (num == 0L)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
|
|
+ G.zipfn));
|
|
+ else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L))
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
|
|
+ G.zipfn));
|
|
+ else
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
|
|
+ , G.zipfn, num, (num==1L)? "":"s"));
|
|
+ if (num_skipped > 0L)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
|
|
+ num_skipped, (num_skipped==1L)? "":"s"));
|
|
+#if CRYPT
|
|
+ if (num_bad_pwd > 0L)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
|
|
+ , num_bad_pwd, (num_bad_pwd==1L)? "":"s"));
|
|
+#endif /* CRYPT */
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* give warning if files not tested or extracted (first condition can still
|
|
+ * happen if zipfile is empty and no files specified on command line) */
|
|
+
|
|
+ if ((filnum == 0) && error_in_archive <= PK_WARN) {
|
|
+ if (num_skipped > 0L)
|
|
+ error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
|
|
+ else
|
|
+ error_in_archive = PK_FIND; /* no files found at all */
|
|
+ }
|
|
+#if CRYPT
|
|
+ else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
|
|
+ error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */
|
|
+#endif
|
|
+ else if ((num_skipped > 0L) && error_in_archive <= PK_WARN)
|
|
+ error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */
|
|
+#if CRYPT
|
|
+ else if ((num_bad_pwd > 0L) && !error_in_archive)
|
|
+ error_in_archive = PK_WARN;
|
|
+#endif
|
|
+
|
|
+ return error_in_archive;
|
|
+
|
|
+} /* end function extract_or_test_files() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/***************************/
|
|
+/* Function store_info() */
|
|
+/***************************/
|
|
+
|
|
+static int store_info(__G) /* return 0 if skipping, 1 if OK */
|
|
+ __GDEF
|
|
+{
|
|
+#ifdef USE_BZIP2
|
|
+# define UNKN_BZ2 (G.crec.compression_method!=BZIPPED)
|
|
+#else
|
|
+# define UNKN_BZ2 TRUE /* bzip2 unknown */
|
|
+#endif
|
|
+
|
|
+#ifdef USE_LZMA
|
|
+# define UNKN_LZMA (G.crec.compression_method!=LZMAED)
|
|
+#else
|
|
+# define UNKN_LZMA TRUE /* LZMA unknown */
|
|
+#endif
|
|
+
|
|
+#ifdef USE_WAVP
|
|
+# define UNKN_WAVP (G.crec.compression_method!=WAVPACKED)
|
|
+#else
|
|
+# define UNKN_WAVP TRUE /* WavPack unknown */
|
|
+#endif
|
|
+
|
|
+#ifdef USE_PPMD
|
|
+# define UNKN_PPMD (G.crec.compression_method!=PPMDED)
|
|
+#else
|
|
+# define UNKN_PPMD TRUE /* PPMd unknown */
|
|
+#endif
|
|
+
|
|
+#ifdef SFX
|
|
+# ifdef USE_DEFLATE64
|
|
+# define UNKN_COMPR \
|
|
+ (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \
|
|
+ && G.crec.compression_method>ENHDEFLATED \
|
|
+ && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
|
|
+# else
|
|
+# define UNKN_COMPR \
|
|
+ (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\
|
|
+ && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)
|
|
+# endif
|
|
+#else
|
|
+# ifdef COPYRIGHT_CLEAN /* no reduced files */
|
|
+# define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
|
|
+ G.crec.compression_method <= REDUCED4)
|
|
+# else
|
|
+# define UNKN_RED FALSE /* reducing not unknown */
|
|
+# endif
|
|
+# ifdef LZW_CLEAN /* no shrunk files */
|
|
+# define UNKN_SHR (G.crec.compression_method == SHRUNK)
|
|
+# else
|
|
+# define UNKN_SHR FALSE /* unshrinking not unknown */
|
|
+# endif
|
|
+# ifdef USE_DEFLATE64
|
|
+# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
|
|
+ G.crec.compression_method==TOKENIZED || \
|
|
+ (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \
|
|
+ && UNKN_WAVP && UNKN_PPMD))
|
|
+# else
|
|
+# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
|
|
+ G.crec.compression_method==TOKENIZED || \
|
|
+ (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \
|
|
+ && UNKN_WAVP && UNKN_PPMD))
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS))
|
|
+ int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS);
|
|
+# define UNZVERS_SUPPORT unzvers_support
|
|
+#else
|
|
+# define UNZVERS_SUPPORT UNZIP_VERSION
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Check central directory info for version/compatibility requirements.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */
|
|
+ G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */
|
|
+ G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */
|
|
+ G.pInfo->crc = G.crec.crc32;
|
|
+ G.pInfo->compr_size = G.crec.csize;
|
|
+ G.pInfo->uncompr_size = G.crec.ucsize;
|
|
+
|
|
+ switch (uO.aflag) {
|
|
+ case 0:
|
|
+ G.pInfo->textmode = FALSE; /* bit field */
|
|
+ break;
|
|
+ case 1:
|
|
+ G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */
|
|
+ break;
|
|
+ default: /* case 2: */
|
|
+ G.pInfo->textmode = TRUE;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (G.crec.version_needed_to_extract[1] == VMS_) {
|
|
+ if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
|
|
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
|
|
+ FnFilter1(G.filename), "VMS",
|
|
+ G.crec.version_needed_to_extract[0] / 10,
|
|
+ G.crec.version_needed_to_extract[0] % 10,
|
|
+ VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
|
|
+ return 0;
|
|
+ }
|
|
+#ifndef VMS /* won't be able to use extra field, but still have data */
|
|
+ else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */
|
|
+ Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
|
|
+ FnFilter1(G.filename)));
|
|
+ fgets(G.answerbuf, sizeof(G.answerbuf), stdin);
|
|
+ if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
|
|
+ return 0;
|
|
+ }
|
|
+#endif /* !VMS */
|
|
+ /* usual file type: don't need VMS to extract */
|
|
+ } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {
|
|
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
|
|
+ FnFilter1(G.filename), "PK",
|
|
+ G.crec.version_needed_to_extract[0] / 10,
|
|
+ G.crec.version_needed_to_extract[0] % 10,
|
|
+ UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (UNKN_COMPR) {
|
|
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
|
|
+#ifndef SFX
|
|
+ unsigned cmpridx;
|
|
+
|
|
+ if ((cmpridx = find_compr_idx(G.crec.compression_method))
|
|
+ < NUM_METHODS)
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
|
|
+ FnFilter1(G.filename),
|
|
+ LoadFarStringSmall(ComprNames[cmpridx])));
|
|
+ else
|
|
+#endif
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
|
|
+ FnFilter1(G.filename),
|
|
+ G.crec.compression_method));
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+#if (!CRYPT)
|
|
+ if (G.pInfo->encrypted) {
|
|
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
|
|
+ FnFilter1(G.filename)));
|
|
+ return 0;
|
|
+ }
|
|
+#endif /* !CRYPT */
|
|
+
|
|
+#ifndef SFX
|
|
+ /* store a copy of the central header filename for later comparison */
|
|
+ if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName),
|
|
+ FnFilter1(G.filename)));
|
|
+ } else
|
|
+ zfstrcpy(G.pInfo->cfilname, G.filename);
|
|
+#endif /* !SFX */
|
|
+
|
|
+ /* map whatever file attributes we have into the local format */
|
|
+ mapattr(__G); /* GRR: worry about return value later */
|
|
+
|
|
+ G.pInfo->diskstart = G.crec.disk_number_start;
|
|
+ G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;
|
|
+ return 1;
|
|
+
|
|
+} /* end function store_info() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifndef SFX
|
|
+/*******************************/
|
|
+/* Function find_compr_idx() */
|
|
+/*******************************/
|
|
+
|
|
+unsigned find_compr_idx(compr_methodnum)
|
|
+ unsigned compr_methodnum;
|
|
+{
|
|
+ unsigned i;
|
|
+
|
|
+ for (i = 0; i < NUM_METHODS; i++) {
|
|
+ if (ComprIDs[i] == compr_methodnum) break;
|
|
+ }
|
|
+ return i;
|
|
+}
|
|
+#endif /* !SFX */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/******************************************/
|
|
+/* Function extract_or_test_entrylist() */
|
|
+/******************************************/
|
|
+
|
|
+static int extract_or_test_entrylist(__G__ numchunk,
|
|
+ pfilnum, pnum_bad_pwd, pold_extra_bytes,
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ pnum_dirs, pdirlist,
|
|
+#endif
|
|
+ error_in_archive) /* return PK-type error code */
|
|
+ __GDEF
|
|
+ unsigned numchunk;
|
|
+ ulg *pfilnum;
|
|
+ ulg *pnum_bad_pwd;
|
|
+ zoff_t *pold_extra_bytes;
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ unsigned *pnum_dirs;
|
|
+ direntry **pdirlist;
|
|
+#endif
|
|
+ int error_in_archive;
|
|
+{
|
|
+ unsigned i;
|
|
+ int renamed, query;
|
|
+ int skip_entry;
|
|
+ zoff_t bufstart, inbuf_offset, request;
|
|
+ int error, errcode;
|
|
+
|
|
+/* possible values for local skip_entry flag: */
|
|
+#define SKIP_NO 0 /* do not skip this entry */
|
|
+#define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */
|
|
+#define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */
|
|
+
|
|
+ /*-----------------------------------------------------------------------
|
|
+ Second loop: process files in current block, extracting or testing
|
|
+ each one.
|
|
+ -----------------------------------------------------------------------*/
|
|
+
|
|
+ for (i = 0; i < numchunk; ++i) {
|
|
+ (*pfilnum)++; /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */
|
|
+ G.pInfo = &G.info[i];
|
|
+#ifdef NOVELL_BUG_FAILSAFE
|
|
+ G.dne = FALSE; /* assume file exists until stat() says otherwise */
|
|
+#endif
|
|
+
|
|
+ /* if the target position is not within the current input buffer
|
|
+ * (either haven't yet read far enough, or (maybe) skipping back-
|
|
+ * ward), skip to the target position and reset readbuf(). */
|
|
+
|
|
+ /* seek_zipf(__G__ pInfo->offset); */
|
|
+ request = G.pInfo->offset + G.extra_bytes;
|
|
+ inbuf_offset = request % INBUFSIZ;
|
|
+ bufstart = request - inbuf_offset;
|
|
+
|
|
+ Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
|
|
+ (long)request, (long)inbuf_offset));
|
|
+ Trace((stderr,
|
|
+ "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
|
|
+ (long)bufstart, (long)G.cur_zipfile_bufstart));
|
|
+ if (request < 0) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
|
|
+ G.zipfn, LoadFarString(ReportMsg)));
|
|
+ error_in_archive = PK_ERR;
|
|
+ if (*pfilnum == 1 && G.extra_bytes != 0L) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(AttemptRecompensate)));
|
|
+ *pold_extra_bytes = G.extra_bytes;
|
|
+ G.extra_bytes = 0L;
|
|
+ request = G.pInfo->offset; /* could also check if != 0 */
|
|
+ inbuf_offset = request % INBUFSIZ;
|
|
+ bufstart = request - inbuf_offset;
|
|
+ Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
|
|
+ (long)request, (long)inbuf_offset));
|
|
+ Trace((stderr,
|
|
+ "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
|
|
+ (long)bufstart, (long)G.cur_zipfile_bufstart));
|
|
+ /* try again */
|
|
+ if (request < 0) {
|
|
+ Trace((stderr,
|
|
+ "debug: recompensated request still < 0\n"));
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(SeekMsg),
|
|
+ G.zipfn, LoadFarString(ReportMsg)));
|
|
+ error_in_archive = PK_BADERR;
|
|
+ continue;
|
|
+ }
|
|
+ } else {
|
|
+ error_in_archive = PK_BADERR;
|
|
+ continue; /* this one hosed; try next */
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (bufstart != G.cur_zipfile_bufstart) {
|
|
+ Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
|
|
+#ifdef USE_STRM_INPUT
|
|
+ zfseeko(G.zipfd, bufstart, SEEK_SET);
|
|
+ G.cur_zipfile_bufstart = zftello(G.zipfd);
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ G.cur_zipfile_bufstart =
|
|
+ zlseek(G.zipfd, bufstart, SEEK_SET);
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+ if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
|
|
+ *pfilnum, "lseek", (long)bufstart));
|
|
+ error_in_archive = PK_BADERR;
|
|
+ continue; /* can still do next file */
|
|
+ }
|
|
+ G.inptr = G.inbuf + (int)inbuf_offset;
|
|
+ G.incnt -= (int)inbuf_offset;
|
|
+ } else {
|
|
+ G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
|
|
+ G.inptr = G.inbuf + (int)inbuf_offset;
|
|
+ }
|
|
+
|
|
+ /* should be in proper position now, so check for sig */
|
|
+ if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
|
|
+ *pfilnum, "EOF", (long)request));
|
|
+ error_in_archive = PK_BADERR;
|
|
+ continue; /* but can still try next one */
|
|
+ }
|
|
+ if (memcmp(G.sig, local_hdr_sig, 4)) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
|
|
+ *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request));
|
|
+ /*
|
|
+ GRRDUMP(G.sig, 4)
|
|
+ GRRDUMP(local_hdr_sig, 4)
|
|
+ */
|
|
+ error_in_archive = PK_ERR;
|
|
+ if ((*pfilnum == 1 && G.extra_bytes != 0L) ||
|
|
+ (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(AttemptRecompensate)));
|
|
+ if (G.extra_bytes) {
|
|
+ *pold_extra_bytes = G.extra_bytes;
|
|
+ G.extra_bytes = 0L;
|
|
+ } else
|
|
+ G.extra_bytes = *pold_extra_bytes; /* third attempt */
|
|
+ if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) ||
|
|
+ (readbuf(__G__ G.sig, 4) == 0)) { /* bad offset */
|
|
+ if (error != PK_BADERR)
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(OffsetMsg), *pfilnum, "EOF",
|
|
+ (long)request));
|
|
+ error_in_archive = PK_BADERR;
|
|
+ continue; /* but can still try next one */
|
|
+ }
|
|
+ if (memcmp(G.sig, local_hdr_sig, 4)) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(OffsetMsg), *pfilnum,
|
|
+ LoadFarStringSmall(LocalHdrSig), (long)request));
|
|
+ error_in_archive = PK_BADERR;
|
|
+ continue;
|
|
+ }
|
|
+ } else
|
|
+ continue; /* this one hosed; try next */
|
|
+ }
|
|
+ if ((error = process_local_file_hdr(__G)) != PK_COOL) {
|
|
+ Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
|
|
+ *pfilnum));
|
|
+ error_in_archive = error; /* only PK_EOF defined */
|
|
+ continue; /* can still try next one */
|
|
+ }
|
|
+#if (!defined(SFX) && defined(UNICODE_SUPPORT))
|
|
+ if (((G.lrec.general_purpose_bit_flag & (1 << 11)) == (1 << 11))
|
|
+ != (G.pInfo->GPFIsUTF8 != 0)) {
|
|
+ if (QCOND2) {
|
|
+# ifdef SMALL_MEM
|
|
+ char *temp_cfilnam = slide + (7 * (WSIZE>>3));
|
|
+
|
|
+ zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);
|
|
+# define cFile_PrintBuf temp_cfilnam
|
|
+# else
|
|
+# define cFile_PrintBuf G.pInfo->cfilname
|
|
+# endif
|
|
+ Info(slide, 0x421, ((char *)slide,
|
|
+ LoadFarStringSmall2(GP11FlagsDiffer),
|
|
+ *pfilnum, FnFilter1(cFile_PrintBuf), G.pInfo->GPFIsUTF8));
|
|
+# undef cFile_PrintBuf
|
|
+ }
|
|
+ if (error_in_archive < PK_WARN)
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+#endif /* !SFX && UNICODE_SUPPORT */
|
|
+ if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) !=
|
|
+ PK_COOL)
|
|
+ {
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+ if (error > PK_WARN) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
|
|
+ FnFilter1(G.filename), "local"));
|
|
+ continue; /* go on to next one */
|
|
+ }
|
|
+ }
|
|
+ if (G.extra_field != (uch *)NULL) {
|
|
+ free(G.extra_field);
|
|
+ G.extra_field = (uch *)NULL;
|
|
+ }
|
|
+ if ((error =
|
|
+ do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
|
|
+ {
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+ if (error > PK_WARN) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(ExtFieldMsg),
|
|
+ FnFilter1(G.filename), "local"));
|
|
+ continue; /* go on */
|
|
+ }
|
|
+ }
|
|
+#ifndef SFX
|
|
+ /* Filename consistency checks must come after reading in the local
|
|
+ * extra field, so that a UTF-8 entry name e.f. block has already
|
|
+ * been processed.
|
|
+ */
|
|
+ if (G.pInfo->cfilname != (char Far *)NULL) {
|
|
+ if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) {
|
|
+# ifdef SMALL_MEM
|
|
+ char *temp_cfilnam = slide + (7 * (WSIZE>>3));
|
|
+
|
|
+ zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);
|
|
+# define cFile_PrintBuf temp_cfilnam
|
|
+# else
|
|
+# define cFile_PrintBuf G.pInfo->cfilname
|
|
+# endif
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall2(LvsCFNamMsg),
|
|
+ FnFilter2(cFile_PrintBuf), FnFilter1(G.filename)));
|
|
+# undef cFile_PrintBuf
|
|
+ zfstrcpy(G.filename, G.pInfo->cfilname);
|
|
+ if (error_in_archive < PK_WARN)
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+ zffree(G.pInfo->cfilname);
|
|
+ G.pInfo->cfilname = (char Far *)NULL;
|
|
+ }
|
|
+#endif /* !SFX */
|
|
+ /* Size consistency checks must come after reading in the local extra
|
|
+ * field, so that any Zip64 extension local e.f. block has already
|
|
+ * been processed.
|
|
+ */
|
|
+ if (G.lrec.compression_method == STORED) {
|
|
+ zusz_t csiz_decrypted = G.lrec.csize;
|
|
+
|
|
+ if (G.pInfo->encrypted) {
|
|
+ if (csiz_decrypted < 12) {
|
|
+ /* handle the error now to prevent unsigned overflow */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipNoFile),
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Inflate)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
+ csiz_decrypted -= 12;
|
|
+ }
|
|
+ if (G.lrec.ucsize != csiz_decrypted) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall2(WrnStorUCSizCSizDiff),
|
|
+ FnFilter1(G.filename),
|
|
+ FmZofft(G.lrec.ucsize, NULL, "u"),
|
|
+ FmZofft(csiz_decrypted, NULL, "u")));
|
|
+ G.lrec.ucsize = csiz_decrypted;
|
|
+ if (error_in_archive < PK_WARN)
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+ }
|
|
+
|
|
+#if CRYPT
|
|
+ if (G.pInfo->encrypted &&
|
|
+ (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
|
|
+ if (error == PK_WARN) {
|
|
+ if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(SkipIncorrectPasswd),
|
|
+ FnFilter1(G.filename)));
|
|
+ ++(*pnum_bad_pwd);
|
|
+ } else { /* (error > PK_WARN) */
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(SkipCannotGetPasswd),
|
|
+ FnFilter1(G.filename)));
|
|
+ }
|
|
+ continue; /* go on to next file */
|
|
+ }
|
|
+#endif /* CRYPT */
|
|
+
|
|
+ /*
|
|
+ * just about to extract file: if extracting to disk, check if
|
|
+ * already exists, and if so, take appropriate action according to
|
|
+ * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
|
|
+ * loop because we don't store the possibly renamed filename[] in
|
|
+ * info[])
|
|
+ */
|
|
+#ifdef DLL
|
|
+ if (!uO.tflag && !uO.cflag && !G.redirect_data)
|
|
+#else
|
|
+ if (!uO.tflag && !uO.cflag)
|
|
+#endif
|
|
+ {
|
|
+ renamed = FALSE; /* user hasn't renamed output file yet */
|
|
+
|
|
+startover:
|
|
+ query = FALSE;
|
|
+ skip_entry = SKIP_NO;
|
|
+ /* for files from DOS FAT, check for use of backslash instead
|
|
+ * of slash as directory separator (bug in some zipper(s); so
|
|
+ * far, not a problem in HPFS, NTFS or VFAT systems)
|
|
+ */
|
|
+#ifndef SFX
|
|
+ if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) {
|
|
+ char *p=G.filename;
|
|
+
|
|
+ if (*p) do {
|
|
+ if (*p == '\\') {
|
|
+ if (!G.reported_backslash) {
|
|
+ Info(slide, 0x21, ((char *)slide,
|
|
+ LoadFarString(BackslashPathSep), G.zipfn));
|
|
+ G.reported_backslash = TRUE;
|
|
+ if (!error_in_archive)
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+ *p = '/';
|
|
+ }
|
|
+ } while (*PREINCSTR(p));
|
|
+ }
|
|
+#endif /* !SFX */
|
|
+
|
|
+ if (!renamed) {
|
|
+ /* remove absolute path specs */
|
|
+ if (G.filename[0] == '/') {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(AbsolutePathWarning),
|
|
+ FnFilter1(G.filename)));
|
|
+ if (!error_in_archive)
|
|
+ error_in_archive = PK_WARN;
|
|
+ do {
|
|
+ char *p = G.filename + 1;
|
|
+ do {
|
|
+ *(p-1) = *p;
|
|
+ } while (*p++ != '\0');
|
|
+ } while (G.filename[0] == '/');
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* mapname can create dirs if not freshening or if renamed */
|
|
+ error = mapname(__G__ renamed);
|
|
+ if ((errcode = error & ~MPN_MASK) != PK_OK &&
|
|
+ error_in_archive < errcode)
|
|
+ error_in_archive = errcode;
|
|
+ if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) {
|
|
+ if (errcode == MPN_CREATED_DIR) {
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ direntry *d_entry;
|
|
+
|
|
+ error = defer_dir_attribs(__G__ &d_entry);
|
|
+ if (d_entry == (direntry *)NULL) {
|
|
+ /* There may be no dir_attribs info available, or
|
|
+ * we have encountered a mem allocation error.
|
|
+ * In case of an error, report it and set program
|
|
+ * error state to warning level.
|
|
+ */
|
|
+ if (error) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(DirlistEntryNoMem)));
|
|
+ if (!error_in_archive)
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+ } else {
|
|
+ d_entry->next = (*pdirlist);
|
|
+ (*pdirlist) = d_entry;
|
|
+ ++(*pnum_dirs);
|
|
+ }
|
|
+#endif /* SET_DIR_ATTRIB */
|
|
+ } else if (errcode == MPN_VOL_LABEL) {
|
|
+#ifdef DOS_OS2_W32
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(SkipVolumeLabel),
|
|
+ FnFilter1(G.filename),
|
|
+ uO.volflag? "hard disk " : ""));
|
|
+#else
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(SkipVolumeLabel),
|
|
+ FnFilter1(G.filename), ""));
|
|
+#endif
|
|
+ } else if (errcode > MPN_INF_SKIP &&
|
|
+ error_in_archive < PK_ERR)
|
|
+ error_in_archive = PK_ERR;
|
|
+ Trace((stderr, "mapname(%s) returns error code = %d\n",
|
|
+ FnFilter1(G.filename), error));
|
|
+ continue; /* go on to next file */
|
|
+ }
|
|
+
|
|
+#ifdef QDOS
|
|
+ QFilename(__G__ G.filename);
|
|
+#endif
|
|
+ switch (check_for_newer(__G__ G.filename)) {
|
|
+ case DOES_NOT_EXIST:
|
|
+#ifdef NOVELL_BUG_FAILSAFE
|
|
+ G.dne = TRUE; /* stat() says file DOES NOT EXIST */
|
|
+#endif
|
|
+ /* freshen (no new files): skip unless just renamed */
|
|
+ if (uO.fflag && !renamed)
|
|
+ skip_entry = SKIP_Y_NONEXIST;
|
|
+ break;
|
|
+ case EXISTS_AND_OLDER:
|
|
+#ifdef UNIXBACKUP
|
|
+ if (!uO.B_flag)
|
|
+#endif
|
|
+ {
|
|
+ if (IS_OVERWRT_NONE)
|
|
+ /* never overwrite: skip file */
|
|
+ skip_entry = SKIP_Y_EXISTING;
|
|
+ else if (!IS_OVERWRT_ALL)
|
|
+ query = TRUE;
|
|
+ }
|
|
+ break;
|
|
+ case EXISTS_AND_NEWER: /* (or equal) */
|
|
+#ifdef UNIXBACKUP
|
|
+ if ((!uO.B_flag && IS_OVERWRT_NONE) ||
|
|
+#else
|
|
+ if (IS_OVERWRT_NONE ||
|
|
+#endif
|
|
+ (uO.uflag && !renamed)) {
|
|
+ /* skip if update/freshen & orig name */
|
|
+ skip_entry = SKIP_Y_EXISTING;
|
|
+ } else {
|
|
+#ifdef UNIXBACKUP
|
|
+ if (!IS_OVERWRT_ALL && !uO.B_flag)
|
|
+#else
|
|
+ if (!IS_OVERWRT_ALL)
|
|
+#endif
|
|
+ query = TRUE;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+#ifdef VMS
|
|
+ /* 2008-07-24 SMS.
|
|
+ * On VMS, if the file name includes a version number,
|
|
+ * and "-V" ("retain VMS version numbers", V_flag) is in
|
|
+ * effect, then the VMS-specific code will handle any
|
|
+ * conflicts with an existing file, making this query
|
|
+ * redundant. (Implicit "y" response here.)
|
|
+ */
|
|
+ if (query && uO.V_flag) {
|
|
+ /* Not discarding file versions. Look for one. */
|
|
+ int cndx = strlen(G.filename) - 1;
|
|
+
|
|
+ while ((cndx > 0) && (isdigit(G.filename[cndx])))
|
|
+ cndx--;
|
|
+ if (G.filename[cndx] == ';')
|
|
+ /* File version found; skip the generic query,
|
|
+ * proceeding with its default response "y".
|
|
+ */
|
|
+ query = FALSE;
|
|
+ }
|
|
+#endif /* VMS */
|
|
+ if (query) {
|
|
+#ifdef WINDLL
|
|
+ switch (G.lpUserFunctions->replace != NULL ?
|
|
+ (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) :
|
|
+ IDM_REPLACE_NONE) {
|
|
+ case IDM_REPLACE_RENAME:
|
|
+ _ISO_INTERN(G.filename);
|
|
+ renamed = TRUE;
|
|
+ goto startover;
|
|
+ case IDM_REPLACE_ALL:
|
|
+ G.overwrite_mode = OVERWRT_ALWAYS;
|
|
+ /* FALL THROUGH, extract */
|
|
+ case IDM_REPLACE_YES:
|
|
+ break;
|
|
+ case IDM_REPLACE_NONE:
|
|
+ G.overwrite_mode = OVERWRT_NEVER;
|
|
+ /* FALL THROUGH, skip */
|
|
+ case IDM_REPLACE_NO:
|
|
+ skip_entry = SKIP_Y_EXISTING;
|
|
+ break;
|
|
+ }
|
|
+#else /* !WINDLL */
|
|
+ extent fnlen;
|
|
+reprompt:
|
|
+ Info(slide, 0x81, ((char *)slide,
|
|
+ LoadFarString(ReplaceQuery),
|
|
+ FnFilter1(G.filename)));
|
|
+ if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin)
|
|
+ == (char *)NULL) {
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(AssumeNone)));
|
|
+ *G.answerbuf = 'N';
|
|
+ if (!error_in_archive)
|
|
+ error_in_archive = 1; /* not extracted: warning */
|
|
+ }
|
|
+ switch (*G.answerbuf) {
|
|
+ case 'r':
|
|
+ case 'R':
|
|
+ do {
|
|
+ Info(slide, 0x81, ((char *)slide,
|
|
+ LoadFarString(NewNameQuery)));
|
|
+ fgets(G.filename, FILNAMSIZ, stdin);
|
|
+ /* usually get \n here: better check for it */
|
|
+ fnlen = strlen(G.filename);
|
|
+ if (lastchar(G.filename, fnlen) == '\n')
|
|
+ G.filename[--fnlen] = '\0';
|
|
+ } while (fnlen == 0);
|
|
+#ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */
|
|
+ _OEM_INTERN(G.filename);
|
|
+#endif
|
|
+ renamed = TRUE;
|
|
+ goto startover; /* sorry for a goto */
|
|
+ case 'A': /* dangerous option: force caps */
|
|
+ G.overwrite_mode = OVERWRT_ALWAYS;
|
|
+ /* FALL THROUGH, extract */
|
|
+ case 'y':
|
|
+ case 'Y':
|
|
+ break;
|
|
+ case 'N':
|
|
+ G.overwrite_mode = OVERWRT_NEVER;
|
|
+ /* FALL THROUGH, skip */
|
|
+ case 'n':
|
|
+ /* skip file */
|
|
+ skip_entry = SKIP_Y_EXISTING;
|
|
+ break;
|
|
+ case '\n':
|
|
+ case '\r':
|
|
+ /* Improve echo of '\n' and/or '\r'
|
|
+ (sizeof(G.answerbuf) == 10 (see globals.h), so
|
|
+ there is enough space for the provided text...) */
|
|
+ strcpy(G.answerbuf, "{ENTER}");
|
|
+ /* fall through ... */
|
|
+ default:
|
|
+ /* usually get \n here: remove it for nice display
|
|
+ (fnlen can be re-used here, we are outside the
|
|
+ "enter new filename" loop) */
|
|
+ fnlen = strlen(G.answerbuf);
|
|
+ if (lastchar(G.answerbuf, fnlen) == '\n')
|
|
+ G.answerbuf[--fnlen] = '\0';
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(InvalidResponse), G.answerbuf));
|
|
+ goto reprompt; /* yet another goto? */
|
|
+ } /* end switch (*answerbuf) */
|
|
+#endif /* ?WINDLL */
|
|
+ } /* end if (query) */
|
|
+ if (skip_entry != SKIP_NO) {
|
|
+#ifdef WINDLL
|
|
+ if (skip_entry == SKIP_Y_EXISTING) {
|
|
+ /* report skipping of an existing entry */
|
|
+ Info(slide, 0, ((char *)slide,
|
|
+ ((IS_OVERWRT_NONE || !uO.uflag || renamed) ?
|
|
+ "Target file exists. Skipping %s\n" :
|
|
+ "Target file newer. Skipping %s\n"),
|
|
+ FnFilter1(G.filename)));
|
|
+ }
|
|
+#endif /* WINDLL */
|
|
+ continue;
|
|
+ }
|
|
+ } /* end if (extracting to disk) */
|
|
+
|
|
+#ifdef DLL
|
|
+ if ((G.statreportcb != NULL) &&
|
|
+ (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
|
|
+ G.filename, NULL)) {
|
|
+ return IZ_CTRLC; /* cancel operation by user request */
|
|
+ }
|
|
+#endif
|
|
+#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
|
|
+ UserStop();
|
|
+#endif
|
|
+#ifdef AMIGA
|
|
+ G.filenote_slot = i;
|
|
+#endif
|
|
+ G.disk_full = 0;
|
|
+ if ((error = extract_or_test_member(__G)) != PK_COOL) {
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error; /* ...and keep going */
|
|
+#ifdef DLL
|
|
+ if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
|
|
+#else
|
|
+ if (G.disk_full > 1) {
|
|
+#endif
|
|
+ return error_in_archive; /* (unless disk full) */
|
|
+ }
|
|
+ }
|
|
+#ifdef DLL
|
|
+ if ((G.statreportcb != NULL) &&
|
|
+ (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
|
|
+ G.filename, (zvoid *)&G.lrec.ucsize)) {
|
|
+ return IZ_CTRLC; /* cancel operation by user request */
|
|
+ }
|
|
+#endif
|
|
+#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
|
|
+ UserStop();
|
|
+#endif
|
|
+ } /* end for-loop (i: files in current block) */
|
|
+
|
|
+ return error_in_archive;
|
|
+
|
|
+} /* end function extract_or_test_entrylist() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/* wsize is used in extract_or_test_member() and UZbunzip2() */
|
|
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
|
+# define wsize G._wsize /* wsize is a variable */
|
|
+#else
|
|
+# define wsize WSIZE /* wsize is a constant */
|
|
+#endif
|
|
+
|
|
+/***************************************/
|
|
+/* Function extract_or_test_member() */
|
|
+/***************************************/
|
|
+
|
|
+static int extract_or_test_member(__G) /* return PK-type error code */
|
|
+ __GDEF
|
|
+{
|
|
+ char *nul="[empty] ", *txt="[text] ", *bin="[binary]";
|
|
+#ifdef CMS_MVS
|
|
+ char *ebc="[ebcdic]";
|
|
+#endif
|
|
+ register int b;
|
|
+ int r, error=PK_COOL;
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Initialize variables, buffers, etc.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ G.bits_left = 0;
|
|
+ G.bitbuf = 0L; /* unreduce and unshrink only */
|
|
+ G.zipeof = 0;
|
|
+ G.newfile = TRUE;
|
|
+ G.crc32val = CRCVAL_INITIAL;
|
|
+
|
|
+#ifdef SYMLINKS
|
|
+ /* If file is a (POSIX-compatible) symbolic link and we are extracting
|
|
+ * to disk, prepare to restore the link. */
|
|
+ G.symlnk = (G.pInfo->symlink &&
|
|
+ !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0));
|
|
+#endif /* SYMLINKS */
|
|
+
|
|
+ if (uO.tflag) {
|
|
+ if (!uO.qflag)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
|
|
+ FnFilter1(G.filename), "", ""));
|
|
+ } else {
|
|
+#ifdef DLL
|
|
+ if (uO.cflag && !G.redirect_data)
|
|
+#else
|
|
+ if (uO.cflag)
|
|
+#endif
|
|
+ {
|
|
+#if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
|
|
+ G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */
|
|
+#else
|
|
+ G.outfile = stdout;
|
|
+#endif
|
|
+#ifdef DOS_FLX_NLM_OS2_W32
|
|
+#if (defined(__HIGHC__) && !defined(FLEXOS))
|
|
+ setmode(G.outfile, _BINARY);
|
|
+#else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
|
|
+ setmode(fileno(G.outfile), O_BINARY);
|
|
+#endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
|
|
+# define NEWLINE "\r\n"
|
|
+#else /* !DOS_FLX_NLM_OS2_W32 */
|
|
+# define NEWLINE "\n"
|
|
+#endif /* ?DOS_FLX_NLM_OS2_W32 */
|
|
+#ifdef VMS
|
|
+ /* VMS: required even for stdout! */
|
|
+ if ((r = open_outfile(__G)) != 0)
|
|
+ switch (r) {
|
|
+ case OPENOUT_SKIPOK:
|
|
+ return PK_OK;
|
|
+ case OPENOUT_SKIPWARN:
|
|
+ return PK_WARN;
|
|
+ default:
|
|
+ return PK_DISK;
|
|
+ }
|
|
+ } else if ((r = open_outfile(__G)) != 0)
|
|
+ switch (r) {
|
|
+ case OPENOUT_SKIPOK:
|
|
+ return PK_OK;
|
|
+ case OPENOUT_SKIPWARN:
|
|
+ return PK_WARN;
|
|
+ default:
|
|
+ return PK_DISK;
|
|
+ }
|
|
+#else /* !VMS */
|
|
+ } else if (open_outfile(__G))
|
|
+ return PK_DISK;
|
|
+#endif /* ?VMS */
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Unpack the file.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */
|
|
+ switch (G.lrec.compression_method) {
|
|
+ case STORED:
|
|
+ if (!uO.tflag && QCOND2) {
|
|
+#ifdef SYMLINKS
|
|
+ if (G.symlnk) /* can also be deflated, but rarer... */
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
|
|
+ "link", FnFilter1(G.filename), "", ""));
|
|
+ else
|
|
+#endif /* SYMLINKS */
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
|
|
+ "extract", FnFilter1(G.filename),
|
|
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
|
|
+ "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
|
|
+ bin)), uO.cflag? NEWLINE : ""));
|
|
+ }
|
|
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
|
+ if (G.redirect_slide) {
|
|
+ wsize = G.redirect_size; redirSlide = G.redirect_buffer;
|
|
+ } else {
|
|
+ wsize = WSIZE; redirSlide = slide;
|
|
+ }
|
|
+#endif
|
|
+ G.outptr = redirSlide;
|
|
+ G.outcnt = 0L;
|
|
+ while ((b = NEXTBYTE) != EOF) {
|
|
+ *G.outptr++ = (uch)b;
|
|
+ if (++G.outcnt == wsize) {
|
|
+ error = flush(__G__ redirSlide, G.outcnt, 0);
|
|
+ G.outptr = redirSlide;
|
|
+ G.outcnt = 0L;
|
|
+ if (error != PK_COOL || G.disk_full) break;
|
|
+ }
|
|
+ }
|
|
+ if (G.outcnt) { /* flush final (partial) buffer */
|
|
+ r = flush(__G__ redirSlide, G.outcnt, 0);
|
|
+ if (error < r) error = r;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+#ifndef SFX
|
|
+#ifndef LZW_CLEAN
|
|
+ case SHRUNK:
|
|
+ if (!uO.tflag && QCOND2) {
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
|
|
+ LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
|
|
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
|
|
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
|
|
+ }
|
|
+ if ((r = unshrink(__G)) != PK_COOL) {
|
|
+ if (r < PK_DISK) {
|
|
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Unshrink),
|
|
+ FnFilter1(G.filename)));
|
|
+ else
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Unshrink)));
|
|
+ }
|
|
+ error = r;
|
|
+ }
|
|
+ break;
|
|
+#endif /* !LZW_CLEAN */
|
|
+
|
|
+#ifndef COPYRIGHT_CLEAN
|
|
+ case REDUCED1:
|
|
+ case REDUCED2:
|
|
+ case REDUCED3:
|
|
+ case REDUCED4:
|
|
+ if (!uO.tflag && QCOND2) {
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
|
|
+ "unreduc", FnFilter1(G.filename),
|
|
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
|
|
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
|
|
+ }
|
|
+ if ((r = unreduce(__G)) != PK_COOL) {
|
|
+ /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */
|
|
+ error = r;
|
|
+ }
|
|
+ break;
|
|
+#endif /* !COPYRIGHT_CLEAN */
|
|
+
|
|
+ case IMPLODED:
|
|
+ if (!uO.tflag && QCOND2) {
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
|
|
+ "explod", FnFilter1(G.filename),
|
|
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
|
|
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
|
|
+ }
|
|
+ if ((r = explode(__G)) != 0) {
|
|
+ if (r == 5) { /* treat 5 specially */
|
|
+ int warning = ((zusz_t)G.used_csize <= G.lrec.csize);
|
|
+
|
|
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(LengthMsg),
|
|
+ "", warning ? "warning" : "error",
|
|
+ FmZofft(G.used_csize, NULL, NULL),
|
|
+ FmZofft(G.lrec.ucsize, NULL, "u"),
|
|
+ warning ? " " : "",
|
|
+ FmZofft(G.lrec.csize, NULL, "u"),
|
|
+ " [", FnFilter1(G.filename), "]"));
|
|
+ else
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(LengthMsg),
|
|
+ "\n", warning ? "warning" : "error",
|
|
+ FmZofft(G.used_csize, NULL, NULL),
|
|
+ FmZofft(G.lrec.ucsize, NULL, "u"),
|
|
+ warning ? " " : "",
|
|
+ FmZofft(G.lrec.csize, NULL, "u"),
|
|
+ "", "", "."));
|
|
+ error = warning ? PK_WARN : PK_ERR;
|
|
+ } else if (r < PK_DISK) {
|
|
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipFile), r == 3?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Explode),
|
|
+ FnFilter1(G.filename)));
|
|
+ else
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipNoFile), r == 3?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Explode)));
|
|
+ error = ((r == 3) ? PK_MEM3 : PK_ERR);
|
|
+ } else {
|
|
+ error = r;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+#endif /* !SFX */
|
|
+
|
|
+ case DEFLATED:
|
|
+#ifdef USE_DEFLATE64
|
|
+ case ENHDEFLATED:
|
|
+#endif
|
|
+ if (!uO.tflag && QCOND2) {
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
|
|
+ "inflat", FnFilter1(G.filename),
|
|
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
|
|
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
|
|
+ }
|
|
+#ifndef USE_ZLIB /* zlib's function is called inflate(), too */
|
|
+# define UZinflate inflate
|
|
+#endif
|
|
+ if ((r = UZinflate(__G__
|
|
+ (G.lrec.compression_method == ENHDEFLATED)))
|
|
+ != 0) {
|
|
+ if (r < PK_DISK) {
|
|
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipFile), r == 3?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Inflate),
|
|
+ FnFilter1(G.filename)));
|
|
+ else
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipNoFile), r == 3?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Inflate)));
|
|
+ error = ((r == 3) ? PK_MEM3 : PK_ERR);
|
|
+ } else {
|
|
+ error = r;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+#ifdef USE_BZIP2
|
|
+ case BZIPPED:
|
|
+ if (!uO.tflag && QCOND2) {
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
|
|
+ "bunzipp", FnFilter1(G.filename),
|
|
+ (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
|
|
+ "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
|
|
+ }
|
|
+ if ((r = UZbunzip2(__G)) != 0) {
|
|
+ if (r < PK_DISK) {
|
|
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipFile), r == 3?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(BUnzip),
|
|
+ FnFilter1(G.filename)));
|
|
+ else
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipNoFile), r == 3?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(BUnzip)));
|
|
+ error = ((r == 3) ? PK_MEM3 : PK_ERR);
|
|
+ } else {
|
|
+ error = r;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+#endif /* USE_BZIP2 */
|
|
+
|
|
+ default: /* should never get to this point */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
|
|
+ /* close and delete file before return? */
|
|
+ undefer_input(__G);
|
|
+ return PK_WARN;
|
|
+
|
|
+ } /* end switch (compression method) */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Close the file and set its date and time (not necessarily in that order),
|
|
+ and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit
|
|
+ machines (redundant on 32-bit machines).
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef VMS /* VMS: required even for stdout! (final flush) */
|
|
+ if (!uO.tflag) /* don't close NULL file */
|
|
+ error = close_outfile(__G);
|
|
+#else
|
|
+#ifdef DLL
|
|
+ if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
|
|
+ if (G.redirect_data)
|
|
+ FINISH_REDIRECT();
|
|
+ else
|
|
+ error = close_outfile(__G);
|
|
+ }
|
|
+#else
|
|
+ if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */
|
|
+ error = close_outfile(__G);
|
|
+#endif
|
|
+#endif /* VMS */
|
|
+
|
|
+ if (G.disk_full) { /* set by flush() */
|
|
+ if (G.disk_full > 1) {
|
|
+#if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
|
|
+ /* delete the incomplete file if we can */
|
|
+ if (unlink(G.filename) != 0)
|
|
+ Trace((stderr, "extract.c: could not delete %s\n",
|
|
+ FnFilter1(G.filename)));
|
|
+#else
|
|
+ /* warn user about the incomplete file */
|
|
+ Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
|
|
+ FnFilter1(G.filename)));
|
|
+#endif
|
|
+ error = PK_DISK;
|
|
+ } else {
|
|
+ error = PK_WARN;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (error > PK_WARN) {/* don't print redundant CRC error if error already */
|
|
+ undefer_input(__G);
|
|
+ return error;
|
|
+ }
|
|
+ if (G.crc32val != G.lrec.crc32) {
|
|
+ /* if quiet enough, we haven't output the filename yet: do it */
|
|
+ if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
|
|
+ Info(slide, 0x401, ((char *)slide, "%-22s ",
|
|
+ FnFilter1(G.filename)));
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
|
|
+ G.lrec.crc32));
|
|
+#if CRYPT
|
|
+ if (G.pInfo->encrypted)
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
|
|
+#endif
|
|
+ error = PK_ERR;
|
|
+ } else if (uO.tflag) {
|
|
+#ifndef SFX
|
|
+ if (G.extra_field) {
|
|
+ if ((r = TestExtraField(__G__ G.extra_field,
|
|
+ G.lrec.extra_field_length)) > error)
|
|
+ error = r;
|
|
+ } else
|
|
+#endif /* !SFX */
|
|
+ if (!uO.qflag)
|
|
+ Info(slide, 0, ((char *)slide, " OK\n"));
|
|
+ } else {
|
|
+ if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */
|
|
+ Info(slide, 0, ((char *)slide, "\n"));
|
|
+ }
|
|
+
|
|
+ undefer_input(__G);
|
|
+ return error;
|
|
+
|
|
+} /* end function extract_or_test_member() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifndef SFX
|
|
+
|
|
+/*******************************/
|
|
+/* Function TestExtraField() */
|
|
+/*******************************/
|
|
+
|
|
+static int TestExtraField(__G__ ef, ef_len)
|
|
+ __GDEF
|
|
+ uch *ef;
|
|
+ unsigned ef_len;
|
|
+{
|
|
+ ush ebID;
|
|
+ unsigned ebLen;
|
|
+ unsigned eb_cmpr_offs = 0;
|
|
+ int r;
|
|
+
|
|
+ /* we know the regular compressed file data tested out OK, or else we
|
|
+ * wouldn't be here ==> print filename if any extra-field errors found
|
|
+ */
|
|
+ while (ef_len >= EB_HEADSIZE) {
|
|
+ ebID = makeword(ef);
|
|
+ ebLen = (unsigned)makeword(ef+EB_LEN);
|
|
+
|
|
+ if (ebLen > (ef_len - EB_HEADSIZE))
|
|
+ {
|
|
+ /* Discovered some extra field inconsistency! */
|
|
+ if (uO.qflag)
|
|
+ Info(slide, 1, ((char *)slide, "%-22s ",
|
|
+ FnFilter1(G.filename)));
|
|
+ Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
|
|
+ ebLen, (ef_len - EB_HEADSIZE)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
+
|
|
+ switch (ebID) {
|
|
+ case EF_OS2:
|
|
+ case EF_ACL:
|
|
+ case EF_MAC3:
|
|
+ case EF_BEOS:
|
|
+ case EF_ATHEOS:
|
|
+ switch (ebID) {
|
|
+ case EF_OS2:
|
|
+ case EF_ACL:
|
|
+ eb_cmpr_offs = EB_OS2_HLEN;
|
|
+ break;
|
|
+ case EF_MAC3:
|
|
+ if (ebLen >= EB_MAC3_HLEN &&
|
|
+ (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
|
|
+ & EB_M3_FL_UNCMPR) &&
|
|
+ (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
|
|
+ eb_cmpr_offs = 0;
|
|
+ else
|
|
+ eb_cmpr_offs = EB_MAC3_HLEN;
|
|
+ break;
|
|
+ case EF_BEOS:
|
|
+ case EF_ATHEOS:
|
|
+ if (ebLen >= EB_BEOS_HLEN &&
|
|
+ (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
|
|
+ (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
|
|
+ eb_cmpr_offs = 0;
|
|
+ else
|
|
+ eb_cmpr_offs = EB_BEOS_HLEN;
|
|
+ break;
|
|
+ }
|
|
+ if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
|
|
+ != PK_OK) {
|
|
+ if (uO.qflag)
|
|
+ Info(slide, 1, ((char *)slide, "%-22s ",
|
|
+ FnFilter1(G.filename)));
|
|
+ switch (r) {
|
|
+ case IZ_EF_TRUNC:
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(TruncEAs),
|
|
+ ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n"));
|
|
+ break;
|
|
+ case PK_ERR:
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(InvalidComprDataEAs)));
|
|
+ break;
|
|
+ case PK_MEM3:
|
|
+ case PK_MEM4:
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(NotEnoughMemEAs)));
|
|
+ break;
|
|
+ default:
|
|
+ if ((r & 0xff) != PK_ERR)
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(UnknErrorEAs)));
|
|
+ else {
|
|
+ ush m = (ush)(r >> 8);
|
|
+ if (m == DEFLATED) /* GRR KLUDGE! */
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(BadCRC_EAs)));
|
|
+ else
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(UnknComprMethodEAs), m));
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ return r;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case EF_NTSD:
|
|
+ Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
|
|
+ r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
|
|
+ ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
|
|
+ (PK_WARN | 0x4000) :
|
|
+ test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
|
|
+ if (r != PK_OK) {
|
|
+ if (uO.qflag)
|
|
+ Info(slide, 1, ((char *)slide, "%-22s ",
|
|
+ FnFilter1(G.filename)));
|
|
+ switch (r) {
|
|
+ case IZ_EF_TRUNC:
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(TruncNTSD),
|
|
+ ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
|
|
+ break;
|
|
+#if (defined(WIN32) && defined(NTSD_EAS))
|
|
+ case PK_WARN:
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(InvalidSecurityEAs)));
|
|
+ break;
|
|
+#endif
|
|
+ case PK_ERR:
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(InvalidComprDataEAs)));
|
|
+ break;
|
|
+ case PK_MEM3:
|
|
+ case PK_MEM4:
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(NotEnoughMemEAs)));
|
|
+ break;
|
|
+ case (PK_WARN | 0x4000):
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(UnsuppNTSDVersEAs),
|
|
+ (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
|
|
+ r = PK_WARN;
|
|
+ break;
|
|
+ default:
|
|
+ if ((r & 0xff) != PK_ERR)
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(UnknErrorEAs)));
|
|
+ else {
|
|
+ ush m = (ush)(r >> 8);
|
|
+ if (m == DEFLATED) /* GRR KLUDGE! */
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(BadCRC_EAs)));
|
|
+ else
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(UnknComprMethodEAs), m));
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ return r;
|
|
+ }
|
|
+ break;
|
|
+ case EF_PKVMS:
|
|
+ /* 2015-01-30 SMS. Added sufficient-bytes test/message
|
|
+ * here. (Removed defective ebLen test above.)
|
|
+ *
|
|
+ * If sufficient bytes (EB_PKVMS_MINLEN) are available,
|
|
+ * then compare the stored CRC value with the calculated
|
|
+ * CRC for the remainder of the data (and complain about
|
|
+ * a mismatch).
|
|
+ */
|
|
+ if (ebLen < EB_PKVMS_MINLEN)
|
|
+ {
|
|
+ /* Insufficient bytes available. */
|
|
+ Info( slide, 1,
|
|
+ ((char *)slide, LoadFarString( TooSmallEBlength),
|
|
+ ebLen, EB_PKVMS_MINLEN));
|
|
+ }
|
|
+ else if (makelong(ef+ EB_HEADSIZE) !=
|
|
+ crc32(CRCVAL_INITIAL,
|
|
+ (ef+ EB_HEADSIZE+ EB_PKVMS_MINLEN),
|
|
+ (extent)(ebLen- EB_PKVMS_MINLEN)))
|
|
+ {
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(BadCRC_EAs)));
|
|
+ }
|
|
+ break;
|
|
+ case EF_PKW32:
|
|
+ case EF_PKUNIX:
|
|
+ case EF_ASIUNIX:
|
|
+ case EF_IZVMS:
|
|
+ case EF_IZUNIX:
|
|
+ case EF_VMCMS:
|
|
+ case EF_MVS:
|
|
+ case EF_SPARK:
|
|
+ case EF_TANDEM:
|
|
+ case EF_THEOS:
|
|
+ case EF_AV:
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ ef_len -= (ebLen + EB_HEADSIZE);
|
|
+ ef += (ebLen + EB_HEADSIZE);
|
|
+ }
|
|
+
|
|
+ if (!uO.qflag)
|
|
+ Info(slide, 0, ((char *)slide, " OK\n"));
|
|
+
|
|
+ return PK_COOL;
|
|
+
|
|
+} /* end function TestExtraField() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/******************************/
|
|
+/* Function test_compr_eb() */
|
|
+/******************************/
|
|
+
|
|
+#ifdef PROTO
|
|
+static int test_compr_eb(
|
|
+ __GPRO__
|
|
+ uch *eb,
|
|
+ unsigned eb_size,
|
|
+ unsigned compr_offset,
|
|
+ int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
|
|
+ uch *eb_ucptr, ulg eb_ucsize))
|
|
+#else /* !PROTO */
|
|
+static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
|
|
+ __GDEF
|
|
+ uch *eb;
|
|
+ unsigned eb_size;
|
|
+ unsigned compr_offset;
|
|
+ int (*test_uc_ebdata)();
|
|
+#endif /* ?PROTO */
|
|
+{
|
|
+ ulg eb_ucsize;
|
|
+ uch *eb_ucptr;
|
|
+ int r;
|
|
+ ush method;
|
|
+
|
|
+ if (compr_offset < 4) /* field is not compressed: */
|
|
+ return PK_OK; /* do nothing and signal OK */
|
|
+
|
|
+ /* Return no/bad-data error status if any problem is found:
|
|
+ * 1. eb_size is too small to hold the uncompressed size
|
|
+ * (eb_ucsize). (Else extract eb_ucsize.)
|
|
+ * 2. eb_ucsize is zero (invalid). 2014-12-04 SMS.
|
|
+ * 3. eb_ucsize is positive, but eb_size is too small to hold
|
|
+ * the compressed data header.
|
|
+ */
|
|
+ if ((eb_size < (EB_UCSIZE_P + 4)) ||
|
|
+ ((eb_ucsize = makelong( eb+ (EB_HEADSIZE+ EB_UCSIZE_P))) == 0L) ||
|
|
+ ((eb_ucsize > 0L) && (eb_size <= (compr_offset + EB_CMPRHEADLEN))))
|
|
+ return IZ_EF_TRUNC; /* no/bad compressed data! */
|
|
+
|
|
+ method = makeword(eb + (EB_HEADSIZE + compr_offset));
|
|
+ if ((method == STORED) && (eb_size != compr_offset + EB_CMPRHEADLEN + eb_ucsize))
|
|
+ return PK_ERR; /* compressed & uncompressed
|
|
+ * should match in STORED
|
|
+ * method */
|
|
+
|
|
+ if (
|
|
+#ifdef INT_16BIT
|
|
+ (((ulg)(extent)eb_ucsize) != eb_ucsize) ||
|
|
+#endif
|
|
+ (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
|
|
+ return PK_MEM4;
|
|
+
|
|
+ r = memextract(__G__ eb_ucptr, eb_ucsize,
|
|
+ eb + (EB_HEADSIZE + compr_offset),
|
|
+ (ulg)(eb_size - compr_offset));
|
|
+
|
|
+ if (r == PK_OK && test_uc_ebdata != NULL)
|
|
+ r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
|
|
+
|
|
+ free(eb_ucptr);
|
|
+ return r;
|
|
+
|
|
+} /* end function test_compr_eb() */
|
|
+
|
|
+#endif /* !SFX */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/***************************/
|
|
+/* Function memextract() */
|
|
+/***************************/
|
|
+
|
|
+int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */
|
|
+ __GDEF /* extra field block; */
|
|
+ uch *tgt; /* return PK-type error */
|
|
+ ulg tgtsize; /* level */
|
|
+ ZCONST uch *src;
|
|
+ ulg srcsize;
|
|
+{
|
|
+ zoff_t old_csize=G.csize;
|
|
+ uch *old_inptr=G.inptr;
|
|
+ int old_incnt=G.incnt;
|
|
+ int r, error=PK_OK;
|
|
+ ush method;
|
|
+ ulg extra_field_crc;
|
|
+
|
|
+
|
|
+ method = makeword(src);
|
|
+ extra_field_crc = makelong(src+2);
|
|
+
|
|
+ /* compressed extra field exists completely in memory at this location: */
|
|
+ G.inptr = (uch *)src + (2 + 4); /* method and extra_field_crc */
|
|
+ G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
|
|
+ G.mem_mode = TRUE;
|
|
+ G.outbufptr = tgt;
|
|
+ G.outsize = tgtsize;
|
|
+
|
|
+ switch (method) {
|
|
+ case STORED:
|
|
+ memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
|
|
+ G.outcnt = (ulg)G.csize; /* for CRC calculation */
|
|
+ break;
|
|
+ case DEFLATED:
|
|
+#ifdef USE_DEFLATE64
|
|
+ case ENHDEFLATED:
|
|
+#endif
|
|
+ G.outcnt = 0L;
|
|
+ if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) {
|
|
+ if (!uO.tflag)
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarStringSmall(ErrUnzipNoFile), r == 3?
|
|
+ LoadFarString(NotEnoughMem) :
|
|
+ LoadFarString(InvalidComprData),
|
|
+ LoadFarStringSmall2(Inflate)));
|
|
+ error = (r == 3)? PK_MEM3 : PK_ERR;
|
|
+ }
|
|
+ if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */
|
|
+ break;
|
|
+ break;
|
|
+ default:
|
|
+ if (uO.tflag)
|
|
+ error = PK_ERR | ((int)method << 8);
|
|
+ else {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(UnsupportedExtraField), method));
|
|
+ error = PK_ERR; /* GRR: should be passed on up via SetEAs() */
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ G.inptr = old_inptr;
|
|
+ G.incnt = old_incnt;
|
|
+ G.csize = old_csize;
|
|
+ G.mem_mode = FALSE;
|
|
+
|
|
+ if (!error) {
|
|
+ register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
|
|
+
|
|
+ if (crcval != extra_field_crc) {
|
|
+ if (uO.tflag)
|
|
+ error = PK_ERR | (DEFLATED << 8); /* kludge for now */
|
|
+ else {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
|
|
+ extra_field_crc));
|
|
+ error = PK_ERR;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return error;
|
|
+
|
|
+} /* end function memextract() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*************************/
|
|
+/* Function memflush() */
|
|
+/*************************/
|
|
+
|
|
+int memflush(__G__ rawbuf, size)
|
|
+ __GDEF
|
|
+ ZCONST uch *rawbuf;
|
|
+ ulg size;
|
|
+{
|
|
+ if (size > G.outsize)
|
|
+ /* Here, PK_DISK is a bit off-topic, but in the sense of marking
|
|
+ "overflow of output space", its use may be tolerated. */
|
|
+ return PK_DISK; /* more data than output buffer can hold */
|
|
+
|
|
+
|
|
+
|
|
+ memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
|
|
+ G.outbufptr += (unsigned int)size;
|
|
+ G.outsize -= size;
|
|
+ G.outcnt += size;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+} /* end function memflush() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#if (defined(VMS) || defined(VMS_TEXT_CONV))
|
|
+
|
|
+/************************************/
|
|
+/* Function extract_izvms_block() */
|
|
+/************************************/
|
|
+
|
|
+/*
|
|
+ * Extracts block from p. If resulting length is less than needed, fill
|
|
+ * extra space with corresponding bytes from 'init'.
|
|
+ * Currently understands 3 formats of block compression:
|
|
+ * - Simple storing
|
|
+ * - Compression of zero bytes to zero bits
|
|
+ * - Deflation (see memextract())
|
|
+ * The IZVMS block data is returned in malloc'd space.
|
|
+ */
|
|
+uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen)
|
|
+ __GDEF
|
|
+ ZCONST uch *ebdata;
|
|
+ unsigned size;
|
|
+ unsigned *retlen;
|
|
+ ZCONST uch *init;
|
|
+ unsigned needlen;
|
|
+{
|
|
+ uch *ucdata; /* Pointer to block allocated */
|
|
+ int cmptype;
|
|
+ unsigned usiz, csiz;
|
|
+
|
|
+ cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK);
|
|
+ csiz = size - EB_IZVMS_HLEN;
|
|
+ usiz = (cmptype == EB_IZVMS_BCSTOR ?
|
|
+ csiz : makeword(ebdata+EB_IZVMS_UCSIZ));
|
|
+
|
|
+ if (retlen)
|
|
+ *retlen = usiz;
|
|
+
|
|
+ if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ if (init && (usiz < needlen))
|
|
+ memcpy((char *)ucdata, (ZCONST char *)init, needlen);
|
|
+
|
|
+ switch (cmptype)
|
|
+ {
|
|
+ case EB_IZVMS_BCSTOR: /* The simplest case */
|
|
+ memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz);
|
|
+ break;
|
|
+ case EB_IZVMS_BC00:
|
|
+ decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN);
|
|
+ break;
|
|
+ case EB_IZVMS_BCDEFL:
|
|
+ memextract(__G__ ucdata, (ulg)usiz,
|
|
+ ebdata+EB_IZVMS_HLEN, (ulg)csiz);
|
|
+ break;
|
|
+ default:
|
|
+ free(ucdata);
|
|
+ ucdata = NULL;
|
|
+ }
|
|
+ return ucdata;
|
|
+
|
|
+} /* end of extract_izvms_block */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/********************************/
|
|
+/* Function decompress_bits() */
|
|
+/********************************/
|
|
+/*
|
|
+ * Simple uncompression routine. The compression uses bit stream.
|
|
+ * Compression scheme:
|
|
+ *
|
|
+ * if (byte!=0)
|
|
+ * putbit(1),putbyte(byte)
|
|
+ * else
|
|
+ * putbit(0)
|
|
+ */
|
|
+static void decompress_bits(outptr, needlen, bitptr)
|
|
+ uch *outptr; /* Pointer into output block */
|
|
+ unsigned needlen; /* Size of uncompressed block */
|
|
+ ZCONST uch *bitptr; /* Pointer into compressed data */
|
|
+{
|
|
+ ulg bitbuf = 0;
|
|
+ int bitcnt = 0;
|
|
+
|
|
+#define _FILL { bitbuf |= (*bitptr++) << bitcnt;\
|
|
+ bitcnt += 8; \
|
|
+ }
|
|
+
|
|
+ while (needlen--)
|
|
+ {
|
|
+ if (bitcnt <= 0)
|
|
+ _FILL;
|
|
+
|
|
+ if (bitbuf & 1)
|
|
+ {
|
|
+ bitbuf >>= 1;
|
|
+ if ((bitcnt -= 1) < 8)
|
|
+ _FILL;
|
|
+ *outptr++ = (uch)bitbuf;
|
|
+ bitcnt -= 8;
|
|
+ bitbuf >>= 8;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ *outptr++ = '\0';
|
|
+ bitcnt -= 1;
|
|
+ bitbuf >>= 1;
|
|
+ }
|
|
+ }
|
|
+} /* end function decompress_bits() */
|
|
+
|
|
+#endif /* VMS || VMS_TEXT_CONV */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifdef SYMLINKS
|
|
+/***********************************/
|
|
+/* Function set_deferred_symlink() */
|
|
+/***********************************/
|
|
+
|
|
+static void set_deferred_symlink(__G__ slnk_entry)
|
|
+ __GDEF
|
|
+ slinkentry *slnk_entry;
|
|
+{
|
|
+ extent ucsize = slnk_entry->targetlen;
|
|
+ char *linkfname = slnk_entry->fname;
|
|
+ char *linktarget = (char *)malloc(ucsize+1);
|
|
+
|
|
+ if (!linktarget) {
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname)));
|
|
+ return;
|
|
+ }
|
|
+ linktarget[ucsize] = '\0';
|
|
+ G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */
|
|
+ /* Check that the following conditions are all fulfilled:
|
|
+ * a) the placeholder file exists,
|
|
+ * b) the placeholder file contains exactly "ucsize" bytes
|
|
+ * (read the expected placeholder content length + 1 extra byte, this
|
|
+ * should return the expected content length),
|
|
+ * c) the placeholder content matches the link target specification as
|
|
+ * stored in the symlink control structure.
|
|
+ */
|
|
+ if (!G.outfile ||
|
|
+ fread(linktarget, 1, ucsize+1, G.outfile) != ucsize ||
|
|
+ strcmp(slnk_entry->target, linktarget))
|
|
+ {
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname)));
|
|
+ free(linktarget);
|
|
+ if (G.outfile)
|
|
+ fclose(G.outfile);
|
|
+ return;
|
|
+ }
|
|
+ fclose(G.outfile); /* close "data" file for good... */
|
|
+ unlink(linkfname); /* ...and delete it */
|
|
+ if (QCOND2)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish),
|
|
+ FnFilter1(linkfname), FnFilter2(linktarget)));
|
|
+ if (symlink(linktarget, linkfname)) /* create the real link */
|
|
+ perror("symlink error");
|
|
+ free(linktarget);
|
|
+#ifdef SET_SYMLINK_ATTRIBS
|
|
+ set_symlnk_attribs(__G__ slnk_entry);
|
|
+#endif
|
|
+ return; /* can't set time on symlinks */
|
|
+
|
|
+} /* end function set_deferred_symlink() */
|
|
+#endif /* SYMLINKS */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*************************/
|
|
+/* Function fnfilter() */ /* here instead of in list.c for SFX */
|
|
+/*************************/
|
|
+
|
|
+char *fnfilter(raw, space, size) /* convert name to safely printable form */
|
|
+ ZCONST char *raw;
|
|
+ uch *space;
|
|
+ extent size;
|
|
+{
|
|
+#ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */
|
|
+ ZCONST uch *r=(ZCONST uch *)raw;
|
|
+ uch *s=space;
|
|
+ uch *slim=NULL;
|
|
+ uch *se=NULL;
|
|
+ int have_overflow = FALSE;
|
|
+
|
|
+ if (size > 0) {
|
|
+ slim = space + size
|
|
+#ifdef _MBCS
|
|
+ - (MB_CUR_MAX - 1)
|
|
+#endif
|
|
+ - 4;
|
|
+ }
|
|
+ while (*r) {
|
|
+ if (size > 0 && s >= slim && se == NULL) {
|
|
+ se = s;
|
|
+ }
|
|
+#ifdef QDOS
|
|
+ if (qlflag & 2) {
|
|
+ if (*r == '/' || *r == '.') {
|
|
+ if (se != NULL && (s > (space + (size-3)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ ++r;
|
|
+ *s++ = '_';
|
|
+ continue;
|
|
+ }
|
|
+ } else
|
|
+#endif
|
|
+#ifdef HAVE_WORKING_ISPRINT
|
|
+# ifndef UZ_FNFILTER_REPLACECHAR
|
|
+ /* A convenient choice for the replacement of unprintable char codes is
|
|
+ * the "single char wildcard", as this character is quite unlikely to
|
|
+ * appear in filenames by itself. The following default definition
|
|
+ * sets the replacement char to a question mark as the most common
|
|
+ * "single char wildcard"; this setting should be overridden in the
|
|
+ * appropiate system-specific configuration header when needed.
|
|
+ */
|
|
+# define UZ_FNFILTER_REPLACECHAR '?'
|
|
+# endif
|
|
+ if (!isprint(*r)) {
|
|
+ if (*r < 32) {
|
|
+ /* ASCII control codes are escaped as "^{letter}". */
|
|
+ if (se != NULL && (s > (space + (size-4)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ *s++ = '^', *s++ = (uch)(64 + *r++);
|
|
+ } else {
|
|
+ /* Other unprintable codes are replaced by the
|
|
+ * placeholder character. */
|
|
+ if (se != NULL && (s > (space + (size-3)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ *s++ = UZ_FNFILTER_REPLACECHAR;
|
|
+ INCSTR(r);
|
|
+ }
|
|
+#else /* !HAVE_WORKING_ISPRINT */
|
|
+ if (*r < 32) {
|
|
+ /* ASCII control codes are escaped as "^{letter}". */
|
|
+ if (se != NULL && (s > (space + (size-4)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ *s++ = '^', *s++ = (uch)(64 + *r++);
|
|
+#endif /* ?HAVE_WORKING_ISPRINT */
|
|
+ } else {
|
|
+#ifdef _MBCS
|
|
+ unsigned i = CLEN(r);
|
|
+ if (se != NULL && (s > (space + (size-i-2)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ for (; i > 0; i--)
|
|
+ *s++ = *r++;
|
|
+#else
|
|
+ if (se != NULL && (s > (space + (size-3)))) {
|
|
+ have_overflow = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ *s++ = *r++;
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
+ if (have_overflow) {
|
|
+ strcpy((char *)se, "...");
|
|
+ } else {
|
|
+ *s = '\0';
|
|
+ }
|
|
+
|
|
+#ifdef WINDLL
|
|
+ INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */
|
|
+#else
|
|
+#if (defined(WIN32) && !defined(_WIN32_WCE))
|
|
+ /* Win9x console always uses OEM character coding, and
|
|
+ WinNT console is set to OEM charset by default, too */
|
|
+ INTERN_TO_OEM((char *)space, (char *)space);
|
|
+#endif /* (WIN32 && !_WIN32_WCE) */
|
|
+#endif /* ?WINDLL */
|
|
+
|
|
+ return (char *)space;
|
|
+
|
|
+#else /* NATIVE: EBCDIC or whatever */
|
|
+ return (char *)raw;
|
|
+#endif
|
|
+
|
|
+} /* end function fnfilter() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+/* must sort saved directories so can set perms from bottom up */
|
|
+
|
|
+/************************/
|
|
+/* Function dircomp() */
|
|
+/************************/
|
|
+
|
|
+static int Cdecl dircomp(a, b) /* used by qsort(); swiped from Zip */
|
|
+ ZCONST zvoid *a, *b;
|
|
+{
|
|
+ /* order is significant: this sorts in reverse order (deepest first) */
|
|
+ return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn);
|
|
+ /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */
|
|
+}
|
|
+
|
|
+#endif /* SET_DIR_ATTRIB */
|
|
+
|
|
+
|
|
+#ifdef USE_BZIP2
|
|
+
|
|
+/**************************/
|
|
+/* Function UZbunzip2() */
|
|
+/**************************/
|
|
+
|
|
+int UZbunzip2(__G)
|
|
+__GDEF
|
|
+/* decompress a bzipped entry using the libbz2 routines */
|
|
+{
|
|
+ int retval = 0; /* return code: 0 = "no error" */
|
|
+ int err=BZ_OK;
|
|
+ int repeated_buf_err;
|
|
+ bz_stream bstrm;
|
|
+
|
|
+ if (G.incnt <= 0 && G.csize <= 0L) {
|
|
+ /* avoid an infinite loop */
|
|
+ Trace((stderr, "UZbunzip2() got empty input\n"));
|
|
+ return 2;
|
|
+ }
|
|
+
|
|
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
|
+ if (G.redirect_slide)
|
|
+ wsize = G.redirect_size, redirSlide = G.redirect_buffer;
|
|
+ else
|
|
+ wsize = WSIZE, redirSlide = slide;
|
|
+#endif
|
|
+
|
|
+ bstrm.next_out = (char *)redirSlide;
|
|
+ bstrm.avail_out = wsize;
|
|
+
|
|
+ bstrm.next_in = (char *)G.inptr;
|
|
+ bstrm.avail_in = G.incnt;
|
|
+
|
|
+ {
|
|
+ /* local buffer for efficiency */
|
|
+ /* $TODO Check for BZIP LIB version? */
|
|
+
|
|
+ bstrm.bzalloc = NULL;
|
|
+ bstrm.bzfree = NULL;
|
|
+ bstrm.opaque = NULL;
|
|
+
|
|
+ Trace((stderr, "initializing bzlib()\n"));
|
|
+ err = BZ2_bzDecompressInit(&bstrm, 0, 0);
|
|
+
|
|
+ if (err == BZ_MEM_ERROR)
|
|
+ return 3;
|
|
+ else if (err != BZ_OK)
|
|
+ Trace((stderr, "oops! (BZ2_bzDecompressInit() err = %d)\n", err));
|
|
+ }
|
|
+
|
|
+#ifdef FUNZIP
|
|
+ while (err != BZ_STREAM_END) {
|
|
+#else /* !FUNZIP */
|
|
+ while (G.csize > 0) {
|
|
+ Trace((stderr, "first loop: G.csize = %ld\n", G.csize));
|
|
+#endif /* ?FUNZIP */
|
|
+ while (bstrm.avail_out > 0) {
|
|
+ err = BZ2_bzDecompress(&bstrm);
|
|
+
|
|
+ if (err == BZ_DATA_ERROR) {
|
|
+ retval = 2; goto uzbunzip_cleanup_exit;
|
|
+ } else if (err == BZ_MEM_ERROR) {
|
|
+ retval = 3; goto uzbunzip_cleanup_exit;
|
|
+ } else if (err != BZ_OK && err != BZ_STREAM_END)
|
|
+ Trace((stderr, "oops! (bzip(first loop) err = %d)\n", err));
|
|
+
|
|
+#ifdef FUNZIP
|
|
+ if (err == BZ_STREAM_END) /* "END-of-entry-condition" ? */
|
|
+#else /* !FUNZIP */
|
|
+ if (G.csize <= 0L) /* "END-of-entry-condition" ? */
|
|
+#endif /* ?FUNZIP */
|
|
+ break;
|
|
+
|
|
+ if (bstrm.avail_in == 0) {
|
|
+ if (fillinbuf(__G) == 0) {
|
|
+ /* no "END-condition" yet, but no more data */
|
|
+ retval = 2; goto uzbunzip_cleanup_exit;
|
|
+ }
|
|
+
|
|
+ bstrm.next_in = (char *)G.inptr;
|
|
+ bstrm.avail_in = G.incnt;
|
|
+ }
|
|
+ Trace((stderr, " avail_in = %u\n", bstrm.avail_in));
|
|
+ }
|
|
+ /* flush slide[] */
|
|
+ if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)
|
|
+ goto uzbunzip_cleanup_exit;
|
|
+ Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n",
|
|
+ (long)(wsize - bstrm.avail_out),
|
|
+ (long)(bstrm.next_out-(char *)redirSlide)));
|
|
+ bstrm.next_out = (char *)redirSlide;
|
|
+ bstrm.avail_out = wsize;
|
|
+ }
|
|
+
|
|
+ /* no more input, so loop until we have all output */
|
|
+ Trace((stderr, "beginning final loop: err = %d\n", err));
|
|
+ repeated_buf_err = FALSE;
|
|
+ while (err != BZ_STREAM_END) {
|
|
+ err = BZ2_bzDecompress(&bstrm);
|
|
+ if (err == BZ_DATA_ERROR) {
|
|
+ retval = 2; goto uzbunzip_cleanup_exit;
|
|
+ } else if (err == BZ_MEM_ERROR) {
|
|
+ retval = 3; goto uzbunzip_cleanup_exit;
|
|
+ } else if (err != BZ_OK && err != BZ_STREAM_END) {
|
|
+ Trace((stderr, "oops! (bzip(final loop) err = %d)\n", err));
|
|
+ DESTROYGLOBALS();
|
|
+ EXIT(PK_MEM3);
|
|
+ }
|
|
+ /* final flush of slide[] */
|
|
+ if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)
|
|
+ goto uzbunzip_cleanup_exit;
|
|
+ Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n",
|
|
+ (long)(wsize - bstrm.avail_out),
|
|
+ (long)(bstrm.next_out-(char *)redirSlide)));
|
|
+ bstrm.next_out = (char *)redirSlide;
|
|
+ bstrm.avail_out = wsize;
|
|
+ }
|
|
+#ifdef LARGE_FILE_SUPPORT
|
|
+ Trace((stderr, "total in = %llu, total out = %llu\n",
|
|
+ (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32,
|
|
+ (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32));
|
|
+#else
|
|
+ Trace((stderr, "total in = %lu, total out = %lu\n", bstrm.total_in_lo32,
|
|
+ bstrm.total_out_lo32));
|
|
+#endif
|
|
+
|
|
+ G.inptr = (uch *)bstrm.next_in;
|
|
+ G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */
|
|
+
|
|
+uzbunzip_cleanup_exit:
|
|
+ err = BZ2_bzDecompressEnd(&bstrm);
|
|
+ if (err != BZ_OK)
|
|
+ Trace((stderr, "oops! (BZ2_bzDecompressEnd() err = %d)\n", err));
|
|
+
|
|
+ return retval;
|
|
+} /* end function UZbunzip2() */
|
|
+#endif /* USE_BZIP2 */
|
|
diff -Naur a/fileio.c b/fileio.c
|
|
--- a/fileio.c 2009-04-20 01:03:44.000000000 +0100
|
|
+++ b/fileio.c 2019-12-02 01:45:40.913845391 +0000
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
|
|
+ Copyright (c) 1990-2017 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.
|
|
@@ -176,6 +176,8 @@
|
|
#endif
|
|
static ZCONST char Far ExtraFieldTooLong[] =
|
|
"warning: extra field too long (%d). Ignoring...\n";
|
|
+static ZCONST char Far ExtraFieldCorrupt[] =
|
|
+ "warning: extra field (type: 0x%04x) corrupt. Continuing...\n";
|
|
|
|
#ifdef WINDLL
|
|
static ZCONST char Far DiskFullQuery[] =
|
|
@@ -1580,6 +1582,8 @@
|
|
int r = IZ_PW_ENTERED;
|
|
char *m;
|
|
char *prompt;
|
|
+ char *ep;
|
|
+ char *zp;
|
|
|
|
#ifndef REENTRANT
|
|
/* tell picky compilers to shut up about "unused variable" warnings */
|
|
@@ -1588,9 +1592,12 @@
|
|
|
|
if (*rcnt == 0) { /* First call for current entry */
|
|
*rcnt = 2;
|
|
- if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
|
|
- sprintf(prompt, LoadFarString(PasswPrompt),
|
|
- FnFilter1(zfn), FnFilter2(efn));
|
|
+ zp = FnFilter1( zfn);
|
|
+ ep = FnFilter2( efn);
|
|
+ prompt = (char *)malloc( /* Slightly too long (2* "%s"). */
|
|
+ sizeof( PasswPrompt)+ strlen( zp)+ strlen( ep));
|
|
+ if (prompt != (char *)NULL) {
|
|
+ sprintf(prompt, LoadFarString(PasswPrompt), zp, ep);
|
|
m = prompt;
|
|
} else
|
|
m = (char *)LoadFarString(PasswPrompt2);
|
|
@@ -2006,6 +2013,7 @@
|
|
unsigned comment_bytes_left;
|
|
unsigned int block_len;
|
|
int error=PK_OK;
|
|
+ unsigned int length2;
|
|
#ifdef AMIGA
|
|
char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */
|
|
#endif
|
|
@@ -2292,10 +2300,20 @@
|
|
seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
|
|
(G.inptr-G.inbuf) + length);
|
|
} else {
|
|
- if (readbuf(__G__ (char *)G.extra_field, length) == 0)
|
|
+ if ((length2 = readbuf(__G__ (char *)G.extra_field, length)) == 0)
|
|
return PK_EOF;
|
|
+ if(length2 < length) {
|
|
+ memset (__G__ (char *)G.extra_field+length2, 0 , length-length2);
|
|
+ length = length2;
|
|
+ }
|
|
/* Looks like here is where extra fields are read */
|
|
- getZip64Data(__G__ G.extra_field, length);
|
|
+ if (getZip64Data(__G__ G.extra_field, length) != PK_COOL)
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString( ExtraFieldCorrupt), EF_PKSZ64));
|
|
+ error = PK_WARN;
|
|
+ }
|
|
+
|
|
#ifdef UNICODE_SUPPORT
|
|
G.unipath_filename = NULL;
|
|
if (G.UzO.U_flag < 2) {
|
|
diff -Naur a/list.c b/list.c
|
|
--- a/list.c 2009-02-08 17:11:34.000000000 +0000
|
|
+++ b/list.c 2019-12-02 01:48:07.035331859 +0000
|
|
@@ -97,7 +97,7 @@
|
|
{
|
|
int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
|
|
#ifndef WINDLL
|
|
- char sgn, cfactorstr[10];
|
|
+ char sgn, cfactorstr[1+10+1+1]; /* <sgn><int>%NUL */
|
|
int longhdr=(uO.vflag>1);
|
|
#endif
|
|
int date_format;
|
|
@@ -181,7 +181,7 @@
|
|
Info(slide, 0x401,
|
|
((char *)slide, LoadFarString(CentSigMsg), j));
|
|
Info(slide, 0x401,
|
|
- ((char *)slide, LoadFarString(ReportMsg)));
|
|
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
return PK_BADERR; /* sig not found */
|
|
}
|
|
}
|
|
@@ -339,7 +339,19 @@
|
|
G.crec.compression_method == ENHDEFLATED) {
|
|
methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
|
|
} else if (methnum >= NUM_METHODS) {
|
|
- sprintf(&methbuf[4], "%03u", G.crec.compression_method);
|
|
+ /* 2013-02-26 SMS.
|
|
+ * http://sourceforge.net/tracker/?func=detail
|
|
+ * &aid=2861648&group_id=118012&atid=679786
|
|
+ * Unexpectedly large compression methods overflow
|
|
+ * &methbuf[]. Use the old, three-digit decimal format
|
|
+ * for values which fit. Otherwise, sacrifice the
|
|
+ * colon, and use four-digit hexadecimal.
|
|
+ */
|
|
+ if (G.crec.compression_method <= 999) {
|
|
+ sprintf( &methbuf[ 4], "%03u", G.crec.compression_method);
|
|
+ } else {
|
|
+ sprintf( &methbuf[ 3], "%04X", G.crec.compression_method);
|
|
+ }
|
|
}
|
|
|
|
#if 0 /* GRR/Euro: add this? */
|
|
@@ -378,9 +390,9 @@
|
|
}
|
|
#else /* !WINDLL */
|
|
if (cfactor == 100)
|
|
- sprintf(cfactorstr, LoadFarString(CompFactor100));
|
|
+ snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactor100));
|
|
else
|
|
- sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
|
|
+ snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactorStr), sgn, cfactor);
|
|
if (longhdr)
|
|
Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
|
|
FmZofft(G.crec.ucsize, "8", "u"), methbuf,
|
|
@@ -460,9 +472,9 @@
|
|
|
|
#else /* !WINDLL */
|
|
if (cfactor == 100)
|
|
- sprintf(cfactorstr, LoadFarString(CompFactor100));
|
|
+ snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactor100));
|
|
else
|
|
- sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
|
|
+ snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactorStr), sgn, cfactor);
|
|
if (longhdr) {
|
|
Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
|
|
FmZofft(tot_ucsize, "8", "u"), FmZofft(tot_csize, "8", "u"),
|
|
@@ -507,7 +519,8 @@
|
|
&& (!G.ecrec.is_zip64_archive)
|
|
&& (memcmp(G.sig, end_central_sig, 4) != 0)
|
|
) { /* just to make sure again */
|
|
- Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide,"%s", LoadFarString(EndSigMsg)));
|
|
error_in_archive = PK_WARN; /* didn't find sig */
|
|
}
|
|
|
|
@@ -591,7 +604,7 @@
|
|
Info(slide, 0x401,
|
|
((char *)slide, LoadFarString(CentSigMsg), j));
|
|
Info(slide, 0x401,
|
|
- ((char *)slide, LoadFarString(ReportMsg)));
|
|
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
return PK_BADERR; /* sig not found */
|
|
}
|
|
}
|
|
@@ -674,7 +687,7 @@
|
|
---------------------------------------------------------------------------*/
|
|
|
|
if (memcmp(G.sig, end_central_sig, 4)) { /* just to make sure again */
|
|
- Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
|
|
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(EndSigMsg)));
|
|
error_in_archive = PK_WARN;
|
|
}
|
|
if (*nmember == 0L && error_in_archive <= PK_WARN)
|
|
diff -Naur a/list.c.orig b/list.c.orig
|
|
--- a/list.c.orig 1970-01-01 01:00:00.000000000 +0100
|
|
+++ b/list.c.orig 2019-12-02 00:34:56.656315493 +0000
|
|
@@ -0,0 +1,746 @@
|
|
+/*
|
|
+ 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
|
|
+*/
|
|
+/*---------------------------------------------------------------------------
|
|
+
|
|
+ list.c
|
|
+
|
|
+ This file contains the non-ZipInfo-specific listing routines for UnZip.
|
|
+
|
|
+ Contains: list_files()
|
|
+ get_time_stamp() [optional feature]
|
|
+ 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 TIMESTAMP
|
|
+ static int fn_is_dir OF((__GPRO));
|
|
+#endif
|
|
+
|
|
+#ifndef WINDLL
|
|
+ static ZCONST char Far CompFactorStr[] = "%c%d%%";
|
|
+ static ZCONST char Far CompFactor100[] = "100%%";
|
|
+
|
|
+#ifdef OS2_EAS
|
|
+ static ZCONST char Far HeadersS[] =
|
|
+ " Length EAs ACLs Date Time Name";
|
|
+ static ZCONST char Far HeadersS1[] =
|
|
+ "--------- --- ---- ---------- ----- ----";
|
|
+#else
|
|
+ static ZCONST char Far HeadersS[] =
|
|
+ " Length Date Time Name";
|
|
+ static ZCONST char Far HeadersS1[] =
|
|
+ "--------- ---------- ----- ----";
|
|
+#endif
|
|
+
|
|
+ static ZCONST char Far HeadersL[] =
|
|
+ " Length Method Size Cmpr Date Time CRC-32 Name";
|
|
+ static ZCONST char Far HeadersL1[] =
|
|
+ "-------- ------ ------- ---- ---------- ----- -------- ----";
|
|
+ static ZCONST char Far *Headers[][2] =
|
|
+ { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} };
|
|
+
|
|
+ static ZCONST char Far CaseConversion[] =
|
|
+ "%s (\"^\" ==> case\n%s conversion)\n";
|
|
+ static ZCONST char Far LongHdrStats[] =
|
|
+ "%s %-7s%s %4s %02u%c%02u%c%02u %02u:%02u %08lx %c";
|
|
+ static ZCONST char Far LongFileTrailer[] =
|
|
+ "-------- ------- --- \
|
|
+ -------\n%s %s %4s %lu file%s\n";
|
|
+#ifdef OS2_EAS
|
|
+ static ZCONST char Far ShortHdrStats[] =
|
|
+ "%s %6lu %6lu %02u%c%02u%c%02u %02u:%02u %c";
|
|
+ static ZCONST char Far ShortFileTrailer[] =
|
|
+ "--------- ----- ----- \
|
|
+ -------\n%s %6lu %6lu %lu file%s\n";
|
|
+ static ZCONST char Far OS2ExtAttrTrailer[] =
|
|
+ "%lu file%s %lu bytes of OS/2 extended attributes attached.\n";
|
|
+ static ZCONST char Far OS2ACLTrailer[] =
|
|
+ "%lu file%s %lu bytes of access control lists attached.\n";
|
|
+#else
|
|
+ static ZCONST char Far ShortHdrStats[] =
|
|
+ "%s %02u%c%02u%c%02u %02u:%02u %c";
|
|
+ static ZCONST char Far ShortFileTrailer[] =
|
|
+ "--------- -------\n%s\
|
|
+ %lu file%s\n";
|
|
+#endif /* ?OS2_EAS */
|
|
+#endif /* !WINDLL */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*************************/
|
|
+/* Function list_files() */
|
|
+/*************************/
|
|
+
|
|
+int list_files(__G) /* return PK-type error code */
|
|
+ __GDEF
|
|
+{
|
|
+ int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
|
|
+#ifndef WINDLL
|
|
+ char sgn, cfactorstr[13];
|
|
+ int longhdr=(uO.vflag>1);
|
|
+#endif
|
|
+ int date_format;
|
|
+ char dt_sepchar;
|
|
+ ulg members=0L;
|
|
+ zusz_t j;
|
|
+ unsigned methnum;
|
|
+#ifdef USE_EF_UT_TIME
|
|
+ iztimes z_utime;
|
|
+ struct tm *t;
|
|
+#endif
|
|
+ unsigned yr, mo, dy, hh, mm;
|
|
+ zusz_t 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 ZCONST char dtype[]="NXFS"; /* see zi_short() */
|
|
+ static ZCONST char Far method[NUM_METHODS+1][8] =
|
|
+ {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
|
|
+ "Implode", "Token", "Defl:#", "Def64#", "ImplDCL", "BZip2",
|
|
+ "LZMA", "Terse", "IBMLZ77", "WavPack", "PPMd", "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
|
|
+ 16717 Defl:X 5252 69% 11-03-97 06:40 1ce0f189 WHERE
|
|
+-------- ------- --- -------
|
|
+ 64159 20502 68% 3 files
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ G.pInfo = &info;
|
|
+ date_format = DATE_FORMAT;
|
|
+ dt_sepchar = DATE_SEPCHAR;
|
|
+
|
|
+#ifndef WINDLL
|
|
+ if (uO.qflag < 2) {
|
|
+ if (uO.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 = 1L;;j++) {
|
|
+
|
|
+ if (readbuf(__G__ G.sig, 4) == 0)
|
|
+ return PK_EOF;
|
|
+ if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a CentDir entry? */
|
|
+ /* no new central directory entry
|
|
+ * -> is the number of processed entries compatible with the
|
|
+ * number of entries as stored in the end_central record?
|
|
+ */
|
|
+ if (((j - 1) &
|
|
+ (ulg)(G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16))
|
|
+ == (ulg)G.ecrec.total_entries_central_dir)
|
|
+ {
|
|
+ /* "j modulus 4T/64k" matches the reported 64/16-bit-unsigned
|
|
+ * number of directory entries -> probably, the regular
|
|
+ * end of the central directory has been reached
|
|
+ */
|
|
+ break;
|
|
+ } else {
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide, LoadFarString(CentSigMsg), j));
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
+ return PK_BADERR; /* sig not found */
|
|
+ }
|
|
+ }
|
|
+ /* process_cdir_file_hdr() sets pInfo->hostnum, 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 */
|
|
+ unsigned i;
|
|
+
|
|
+ if (G.filespecs == 0)
|
|
+ do_this_file = TRUE;
|
|
+ else { /* check if this entry matches an `include' argument */
|
|
+ do_this_file = FALSE;
|
|
+ for (i = 0; i < G.filespecs; i++)
|
|
+ if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {
|
|
+ do_this_file = TRUE;
|
|
+ break; /* found match, so stop looping */
|
|
+ }
|
|
+ }
|
|
+ if (do_this_file) { /* check if this is an excluded file */
|
|
+ for (i = 0; i < G.xfilespecs; i++)
|
|
+ if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {
|
|
+ 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;
|
|
+ ++members;
|
|
+ } else {
|
|
+#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 &&
|
|
+#ifdef IZ_CHECK_TZ
|
|
+ G.tz_is_valid &&
|
|
+#endif
|
|
+ (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
|
|
+ G.crec.last_mod_dos_datetime, &z_utime, NULL)
|
|
+ & EB_UT_FL_MTIME))
|
|
+ {
|
|
+ TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0, Mac */
|
|
+ t = localtime(&(z_utime.mtime));
|
|
+ } else
|
|
+ t = (struct tm *)NULL;
|
|
+ if (t != (struct tm *)NULL) {
|
|
+ mo = (unsigned)(t->tm_mon + 1);
|
|
+ dy = (unsigned)(t->tm_mday);
|
|
+ yr = (unsigned)(t->tm_year + 1900);
|
|
+ hh = (unsigned)(t->tm_hour);
|
|
+ mm = (unsigned)(t->tm_min);
|
|
+ } else
|
|
+#endif /* USE_EF_UT_TIME */
|
|
+ {
|
|
+ yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f)
|
|
+ + 1980));
|
|
+ mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f);
|
|
+ dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f);
|
|
+ hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f);
|
|
+ mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f);
|
|
+ }
|
|
+ /* permute date so it displays according to nat'l convention
|
|
+ * ('methnum' is not yet set, it is used as temporary buffer) */
|
|
+ switch (date_format) {
|
|
+ case DF_YMD:
|
|
+ methnum = mo;
|
|
+ mo = yr; yr = dy; dy = methnum;
|
|
+ break;
|
|
+ case DF_DMY:
|
|
+ methnum = mo;
|
|
+ mo = dy; dy = methnum;
|
|
+ }
|
|
+
|
|
+ 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) {
|
|
+#ifndef WINDLL
|
|
+ sgn = '-';
|
|
+#endif
|
|
+ cfactor = (-cfactor + 5) / 10;
|
|
+ } else {
|
|
+#ifndef WINDLL
|
|
+ sgn = ' ';
|
|
+#endif
|
|
+ cfactor = (cfactor + 5) / 10;
|
|
+ }
|
|
+
|
|
+ methnum = find_compr_idx(G.crec.compression_method);
|
|
+ zfstrcpy(methbuf, method[methnum]);
|
|
+ if (G.crec.compression_method == DEFLATED ||
|
|
+ G.crec.compression_method == ENHDEFLATED) {
|
|
+ methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
|
|
+ } else if (methnum >= NUM_METHODS) {
|
|
+ /* 2013-02-26 SMS.
|
|
+ * http://sourceforge.net/tracker/?func=detail
|
|
+ * &aid=2861648&group_id=118012&atid=679786
|
|
+ * Unexpectedly large compression methods overflow
|
|
+ * &methbuf[]. Use the old, three-digit decimal format
|
|
+ * for values which fit. Otherwise, sacrifice the
|
|
+ * colon, and use four-digit hexadecimal.
|
|
+ */
|
|
+ if (G.crec.compression_method <= 999) {
|
|
+ sprintf( &methbuf[ 4], "%03u", G.crec.compression_method);
|
|
+ } else {
|
|
+ sprintf( &methbuf[ 3], "%04X", G.crec.compression_method);
|
|
+ }
|
|
+ }
|
|
+
|
|
+#if 0 /* GRR/Euro: add this? */
|
|
+#if defined(DOS_FLX_NLM_OS2_W32) || defined(THEOS) || defined(UNIX)
|
|
+ for (p = G.filename; *p; ++p)
|
|
+ if (!isprint(*p))
|
|
+ *p = '?'; /* change non-printable chars to '?' */
|
|
+#endif /* DOS_FLX_NLM_OS2_W32 || THEOS || UNIX */
|
|
+#endif /* 0 */
|
|
+
|
|
+#ifdef WINDLL
|
|
+ /* send data to application for formatting and printing */
|
|
+ if (G.lpUserFunctions->SendApplicationMessage != NULL)
|
|
+ (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize,
|
|
+ csiz, (unsigned)cfactor, mo, dy, yr, hh, mm,
|
|
+ (char)(G.pInfo->lcflag ? '^' : ' '),
|
|
+ (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)),
|
|
+ (LPCSTR)methbuf, G.crec.crc32,
|
|
+ (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
|
|
+ else if (G.lpUserFunctions->SendApplicationMessage_i32 != NULL) {
|
|
+ unsigned long ucsize_lo, csiz_lo;
|
|
+ unsigned long ucsize_hi=0L, csiz_hi=0L;
|
|
+ ucsize_lo = (unsigned long)(G.crec.ucsize);
|
|
+ csiz_lo = (unsigned long)(csiz);
|
|
+#ifdef ZIP64_SUPPORT
|
|
+ ucsize_hi = (unsigned long)(G.crec.ucsize >> 32);
|
|
+ csiz_hi = (unsigned long)(csiz >> 32);
|
|
+#endif /* ZIP64_SUPPORT */
|
|
+ (*G.lpUserFunctions->SendApplicationMessage_i32)(ucsize_lo,
|
|
+ ucsize_hi, csiz_lo, csiz_hi, (unsigned)cfactor,
|
|
+ mo, dy, yr, hh, mm,
|
|
+ (char)(G.pInfo->lcflag ? '^' : ' '),
|
|
+ (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)),
|
|
+ (LPCSTR)methbuf, G.crec.crc32,
|
|
+ (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
|
|
+ }
|
|
+#else /* !WINDLL */
|
|
+ if (cfactor == 100)
|
|
+ sprintf(cfactorstr, LoadFarString(CompFactor100));
|
|
+ else
|
|
+ sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
|
|
+ if (longhdr)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
|
|
+ FmZofft(G.crec.ucsize, "8", "u"), methbuf,
|
|
+ FmZofft(csiz, "8", "u"), cfactorstr,
|
|
+ mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm,
|
|
+ G.crec.crc32, (G.pInfo->lcflag? '^':' ')));
|
|
+ else
|
|
+#ifdef OS2_EAS
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
|
|
+ FmZofft(G.crec.ucsize, "9", "u"), ea_size, acl_size,
|
|
+ mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm,
|
|
+ (G.pInfo->lcflag? '^':' ')));
|
|
+#else
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
|
|
+ FmZofft(G.crec.ucsize, "9", "u"),
|
|
+ mo, dt_sepchar, dy, dt_sepchar, 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
|
|
+#ifdef OS2DLL
|
|
+ } /* end of "if (G.processExternally) {...} else {..." */
|
|
+#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 (uO.qflag < 2
|
|
+#ifdef OS2DLL
|
|
+ && !G.processExternally
|
|
+#endif
|
|
+ ) {
|
|
+ if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) {
|
|
+#ifndef WINDLL
|
|
+ sgn = '-';
|
|
+#endif
|
|
+ cfactor = (-cfactor + 5) / 10;
|
|
+ } else {
|
|
+#ifndef WINDLL
|
|
+ sgn = ' ';
|
|
+#endif
|
|
+ cfactor = (cfactor + 5) / 10;
|
|
+ }
|
|
+#ifdef WINDLL
|
|
+ /* pass the totals back to the calling application */
|
|
+ G.lpUserFunctions->TotalSizeComp = tot_csize;
|
|
+ G.lpUserFunctions->TotalSize = tot_ucsize;
|
|
+ G.lpUserFunctions->CompFactor = (ulg)cfactor;
|
|
+ G.lpUserFunctions->NumMembers = members;
|
|
+
|
|
+#else /* !WINDLL */
|
|
+ if (cfactor == 100)
|
|
+ sprintf(cfactorstr, LoadFarString(CompFactor100));
|
|
+ else
|
|
+ sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
|
|
+ if (longhdr) {
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
|
|
+ FmZofft(tot_ucsize, "8", "u"), FmZofft(tot_csize, "8", "u"),
|
|
+ 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),
|
|
+ FmZofft(tot_ucsize, "9", "u"), tot_easize, tot_aclsize,
|
|
+ members, members == 1 ? "" : "s"));
|
|
+#else
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
|
|
+ FmZofft(tot_ucsize, "9", "u"),
|
|
+ members, members == 1 ? "" : "s"));
|
|
+#endif /* OS2_EAS */
|
|
+#endif /* ?WINDLL */
|
|
+ }
|
|
+
|
|
+ /* Skip the following checks in case of a premature listing break. */
|
|
+ if (error_in_archive <= PK_WARN) {
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Double check that we're back at the end-of-central-directory record.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if ( (memcmp(G.sig,
|
|
+ (G.ecrec.have_ecr64 ?
|
|
+ end_central64_sig : end_central_sig),
|
|
+ 4) != 0)
|
|
+ && (!G.ecrec.is_zip64_archive)
|
|
+ && (memcmp(G.sig, end_central_sig, 4) != 0)
|
|
+ ) { /* just to make sure again */
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide,"%s", LoadFarString(EndSigMsg)));
|
|
+ error_in_archive = PK_WARN; /* didn't find sig */
|
|
+ }
|
|
+
|
|
+ /* Set specific return code when no files have been found. */
|
|
+ if (members == 0L && 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 = lastchar(G.filename, fn_len)) == '/' ||
|
|
+ (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/') &&
|
|
+ endc == '\\'));
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*****************************/
|
|
+/* Function get_time_stamp() */
|
|
+/*****************************/
|
|
+
|
|
+int get_time_stamp(__G__ last_modtime, nmember) /* return PK-type error code */
|
|
+ __GDEF
|
|
+ time_t *last_modtime;
|
|
+ ulg *nmember;
|
|
+{
|
|
+ int do_this_file=FALSE, error, error_in_archive=PK_COOL;
|
|
+ ulg j;
|
|
+#ifdef USE_EF_UT_TIME
|
|
+ iztimes z_utime;
|
|
+#endif
|
|
+ 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.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ *last_modtime = 0L; /* assuming no zipfile data older than 1970 */
|
|
+ *nmember = 0L;
|
|
+ G.pInfo = &info;
|
|
+
|
|
+ for (j = 1L;; j++) {
|
|
+
|
|
+ if (readbuf(__G__ G.sig, 4) == 0)
|
|
+ return PK_EOF;
|
|
+ if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a CentDir entry? */
|
|
+ if (((unsigned)(j - 1) & (unsigned)0xFFFF) ==
|
|
+ (unsigned)G.ecrec.total_entries_central_dir) {
|
|
+ /* "j modulus 64k" matches the reported 16-bit-unsigned
|
|
+ * number of directory entries -> probably, the regular
|
|
+ * end of the central directory has been reached
|
|
+ */
|
|
+ break;
|
|
+ } else {
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide, LoadFarString(CentSigMsg), j));
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
+ return PK_BADERR; /* sig not found */
|
|
+ }
|
|
+ }
|
|
+ /* 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 */
|
|
+ unsigned i;
|
|
+
|
|
+ if (G.filespecs == 0)
|
|
+ do_this_file = TRUE;
|
|
+ else { /* check if this entry matches an `include' argument */
|
|
+ do_this_file = FALSE;
|
|
+ for (i = 0; i < G.filespecs; i++)
|
|
+ if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {
|
|
+ do_this_file = TRUE;
|
|
+ break; /* found match, so stop looping */
|
|
+ }
|
|
+ }
|
|
+ if (do_this_file) { /* check if this is an excluded file */
|
|
+ for (i = 0; i < G.xfilespecs; i++)
|
|
+ if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {
|
|
+ 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 &&
|
|
+#ifdef IZ_CHECK_TZ
|
|
+ G.tz_is_valid &&
|
|
+#endif
|
|
+ (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
|
|
+ G.crec.last_mod_dos_datetime, &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_dos_datetime);
|
|
+
|
|
+ if (*last_modtime < modtime)
|
|
+ *last_modtime = modtime;
|
|
+ }
|
|
+ ++*nmember;
|
|
+ }
|
|
+ SKIP_(G.crec.file_comment_length)
|
|
+
|
|
+ } /* end for-loop (j: files in central directory) */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Double check that we're back at the end-of-central-directory record.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (memcmp(G.sig, end_central_sig, 4)) { /* just to make sure again */
|
|
+ Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(EndSigMsg)));
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+ if (*nmember == 0L && error_in_archive <= PK_WARN)
|
|
+ error_in_archive = PK_FIND;
|
|
+
|
|
+ return error_in_archive;
|
|
+
|
|
+} /* end function get_time_stamp() */
|
|
+
|
|
+#endif /* TIMESTAMP */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/********************/
|
|
+/* Function ratio() */ /* also used by ZipInfo routines */
|
|
+/********************/
|
|
+
|
|
+int ratio(uc, c)
|
|
+ zusz_t uc, c;
|
|
+{
|
|
+ zusz_t 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, (extent)(WSIZE>>1));
|
|
+
|
|
+ (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0);
|
|
+ (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
|
|
+
|
|
+} /* end function fnprint() */
|
|
diff -Naur a/match.c b/match.c
|
|
--- a/match.c 2005-08-14 18:00:36.000000000 +0100
|
|
+++ b/match.c 2019-12-02 00:19:45.331163073 +0000
|
|
@@ -27,16 +27,14 @@
|
|
|
|
---------------------------------------------------------------------------
|
|
|
|
- Copyright on recmatch() from Zip's util.c (although recmatch() was almost
|
|
- certainly written by Mark Adler...ask me how I can tell :-) ):
|
|
+ Copyright on recmatch() from Zip's util.c
|
|
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
|
|
|
|
- Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
|
|
- Kai Uwe Rommel and Igor Mandrichenko.
|
|
+ See the accompanying file LICENSE, version 2004-May-22 or later
|
|
+ for terms of use.
|
|
+ If, for some reason, both of these files are missing, the Info-ZIP license
|
|
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
|
|
|
|
- Permission is granted to any individual or institution to use, copy,
|
|
- or redistribute this software so long as all of the original files are
|
|
- included unmodified, that it is not sold for profit, and that this copy-
|
|
- right notice is retained.
|
|
|
|
---------------------------------------------------------------------------
|
|
|
|
@@ -53,7 +51,7 @@
|
|
|
|
A set is composed of characters or ranges; a range looks like ``character
|
|
hyphen character'' (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of
|
|
- characters allowed in the [..] pattern construct. Other characters are
|
|
+ characters ALlowed in the [..] pattern construct. Other characters are
|
|
allowed (i.e., 8-bit characters) if your system will support them.
|
|
|
|
To suppress the special syntactic significance of any of ``[]*?!^-\'', in-
|
|
@@ -101,8 +99,32 @@
|
|
# define WILDCHAR '?'
|
|
# define BEG_RANGE '['
|
|
# define END_RANGE ']'
|
|
+# define WILDCHR_SINGLE '?'
|
|
+# define DIRSEP_CHR '/'
|
|
+# define WILDCHR_MULTI '*'
|
|
#endif
|
|
|
|
+#ifdef WILD_STOP_AT_DIR
|
|
+ int wild_stop_at_dir = 1; /* default wildcards do not include / in matches */
|
|
+#else
|
|
+ int wild_stop_at_dir = 0; /* default wildcards do include / in matches */
|
|
+#endif
|
|
+
|
|
+
|
|
+
|
|
+/*
|
|
+ * case mapping functions. case_map is used to ignore case in comparisons,
|
|
+ * to_up is used to force upper case even on Unix (for dosify option).
|
|
+ */
|
|
+#ifdef USE_CASE_MAP
|
|
+# define case_map(c) upper[(c) & 0xff]
|
|
+# define to_up(c) upper[(c) & 0xff]
|
|
+#else
|
|
+# define case_map(c) (c)
|
|
+# define to_up(c) ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c))
|
|
+#endif /* USE_CASE_MAP */
|
|
+
|
|
+
|
|
#if 0 /* GRR: add this to unzip.h someday... */
|
|
#if !(defined(MSDOS) && defined(DOSWILD))
|
|
#ifdef WILD_STOP_AT_DIR
|
|
@@ -114,8 +136,8 @@
|
|
int ignore_case __WDLPRO));
|
|
#endif
|
|
#endif /* 0 */
|
|
-static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string,
|
|
- int ignore_case __WDLPRO));
|
|
+static int recmatch OF((ZCONST char *, ZCONST char *,
|
|
+ int));
|
|
static char *isshexp OF((ZCONST char *p));
|
|
static int namecmp OF((ZCONST char *s1, ZCONST char *s2));
|
|
|
|
@@ -154,192 +176,240 @@
|
|
}
|
|
dospattern[j-1] = '\0'; /* nuke the end "." */
|
|
}
|
|
- j = recmatch((uch *)dospattern, (uch *)string, ignore_case __WDL);
|
|
+ j = recmatch(dospattern, string, ignore_case);
|
|
free(dospattern);
|
|
return j == 1;
|
|
} else
|
|
#endif /* MSDOS && DOSWILD */
|
|
- return recmatch((uch *)pattern, (uch *)string, ignore_case __WDL) == 1;
|
|
+ return recmatch(pattern, string, ignore_case) == 1;
|
|
}
|
|
|
|
+#ifdef _MBCS
|
|
+
|
|
+char *___tmp_ptr;
|
|
|
|
+#endif
|
|
|
|
-static int recmatch(p, s, ic __WDL)
|
|
- ZCONST uch *p; /* sh pattern to match */
|
|
- ZCONST uch *s; /* string to which to match it */
|
|
- int ic; /* true for case insensitivity */
|
|
- __WDLDEF /* directory sepchar for WildStopAtDir mode, or 0 */
|
|
+static int recmatch(p, s, ci)
|
|
+ZCONST char *p; /* sh pattern to match */
|
|
+ZCONST char *s; /* string to match it to */
|
|
+int ci; /* flag: force case-insensitive matching */
|
|
/* Recursively compare the sh pattern p with the string s and return 1 if
|
|
- * they match, and 0 or 2 if they don't or if there is a syntax error in the
|
|
- * pattern. This routine recurses on itself no more deeply than the number
|
|
- * of characters in the pattern. */
|
|
+ they match, and 0 or 2 if they don't or if there is a syntax error in the
|
|
+ pattern. This routine recurses on itself no deeper than the number of
|
|
+ characters in the pattern. */
|
|
{
|
|
- unsigned int c; /* pattern char or start of range in [-] loop */
|
|
+ int c; /* pattern char or start of range in [-] loop */
|
|
+ /* Get first character, the pattern for new recmatch calls follows */
|
|
+ /* borrowed from Zip's global.c */
|
|
+ int no_wild = 0;
|
|
+ int allow_regex=1;
|
|
+ /* This fix provided by akt@m5.dion.ne.jp for Japanese.
|
|
+ See 21 July 2006 mail.
|
|
+ It only applies when p is pointing to a doublebyte character and
|
|
+ things like / and wildcards are not doublebyte. This probably
|
|
+ should not be needed. */
|
|
|
|
- /* Get first character, the pattern for new recmatch calls follows */
|
|
- c = *p; INCSTR(p);
|
|
+#ifdef _MBCS
|
|
+ if (CLEN(p) == 2) {
|
|
+ if (CLEN(s) == 2) {
|
|
+ return (*p == *s && *(p+1) == *(s+1)) ?
|
|
+ recmatch(p + 2, s + 2, ci) : 0;
|
|
+ } else {
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+#endif /* ?_MBCS */
|
|
|
|
- /* If that was the end of the pattern, match if string empty too */
|
|
- if (c == 0)
|
|
- return *s == 0;
|
|
+ c = *POSTINCSTR(p);
|
|
|
|
- /* '?' (or '%') matches any character (but not an empty string). */
|
|
- if (c == WILDCHAR)
|
|
-#ifdef WILD_STOP_AT_DIR
|
|
- /* If uO.W_flag is non-zero, it won't match '/' */
|
|
- return (*s && (!sepc || *s != (uch)sepc))
|
|
- ? recmatch(p, s + CLEN(s), ic, sepc) : 0;
|
|
-#else
|
|
- return *s ? recmatch(p, s + CLEN(s), ic) : 0;
|
|
-#endif
|
|
+ /* If that was the end of the pattern, match if string empty too */
|
|
+ if (c == 0)
|
|
+ return *s == 0;
|
|
+
|
|
+ /* '?' (or '%' or '#') matches any character (but not an empty string) */
|
|
+ if (c == WILDCHR_SINGLE) {
|
|
+ if (wild_stop_at_dir)
|
|
+ return (*s && *s != DIRSEP_CHR) ? recmatch(p, s + CLEN(s), ci) : 0;
|
|
+ else
|
|
+ return *s ? recmatch(p, s + CLEN(s), ci) : 0;
|
|
+ }
|
|
|
|
- /* '*' matches any number of characters, including zero */
|
|
+ /* WILDCHR_MULTI ('*') matches any number of characters, including zero */
|
|
#ifdef AMIGA
|
|
- if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
|
|
- c = '*', p++;
|
|
+ if (!no_wild && c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */
|
|
+ c = WILDCHR_MULTI, p++;
|
|
#endif /* AMIGA */
|
|
- if (c == '*') {
|
|
-#ifdef WILD_STOP_AT_DIR
|
|
- if (sepc) {
|
|
- /* check for single "*" or double "**" */
|
|
-# ifdef AMIGA
|
|
- if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */
|
|
- c = '*', p++;
|
|
- if (c != '*') {
|
|
-# else /* !AMIGA */
|
|
- if (*p != '*') {
|
|
-# endif /* ?AMIGA */
|
|
- /* single "*": this doesn't match the dirsep character */
|
|
- for (; *s && *s != (uch)sepc; INCSTR(s))
|
|
- if ((c = recmatch(p, s, ic, sepc)) != 0)
|
|
- return (int)c;
|
|
- /* end of pattern: matched if at end of string, else continue */
|
|
- if (*p == '\0')
|
|
- return (*s == 0);
|
|
- /* continue to match if at sepc in pattern, else give up */
|
|
- return (*p == (uch)sepc || (*p == '\\' && p[1] == (uch)sepc))
|
|
- ? recmatch(p, s, ic, sepc) : 2;
|
|
- }
|
|
- /* "**": this matches slashes */
|
|
- ++p; /* move p behind the second '*' */
|
|
- /* and continue with the non-W_flag code variant */
|
|
- }
|
|
-#endif /* WILD_STOP_AT_DIR */
|
|
+ if (!no_wild && c == WILDCHR_MULTI)
|
|
+ {
|
|
+ if (wild_stop_at_dir) {
|
|
+ /* Check for an immediately following WILDCHR_MULTI */
|
|
+# ifdef AMIGA
|
|
+ if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */
|
|
+ c = WILDCHR_MULTI, p++;
|
|
+ if (c != WILDCHR_MULTI) {
|
|
+# else /* !AMIGA */
|
|
+ if (*p != WILDCHR_MULTI) {
|
|
+# endif /* ?AMIGA */
|
|
+ /* Single WILDCHR_MULTI ('*'): this doesn't match slashes */
|
|
+ for (; *s && *s != DIRSEP_CHR; INCSTR(s))
|
|
+ if ((c = recmatch(p, s, ci)) != 0)
|
|
+ return c;
|
|
+ /* end of pattern: matched if at end of string, else continue */
|
|
if (*p == 0)
|
|
- return 1;
|
|
- if (isshexp((ZCONST char *)p) == NULL) {
|
|
- /* Optimization for rest of pattern being a literal string:
|
|
- * If there are no other shell expression chars in the rest
|
|
- * of the pattern behind the multi-char wildcard, then just
|
|
- * compare the literal string tail.
|
|
- */
|
|
- ZCONST uch *srest;
|
|
-
|
|
- srest = s + (strlen((ZCONST char *)s) - strlen((ZCONST char *)p));
|
|
- if (srest - s < 0)
|
|
- /* remaining literal string from pattern is longer than rest
|
|
- * of test string, there can't be a match
|
|
- */
|
|
- return 0;
|
|
- else
|
|
- /* compare the remaining literal pattern string with the last
|
|
- * bytes of the test string to check for a match
|
|
- */
|
|
+ return (*s == 0);
|
|
+ /* continue to match if at DIRSEP_CHR in pattern, else give up */
|
|
+ return (*p == DIRSEP_CHR || (*p == '\\' && p[1] == DIRSEP_CHR))
|
|
+ ? recmatch(p, s, ci) : 2;
|
|
+ }
|
|
+ /* Two consecutive WILDCHR_MULTI ("**"): this matches DIRSEP_CHR ('/') */
|
|
+ p++; /* move p past the second WILDCHR_MULTI */
|
|
+ /* continue with the normal non-WILD_STOP_AT_DIR code */
|
|
+ } /* wild_stop_at_dir */
|
|
+
|
|
+ /* Not wild_stop_at_dir */
|
|
+ if (*p == 0)
|
|
+ return 1;
|
|
+ if (!isshexp((char *)p))
|
|
+ {
|
|
+ /* optimization for rest of pattern being a literal string */
|
|
+
|
|
+ /* optimization to handle patterns like *.txt */
|
|
+ /* if the first char in the pattern is '*' and there */
|
|
+ /* are no other shell expression chars, i.e. a literal string */
|
|
+ /* then just compare the literal string at the end */
|
|
+
|
|
+ ZCONST char *srest;
|
|
+
|
|
+ srest = s + (strlen(s) - strlen(p));
|
|
+ if (srest - s < 0)
|
|
+ /* remaining literal string from pattern is longer than rest of
|
|
+ test string, there can't be a match
|
|
+ */
|
|
+ return 0;
|
|
+ else
|
|
+ /* compare the remaining literal pattern string with the last bytes
|
|
+ of the test string to check for a match */
|
|
#ifdef _MBCS
|
|
- {
|
|
- ZCONST uch *q = s;
|
|
+ {
|
|
+ ZCONST char *q = s;
|
|
|
|
- /* MBCS-aware code must not scan backwards into a string from
|
|
- * the end.
|
|
- * So, we have to move forward by character from our well-known
|
|
- * character position s in the test string until we have
|
|
- * advanced to the srest position.
|
|
- */
|
|
- while (q < srest)
|
|
- INCSTR(q);
|
|
- /* In case the byte *srest is a trailing byte of a multibyte
|
|
- * character in the test string s, we have actually advanced
|
|
- * past the position (srest).
|
|
- * For this case, the match has failed!
|
|
- */
|
|
- if (q != srest)
|
|
- return 0;
|
|
- return ((ic
|
|
- ? namecmp((ZCONST char *)p, (ZCONST char *)q)
|
|
- : strcmp((ZCONST char *)p, (ZCONST char *)q)
|
|
- ) == 0);
|
|
- }
|
|
+ /* MBCS-aware code must not scan backwards into a string from
|
|
+ * the end.
|
|
+ * So, we have to move forward by character from our well-known
|
|
+ * character position s in the test string until we have advanced
|
|
+ * to the srest position.
|
|
+ */
|
|
+ while (q < srest)
|
|
+ INCSTR(q);
|
|
+ /* In case the byte *srest is a trailing byte of a multibyte
|
|
+ * character, we have actually advanced past the position (srest).
|
|
+ * For this case, the match has failed!
|
|
+ */
|
|
+ if (q != srest)
|
|
+ return 0;
|
|
+ return ((!ci ? strcmp(p, q) : namecmp(p, q)) == 0);
|
|
+ }
|
|
#else /* !_MBCS */
|
|
- return ((ic
|
|
- ? namecmp((ZCONST char *)p, (ZCONST char *)srest)
|
|
- : strcmp((ZCONST char *)p, (ZCONST char *)srest)
|
|
- ) == 0);
|
|
+ return ((!ci ? strcmp(p, srest) : namecmp(p, srest)) == 0);
|
|
#endif /* ?_MBCS */
|
|
- } else {
|
|
- /* pattern contains more wildcards, continue with recursion... */
|
|
- for (; *s; INCSTR(s))
|
|
- if ((c = recmatch(p, s, ic __WDL)) != 0)
|
|
- return (int)c;
|
|
- return 2; /* 2 means give up--match will return false */
|
|
- }
|
|
}
|
|
-
|
|
- /* Parse and process the list of characters and ranges in brackets */
|
|
- if (c == BEG_RANGE) {
|
|
- int e; /* flag true if next char to be taken literally */
|
|
- ZCONST uch *q; /* pointer to end of [-] group */
|
|
- int r; /* flag true to match anything but the range */
|
|
-
|
|
- if (*s == 0) /* need a character to match */
|
|
- return 0;
|
|
- p += (r = (*p == '!' || *p == '^')); /* see if reverse */
|
|
- for (q = p, e = 0; *q; INCSTR(q)) /* find closing bracket */
|
|
- if (e)
|
|
- e = 0;
|
|
- else
|
|
- if (*q == '\\') /* GRR: change to ^ for MS-DOS, OS/2? */
|
|
- e = 1;
|
|
- else if (*q == END_RANGE)
|
|
- break;
|
|
- if (*q != END_RANGE) /* nothing matches if bad syntax */
|
|
- return 0;
|
|
- for (c = 0, e = (*p == '-'); p < q; INCSTR(p)) {
|
|
- /* go through the list */
|
|
- if (!e && *p == '\\') /* set escape flag if \ */
|
|
- e = 1;
|
|
- else if (!e && *p == '-') /* set start of range if - */
|
|
- c = *(p-1);
|
|
- else {
|
|
- unsigned int cc = Case(*s);
|
|
-
|
|
- if (*(p+1) != '-')
|
|
- for (c = c ? c : *p; c <= *p; c++) /* compare range */
|
|
- if ((unsigned)Case(c) == cc) /* typecast for MSC bug */
|
|
- return r ? 0 : recmatch(q + 1, s + 1, ic __WDL);
|
|
- c = e = 0; /* clear range, escape flags */
|
|
- }
|
|
- }
|
|
- return r ? recmatch(q + CLEN(q), s + CLEN(s), ic __WDL) : 0;
|
|
- /* bracket match failed */
|
|
+ else
|
|
+ {
|
|
+ /* pattern contains more wildcards, continue with recursion... */
|
|
+ for (; *s; INCSTR(s))
|
|
+ if ((c = recmatch(p, s, ci)) != 0)
|
|
+ return c;
|
|
+ return 2; /* 2 means give up--shmatch will return false */
|
|
}
|
|
+ }
|
|
|
|
- /* if escape ('\\'), just compare next character */
|
|
- if (c == '\\' && (c = *p++) == 0) /* if \ at end, then syntax error */
|
|
- return 0;
|
|
+#ifndef VMS /* No bracket matching in VMS */
|
|
+ /* Parse and process the list of characters and ranges in brackets */
|
|
+ if (!no_wild && allow_regex && c == '[')
|
|
+ {
|
|
+ int e; /* flag true if next char to be taken literally */
|
|
+ ZCONST char *q; /* pointer to end of [-] group */
|
|
+ int r; /* flag true to match anything but the range */
|
|
+
|
|
+ if (*s == 0) /* need a character to match */
|
|
+ return 0;
|
|
+ p += (r = (*p == '!' || *p == '^')); /* see if reverse */
|
|
+ for (q = p, e = 0; *q; q++) /* find closing bracket */
|
|
+ if (e)
|
|
+ e = 0;
|
|
+ else
|
|
+ if (*q == '\\')
|
|
+ e = 1;
|
|
+ else if (*q == ']')
|
|
+ break;
|
|
+ if (*q != ']') /* nothing matches if bad syntax */
|
|
+ return 0;
|
|
+ for (c = 0, e = *p == '-'; p < q; p++) /* go through the list */
|
|
+ {
|
|
+ if (e == 0 && *p == '\\') /* set escape flag if \ */
|
|
+ e = 1;
|
|
+ else if (e == 0 && *p == '-') /* set start of range if - */
|
|
+ c = *(p-1);
|
|
+ else
|
|
+ {
|
|
+ uch cc = (!ci ? (uch)*s : to_up((uch)*s));
|
|
+ uch uc = (uch) c;
|
|
+ if (*(p+1) != '-')
|
|
+ for (uc = uc ? uc : (uch)*p; uc <= (uch)*p; uc++)
|
|
+ /* compare range */
|
|
+ if ((!ci ? uc : to_up(uc)) == cc)
|
|
+ return r ? 0 : recmatch(q + CLEN(q), s + CLEN(s), ci);
|
|
+ c = e = 0; /* clear range, escape flags */
|
|
+ }
|
|
+ }
|
|
+ return r ? recmatch(q + CLEN(q), s + CLEN(s), ci) : 0;
|
|
+ /* bracket match failed */
|
|
+ }
|
|
+#endif /* !VMS */
|
|
|
|
- /* just a character--compare it */
|
|
-#ifdef QDOS
|
|
- return QMatch(Case((uch)c), Case(*s)) ?
|
|
- recmatch(p, s + CLEN(s), ic __WDL) : 0;
|
|
-#else
|
|
- return Case((uch)c) == Case(*s) ?
|
|
- recmatch(p, s + CLEN(s), ic __WDL) : 0;
|
|
-#endif
|
|
+ /* If escape ('\'), just compare next character */
|
|
+ if (!no_wild && c == '\\')
|
|
+ if ((c = *p++) == '\0') /* if \ at end, then syntax error */
|
|
+ return 0;
|
|
+
|
|
+#ifdef VMS
|
|
+ /* 2005-11-06 SMS.
|
|
+ Handle "..." wildcard in p with "." or "]" in s.
|
|
+ */
|
|
+ if ((c == '.') && (*p == '.') && (*(p+ CLEN( p)) == '.') &&
|
|
+ ((*s == '.') || (*s == ']')))
|
|
+ {
|
|
+ /* Match "...]" with "]". Continue after "]" in both. */
|
|
+ if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
|
|
+ return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), ci);
|
|
+
|
|
+ /* Else, look for a reduced match in s, until "]" in or end of s. */
|
|
+ for (; *s && (*s != ']'); INCSTR(s))
|
|
+ if (*s == '.')
|
|
+ /* If reduced match, then continue after "..." in p, "." in s. */
|
|
+ if ((c = recmatch( (p+ CLEN( p)), s, ci)) != 0)
|
|
+ return (int)c;
|
|
+
|
|
+ /* Match "...]" with "]". Continue after "]" in both. */
|
|
+ if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))
|
|
+ return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), ci);
|
|
+
|
|
+ /* No reduced match. Quit. */
|
|
+ return 2;
|
|
+ }
|
|
+
|
|
+#endif /* def VMS */
|
|
+
|
|
+ /* Just a character--compare it */
|
|
+ return (!ci ? c == *s : to_up((uch)c) == to_up((uch)*s)) ?
|
|
+ recmatch(p, s + CLEN(s), ci) : 0;
|
|
+}
|
|
|
|
-} /* end function recmatch() */
|
|
|
|
|
|
|
|
+/*************************************************************************************************/
|
|
static char *isshexp(p)
|
|
ZCONST char *p;
|
|
/* If p is a sh expression, a pointer to the first special character is
|
|
diff -Naur a/process.c b/process.c
|
|
--- a/process.c 2009-03-06 01:25:10.000000000 +0000
|
|
+++ b/process.c 2019-12-02 01:44:23.792587920 +0000
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
|
|
+ Copyright (c) 1990-2014 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.
|
|
@@ -1888,48 +1888,83 @@
|
|
and a 4-byte version of disk start number.
|
|
Sets both local header and central header fields. Not terribly clever,
|
|
but it means that this procedure is only called in one place.
|
|
+
|
|
+ 2014-12-05 SMS.
|
|
+ Added checks to ensure that enough data are available before calling
|
|
+ makeint64() or makelong(). Replaced various sizeof() values with
|
|
+ simple ("4" or "8") constants. (The Zip64 structures do not depend
|
|
+ on our variable sizes.) Error handling is crude, but we should now
|
|
+ stay within the buffer.
|
|
---------------------------------------------------------------------------*/
|
|
|
|
+#define Z64FLGS 0xffff
|
|
+#define Z64FLGL 0xffffffff
|
|
+
|
|
if (ef_len == 0 || ef_buf == NULL)
|
|
return PK_COOL;
|
|
|
|
Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n",
|
|
ef_len));
|
|
|
|
- while (ef_len >= EB_HEADSIZE) {
|
|
+ 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! */
|
|
+ if (eb_len > (ef_len - EB_HEADSIZE))
|
|
+ {
|
|
+ /* Extra block length exceeds remaining extra field length. */
|
|
Trace((stderr,
|
|
"getZip64Data: block length %u > rest ef_size %u\n", eb_len,
|
|
ef_len - EB_HEADSIZE));
|
|
break;
|
|
}
|
|
- if (eb_id == EF_PKSZ64) {
|
|
|
|
+ if (eb_id == EF_PKSZ64)
|
|
+ {
|
|
int offset = EB_HEADSIZE;
|
|
|
|
- if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){
|
|
- G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf);
|
|
- offset += sizeof(G.crec.ucsize);
|
|
+ if ((G.crec.ucsize == Z64FLGL) || (G.lrec.ucsize == Z64FLGL))
|
|
+ {
|
|
+ if (offset+ 8 > ef_len)
|
|
+ return PK_ERR;
|
|
+
|
|
+ G.crec.ucsize = G.lrec.ucsize = makeint64(offset + ef_buf);
|
|
+ offset += 8;
|
|
}
|
|
- if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){
|
|
- G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf);
|
|
- offset += sizeof(G.crec.csize);
|
|
+
|
|
+ if ((G.crec.csize == Z64FLGL) || (G.lrec.csize == Z64FLGL))
|
|
+ {
|
|
+ if (offset+ 8 > ef_len)
|
|
+ return PK_ERR;
|
|
+
|
|
+ G.csize = G.crec.csize = G.lrec.csize = makeint64(offset + ef_buf);
|
|
+ offset += 8;
|
|
}
|
|
- if (G.crec.relative_offset_local_header == 0xffffffff){
|
|
+
|
|
+ if (G.crec.relative_offset_local_header == Z64FLGL)
|
|
+ {
|
|
+ if (offset+ 8 > ef_len)
|
|
+ return PK_ERR;
|
|
+
|
|
G.crec.relative_offset_local_header = makeint64(offset + ef_buf);
|
|
- offset += sizeof(G.crec.relative_offset_local_header);
|
|
+ offset += 8;
|
|
}
|
|
- if (G.crec.disk_number_start == 0xffff){
|
|
+
|
|
+ if (G.crec.disk_number_start == Z64FLGS)
|
|
+ {
|
|
+ if (offset+ 4 > ef_len)
|
|
+ return PK_ERR;
|
|
+
|
|
G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf);
|
|
- offset += sizeof(G.crec.disk_number_start);
|
|
+ offset += 4;
|
|
}
|
|
+#if 0
|
|
+ break; /* Expect only one EF_PKSZ64 block. */
|
|
+#endif /* 0 */
|
|
}
|
|
|
|
- /* Skip this extra field block */
|
|
+ /* Skip this extra field block. */
|
|
ef_buf += (eb_len + EB_HEADSIZE);
|
|
ef_len -= (eb_len + EB_HEADSIZE);
|
|
}
|
|
@@ -2867,10 +2902,13 @@
|
|
break;
|
|
|
|
case EF_IZUNIX2:
|
|
- if (have_new_type_eb == 0) {
|
|
- flags &= ~0x0ff; /* ignore any previous IZUNIX field */
|
|
+ if (have_new_type_eb == 0) { /* (< 1) */
|
|
have_new_type_eb = 1;
|
|
}
|
|
+ if (have_new_type_eb <= 1) {
|
|
+ /* Ignore any prior (EF_IZUNIX/EF_PKUNIX) UID/GID. */
|
|
+ flags &= 0x0ff;
|
|
+ }
|
|
#ifdef IZ_HAVE_UXUIDGID
|
|
if (have_new_type_eb > 1)
|
|
break; /* IZUNIX3 overrides IZUNIX2 e.f. block ! */
|
|
@@ -2886,6 +2924,8 @@
|
|
/* new 3rd generation Unix ef */
|
|
have_new_type_eb = 2;
|
|
|
|
+ /* Ignore any prior EF_IZUNIX/EF_PKUNIX/EF_IZUNIX2 UID/GID. */
|
|
+ flags &= 0x0ff;
|
|
/*
|
|
Version 1 byte version of this extra field, currently 1
|
|
UIDSize 1 byte Size of UID field
|
|
@@ -2895,9 +2935,9 @@
|
|
*/
|
|
|
|
#ifdef IZ_HAVE_UXUIDGID
|
|
- if (eb_len >= EB_UX3_MINLEN
|
|
- && z_uidgid != NULL
|
|
- && (*((EB_HEADSIZE + 0) + ef_buf) == 1)
|
|
+ if ((eb_len >= EB_UX3_MINLEN)
|
|
+ && (z_uidgid != NULL)
|
|
+ && ((*((EB_HEADSIZE + 0) + ef_buf) == 1)))
|
|
/* only know about version 1 */
|
|
{
|
|
uch uid_size;
|
|
@@ -2906,13 +2946,11 @@
|
|
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])
|
|
+ uid_size, &z_uidgid[0])
|
|
&&
|
|
read_ux3_value((EB_HEADSIZE + uid_size + 3) + ef_buf,
|
|
- gid_size, z_uidgid[1]) )
|
|
+ gid_size, &z_uidgid[1]) )
|
|
{
|
|
flags |= EB_UX2_VALID; /* signal success */
|
|
}
|
|
diff -Naur a/process.c.orig b/process.c.orig
|
|
--- a/process.c.orig 1970-01-01 01:00:00.000000000 +0100
|
|
+++ b/process.c.orig 2019-12-02 00:32:11.309743527 +0000
|
|
@@ -0,0 +1,3123 @@
|
|
+/*
|
|
+ Copyright (c) 1990-2014 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
|
|
+ static ZCONST char Far Unzip[] = "unzip";
|
|
+#else
|
|
+ static ZCONST char Far Unzip[] = "UnZip DLL";
|
|
+#endif
|
|
+#ifdef DO_SAFECHECK_2GB
|
|
+ static ZCONST char Far ZipfileTooBig[] =
|
|
+ "Trying to read large file (> 2 GiB) without large file support\n";
|
|
+#endif /* DO_SAFECHECK_2GB */
|
|
+ static ZCONST char Far MaybeExe[] =
|
|
+ "note: %s may be a plain executable, not an archive\n";
|
|
+ static ZCONST char Far CentDirNotInZipMsg[] = "\n\
|
|
+ [%s]:\n\
|
|
+ Zipfile is disk %lu of a multi-disk archive, and this is not the disk on\n\
|
|
+ which the central zipfile directory begins (disk %lu).\n";
|
|
+ static ZCONST char Far EndCentDirBogus[] =
|
|
+ "\nwarning [%s]: end-of-central-directory record claims this\n\
|
|
+ is disk %lu but that the central directory starts on disk %lu; this is a\n\
|
|
+ contradiction. Attempting to process anyway.\n";
|
|
+# ifdef NO_MULTIPART
|
|
+ static ZCONST char Far NoMultiDiskArcSupport[] =
|
|
+ "\nerror [%s]: zipfile is part of multi-disk archive\n\
|
|
+ (sorry, not yet supported).\n";
|
|
+ static ZCONST char Far MaybePakBug[] = "warning [%s]:\
|
|
+ zipfile claims to be 2nd disk of a 2-part archive;\n\
|
|
+ attempting to process anyway. If no further errors occur, this archive\n\
|
|
+ was probably created by PAK v2.51 or earlier. This bug was reported to\n\
|
|
+ NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\
|
|
+ of mid-1992 it still hadn't been. (If further errors do occur, archive\n\
|
|
+ was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\
|
|
+ multi-part archives.)\n";
|
|
+# else
|
|
+ static ZCONST char Far MaybePakBug[] = "warning [%s]:\
|
|
+ zipfile claims to be last disk of a multi-part archive;\n\
|
|
+ attempting to process anyway, assuming all parts have been concatenated\n\
|
|
+ together in order. Expect \"errors\" and warnings...true multi-part support\
|
|
+\n doesn't exist yet (coming soon).\n";
|
|
+# endif
|
|
+ static ZCONST char Far ExtraBytesAtStart[] =
|
|
+ "warning [%s]: %s extra byte%s at beginning or within zipfile\n\
|
|
+ (attempting to process anyway)\n";
|
|
+#endif /* ?SFX */
|
|
+
|
|
+#if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO))
|
|
+ static ZCONST char Far LogInitline[] = "Archive: %s\n";
|
|
+#endif
|
|
+
|
|
+static ZCONST char Far MissingBytes[] =
|
|
+ "error [%s]: missing %s bytes in zipfile\n\
|
|
+ (attempting to process anyway)\n";
|
|
+static ZCONST char Far NullCentDirOffset[] =
|
|
+ "error [%s]: NULL central directory offset\n\
|
|
+ (attempting to process anyway)\n";
|
|
+static ZCONST char Far ZipfileEmpty[] = "warning [%s]: zipfile is empty\n";
|
|
+static ZCONST char Far CentDirStartNotFound[] =
|
|
+ "error [%s]: start of central directory not found;\n\
|
|
+ zipfile corrupt.\n%s";
|
|
+static ZCONST char Far Cent64EndSigSearchErr[] =
|
|
+ "fatal error: read failure while seeking for End-of-centdir-64 signature.\n\
|
|
+ This zipfile is corrupt.\n";
|
|
+static ZCONST char Far Cent64EndSigSearchOff[] =
|
|
+ "error: End-of-centdir-64 signature not where expected (prepended bytes?)\n\
|
|
+ (attempting to process anyway)\n";
|
|
+#ifndef SFX
|
|
+ static ZCONST char Far CentDirTooLong[] =
|
|
+ "error [%s]: reported length of central directory is\n\
|
|
+ %s bytes too long (Atari STZip zipfile? J.H.Holm ZIPSPLIT 1.1\n\
|
|
+ zipfile?). Compensating...\n";
|
|
+ static ZCONST char Far CentDirEndSigNotFound[] = "\
|
|
+ End-of-central-directory signature not found. Either this file is not\n\
|
|
+ a zipfile, or it constitutes one disk of a multi-part archive. In the\n\
|
|
+ latter case the central directory and zipfile comment will be found on\n\
|
|
+ the last disk(s) of this archive.\n";
|
|
+#else /* SFX */
|
|
+ static ZCONST char Far CentDirEndSigNotFound[] =
|
|
+ " End-of-central-directory signature not found.\n";
|
|
+#endif /* ?SFX */
|
|
+#ifdef TIMESTAMP
|
|
+ static ZCONST char Far ZipTimeStampFailed[] =
|
|
+ "warning: cannot set time for %s\n";
|
|
+ static ZCONST char Far ZipTimeStampSuccess[] =
|
|
+ "Updated time stamp for %s.\n";
|
|
+#endif
|
|
+static ZCONST char Far ZipfileCommTrunc1[] =
|
|
+ "\ncaution: zipfile comment truncated\n";
|
|
+#ifndef NO_ZIPINFO
|
|
+ static ZCONST char Far NoZipfileComment[] =
|
|
+ "There is no zipfile comment.\n";
|
|
+ static ZCONST char Far ZipfileCommentDesc[] =
|
|
+ "The zipfile comment is %u bytes long and contains the following text:\n";
|
|
+ static ZCONST char Far ZipfileCommBegin[] =
|
|
+ "======================== zipfile comment begins\
|
|
+ ==========================\n";
|
|
+ static ZCONST char Far ZipfileCommEnd[] =
|
|
+ "========================= zipfile comment ends\
|
|
+ ===========================\n";
|
|
+ static ZCONST char Far ZipfileCommTrunc2[] =
|
|
+ "\n The zipfile comment is truncated.\n";
|
|
+#endif /* !NO_ZIPINFO */
|
|
+#ifdef UNICODE_SUPPORT
|
|
+ static ZCONST char Far UnicodeVersionError[] =
|
|
+ "\nwarning: Unicode Path version > 1\n";
|
|
+ static ZCONST char Far UnicodeMismatchError[] =
|
|
+ "\nwarning: Unicode Path checksum invalid\n";
|
|
+#endif
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*******************************/
|
|
+/* Function process_zipfiles() */
|
|
+/*******************************/
|
|
+
|
|
+int process_zipfiles(__G) /* return PK-type error code */
|
|
+ __GDEF
|
|
+{
|
|
+#ifndef SFX
|
|
+ char *lastzipfn = (char *)NULL;
|
|
+ int NumWinFiles, NumLoseFiles, NumWarnFiles;
|
|
+ int NumMissDirs, NumMissFiles;
|
|
+#endif
|
|
+ int error=0, error_in_archive=0;
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Start by allocating buffers and (re)constructing the various PK signature
|
|
+ strings.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ G.inbuf = (uch *)malloc(INBUFSIZ + 4); /* 4 extra for hold[] (below) */
|
|
+ G.outbuf = (uch *)malloc(OUTBUFSIZ + 1); /* 1 extra for string term. */
|
|
+
|
|
+ if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CannotAllocateBuffers)));
|
|
+ return(PK_MEM);
|
|
+ }
|
|
+ G.hold = G.inbuf + INBUFSIZ; /* to check for boundary-spanning sigs */
|
|
+#ifndef VMS /* VMS uses its own buffer scheme for textmode flush(). */
|
|
+#ifdef SMALL_MEM
|
|
+ G.outbuf2 = G.outbuf+RAWBUFSIZ; /* never changes */
|
|
+#endif
|
|
+#endif /* !VMS */
|
|
+
|
|
+#if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */
|
|
+ /* allocate the CRC table later when we know we can read zipfile data */
|
|
+ CRC_32_TAB = NULL;
|
|
+#endif /* 0 */
|
|
+
|
|
+ /* finish up initialization of magic signature strings */
|
|
+ local_hdr_sig[0] /* = extd_local_sig[0] */ = /* ASCII 'P', */
|
|
+ central_hdr_sig[0] = end_central_sig[0] = /* not EBCDIC */
|
|
+ end_centloc64_sig[0] = end_central64_sig[0] = 0x50;
|
|
+
|
|
+ local_hdr_sig[1] /* = extd_local_sig[1] */ = /* ASCII 'K', */
|
|
+ central_hdr_sig[1] = end_central_sig[1] = /* not EBCDIC */
|
|
+ end_centloc64_sig[1] = end_central64_sig[1] = 0x4B;
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Make sure timezone info is set correctly; localtime() returns GMT on some
|
|
+ OSes (e.g., Solaris 2.x) if this isn't done first. The ifdefs around
|
|
+ tzset() were initially copied from dos_to_unix_time() in fileio.c. They
|
|
+ may still be too strict; any listed OS that supplies tzset(), regardless
|
|
+ of whether the function does anything, should be removed from the ifdefs.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#if (defined(WIN32) && defined(USE_EF_UT_TIME))
|
|
+ /* For the Win32 environment, we may have to "prepare" the environment
|
|
+ prior to the tzset() call, to work around tzset() implementation bugs.
|
|
+ */
|
|
+ iz_w32_prepareTZenv();
|
|
+#endif
|
|
+
|
|
+#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
|
|
+# ifndef VALID_TIMEZONE
|
|
+# define VALID_TIMEZONE(tmp) \
|
|
+ (((tmp = getenv("TZ")) != NULL) && (*tmp != '\0'))
|
|
+# endif
|
|
+ {
|
|
+ char *p;
|
|
+ G.tz_is_valid = VALID_TIMEZONE(p);
|
|
+# ifndef SFX
|
|
+ if (!G.tz_is_valid) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ)));
|
|
+ error_in_archive = error = PK_WARN;
|
|
+ }
|
|
+# endif /* !SFX */
|
|
+ }
|
|
+#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */
|
|
+
|
|
+/* For systems that do not have tzset() but supply this function using another
|
|
+ name (_tzset() or something similar), an appropiate "#define tzset ..."
|
|
+ should be added to the system specifc configuration section. */
|
|
+#if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS))
|
|
+#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))
|
|
+ tzset();
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+/* Initialize UnZip's built-in pseudo hard-coded "ISO <--> OEM" translation,
|
|
+ depending on the detected codepage setup. */
|
|
+#ifdef NEED_ISO_OEM_INIT
|
|
+ prepare_ISO_OEM_translat(__G);
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Initialize the internal flag holding the mode of processing "overwrite
|
|
+ existing file" cases. We do not use the calling interface flags directly
|
|
+ because the overwrite mode may be changed by user interaction while
|
|
+ processing archive files. Such a change should not affect the option
|
|
+ settings as passed through the DLL calling interface.
|
|
+ In case of conflicting options, the 'safer' flag uO.overwrite_none takes
|
|
+ precedence.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+ G.overwrite_mode = (uO.overwrite_none ? OVERWRT_NEVER :
|
|
+ (uO.overwrite_all ? OVERWRT_ALWAYS : OVERWRT_QUERY));
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Match (possible) wildcard zipfile specification with existing files and
|
|
+ attempt to process each. If no hits, try again after appending ".zip"
|
|
+ suffix. If still no luck, give up.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef SFX
|
|
+ if ((error = do_seekable(__G__ 0)) == PK_NOZIP) {
|
|
+#ifdef EXE_EXTENSION
|
|
+ int len=strlen(G.argv0);
|
|
+
|
|
+ /* append .exe if appropriate; also .sfx? */
|
|
+ if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) !=
|
|
+ (char *)NULL ) {
|
|
+ strcpy(G.zipfn, G.argv0);
|
|
+ strcpy(G.zipfn+len, EXE_EXTENSION);
|
|
+ error = do_seekable(__G__ 0);
|
|
+ free(G.zipfn);
|
|
+ G.zipfn = G.argv0; /* for "cannot find myself" message only */
|
|
+ }
|
|
+#endif /* EXE_EXTENSION */
|
|
+#ifdef WIN32
|
|
+ G.zipfn = G.argv0; /* for "cannot find myself" message only */
|
|
+#endif
|
|
+ }
|
|
+ if (error) {
|
|
+ if (error == IZ_DIR)
|
|
+ error_in_archive = PK_NOZIP;
|
|
+ else
|
|
+ error_in_archive = error;
|
|
+ if (error == PK_NOZIP)
|
|
+ Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself),
|
|
+ G.zipfn));
|
|
+ }
|
|
+#ifdef CHEAP_SFX_AUTORUN
|
|
+ if (G.autorun_command[0] && !uO.qflag) { /* NO autorun without prompt! */
|
|
+ Info(slide, 0x81, ((char *)slide, LoadFarString(AutorunPrompt),
|
|
+ FnFilter1(G.autorun_command)));
|
|
+ if (fgets(G.answerbuf, 9, stdin) != (char *)NULL
|
|
+ && toupper(*G.answerbuf) == 'Y')
|
|
+ system(G.autorun_command);
|
|
+ else
|
|
+ Info(slide, 1, ((char *)slide, LoadFarString(NotAutoRunning)));
|
|
+ }
|
|
+#endif /* CHEAP_SFX_AUTORUN */
|
|
+
|
|
+#else /* !SFX */
|
|
+ NumWinFiles = NumLoseFiles = NumWarnFiles = 0;
|
|
+ NumMissDirs = NumMissFiles = 0;
|
|
+
|
|
+ while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) {
|
|
+ Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn));
|
|
+
|
|
+ lastzipfn = G.zipfn;
|
|
+
|
|
+ /* print a blank line between the output of different zipfiles */
|
|
+ if (!uO.qflag && error != PK_NOZIP && error != IZ_DIR
|
|
+#ifdef TIMESTAMP
|
|
+ && (!uO.T_flag || uO.zipinfo_mode)
|
|
+#endif
|
|
+ && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)
|
|
+ (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
|
|
+
|
|
+ if ((error = do_seekable(__G__ 0)) == PK_WARN)
|
|
+ ++NumWarnFiles;
|
|
+ else if (error == IZ_DIR)
|
|
+ ++NumMissDirs;
|
|
+ else if (error == PK_NOZIP)
|
|
+ ++NumMissFiles;
|
|
+ else if (error != PK_OK)
|
|
+ ++NumLoseFiles;
|
|
+ else
|
|
+ ++NumWinFiles;
|
|
+
|
|
+ Trace((stderr, "do_seekable(0) returns %d\n", error));
|
|
+ if (error != IZ_DIR && error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+#ifdef WINDLL
|
|
+ if (error == IZ_CTRLC) {
|
|
+ free_G_buffers(__G);
|
|
+ return error;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ } /* end while-loop (wildcard zipfiles) */
|
|
+
|
|
+ if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0 &&
|
|
+ (NumMissDirs + NumMissFiles) == 1 && lastzipfn != (char *)NULL)
|
|
+ {
|
|
+#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */
|
|
+ if (iswild(G.wildzipfn)) {
|
|
+ if (iswild(lastzipfn)) {
|
|
+ NumMissDirs = NumMissFiles = 0;
|
|
+ error_in_archive = PK_COOL;
|
|
+ if (uO.qflag < 3)
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CannotFindWildcardMatch),
|
|
+ LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),
|
|
+ G.wildzipfn));
|
|
+ }
|
|
+ } else
|
|
+#endif
|
|
+ {
|
|
+#ifndef VMS
|
|
+ /* 2004-11-24 SMS.
|
|
+ * VMS has already tried a default file type of ".zip" in
|
|
+ * do_wild(), so adding ZSUFX here only causes confusion by
|
|
+ * corrupting some valid (though nonexistent) file names.
|
|
+ * Complaining below about "fred;4.zip" is unlikely to be
|
|
+ * helpful to the victim.
|
|
+ */
|
|
+ /* 2005-08-14 Chr. Spieler
|
|
+ * Although we already "know" the failure result, we call
|
|
+ * do_seekable() again with the same zipfile name (and the
|
|
+ * lastchance flag set), just to trigger the error report...
|
|
+ */
|
|
+#if defined(UNIX) || defined(QDOS)
|
|
+ char *p =
|
|
+#endif
|
|
+ strcpy(lastzipfn + strlen(lastzipfn), ZSUFX);
|
|
+#endif /* !VMS */
|
|
+
|
|
+ G.zipfn = lastzipfn;
|
|
+
|
|
+ NumMissDirs = NumMissFiles = 0;
|
|
+ error_in_archive = PK_COOL;
|
|
+
|
|
+#if defined(UNIX) || defined(QDOS)
|
|
+ /* only Unix has case-sensitive filesystems */
|
|
+ /* Well FlexOS (sometimes) also has them, but support is per media */
|
|
+ /* and a pig to code for, so treat as case insensitive for now */
|
|
+ /* we do this under QDOS to check for .zip as well as _zip */
|
|
+ if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) {
|
|
+ if (error == IZ_DIR)
|
|
+ ++NumMissDirs;
|
|
+ strcpy(p, ALT_ZSUFX);
|
|
+ error = do_seekable(__G__ 1);
|
|
+ }
|
|
+#else
|
|
+ error = do_seekable(__G__ 1);
|
|
+#endif
|
|
+ Trace((stderr, "do_seekable(1) returns %d\n", error));
|
|
+ switch (error) {
|
|
+ case PK_WARN:
|
|
+ ++NumWarnFiles;
|
|
+ break;
|
|
+ case IZ_DIR:
|
|
+ ++NumMissDirs;
|
|
+ error = PK_NOZIP;
|
|
+ break;
|
|
+ case PK_NOZIP:
|
|
+ /* increment again => bug:
|
|
+ "1 file had no zipfile directory." */
|
|
+ /* ++NumMissFiles */ ;
|
|
+ break;
|
|
+ default:
|
|
+ if (error)
|
|
+ ++NumLoseFiles;
|
|
+ else
|
|
+ ++NumWinFiles;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (error > error_in_archive)
|
|
+ error_in_archive = error;
|
|
+#ifdef WINDLL
|
|
+ if (error == IZ_CTRLC) {
|
|
+ free_G_buffers(__G);
|
|
+ return error;
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
+#endif /* ?SFX */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Print summary of all zipfiles, assuming zipfile spec was a wildcard (no
|
|
+ need for a summary if just one zipfile).
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifndef SFX
|
|
+ if (iswild(G.wildzipfn) && uO.qflag < 3
|
|
+#ifdef TIMESTAMP
|
|
+ && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag > 1)
|
|
+#endif
|
|
+ )
|
|
+ {
|
|
+ if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)
|
|
+#ifdef TIMESTAMP
|
|
+ && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag)
|
|
+#endif
|
|
+ && !(uO.tflag && uO.qflag > 1))
|
|
+ (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401);
|
|
+ if ((NumWinFiles > 1) ||
|
|
+ (NumWinFiles == 1 &&
|
|
+ NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK),
|
|
+ NumWinFiles, (NumWinFiles == 1)? " was" : "s were"));
|
|
+ if (NumWarnFiles > 0)
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning),
|
|
+ NumWarnFiles, (NumWarnFiles == 1)? "" : "s"));
|
|
+ if (NumLoseFiles > 0)
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError),
|
|
+ NumLoseFiles, (NumLoseFiles == 1)? "" : "s"));
|
|
+ if (NumMissFiles > 0)
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(FileHadNoZipfileDir), NumMissFiles,
|
|
+ (NumMissFiles == 1)? "" : "s"));
|
|
+ if (NumMissDirs == 1)
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir)));
|
|
+ else if (NumMissDirs > 0)
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(ManyZipfilesWereDir), NumMissDirs));
|
|
+ if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound)));
|
|
+ }
|
|
+#endif /* !SFX */
|
|
+
|
|
+ /* free allocated memory */
|
|
+ free_G_buffers(__G);
|
|
+
|
|
+ return error_in_archive;
|
|
+
|
|
+} /* end function process_zipfiles() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*****************************/
|
|
+/* Function free_G_buffers() */
|
|
+/*****************************/
|
|
+
|
|
+void free_G_buffers(__G) /* releases all memory allocated in global vars */
|
|
+ __GDEF
|
|
+{
|
|
+#ifndef SFX
|
|
+ unsigned i;
|
|
+#endif
|
|
+
|
|
+#ifdef SYSTEM_SPECIFIC_DTOR
|
|
+ SYSTEM_SPECIFIC_DTOR(__G);
|
|
+#endif
|
|
+
|
|
+ inflate_free(__G);
|
|
+ checkdir(__G__ (char *)NULL, END);
|
|
+
|
|
+#ifdef DYNALLOC_CRCTAB
|
|
+ if (CRC_32_TAB) {
|
|
+ free_crc_table();
|
|
+ CRC_32_TAB = NULL;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ if (G.key != (char *)NULL) {
|
|
+ free(G.key);
|
|
+ G.key = (char *)NULL;
|
|
+ }
|
|
+
|
|
+ if (G.extra_field != (uch *)NULL) {
|
|
+ free(G.extra_field);
|
|
+ G.extra_field = (uch *)NULL;
|
|
+ }
|
|
+
|
|
+#if (!defined(VMS) && !defined(SMALL_MEM))
|
|
+ /* VMS uses its own buffer scheme for textmode flush() */
|
|
+ if (G.outbuf2) {
|
|
+ free(G.outbuf2); /* malloc'd ONLY if unshrink and -a */
|
|
+ G.outbuf2 = (uch *)NULL;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ if (G.outbuf)
|
|
+ free(G.outbuf);
|
|
+ if (G.inbuf)
|
|
+ free(G.inbuf);
|
|
+ G.inbuf = G.outbuf = (uch *)NULL;
|
|
+
|
|
+#ifdef UNICODE_SUPPORT
|
|
+ if (G.filename_full) {
|
|
+ free(G.filename_full);
|
|
+ G.filename_full = (char *)NULL;
|
|
+ G.fnfull_bufsize = 0;
|
|
+ }
|
|
+#endif /* UNICODE_SUPPORT */
|
|
+
|
|
+#ifndef SFX
|
|
+ for (i = 0; i < DIR_BLKSIZ; i++) {
|
|
+ if (G.info[i].cfilname != (char Far *)NULL) {
|
|
+ zffree(G.info[i].cfilname);
|
|
+ G.info[i].cfilname = (char Far *)NULL;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
+#ifdef MALLOC_WORK
|
|
+ if (G.area.Slide) {
|
|
+ free(G.area.Slide);
|
|
+ G.area.Slide = (uch *)NULL;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+} /* end function free_G_buffers() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/**************************/
|
|
+/* Function do_seekable() */
|
|
+/**************************/
|
|
+
|
|
+static int do_seekable(__G__ lastchance) /* return PK-type error code */
|
|
+ __GDEF
|
|
+ int lastchance;
|
|
+{
|
|
+#ifndef SFX
|
|
+ /* static int no_ecrec = FALSE; SKM: moved to globals.h */
|
|
+ int maybe_exe=FALSE;
|
|
+ int too_weird_to_continue=FALSE;
|
|
+#ifdef TIMESTAMP
|
|
+ time_t uxstamp;
|
|
+ ulg nmember = 0L;
|
|
+#endif
|
|
+#endif
|
|
+ int error=0, error_in_archive;
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Open the zipfile for reading in BINARY mode to prevent CR/LF translation,
|
|
+ which would corrupt the bit streams.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (SSTAT(G.zipfn, &G.statbuf) ||
|
|
+#ifdef THEOS
|
|
+ (error = S_ISLIB(G.statbuf.st_mode)) != 0 ||
|
|
+#endif
|
|
+ (error = S_ISDIR(G.statbuf.st_mode)) != 0)
|
|
+ {
|
|
+#ifndef SFX
|
|
+ if (lastchance && (uO.qflag < 3)) {
|
|
+#if defined(UNIX) || defined(QDOS)
|
|
+ if (G.no_ecrec)
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(CannotFindZipfileDirMsg),
|
|
+ LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),
|
|
+ G.wildzipfn, uO.zipinfo_mode? " " : "", G.wildzipfn,
|
|
+ G.zipfn));
|
|
+ else
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ LoadFarString(CannotFindEitherZipfile),
|
|
+ LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),
|
|
+ G.wildzipfn, G.wildzipfn, G.zipfn));
|
|
+#else /* !(UNIX || QDOS) */
|
|
+ if (G.no_ecrec)
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CannotFindZipfileDirMsg),
|
|
+ LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),
|
|
+ G.wildzipfn, uO.zipinfo_mode? " " : "", G.zipfn));
|
|
+ else
|
|
+#ifdef VMS
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CannotFindEitherZipfile),
|
|
+ LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),
|
|
+ G.wildzipfn,
|
|
+ (*G.zipfn ? G.zipfn : vms_msg_text())));
|
|
+#else /* !VMS */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CannotFindEitherZipfile),
|
|
+ LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),
|
|
+ G.wildzipfn, G.zipfn));
|
|
+#endif /* ?VMS */
|
|
+#endif /* ?(UNIX || QDOS) */
|
|
+ }
|
|
+#endif /* !SFX */
|
|
+ return error? IZ_DIR : PK_NOZIP;
|
|
+ }
|
|
+ G.ziplen = G.statbuf.st_size;
|
|
+
|
|
+#ifndef SFX
|
|
+#if defined(UNIX) || defined(DOS_OS2_W32) || defined(THEOS)
|
|
+ if (G.statbuf.st_mode & S_IEXEC) /* no extension on Unix exes: might */
|
|
+ maybe_exe = TRUE; /* find unzip, not unzip.zip; etc. */
|
|
+#endif
|
|
+#endif /* !SFX */
|
|
+
|
|
+#ifdef VMS
|
|
+ if (check_format(__G)) /* check for variable-length format */
|
|
+ return PK_ERR;
|
|
+#endif
|
|
+
|
|
+ if (open_input_file(__G)) /* this should never happen, given */
|
|
+ return PK_NOZIP; /* the stat() test above, but... */
|
|
+
|
|
+#ifdef DO_SAFECHECK_2GB
|
|
+ /* Need more care: Do not trust the size returned by stat() but
|
|
+ determine it by reading beyond the end of the file. */
|
|
+ G.ziplen = file_size(G.zipfd);
|
|
+
|
|
+ if (G.ziplen == EOF) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileTooBig)));
|
|
+ /*
|
|
+ printf(
|
|
+" We need a better error message for: 64-bit file, 32-bit program.\n");
|
|
+ */
|
|
+ CLOSE_INFILE();
|
|
+ return IZ_ERRBF;
|
|
+ }
|
|
+#endif /* DO_SAFECHECK_2GB */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Find and process the end-of-central-directory header. UnZip need only
|
|
+ check last 65557 bytes of zipfile: comment may be up to 65535, end-of-
|
|
+ central-directory record is 18 bytes, and signature itself is 4 bytes;
|
|
+ add some to allow for appended garbage. Since ZipInfo is often used as
|
|
+ a debugging tool, search the whole zipfile if zipinfo_mode is true.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ G.cur_zipfile_bufstart = 0;
|
|
+ G.inptr = G.inbuf;
|
|
+
|
|
+#if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO))
|
|
+# if (!defined(WINDLL) && !defined(SFX))
|
|
+ if ( (!uO.zipinfo_mode && !uO.qflag
|
|
+# ifdef TIMESTAMP
|
|
+ && !uO.T_flag
|
|
+# endif
|
|
+ )
|
|
+# ifndef NO_ZIPINFO
|
|
+ || (uO.zipinfo_mode && uO.hflag)
|
|
+# endif
|
|
+ )
|
|
+# else /* not (!WINDLL && !SFX) ==> !NO_ZIPINFO !! */
|
|
+ if (uO.zipinfo_mode && uO.hflag)
|
|
+# endif /* if..else..: (!WINDLL && !SFX) */
|
|
+# ifdef WIN32 /* Win32 console may require codepage conversion for G.zipfn */
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(LogInitline),
|
|
+ FnFilter1(G.zipfn)));
|
|
+# else
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(LogInitline), G.zipfn));
|
|
+# endif
|
|
+#endif /* (!WINDLL && !SFX) || !NO_ZIPINFO */
|
|
+
|
|
+ if ( (error_in_archive = find_ecrec(__G__
|
|
+#ifndef NO_ZIPINFO
|
|
+ uO.zipinfo_mode ? G.ziplen :
|
|
+#endif
|
|
+ MIN(G.ziplen, 66000L)))
|
|
+ > PK_WARN )
|
|
+ {
|
|
+ CLOSE_INFILE();
|
|
+
|
|
+#ifdef SFX
|
|
+ ++lastchance; /* avoid picky compiler warnings */
|
|
+ return error_in_archive;
|
|
+#else
|
|
+ if (maybe_exe)
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe),
|
|
+ G.zipfn));
|
|
+ if (lastchance)
|
|
+ return error_in_archive;
|
|
+ else {
|
|
+ G.no_ecrec = TRUE; /* assume we found wrong file: e.g., */
|
|
+ return PK_NOZIP; /* unzip instead of unzip.zip */
|
|
+ }
|
|
+#endif /* ?SFX */
|
|
+ }
|
|
+
|
|
+ if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */
|
|
+ CLOSE_INFILE();
|
|
+ return error_in_archive;
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Test the end-of-central-directory info for incompatibilities (multi-disk
|
|
+ archives) or inconsistencies (missing or extra bytes in zipfile).
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef NO_MULTIPART
|
|
+ error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) &&
|
|
+ (G.ecrec.num_disk_start_cdir == 1);
|
|
+#else
|
|
+ error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0);
|
|
+#endif
|
|
+
|
|
+#ifndef SFX
|
|
+ if (uO.zipinfo_mode &&
|
|
+ G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir)
|
|
+ {
|
|
+ if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CentDirNotInZipMsg), G.zipfn,
|
|
+ (ulg)G.ecrec.number_this_disk,
|
|
+ (ulg)G.ecrec.num_disk_start_cdir));
|
|
+ error_in_archive = PK_FIND;
|
|
+ too_weird_to_continue = TRUE;
|
|
+ } else {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(EndCentDirBogus), G.zipfn,
|
|
+ (ulg)G.ecrec.number_this_disk,
|
|
+ (ulg)G.ecrec.num_disk_start_cdir));
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+#ifdef NO_MULTIPART /* concatenation of multiple parts works in some cases */
|
|
+ } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport),
|
|
+ G.zipfn));
|
|
+ error_in_archive = PK_FIND;
|
|
+ too_weird_to_continue = TRUE;
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ if (!too_weird_to_continue) { /* (relatively) normal zipfile: go for it */
|
|
+ if (error) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug),
|
|
+ G.zipfn));
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+#endif /* !SFX */
|
|
+ if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) <
|
|
+ (zoff_t)0)
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes),
|
|
+ G.zipfn, FmZofft((-G.extra_bytes), NULL, NULL)));
|
|
+ error_in_archive = PK_ERR;
|
|
+ } else if (G.extra_bytes > 0) {
|
|
+ if ((G.ecrec.offset_start_central_directory == 0) &&
|
|
+ (G.ecrec.size_central_directory != 0)) /* zip 1.5 -go bug */
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(NullCentDirOffset), G.zipfn));
|
|
+ G.ecrec.offset_start_central_directory = G.extra_bytes;
|
|
+ G.extra_bytes = 0;
|
|
+ error_in_archive = PK_ERR;
|
|
+ }
|
|
+#ifndef SFX
|
|
+ else {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(ExtraBytesAtStart), G.zipfn,
|
|
+ FmZofft(G.extra_bytes, NULL, NULL),
|
|
+ (G.extra_bytes == 1)? "":"s"));
|
|
+ error_in_archive = PK_WARN;
|
|
+ }
|
|
+#endif /* !SFX */
|
|
+ }
|
|
+
|
|
+ /*-----------------------------------------------------------------------
|
|
+ Check for empty zipfile and exit now if so.
|
|
+ -----------------------------------------------------------------------*/
|
|
+
|
|
+ if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) {
|
|
+ if (uO.zipinfo_mode)
|
|
+ Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n",
|
|
+ uO.lflag>9? "\n " : ""));
|
|
+ else
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty),
|
|
+ G.zipfn));
|
|
+ CLOSE_INFILE();
|
|
+ return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;
|
|
+ }
|
|
+
|
|
+ /*-----------------------------------------------------------------------
|
|
+ Compensate for missing or extra bytes, and seek to where the start
|
|
+ of central directory should be. If header not found, uncompensate
|
|
+ and try again (necessary for at least some Atari archives created
|
|
+ with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).
|
|
+ -----------------------------------------------------------------------*/
|
|
+
|
|
+ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
|
|
+ if (error == PK_BADERR) {
|
|
+ CLOSE_INFILE();
|
|
+ return PK_BADERR;
|
|
+ }
|
|
+#ifdef OLD_SEEK_TEST
|
|
+ if (error != PK_OK || readbuf(__G__ G.sig, 4) == 0) {
|
|
+ CLOSE_INFILE();
|
|
+ return PK_ERR; /* file may be locked, or possibly disk error(?) */
|
|
+ }
|
|
+ if (memcmp(G.sig, central_hdr_sig, 4))
|
|
+#else
|
|
+ if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) ||
|
|
+ memcmp(G.sig, central_hdr_sig, 4))
|
|
+#endif
|
|
+ {
|
|
+#ifndef SFX
|
|
+ zoff_t tmp = G.extra_bytes;
|
|
+#endif
|
|
+
|
|
+ G.extra_bytes = 0;
|
|
+ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
|
|
+ if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) ||
|
|
+ memcmp(G.sig, central_hdr_sig, 4))
|
|
+ {
|
|
+ if (error != PK_BADERR)
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CentDirStartNotFound), G.zipfn,
|
|
+ LoadFarStringSmall(ReportMsg)));
|
|
+ CLOSE_INFILE();
|
|
+ return (error != PK_OK ? error : PK_BADERR);
|
|
+ }
|
|
+#ifndef SFX
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong),
|
|
+ G.zipfn, FmZofft((-tmp), NULL, NULL)));
|
|
+#endif
|
|
+ error_in_archive = PK_ERR;
|
|
+ }
|
|
+
|
|
+ /*-----------------------------------------------------------------------
|
|
+ Seek to the start of the central directory one last time, since we
|
|
+ have just read the first entry's signature bytes; then list, extract
|
|
+ or test member files as instructed, and close the zipfile.
|
|
+ -----------------------------------------------------------------------*/
|
|
+
|
|
+ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
|
|
+ if (error != PK_OK) {
|
|
+ CLOSE_INFILE();
|
|
+ return error;
|
|
+ }
|
|
+
|
|
+ Trace((stderr, "about to extract/list files (error = %d)\n",
|
|
+ error_in_archive));
|
|
+
|
|
+#ifdef DLL
|
|
+ /* G.fValidate is used only to look at an archive to see if
|
|
+ it appears to be a valid archive. There is no interest
|
|
+ in what the archive contains, nor in validating that the
|
|
+ entries in the archive are in good condition. This is
|
|
+ currently used only in the Windows DLLs for purposes of
|
|
+ checking archives within an archive to determine whether
|
|
+ or not to display the inner archives.
|
|
+ */
|
|
+ if (!G.fValidate)
|
|
+#endif
|
|
+ {
|
|
+#ifndef NO_ZIPINFO
|
|
+ if (uO.zipinfo_mode)
|
|
+ error = zipinfo(__G); /* ZIPINFO 'EM */
|
|
+ else
|
|
+#endif
|
|
+#ifndef SFX
|
|
+#ifdef TIMESTAMP
|
|
+ if (uO.T_flag)
|
|
+ error = get_time_stamp(__G__ &uxstamp, &nmember);
|
|
+ else
|
|
+#endif
|
|
+ if (uO.vflag && !uO.tflag && !uO.cflag)
|
|
+ error = list_files(__G); /* LIST 'EM */
|
|
+ else
|
|
+#endif /* !SFX */
|
|
+ error = extract_or_test_files(__G); /* EXTRACT OR TEST 'EM */
|
|
+
|
|
+ Trace((stderr, "done with extract/list files (error = %d)\n",
|
|
+ error));
|
|
+ }
|
|
+
|
|
+ if (error > error_in_archive) /* don't overwrite stronger error */
|
|
+ error_in_archive = error; /* with (for example) a warning */
|
|
+#ifndef SFX
|
|
+ } /* end if (!too_weird_to_continue) */
|
|
+#endif
|
|
+
|
|
+ CLOSE_INFILE();
|
|
+
|
|
+#ifdef TIMESTAMP
|
|
+ if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0L)) {
|
|
+# ifdef WIN32
|
|
+ if (stamp_file(__G__ G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */
|
|
+# else
|
|
+ if (stamp_file(G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */
|
|
+# endif
|
|
+ if (uO.qflag < 3)
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ LoadFarString(ZipTimeStampFailed), G.zipfn));
|
|
+ if (error_in_archive < PK_WARN)
|
|
+ error_in_archive = PK_WARN;
|
|
+ } else {
|
|
+ if (!uO.qflag)
|
|
+ Info(slide, 0, ((char *)slide,
|
|
+ LoadFarString(ZipTimeStampSuccess), G.zipfn));
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+ return error_in_archive;
|
|
+
|
|
+} /* end function do_seekable() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifdef DO_SAFECHECK_2GB
|
|
+/************************/
|
|
+/* Function file_size() */
|
|
+/************************/
|
|
+/* File size determination which does not mislead for large files in a
|
|
+ small-file program. Probably should be somewhere else.
|
|
+ The file has to be opened previously
|
|
+*/
|
|
+#ifdef USE_STRM_INPUT
|
|
+static zoff_t file_size(file)
|
|
+ FILE *file;
|
|
+{
|
|
+ int sts;
|
|
+ size_t siz;
|
|
+#else /* !USE_STRM_INPUT */
|
|
+static zoff_t file_size(fh)
|
|
+ int fh;
|
|
+{
|
|
+ int siz;
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+ zoff_t ofs;
|
|
+ char waste[4];
|
|
+
|
|
+#ifdef USE_STRM_INPUT
|
|
+ /* Seek to actual EOF. */
|
|
+ sts = zfseeko(file, 0, SEEK_END);
|
|
+ if (sts != 0) {
|
|
+ /* fseeko() failed. (Unlikely.) */
|
|
+ ofs = EOF;
|
|
+ } else {
|
|
+ /* Get apparent offset at EOF. */
|
|
+ ofs = zftello(file);
|
|
+ if (ofs < 0) {
|
|
+ /* Offset negative (overflow). File too big. */
|
|
+ ofs = EOF;
|
|
+ } else {
|
|
+ /* Seek to apparent EOF offset.
|
|
+ Won't be at actual EOF if offset was truncated.
|
|
+ */
|
|
+ sts = zfseeko(file, ofs, SEEK_SET);
|
|
+ if (sts != 0) {
|
|
+ /* fseeko() failed. (Unlikely.) */
|
|
+ ofs = EOF;
|
|
+ } else {
|
|
+ /* Read a byte at apparent EOF. Should set EOF flag. */
|
|
+ siz = fread(waste, 1, 1, file);
|
|
+ if (feof(file) == 0) {
|
|
+ /* Not at EOF, but should be. File too big. */
|
|
+ ofs = EOF;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ /* Seek to actual EOF. */
|
|
+ ofs = zlseek(fh, 0, SEEK_END);
|
|
+ if (ofs == (zoff_t) -1) {
|
|
+ /* zlseek() failed. (Unlikely.) */
|
|
+ ofs = EOF;
|
|
+ } else if (ofs < 0) {
|
|
+ /* Offset negative (overflow). File too big. */
|
|
+ ofs = EOF;
|
|
+ } else {
|
|
+ /* Seek to apparent EOF offset.
|
|
+ Won't be at actual EOF if offset was truncated.
|
|
+ */
|
|
+ ofs = zlseek(fh, ofs, SEEK_SET);
|
|
+ if (ofs == (zoff_t) -1) {
|
|
+ /* zlseek() failed. (Unlikely.) */
|
|
+ ofs = EOF;
|
|
+ } else {
|
|
+ /* Read a byte at apparent EOF. Should set EOF flag. */
|
|
+ siz = read(fh, waste, 1);
|
|
+ if (siz != 0) {
|
|
+ /* Not at EOF, but should be. File too big. */
|
|
+ ofs = EOF;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+ return ofs;
|
|
+} /* end function file_size() */
|
|
+#endif /* DO_SAFECHECK_2GB */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/***********************/
|
|
+/* Function rec_find() */
|
|
+/***********************/
|
|
+
|
|
+static int rec_find(__G__ searchlen, signature, rec_size)
|
|
+ /* return 0 when rec found, 1 when not found, 2 in case of read error */
|
|
+ __GDEF
|
|
+ zoff_t searchlen;
|
|
+ char* signature;
|
|
+ int rec_size;
|
|
+{
|
|
+ int i, numblks, found=FALSE;
|
|
+ zoff_t tail_len;
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Zipfile is longer than INBUFSIZ: may need to loop. Start with short
|
|
+ block at end of zipfile (if not TOO short).
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if ((tail_len = G.ziplen % INBUFSIZ) > rec_size) {
|
|
+#ifdef USE_STRM_INPUT
|
|
+ zfseeko(G.zipfd, G.ziplen-tail_len, SEEK_SET);
|
|
+ G.cur_zipfile_bufstart = zftello(G.zipfd);
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ G.cur_zipfile_bufstart = zlseek(G.zipfd, G.ziplen-tail_len, SEEK_SET);
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+ if ((G.incnt = read(G.zipfd, (char *)G.inbuf,
|
|
+ (unsigned int)tail_len)) != (int)tail_len)
|
|
+ return 2; /* it's expedient... */
|
|
+
|
|
+ /* 'P' must be at least (rec_size+4) bytes from end of zipfile */
|
|
+ for (G.inptr = G.inbuf+(int)tail_len-(rec_size+4);
|
|
+ G.inptr >= G.inbuf;
|
|
+ --G.inptr) {
|
|
+ if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */
|
|
+ !memcmp((char *)G.inptr, signature, 4) ) {
|
|
+ G.incnt -= (int)(G.inptr - G.inbuf);
|
|
+ found = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ /* sig may span block boundary: */
|
|
+ memcpy((char *)G.hold, (char *)G.inbuf, 3);
|
|
+ } else
|
|
+ G.cur_zipfile_bufstart = G.ziplen - tail_len;
|
|
+
|
|
+/*-----------------------------------------------------------------------
|
|
+ Loop through blocks of zipfile data, starting at the end and going
|
|
+ toward the beginning. In general, need not check whole zipfile for
|
|
+ signature, but may want to do so if testing.
|
|
+ -----------------------------------------------------------------------*/
|
|
+
|
|
+ numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
|
|
+ /* ==amount= ==done== ==rounding== =blksiz= */
|
|
+
|
|
+ for (i = 1; !found && (i <= numblks); ++i) {
|
|
+ G.cur_zipfile_bufstart -= INBUFSIZ;
|
|
+#ifdef USE_STRM_INPUT
|
|
+ zfseeko(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ zlseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ))
|
|
+ != INBUFSIZ)
|
|
+ return 2; /* read error is fatal failure */
|
|
+
|
|
+ for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf; --G.inptr)
|
|
+ if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */
|
|
+ !memcmp((char *)G.inptr, signature, 4) ) {
|
|
+ G.incnt -= (int)(G.inptr - G.inbuf);
|
|
+ found = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ /* sig may span block boundary: */
|
|
+ memcpy((char *)G.hold, (char *)G.inbuf, 3);
|
|
+ }
|
|
+ return (found ? 0 : 1);
|
|
+} /* end function rec_find() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#if 0
|
|
+/********************************/
|
|
+/* Function check_ecrec_zip64() */
|
|
+/********************************/
|
|
+
|
|
+static int check_ecrec_zip64(__G)
|
|
+ __GDEF
|
|
+{
|
|
+ return G.ecrec.offset_start_central_directory == 0xFFFFFFFFL
|
|
+ || G.ecrec.size_central_directory == 0xFFFFFFFFL
|
|
+ || G.ecrec.total_entries_central_dir == 0xFFFF
|
|
+ || G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF
|
|
+ || G.ecrec.num_disk_start_cdir == 0xFFFF
|
|
+ || G.ecrec.number_this_disk == 0xFFFF;
|
|
+} /* end function check_ecrec_zip64() */
|
|
+#endif /* never */
|
|
+
|
|
+
|
|
+
|
|
+/***************************/
|
|
+/* Function find_ecrec64() */
|
|
+/***************************/
|
|
+
|
|
+static int find_ecrec64(__G__ searchlen) /* return PK-class error */
|
|
+ __GDEF
|
|
+ zoff_t searchlen;
|
|
+{
|
|
+ ec_byte_rec64 byterec; /* buf for ecrec64 */
|
|
+ ec_byte_loc64 byterecL; /* buf for ecrec64 locator */
|
|
+ zoff_t ecloc64_start_offset; /* start offset of ecrec64 locator */
|
|
+ zusz_t ecrec64_start_offset; /* start offset of ecrec64 */
|
|
+ zuvl_t ecrec64_start_disk; /* start disk of ecrec64 */
|
|
+ zuvl_t ecloc64_total_disks; /* total disks */
|
|
+ zuvl_t ecrec64_disk_cdstart; /* disk number of central dir start */
|
|
+ zucn_t ecrec64_this_entries; /* entries on disk with ecrec64 */
|
|
+ zucn_t ecrec64_tot_entries; /* total number of entries */
|
|
+ zusz_t ecrec64_cdirsize; /* length of central dir */
|
|
+ zusz_t ecrec64_offs_cdstart; /* offset of central dir start */
|
|
+
|
|
+ /* First, find the ecrec64 locator. By definition, this must be before
|
|
+ ecrec with nothing in between. We back up the size of the ecrec64
|
|
+ locator and check. */
|
|
+
|
|
+ ecloc64_start_offset = G.real_ecrec_offset - (ECLOC64_SIZE+4);
|
|
+ if (ecloc64_start_offset < 0)
|
|
+ /* Seeking would go past beginning, so probably empty archive */
|
|
+ return PK_COOL;
|
|
+
|
|
+#ifdef USE_STRM_INPUT
|
|
+ zfseeko(G.zipfd, ecloc64_start_offset, SEEK_SET);
|
|
+ G.cur_zipfile_bufstart = zftello(G.zipfd);
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecloc64_start_offset, SEEK_SET);
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+
|
|
+ if ((G.incnt = read(G.zipfd, (char *)byterecL, ECLOC64_SIZE+4))
|
|
+ != (ECLOC64_SIZE+4)) {
|
|
+ if (uO.qflag || uO.zipinfo_mode)
|
|
+ Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(Cent64EndSigSearchErr)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
+
|
|
+ if (memcmp((char *)byterecL, end_centloc64_sig, 4) ) {
|
|
+ /* not found */
|
|
+ return PK_COOL;
|
|
+ }
|
|
+
|
|
+ /* Read the locator. */
|
|
+ ecrec64_start_disk = (zuvl_t)makelong(&byterecL[NUM_DISK_START_EOCDR64]);
|
|
+ ecrec64_start_offset = (zusz_t)makeint64(&byterecL[OFFSET_START_EOCDR64]);
|
|
+ ecloc64_total_disks = (zuvl_t)makelong(&byterecL[NUM_THIS_DISK_LOC64]);
|
|
+
|
|
+ /* Check for consistency */
|
|
+#ifdef TEST
|
|
+ fprintf(stdout,"\nnumber of disks (ECR) %u, (ECLOC64) %lu\n",
|
|
+ G.ecrec.number_this_disk, ecloc64_total_disks); fflush(stdout);
|
|
+#endif
|
|
+ if ((G.ecrec.number_this_disk != 0xFFFF) &&
|
|
+ (G.ecrec.number_this_disk != ecloc64_total_disks - 1)) {
|
|
+ /* Note: For some unknown reason, the developers at PKWARE decided to
|
|
+ store the "zip64 total disks" value as a counter starting from 1,
|
|
+ whereas all other "split/span volume" related fields use 0-based
|
|
+ volume numbers. Sigh... */
|
|
+ /* When the total number of disks as found in the traditional ecrec
|
|
+ is not 0xFFFF, the disk numbers in ecrec and ecloc64 must match.
|
|
+ When this is not the case, the found ecrec64 locator cannot be valid.
|
|
+ -> This is not a Zip64 archive.
|
|
+ */
|
|
+ Trace((stderr,
|
|
+ "\ninvalid ECLOC64, differing disk# (ECR %u, ECL64 %lu)\n",
|
|
+ G.ecrec.number_this_disk, ecloc64_total_disks - 1));
|
|
+ return PK_COOL;
|
|
+ }
|
|
+
|
|
+ /* If found locator, look for ecrec64 where the locator says it is. */
|
|
+
|
|
+ /* For now assume that ecrec64 is on the same disk as ecloc64 and ecrec,
|
|
+ which is usually the case and is how Zip writes it. To do this right,
|
|
+ however, we should allow the ecrec64 to be on another disk since
|
|
+ the AppNote allows it and the ecrec64 can be large, especially if
|
|
+ Version 2 is used (AppNote uses 8 bytes for the size of this record). */
|
|
+
|
|
+ /* FIX BELOW IF ADD SUPPORT FOR MULTIPLE DISKS */
|
|
+
|
|
+ if (ecrec64_start_offset > (zusz_t)ecloc64_start_offset) {
|
|
+ /* ecrec64 has to be before ecrec64 locator */
|
|
+ if (uO.qflag || uO.zipinfo_mode)
|
|
+ Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(Cent64EndSigSearchErr)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
+
|
|
+#ifdef USE_STRM_INPUT
|
|
+ zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET);
|
|
+ G.cur_zipfile_bufstart = zftello(G.zipfd);
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET);
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+
|
|
+ if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4))
|
|
+ != (ECREC64_SIZE+4)) {
|
|
+ if (uO.qflag || uO.zipinfo_mode)
|
|
+ Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(Cent64EndSigSearchErr)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
+
|
|
+ if (memcmp((char *)byterec, end_central64_sig, 4) ) {
|
|
+ /* Zip64 EOCD Record not found */
|
|
+ /* Since we already have seen the Zip64 EOCD Locator, it's
|
|
+ possible we got here because there are bytes prepended
|
|
+ to the archive, like the sfx prefix. */
|
|
+
|
|
+ /* Make a guess as to where the Zip64 EOCD Record might be */
|
|
+ ecrec64_start_offset = ecloc64_start_offset - ECREC64_SIZE - 4;
|
|
+
|
|
+#ifdef USE_STRM_INPUT
|
|
+ zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET);
|
|
+ G.cur_zipfile_bufstart = zftello(G.zipfd);
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET);
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+
|
|
+ if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4))
|
|
+ != (ECREC64_SIZE+4)) {
|
|
+ if (uO.qflag || uO.zipinfo_mode)
|
|
+ Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(Cent64EndSigSearchErr)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
+
|
|
+ if (memcmp((char *)byterec, end_central64_sig, 4) ) {
|
|
+ /* Zip64 EOCD Record not found */
|
|
+ /* Probably something not so easy to handle so exit */
|
|
+ if (uO.qflag || uO.zipinfo_mode)
|
|
+ Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(Cent64EndSigSearchErr)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
+
|
|
+ if (uO.qflag || uO.zipinfo_mode)
|
|
+ Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(Cent64EndSigSearchOff)));
|
|
+ }
|
|
+
|
|
+ /* Check consistency of found ecrec64 with ecloc64 (and ecrec): */
|
|
+ if ( (zuvl_t)makelong(&byterec[NUMBER_THIS_DSK_REC64])
|
|
+ != ecrec64_start_disk )
|
|
+ /* found ecrec64 does not match ecloc64 info -> no Zip64 archive */
|
|
+ return PK_COOL;
|
|
+ /* Read all relevant ecrec64 fields and compare them to the corresponding
|
|
+ ecrec fields unless those are set to "all-ones".
|
|
+ */
|
|
+ ecrec64_disk_cdstart =
|
|
+ (zuvl_t)makelong(&byterec[NUM_DISK_START_CEN_DIR64]);
|
|
+ if ( (G.ecrec.num_disk_start_cdir != 0xFFFF) &&
|
|
+ (G.ecrec.num_disk_start_cdir != ecrec64_disk_cdstart) )
|
|
+ return PK_COOL;
|
|
+ ecrec64_this_entries
|
|
+ = makeint64(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK64]);
|
|
+ if ( (G.ecrec.num_entries_centrl_dir_ths_disk != 0xFFFF) &&
|
|
+ (G.ecrec.num_entries_centrl_dir_ths_disk != ecrec64_this_entries) )
|
|
+ return PK_COOL;
|
|
+ ecrec64_tot_entries
|
|
+ = makeint64(&byterec[TOTAL_ENTRIES_CENTRAL_DIR64]);
|
|
+ if ( (G.ecrec.total_entries_central_dir != 0xFFFF) &&
|
|
+ (G.ecrec.total_entries_central_dir != ecrec64_tot_entries) )
|
|
+ return PK_COOL;
|
|
+ ecrec64_cdirsize
|
|
+ = makeint64(&byterec[SIZE_CENTRAL_DIRECTORY64]);
|
|
+ if ( (G.ecrec.size_central_directory != 0xFFFFFFFFL) &&
|
|
+ (G.ecrec.size_central_directory != ecrec64_cdirsize) )
|
|
+ return PK_COOL;
|
|
+ ecrec64_offs_cdstart
|
|
+ = makeint64(&byterec[OFFSET_START_CENTRAL_DIRECT64]);
|
|
+ if ( (G.ecrec.offset_start_central_directory != 0xFFFFFFFFL) &&
|
|
+ (G.ecrec.offset_start_central_directory != ecrec64_offs_cdstart) )
|
|
+ return PK_COOL;
|
|
+
|
|
+ /* Now, we are (almost) sure that we have a Zip64 archive. */
|
|
+ G.ecrec.have_ecr64 = 1;
|
|
+
|
|
+ /* Update the "end-of-central-dir offset" for later checks. */
|
|
+ G.real_ecrec_offset = ecrec64_start_offset;
|
|
+
|
|
+ /* Update all ecdir_rec data that are flagged to be invalid
|
|
+ in Zip64 mode. Set the ecrec64-mandatory flag when such a
|
|
+ case is found. */
|
|
+ if (G.ecrec.number_this_disk == 0xFFFF) {
|
|
+ G.ecrec.number_this_disk = ecrec64_start_disk;
|
|
+ if (ecrec64_start_disk != 0xFFFF) G.ecrec.is_zip64_archive = TRUE;
|
|
+ }
|
|
+ if (G.ecrec.num_disk_start_cdir == 0xFFFF) {
|
|
+ G.ecrec.num_disk_start_cdir = ecrec64_disk_cdstart;
|
|
+ if (ecrec64_disk_cdstart != 0xFFFF) G.ecrec.is_zip64_archive = TRUE;
|
|
+ }
|
|
+ if (G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF) {
|
|
+ G.ecrec.num_entries_centrl_dir_ths_disk = ecrec64_this_entries;
|
|
+ if (ecrec64_this_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE;
|
|
+ }
|
|
+ if (G.ecrec.total_entries_central_dir == 0xFFFF) {
|
|
+ G.ecrec.total_entries_central_dir = ecrec64_tot_entries;
|
|
+ if (ecrec64_tot_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE;
|
|
+ }
|
|
+ if (G.ecrec.size_central_directory == 0xFFFFFFFFL) {
|
|
+ G.ecrec.size_central_directory = ecrec64_cdirsize;
|
|
+ if (ecrec64_cdirsize != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE;
|
|
+ }
|
|
+ if (G.ecrec.offset_start_central_directory == 0xFFFFFFFFL) {
|
|
+ G.ecrec.offset_start_central_directory = ecrec64_offs_cdstart;
|
|
+ if (ecrec64_offs_cdstart != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE;
|
|
+ }
|
|
+
|
|
+ return PK_COOL;
|
|
+} /* end function find_ecrec64() */
|
|
+
|
|
+
|
|
+
|
|
+/*************************/
|
|
+/* Function find_ecrec() */
|
|
+/*************************/
|
|
+
|
|
+static int find_ecrec(__G__ searchlen) /* return PK-class error */
|
|
+ __GDEF
|
|
+ zoff_t searchlen;
|
|
+{
|
|
+ int found = FALSE;
|
|
+ int error_in_archive;
|
|
+ int result;
|
|
+ ec_byte_rec byterec;
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Treat case of short zipfile separately.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (G.ziplen <= INBUFSIZ) {
|
|
+#ifdef USE_STRM_INPUT
|
|
+ zfseeko(G.zipfd, 0L, SEEK_SET);
|
|
+#else /* !USE_STRM_INPUT */
|
|
+ zlseek(G.zipfd, 0L, SEEK_SET);
|
|
+#endif /* ?USE_STRM_INPUT */
|
|
+ if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen))
|
|
+ == (int)G.ziplen)
|
|
+
|
|
+ /* 'P' must be at least (ECREC_SIZE+4) bytes from end of zipfile */
|
|
+ for (G.inptr = G.inbuf+(int)G.ziplen-(ECREC_SIZE+4);
|
|
+ G.inptr >= G.inbuf;
|
|
+ --G.inptr) {
|
|
+ if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */
|
|
+ !memcmp((char *)G.inptr, end_central_sig, 4)) {
|
|
+ G.incnt -= (int)(G.inptr - G.inbuf);
|
|
+ found = TRUE;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Zipfile is longer than INBUFSIZ:
|
|
+
|
|
+ MB - this next block of code moved to rec_find so that same code can be
|
|
+ used to look for zip64 ec record. No need to include code above since
|
|
+ a zip64 ec record will only be looked for if it is a BIG file.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ } else {
|
|
+ found =
|
|
+ (rec_find(__G__ searchlen, end_central_sig, ECREC_SIZE) == 0
|
|
+ ? TRUE : FALSE);
|
|
+ } /* end if (ziplen > INBUFSIZ) */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Searched through whole region where signature should be without finding
|
|
+ it. Print informational message and die a horrible death.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (!found) {
|
|
+ if (uO.qflag || uO.zipinfo_mode)
|
|
+ Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CentDirEndSigNotFound)));
|
|
+ return PK_ERR; /* failed */
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Found the signature, so get the end-central data before returning. Do
|
|
+ any necessary machine-type conversions (byte ordering, structure padding
|
|
+ compensation) by reading data into character array and copying to struct.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf);
|
|
+#ifdef TEST
|
|
+ printf("\n found end-of-central-dir signature at offset %s (%sh)\n",
|
|
+ FmZofft(G.real_ecrec_offset, NULL, NULL),
|
|
+ FmZofft(G.real_ecrec_offset, FZOFFT_HEX_DOT_WID, "X"));
|
|
+ printf(" from beginning of file; offset %d (%.4Xh) within block\n",
|
|
+ G.inptr-G.inbuf, G.inptr-G.inbuf);
|
|
+#endif
|
|
+
|
|
+ if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0)
|
|
+ return PK_EOF;
|
|
+
|
|
+ G.ecrec.number_this_disk =
|
|
+ makeword(&byterec[NUMBER_THIS_DISK]);
|
|
+ G.ecrec.num_disk_start_cdir =
|
|
+ makeword(&byterec[NUM_DISK_WITH_START_CEN_DIR]);
|
|
+ G.ecrec.num_entries_centrl_dir_ths_disk =
|
|
+ makeword(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK]);
|
|
+ G.ecrec.total_entries_central_dir =
|
|
+ makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
|
|
+ G.ecrec.size_central_directory =
|
|
+ makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
|
|
+ G.ecrec.offset_start_central_directory =
|
|
+ makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
|
|
+ G.ecrec.zipfile_comment_length =
|
|
+ makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
|
|
+
|
|
+ /* Now, we have to read the archive comment, BEFORE the file pointer
|
|
+ is moved away backwards to seek for a Zip64 ECLOC64 structure.
|
|
+ */
|
|
+ if ( (error_in_archive = process_zip_cmmnt(__G)) > PK_WARN )
|
|
+ return error_in_archive;
|
|
+
|
|
+ /* Next: Check for existence of Zip64 end-of-cent-dir locator
|
|
+ ECLOC64. This structure must reside on the same volume as the
|
|
+ classic ECREC, at exactly (ECLOC64_SIZE+4) bytes in front
|
|
+ of the ECREC.
|
|
+ The ECLOC64 structure directs to the longer ECREC64 structure
|
|
+ A ECREC64 will ALWAYS exist for a proper Zip64 archive, as
|
|
+ the "Version Needed To Extract" field is required to be set
|
|
+ to 4.5 or higher whenever any Zip64 features are used anywhere
|
|
+ in the archive, so just check for that to see if this is a
|
|
+ Zip64 archive.
|
|
+ */
|
|
+ result = find_ecrec64(__G__ searchlen+76);
|
|
+ /* 76 bytes for zip64ec & zip64 locator */
|
|
+ if (result != PK_COOL) {
|
|
+ if (error_in_archive < result)
|
|
+ error_in_archive = result;
|
|
+ return error_in_archive;
|
|
+ }
|
|
+
|
|
+ G.expect_ecrec_offset = G.ecrec.offset_start_central_directory +
|
|
+ G.ecrec.size_central_directory;
|
|
+
|
|
+#ifndef NO_ZIPINFO
|
|
+ if (uO.zipinfo_mode) {
|
|
+ /* In ZipInfo mode, additional info about the data found in the
|
|
+ end-of-central-directory areas is printed out.
|
|
+ */
|
|
+ zi_end_central(__G);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ return error_in_archive;
|
|
+
|
|
+} /* end function find_ecrec() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/********************************/
|
|
+/* Function process_zip_cmmnt() */
|
|
+/********************************/
|
|
+
|
|
+static int process_zip_cmmnt(__G) /* return PK-type error code */
|
|
+ __GDEF
|
|
+{
|
|
+ int error = PK_COOL;
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Get the zipfile comment (up to 64KB long), if any, and print it out.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef WINDLL
|
|
+ /* for comment button: */
|
|
+ if ((!G.fValidate) && (G.lpUserFunctions != NULL))
|
|
+ G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length;
|
|
+#endif /* WINDLL */
|
|
+
|
|
+#ifndef NO_ZIPINFO
|
|
+ /* ZipInfo, verbose format */
|
|
+ if (uO.zipinfo_mode && uO.lflag > 9) {
|
|
+ /*-------------------------------------------------------------------
|
|
+ Get the zipfile comment, if any, and print it out.
|
|
+ (Comment may be up to 64KB long. May the fleas of a thousand
|
|
+ camels infest the arm-pits of anyone who actually takes advantage
|
|
+ of this fact.)
|
|
+ -------------------------------------------------------------------*/
|
|
+
|
|
+ if (!G.ecrec.zipfile_comment_length)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment)));
|
|
+ else {
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc),
|
|
+ G.ecrec.zipfile_comment_length));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin)));
|
|
+ if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY))
|
|
+ error = PK_WARN;
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd)));
|
|
+ if (error)
|
|
+ Info(slide, 0, ((char *)slide,
|
|
+ LoadFarString(ZipfileCommTrunc2)));
|
|
+ } /* endif (comment exists) */
|
|
+
|
|
+ /* ZipInfo, non-verbose mode: print zipfile comment only if requested */
|
|
+ } else if (G.ecrec.zipfile_comment_length &&
|
|
+ (uO.zflag > 0) && uO.zipinfo_mode) {
|
|
+ if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(ZipfileCommTrunc1)));
|
|
+ error = PK_WARN;
|
|
+ }
|
|
+ } else
|
|
+#endif /* !NO_ZIPINFO */
|
|
+ if ( G.ecrec.zipfile_comment_length &&
|
|
+ (uO.zflag > 0
|
|
+#ifndef WINDLL
|
|
+ || (uO.zflag == 0
|
|
+# ifndef NO_ZIPINFO
|
|
+ && !uO.zipinfo_mode
|
|
+# endif
|
|
+# ifdef TIMESTAMP
|
|
+ && !uO.T_flag
|
|
+# endif
|
|
+ && !uO.qflag)
|
|
+#endif /* !WINDLL */
|
|
+ ) )
|
|
+ {
|
|
+ if (do_string(__G__ G.ecrec.zipfile_comment_length,
|
|
+#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
|
|
+# ifndef NO_ZIPINFO
|
|
+ (oU.zipinfo_mode ? DISPLAY : CHECK_AUTORUN)
|
|
+# else
|
|
+ CHECK_AUTORUN
|
|
+# endif
|
|
+#else
|
|
+ DISPLAY
|
|
+#endif
|
|
+ ))
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(ZipfileCommTrunc1)));
|
|
+ error = PK_WARN;
|
|
+ }
|
|
+ }
|
|
+#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
|
|
+ else if (G.ecrec.zipfile_comment_length) {
|
|
+ if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN_Q))
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(ZipfileCommTrunc1)));
|
|
+ error = PK_WARN;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+ return error;
|
|
+
|
|
+} /* end function process_zip_cmmnt() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/************************************/
|
|
+/* Function process_cdir_file_hdr() */
|
|
+/************************************/
|
|
+
|
|
+int process_cdir_file_hdr(__G) /* return PK-type error code */
|
|
+ __GDEF
|
|
+{
|
|
+ int error;
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Get central directory info, save host and method numbers, and set flag
|
|
+ for lowercase conversion of filename, depending on the OS from which the
|
|
+ file is coming.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if ((error = get_cdir_ent(__G)) != 0)
|
|
+ return error;
|
|
+
|
|
+ G.pInfo->hostver = G.crec.version_made_by[0];
|
|
+ G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS);
|
|
+/* extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */
|
|
+
|
|
+ G.pInfo->lcflag = 0;
|
|
+ if (uO.L_flag == 1) /* name conversion for monocase systems */
|
|
+ switch (G.pInfo->hostnum) {
|
|
+ case FS_FAT_: /* PKZIP and zip -k store in uppercase */
|
|
+ case CPM_: /* like MS-DOS, right? */
|
|
+ case VM_CMS_: /* all caps? */
|
|
+ case MVS_: /* all caps? */
|
|
+ case TANDEM_:
|
|
+ case TOPS20_:
|
|
+ case VMS_: /* our Zip uses lowercase, but ASi's doesn't */
|
|
+ /* case Z_SYSTEM_: ? */
|
|
+ /* case QDOS_: ? */
|
|
+ G.pInfo->lcflag = 1; /* convert filename to lowercase */
|
|
+ break;
|
|
+
|
|
+ default: /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */
|
|
+ break; /* FS_VFAT_, ATHEOS_, BEOS_ (Z_SYSTEM_), THEOS_: */
|
|
+ /* no conversion */
|
|
+ }
|
|
+ else if (uO.L_flag > 1) /* let -LL force lower case for all names */
|
|
+ G.pInfo->lcflag = 1;
|
|
+
|
|
+ /* do Amigas (AMIGA_) also have volume labels? */
|
|
+ if (IS_VOLID(G.crec.external_file_attributes) &&
|
|
+ (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ ||
|
|
+ G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_))
|
|
+ {
|
|
+ G.pInfo->vollabel = TRUE;
|
|
+ G.pInfo->lcflag = 0; /* preserve case of volume labels */
|
|
+ } else
|
|
+ G.pInfo->vollabel = FALSE;
|
|
+
|
|
+ /* this flag is needed to detect archives made by "PKZIP for Unix" when
|
|
+ deciding which kind of codepage conversion has to be applied to
|
|
+ strings (see do_string() function in fileio.c) */
|
|
+ G.pInfo->HasUxAtt = (G.crec.external_file_attributes & 0xffff0000L) != 0L;
|
|
+
|
|
+#ifdef UNICODE_SUPPORT
|
|
+ /* remember the state of GPB11 (General Purpuse Bit 11) which indicates
|
|
+ that the standard path and comment are UTF-8. */
|
|
+ G.pInfo->GPFIsUTF8
|
|
+ = (G.crec.general_purpose_bit_flag & (1 << 11)) == (1 << 11);
|
|
+#endif
|
|
+
|
|
+ return PK_COOL;
|
|
+
|
|
+} /* end function process_cdir_file_hdr() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/***************************/
|
|
+/* Function get_cdir_ent() */
|
|
+/***************************/
|
|
+
|
|
+static int get_cdir_ent(__G) /* return PK-type error code */
|
|
+ __GDEF
|
|
+{
|
|
+ cdir_byte_hdr byterec;
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Read the next central directory entry and do any necessary machine-type
|
|
+ conversions (byte ordering, structure padding compensation--do so by
|
|
+ copying the data from the array into which it was read (byterec) to the
|
|
+ usable struct (crec)).
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0)
|
|
+ return PK_EOF;
|
|
+
|
|
+ G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
|
|
+ G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
|
|
+ G.crec.version_needed_to_extract[0] =
|
|
+ byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
|
|
+ G.crec.version_needed_to_extract[1] =
|
|
+ byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
|
|
+
|
|
+ G.crec.general_purpose_bit_flag =
|
|
+ makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
|
|
+ G.crec.compression_method =
|
|
+ makeword(&byterec[C_COMPRESSION_METHOD]);
|
|
+ G.crec.last_mod_dos_datetime =
|
|
+ makelong(&byterec[C_LAST_MOD_DOS_DATETIME]);
|
|
+ G.crec.crc32 =
|
|
+ makelong(&byterec[C_CRC32]);
|
|
+ G.crec.csize =
|
|
+ makelong(&byterec[C_COMPRESSED_SIZE]);
|
|
+ G.crec.ucsize =
|
|
+ makelong(&byterec[C_UNCOMPRESSED_SIZE]);
|
|
+ G.crec.filename_length =
|
|
+ makeword(&byterec[C_FILENAME_LENGTH]);
|
|
+ G.crec.extra_field_length =
|
|
+ makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
|
|
+ G.crec.file_comment_length =
|
|
+ makeword(&byterec[C_FILE_COMMENT_LENGTH]);
|
|
+ G.crec.disk_number_start =
|
|
+ makeword(&byterec[C_DISK_NUMBER_START]);
|
|
+ G.crec.internal_file_attributes =
|
|
+ makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
|
|
+ G.crec.external_file_attributes =
|
|
+ makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]); /* LONG, not word! */
|
|
+ G.crec.relative_offset_local_header =
|
|
+ makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
|
|
+
|
|
+ return PK_COOL;
|
|
+
|
|
+} /* end function get_cdir_ent() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*************************************/
|
|
+/* Function process_local_file_hdr() */
|
|
+/*************************************/
|
|
+
|
|
+int process_local_file_hdr(__G) /* return PK-type error code */
|
|
+ __GDEF
|
|
+{
|
|
+ local_byte_hdr byterec;
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Read the next local file header and do any necessary machine-type con-
|
|
+ versions (byte ordering, structure padding compensation--do so by copy-
|
|
+ ing the data from the array into which it was read (byterec) to the
|
|
+ usable struct (lrec)).
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0)
|
|
+ return PK_EOF;
|
|
+
|
|
+ G.lrec.version_needed_to_extract[0] =
|
|
+ byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
|
|
+ G.lrec.version_needed_to_extract[1] =
|
|
+ byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
|
|
+
|
|
+ G.lrec.general_purpose_bit_flag =
|
|
+ makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
|
|
+ G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
|
|
+ G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]);
|
|
+ G.lrec.crc32 = makelong(&byterec[L_CRC32]);
|
|
+ G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);
|
|
+ G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
|
|
+ G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
|
|
+ G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
|
|
+
|
|
+ if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
|
|
+ /* can't trust local header, use central directory: */
|
|
+ G.lrec.crc32 = G.pInfo->crc;
|
|
+ G.lrec.csize = G.pInfo->compr_size;
|
|
+ G.lrec.ucsize = G.pInfo->uncompr_size;
|
|
+ }
|
|
+
|
|
+ G.csize = G.lrec.csize;
|
|
+
|
|
+ return PK_COOL;
|
|
+
|
|
+} /* end function process_local_file_hdr() */
|
|
+
|
|
+
|
|
+/*******************************/
|
|
+/* Function getZip64Data() */
|
|
+/*******************************/
|
|
+
|
|
+int getZip64Data(__G__ ef_buf, ef_len)
|
|
+ __GDEF
|
|
+ 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 zip64 information, ie 8-byte
|
|
+ versions of compressed file size, uncompressed file size, relative offset
|
|
+ and a 4-byte version of disk start number.
|
|
+ Sets both local header and central header fields. Not terribly clever,
|
|
+ but it means that this procedure is only called in one place.
|
|
+
|
|
+ 2014-12-05 SMS.
|
|
+ Added checks to ensure that enough data are available before calling
|
|
+ makeint64() or makelong(). Replaced various sizeof() values with
|
|
+ simple ("4" or "8") constants. (The Zip64 structures do not depend
|
|
+ on our variable sizes.) Error handling is crude, but we should now
|
|
+ stay within the buffer.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#define Z64FLGS 0xffff
|
|
+#define Z64FLGL 0xffffffff
|
|
+
|
|
+ if (ef_len == 0 || ef_buf == NULL)
|
|
+ return PK_COOL;
|
|
+
|
|
+ Trace((stderr,"\ngetZip64Data: 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))
|
|
+ {
|
|
+ /* Extra block length exceeds remaining extra field length. */
|
|
+ Trace((stderr,
|
|
+ "getZip64Data: block length %u > rest ef_size %u\n", eb_len,
|
|
+ ef_len - EB_HEADSIZE));
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (eb_id == EF_PKSZ64)
|
|
+ {
|
|
+ int offset = EB_HEADSIZE;
|
|
+
|
|
+ if ((G.crec.ucsize == Z64FLGL) || (G.lrec.ucsize == Z64FLGL))
|
|
+ {
|
|
+ if (offset+ 8 > ef_len)
|
|
+ return PK_ERR;
|
|
+
|
|
+ G.crec.ucsize = G.lrec.ucsize = makeint64(offset + ef_buf);
|
|
+ offset += 8;
|
|
+ }
|
|
+
|
|
+ if ((G.crec.csize == Z64FLGL) || (G.lrec.csize == Z64FLGL))
|
|
+ {
|
|
+ if (offset+ 8 > ef_len)
|
|
+ return PK_ERR;
|
|
+
|
|
+ G.csize = G.crec.csize = G.lrec.csize = makeint64(offset + ef_buf);
|
|
+ offset += 8;
|
|
+ }
|
|
+
|
|
+ if (G.crec.relative_offset_local_header == Z64FLGL)
|
|
+ {
|
|
+ if (offset+ 8 > ef_len)
|
|
+ return PK_ERR;
|
|
+
|
|
+ G.crec.relative_offset_local_header = makeint64(offset + ef_buf);
|
|
+ offset += 8;
|
|
+ }
|
|
+
|
|
+ if (G.crec.disk_number_start == Z64FLGS)
|
|
+ {
|
|
+ if (offset+ 4 > ef_len)
|
|
+ return PK_ERR;
|
|
+
|
|
+ G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf);
|
|
+ offset += 4;
|
|
+ }
|
|
+#if 0
|
|
+ break; /* Expect only one EF_PKSZ64 block. */
|
|
+#endif /* 0 */
|
|
+ }
|
|
+
|
|
+ /* Skip this extra field block. */
|
|
+ ef_buf += (eb_len + EB_HEADSIZE);
|
|
+ ef_len -= (eb_len + EB_HEADSIZE);
|
|
+ }
|
|
+
|
|
+ return PK_COOL;
|
|
+} /* end function getZip64Data() */
|
|
+
|
|
+
|
|
+#ifdef UNICODE_SUPPORT
|
|
+
|
|
+/*******************************/
|
|
+/* Function getUnicodeData() */
|
|
+/*******************************/
|
|
+
|
|
+int getUnicodeData(__G__ ef_buf, ef_len)
|
|
+ __GDEF
|
|
+ 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 Unicode information, ie UTF-8
|
|
+ path extra fields.
|
|
+
|
|
+ On return, G.unipath_filename =
|
|
+ NULL, if no Unicode path extra field or error
|
|
+ "", if the standard path is UTF-8 (free when done)
|
|
+ null-terminated UTF-8 path (free when done)
|
|
+ Return PK_COOL if no error.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ G.unipath_filename = NULL;
|
|
+
|
|
+ if (ef_len == 0 || ef_buf == NULL)
|
|
+ return PK_COOL;
|
|
+
|
|
+ Trace((stderr,"\ngetUnicodeData: 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,
|
|
+ "getUnicodeData: block length %u > rest ef_size %u\n", eb_len,
|
|
+ ef_len - EB_HEADSIZE));
|
|
+ break;
|
|
+ }
|
|
+ if (eb_id == EF_UNIPATH) {
|
|
+
|
|
+ int offset = EB_HEADSIZE;
|
|
+ ush ULen = eb_len - 5;
|
|
+ ulg chksum = CRCVAL_INITIAL;
|
|
+
|
|
+ /* version */
|
|
+ G.unipath_version = (uch) *(offset + ef_buf);
|
|
+ offset += 1;
|
|
+ if (G.unipath_version > 1) {
|
|
+ /* can do only version 1 */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(UnicodeVersionError)));
|
|
+ return PK_ERR;
|
|
+ }
|
|
+
|
|
+ /* filename CRC */
|
|
+ G.unipath_checksum = makelong(offset + ef_buf);
|
|
+ offset += 4;
|
|
+
|
|
+ /*
|
|
+ * Compute 32-bit crc
|
|
+ */
|
|
+
|
|
+ chksum = crc32(chksum, (uch *)(G.filename_full),
|
|
+ strlen(G.filename_full));
|
|
+
|
|
+ /* If the checksums's don't match then likely filename has been
|
|
+ * modified and the Unicode Path is no longer valid.
|
|
+ */
|
|
+ if (chksum != G.unipath_checksum) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(UnicodeMismatchError)));
|
|
+ if (G.unicode_mismatch == 1) {
|
|
+ /* warn and continue */
|
|
+ } else if (G.unicode_mismatch == 2) {
|
|
+ /* ignore and continue */
|
|
+ } else if (G.unicode_mismatch == 0) {
|
|
+ }
|
|
+ return PK_ERR;
|
|
+ }
|
|
+
|
|
+ /* UTF-8 Path */
|
|
+ if ((G.unipath_filename = malloc(ULen + 1)) == NULL) {
|
|
+ return PK_ERR;
|
|
+ }
|
|
+ if (ULen == 0) {
|
|
+ /* standard path is UTF-8 so use that */
|
|
+ G.unipath_filename[0] = '\0';
|
|
+ } else {
|
|
+ /* UTF-8 path */
|
|
+ strncpy(G.unipath_filename,
|
|
+ (ZCONST char *)(offset + ef_buf), ULen);
|
|
+ G.unipath_filename[ULen] = '\0';
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Skip this extra field block */
|
|
+ ef_buf += (eb_len + EB_HEADSIZE);
|
|
+ ef_len -= (eb_len + EB_HEADSIZE);
|
|
+ }
|
|
+
|
|
+ return PK_COOL;
|
|
+} /* end function getUnicodeData() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifdef UNICODE_WCHAR
|
|
+ /*---------------------------------------------
|
|
+ * Unicode conversion functions
|
|
+ *
|
|
+ * Based on functions provided by Paul Kienitz
|
|
+ *
|
|
+ *---------------------------------------------
|
|
+ */
|
|
+
|
|
+/*
|
|
+ NOTES APPLICABLE TO ALL STRING FUNCTIONS:
|
|
+
|
|
+ All of the x_to_y functions take parameters for an output buffer and
|
|
+ its available length, and return an int. The value returned is the
|
|
+ length of the string that the input produces, which may be larger than
|
|
+ the provided buffer length. If the returned value is less than the
|
|
+ buffer length, then the contents of the buffer will be null-terminated;
|
|
+ otherwise, it will not be terminated and may be invalid, possibly
|
|
+ stopping in the middle of a multibyte sequence.
|
|
+
|
|
+ In all cases you may pass NULL as the buffer and/or 0 as the length, if
|
|
+ you just want to learn how much space the string is going to require.
|
|
+
|
|
+ The functions will return -1 if the input is invalid UTF-8 or cannot be
|
|
+ encoded as UTF-8.
|
|
+*/
|
|
+
|
|
+static int utf8_char_bytes OF((ZCONST char *utf8));
|
|
+static ulg ucs4_char_from_utf8 OF((ZCONST char **utf8));
|
|
+static int utf8_to_ucs4_string OF((ZCONST char *utf8, ulg *ucs4buf,
|
|
+ int buflen));
|
|
+
|
|
+/* utility functions for managing UTF-8 and UCS-4 strings */
|
|
+
|
|
+
|
|
+/* utf8_char_bytes
|
|
+ *
|
|
+ * Returns the number of bytes used by the first character in a UTF-8
|
|
+ * string, or -1 if the UTF-8 is invalid or null.
|
|
+ */
|
|
+static int utf8_char_bytes(utf8)
|
|
+ ZCONST char *utf8;
|
|
+{
|
|
+ int t, r;
|
|
+ unsigned lead;
|
|
+
|
|
+ if (!utf8)
|
|
+ return -1; /* no input */
|
|
+ lead = (unsigned char) *utf8;
|
|
+ if (lead < 0x80)
|
|
+ r = 1; /* an ascii-7 character */
|
|
+ else if (lead < 0xC0)
|
|
+ return -1; /* error: trailing byte without lead byte */
|
|
+ else if (lead < 0xE0)
|
|
+ r = 2; /* an 11 bit character */
|
|
+ else if (lead < 0xF0)
|
|
+ r = 3; /* a 16 bit character */
|
|
+ else if (lead < 0xF8)
|
|
+ r = 4; /* a 21 bit character (the most currently used) */
|
|
+ else if (lead < 0xFC)
|
|
+ r = 5; /* a 26 bit character (shouldn't happen) */
|
|
+ else if (lead < 0xFE)
|
|
+ r = 6; /* a 31 bit character (shouldn't happen) */
|
|
+ else
|
|
+ return -1; /* error: invalid lead byte */
|
|
+ for (t = 1; t < r; t++)
|
|
+ if ((unsigned char) utf8[t] < 0x80 || (unsigned char) utf8[t] >= 0xC0)
|
|
+ return -1; /* error: not enough valid trailing bytes */
|
|
+ return r;
|
|
+}
|
|
+
|
|
+
|
|
+/* ucs4_char_from_utf8
|
|
+ *
|
|
+ * Given a reference to a pointer into a UTF-8 string, returns the next
|
|
+ * UCS-4 character and advances the pointer to the next character sequence.
|
|
+ * Returns ~0 (= -1 in twos-complement notation) and does not advance the
|
|
+ * pointer when input is ill-formed.
|
|
+ */
|
|
+static ulg ucs4_char_from_utf8(utf8)
|
|
+ ZCONST char **utf8;
|
|
+{
|
|
+ ulg ret;
|
|
+ int t, bytes;
|
|
+
|
|
+ if (!utf8)
|
|
+ return ~0L; /* no input */
|
|
+ bytes = utf8_char_bytes(*utf8);
|
|
+ if (bytes <= 0)
|
|
+ return ~0L; /* invalid input */
|
|
+ if (bytes == 1)
|
|
+ ret = **utf8; /* ascii-7 */
|
|
+ else
|
|
+ ret = **utf8 & (0x7F >> bytes); /* lead byte of a multibyte sequence */
|
|
+ (*utf8)++;
|
|
+ for (t = 1; t < bytes; t++) /* consume trailing bytes */
|
|
+ ret = (ret << 6) | (*((*utf8)++) & 0x3F);
|
|
+ return (zwchar) ret;
|
|
+}
|
|
+
|
|
+
|
|
+#if 0 /* currently unused */
|
|
+/* utf8_from_ucs4_char - Convert UCS char to UTF-8
|
|
+ *
|
|
+ * Returns the number of bytes put into utf8buf to represent ch, from 1 to 6,
|
|
+ * or -1 if ch is too large to represent. utf8buf must have room for 6 bytes.
|
|
+ */
|
|
+static int utf8_from_ucs4_char(utf8buf, ch)
|
|
+ char *utf8buf;
|
|
+ ulg ch;
|
|
+{
|
|
+ int trailing = 0;
|
|
+ int leadmask = 0x80;
|
|
+ int leadbits = 0x3F;
|
|
+ int tch = ch;
|
|
+ int ret;
|
|
+
|
|
+ if (ch > 0x7FFFFFFFL)
|
|
+ return -1; /* UTF-8 can represent 31 bits */
|
|
+ if (ch < 0x7F)
|
|
+ {
|
|
+ *utf8buf++ = (char) ch; /* ascii-7 */
|
|
+ return 1;
|
|
+ }
|
|
+ do {
|
|
+ trailing++;
|
|
+ leadmask = (leadmask >> 1) | 0x80;
|
|
+ leadbits >>= 1;
|
|
+ tch >>= 6;
|
|
+ } while (tch & ~leadbits);
|
|
+ ret = trailing + 1;
|
|
+ /* produce lead byte */
|
|
+ *utf8buf++ = (char) (leadmask | (ch >> (6 * trailing)));
|
|
+ while (--trailing >= 0)
|
|
+ /* produce trailing bytes */
|
|
+ *utf8buf++ = (char) (0x80 | ((ch >> (6 * trailing)) & 0x3F));
|
|
+ return ret;
|
|
+}
|
|
+#endif /* unused */
|
|
+
|
|
+
|
|
+/*===================================================================*/
|
|
+
|
|
+/* utf8_to_ucs4_string - convert UTF-8 string to UCS string
|
|
+ *
|
|
+ * Return UCS count. Now returns int so can return -1.
|
|
+ */
|
|
+static int utf8_to_ucs4_string(utf8, ucs4buf, buflen)
|
|
+ ZCONST char *utf8;
|
|
+ ulg *ucs4buf;
|
|
+ int buflen;
|
|
+{
|
|
+ int count = 0;
|
|
+
|
|
+ for (;;)
|
|
+ {
|
|
+ ulg ch = ucs4_char_from_utf8(&utf8);
|
|
+ if (ch == ~0L)
|
|
+ return -1;
|
|
+ else
|
|
+ {
|
|
+ if (ucs4buf && count < buflen)
|
|
+ ucs4buf[count] = ch;
|
|
+ if (ch == 0)
|
|
+ return count;
|
|
+ count++;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+#if 0 /* currently unused */
|
|
+/* ucs4_string_to_utf8
|
|
+ *
|
|
+ *
|
|
+ */
|
|
+static int ucs4_string_to_utf8(ucs4, utf8buf, buflen)
|
|
+ ZCONST ulg *ucs4;
|
|
+ char *utf8buf;
|
|
+ int buflen;
|
|
+{
|
|
+ char mb[6];
|
|
+ int count = 0;
|
|
+
|
|
+ if (!ucs4)
|
|
+ return -1;
|
|
+ for (;;)
|
|
+ {
|
|
+ int mbl = utf8_from_ucs4_char(mb, *ucs4++);
|
|
+ int c;
|
|
+ if (mbl <= 0)
|
|
+ return -1;
|
|
+ /* We could optimize this a bit by passing utf8buf + count */
|
|
+ /* directly to utf8_from_ucs4_char when buflen >= count + 6... */
|
|
+ c = buflen - count;
|
|
+ if (mbl < c)
|
|
+ c = mbl;
|
|
+ if (utf8buf && count < buflen)
|
|
+ strncpy(utf8buf + count, mb, c);
|
|
+ if (mbl == 1 && !mb[0])
|
|
+ return count; /* terminating nul */
|
|
+ count += mbl;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+/* utf8_chars
|
|
+ *
|
|
+ * Wrapper: counts the actual unicode characters in a UTF-8 string.
|
|
+ */
|
|
+static int utf8_chars(utf8)
|
|
+ ZCONST char *utf8;
|
|
+{
|
|
+ return utf8_to_ucs4_string(utf8, NULL, 0);
|
|
+}
|
|
+#endif /* unused */
|
|
+
|
|
+/* --------------------------------------------------- */
|
|
+/* Unicode Support
|
|
+ *
|
|
+ * These functions common for all Unicode ports.
|
|
+ *
|
|
+ * These functions should allocate and return strings that can be
|
|
+ * freed with free().
|
|
+ *
|
|
+ * 8/27/05 EG
|
|
+ *
|
|
+ * Use zwchar for wide char which is unsigned long
|
|
+ * in zip.h and 32 bits. This avoids problems with
|
|
+ * different sizes of wchar_t.
|
|
+ */
|
|
+
|
|
+#if 0 /* currently unused */
|
|
+/* is_ascii_string
|
|
+ * Checks if a string is all ascii
|
|
+ */
|
|
+int is_ascii_string(mbstring)
|
|
+ ZCONST char *mbstring;
|
|
+{
|
|
+ char *p;
|
|
+ uch c;
|
|
+
|
|
+ for (p = mbstring; c = (uch)*p; p++) {
|
|
+ if (c > 0x7F) {
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+/* local to UTF-8 */
|
|
+char *local_to_utf8_string(local_string)
|
|
+ ZCONST char *local_string;
|
|
+{
|
|
+ return wide_to_utf8_string(local_to_wide_string(local_string));
|
|
+}
|
|
+# endif /* unused */
|
|
+
|
|
+/* wide_to_escape_string
|
|
+ provides a string that represents a wide char not in local char set
|
|
+
|
|
+ An initial try at an algorithm. Suggestions welcome.
|
|
+
|
|
+ According to the standard, Unicode character points are restricted to
|
|
+ the number range from 0 to 0x10FFFF, respective 21 bits.
|
|
+ For a hexadecimal notation, 2 octets are sufficient for the mostly
|
|
+ used characters from the "Basic Multilingual Plane", all other
|
|
+ Unicode characters can be represented by 3 octets (= 6 hex digits).
|
|
+ The Unicode standard suggests to write Unicode character points
|
|
+ as 4 resp. 6 hex digits, preprended by "U+".
|
|
+ (e.g.: U+10FFFF for the highest character point, or U+0030 for the ASCII
|
|
+ digit "0")
|
|
+
|
|
+ However, for the purpose of escaping non-ASCII chars in an ASCII character
|
|
+ stream, the "U" is not a very good escape initializer. Therefore, we
|
|
+ use the following convention within our Info-ZIP code:
|
|
+
|
|
+ If not an ASCII char probably need 2 bytes at least. So if
|
|
+ a 2-byte wide encode it as 4 hex digits with a leading #U. If
|
|
+ needs 3 bytes then prefix the string with #L. So
|
|
+ #U1234
|
|
+ is a 2-byte wide character with bytes 0x12 and 0x34 while
|
|
+ #L123456
|
|
+ is a 3-byte wide character with bytes 0x12, 0x34, 0x56.
|
|
+ On Windows, wide that need two wide characters need to be converted
|
|
+ to a single number.
|
|
+ */
|
|
+
|
|
+ /* set this to the max bytes an escape can be */
|
|
+#define MAX_ESCAPE_BYTES 8
|
|
+
|
|
+char *wide_to_escape_string(wide_char)
|
|
+ zwchar wide_char;
|
|
+{
|
|
+ int i;
|
|
+ zwchar w = wide_char;
|
|
+ uch b[sizeof(zwchar)];
|
|
+ char d[3];
|
|
+ char e[11];
|
|
+ int len;
|
|
+ char *r;
|
|
+
|
|
+ /* fill byte array with zeros */
|
|
+ memzero(b, sizeof(zwchar));
|
|
+ /* get bytes in right to left order */
|
|
+ for (len = 0; w; len++) {
|
|
+ b[len] = (char)(w % 0x100);
|
|
+ w /= 0x100;
|
|
+ }
|
|
+ strcpy(e, "#");
|
|
+ /* either 2 bytes or 3 bytes */
|
|
+ if (len <= 2) {
|
|
+ len = 2;
|
|
+ strcat(e, "U");
|
|
+ } else {
|
|
+ strcat(e, "L");
|
|
+ }
|
|
+ for (i = len - 1; i >= 0; i--) {
|
|
+ sprintf(d, "%02x", b[i]);
|
|
+ strcat(e, d);
|
|
+ }
|
|
+ if ((r = malloc(strlen(e) + 1)) == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+ strcpy(r, e);
|
|
+ return r;
|
|
+}
|
|
+
|
|
+#if 0 /* currently unused */
|
|
+/* returns the wide character represented by the escape string */
|
|
+zwchar escape_string_to_wide(escape_string)
|
|
+ ZCONST char *escape_string;
|
|
+{
|
|
+ int i;
|
|
+ zwchar w;
|
|
+ char c;
|
|
+ int len;
|
|
+ ZCONST char *e = escape_string;
|
|
+
|
|
+ if (e == NULL) {
|
|
+ return 0;
|
|
+ }
|
|
+ if (e[0] != '#') {
|
|
+ /* no leading # */
|
|
+ return 0;
|
|
+ }
|
|
+ len = strlen(e);
|
|
+ /* either #U1234 or #L123456 format */
|
|
+ if (len != 6 && len != 8) {
|
|
+ return 0;
|
|
+ }
|
|
+ w = 0;
|
|
+ if (e[1] == 'L') {
|
|
+ if (len != 8) {
|
|
+ return 0;
|
|
+ }
|
|
+ /* 3 bytes */
|
|
+ for (i = 2; i < 8; i++) {
|
|
+ c = e[i];
|
|
+ if (c < '0' || c > '9') {
|
|
+ return 0;
|
|
+ }
|
|
+ w = w * 0x10 + (zwchar)(c - '0');
|
|
+ }
|
|
+ } else if (e[1] == 'U') {
|
|
+ /* 2 bytes */
|
|
+ for (i = 2; i < 6; i++) {
|
|
+ c = e[i];
|
|
+ if (c < '0' || c > '9') {
|
|
+ return 0;
|
|
+ }
|
|
+ w = w * 0x10 + (zwchar)(c - '0');
|
|
+ }
|
|
+ }
|
|
+ return w;
|
|
+}
|
|
+#endif /* unused */
|
|
+
|
|
+#ifndef WIN32 /* WIN32 supplies a special variant of this function */
|
|
+/* convert wide character string to multi-byte character string */
|
|
+char *wide_to_local_string(wide_string, escape_all)
|
|
+ ZCONST zwchar *wide_string;
|
|
+ int escape_all;
|
|
+{
|
|
+ int i;
|
|
+ wchar_t wc;
|
|
+ int b;
|
|
+ int state_dependent;
|
|
+ int wsize = 0;
|
|
+ int max_bytes = MB_CUR_MAX;
|
|
+ char buf[9];
|
|
+ char *buffer = NULL;
|
|
+ char *local_string = NULL;
|
|
+
|
|
+ for (wsize = 0; wide_string[wsize]; wsize++) ;
|
|
+
|
|
+ if (max_bytes < MAX_ESCAPE_BYTES)
|
|
+ max_bytes = MAX_ESCAPE_BYTES;
|
|
+
|
|
+ if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ /* convert it */
|
|
+ buffer[0] = '\0';
|
|
+ /* set initial state if state-dependent encoding */
|
|
+ wc = (wchar_t)'a';
|
|
+ b = wctomb(NULL, wc);
|
|
+ if (b == 0)
|
|
+ state_dependent = 0;
|
|
+ else
|
|
+ state_dependent = 1;
|
|
+ for (i = 0; i < wsize; i++) {
|
|
+ if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) {
|
|
+ /* wchar_t probably 2 bytes */
|
|
+ /* could do surrogates if state_dependent and wctomb can do */
|
|
+ wc = zwchar_to_wchar_t_default_char;
|
|
+ } else {
|
|
+ wc = (wchar_t)wide_string[i];
|
|
+ }
|
|
+ b = wctomb(buf, wc);
|
|
+ if (escape_all) {
|
|
+ if (b == 1 && (uch)buf[0] <= 0x7f) {
|
|
+ /* ASCII */
|
|
+ strncat(buffer, buf, b);
|
|
+ } else {
|
|
+ /* use escape for wide character */
|
|
+ char *escape_string = wide_to_escape_string(wide_string[i]);
|
|
+ strcat(buffer, escape_string);
|
|
+ free(escape_string);
|
|
+ }
|
|
+ } else if (b > 0) {
|
|
+ /* multi-byte char */
|
|
+ strncat(buffer, buf, b);
|
|
+ } else {
|
|
+ /* no MB for this wide */
|
|
+ /* use escape for wide character */
|
|
+ char *escape_string = wide_to_escape_string(wide_string[i]);
|
|
+ strcat(buffer, escape_string);
|
|
+ free(escape_string);
|
|
+ }
|
|
+ }
|
|
+ if ((local_string = (char *)malloc(strlen(buffer) + 1)) != NULL) {
|
|
+ strcpy(local_string, buffer);
|
|
+ }
|
|
+ free(buffer);
|
|
+
|
|
+ return local_string;
|
|
+}
|
|
+#endif /* !WIN32 */
|
|
+
|
|
+#if 0 /* currently unused */
|
|
+/* convert local string to display character set string */
|
|
+char *local_to_display_string(local_string)
|
|
+ ZCONST char *local_string;
|
|
+{
|
|
+ char *display_string;
|
|
+
|
|
+ /* For Windows, OEM string should never be bigger than ANSI string, says
|
|
+ CharToOem description.
|
|
+ For all other ports, just make a copy of local_string.
|
|
+ */
|
|
+ if ((display_string = (char *)malloc(strlen(local_string) + 1)) == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ strcpy(display_string, local_string);
|
|
+
|
|
+#ifdef EBCDIC
|
|
+ {
|
|
+ char *ebc;
|
|
+
|
|
+ if ((ebc = malloc(strlen(display_string) + 1)) == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+ strtoebc(ebc, display_string);
|
|
+ free(display_string);
|
|
+ display_string = ebc;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ return display_string;
|
|
+}
|
|
+#endif /* unused */
|
|
+
|
|
+/* UTF-8 to local */
|
|
+char *utf8_to_local_string(utf8_string, escape_all)
|
|
+ ZCONST char *utf8_string;
|
|
+ int escape_all;
|
|
+{
|
|
+ zwchar *wide = utf8_to_wide_string(utf8_string);
|
|
+ char *loc = wide_to_local_string(wide, escape_all);
|
|
+ free(wide);
|
|
+ return loc;
|
|
+}
|
|
+
|
|
+#if 0 /* currently unused */
|
|
+/* convert multi-byte character string to wide character string */
|
|
+zwchar *local_to_wide_string(local_string)
|
|
+ ZCONST char *local_string;
|
|
+{
|
|
+ int wsize;
|
|
+ wchar_t *wc_string;
|
|
+ zwchar *wide_string;
|
|
+
|
|
+ /* for now try to convert as string - fails if a bad char in string */
|
|
+ wsize = mbstowcs(NULL, local_string, strlen(local_string) + 1);
|
|
+ if (wsize == (size_t)-1) {
|
|
+ /* could not convert */
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ /* convert it */
|
|
+ if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+ wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1);
|
|
+ wc_string[wsize] = (wchar_t) 0;
|
|
+
|
|
+ /* in case wchar_t is not zwchar */
|
|
+ if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+ 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)
|
|
+ ? (dos_mdatetime == DOSTIME_MINIMUM)
|
|
+ : (dos_mdatetime >= DOSTIME_2038_01_18);
|
|
+ if (!ut_zip_unzip_compatible) {
|
|
+ /* UnZip interprets mtime differently than Zip;
|
|
+ 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_zip_unzip_compatible = FALSE;
|
|
+ }
|
|
+ z_utim->mtime = (time_t)i_time;
|
|
+#endif /* ?TIME_T_TYPE_DOUBLE */
|
|
+ } else {
|
|
+ flags &= ~EB_UT_FL_MTIME;
|
|
+ TTrace((stderr," UT e.f. truncated; no modtime\n"));
|
|
+ }
|
|
+ }
|
|
+ if (ef_is_c) {
|
|
+ break; /* central version of TIME field ends here */
|
|
+ }
|
|
+
|
|
+ if (flags & EB_UT_FL_ATIME) {
|
|
+ if ((eb_idx+4) <= eb_len) {
|
|
+ i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
|
|
+ eb_idx += 4;
|
|
+ TTrace((stderr," UT e.f. access time = %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 {
|
|
+ /* sign of 32-bit time is unknown -> ignore it */
|
|
+ flags &= ~EB_UT_FL_ATIME;
|
|
+ TTrace((stderr,
|
|
+ " UT 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 &= ~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;
|
|
+ }
|
|
+
|
|
+ if (eb_id == EF_SPARK && (eb_len == 24 || eb_len == 20)) {
|
|
+ if (makelong(EB_HEADSIZE + ef_buf) == SPARKID_2) {
|
|
+ /* Return a pointer to the valid SPARK filetype ef block */
|
|
+ return (zvoid *)ef_buf;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Skip this extra field block */
|
|
+ ef_buf += (eb_len + EB_HEADSIZE);
|
|
+ ef_len -= (eb_len + EB_HEADSIZE);
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+#endif /* (RISCOS || ACORN_FTYPE_NFS) */
|
|
diff -Naur a/unix/configure b/unix/configure
|
|
--- a/unix/configure 2009-04-16 20:25:12.000000000 +0100
|
|
+++ b/unix/configure 2019-12-01 23:54:04.330597267 +0000
|
|
@@ -17,7 +17,7 @@
|
|
IZ_BZIP2=${3}
|
|
CFLAGS="${CFLAGS} -I. -DUNIX"
|
|
LFLAGS1=""
|
|
-LFLAGS2="-s"
|
|
+LFLAGS2="${LFLAGS2}"
|
|
LN="ln -s"
|
|
|
|
CFLAGS_OPT=''
|
|
@@ -640,7 +640,24 @@
|
|
D_USE_BZ2="-DUSE_BZIP2"
|
|
L_BZ2="${BZLF} -lbz2"
|
|
else
|
|
- echo "-- bzip2 sources not found - no bzip2 support"
|
|
+ echo " Check if OS already has bzip2 library installed"
|
|
+ cat > conftest.c << _EOF_
|
|
+#include "bzlib.h"
|
|
+int main()
|
|
+{
|
|
+ bz_stream strm;
|
|
+ BZ2_bzCompressEnd(&strm);
|
|
+ return 0;
|
|
+}
|
|
+_EOF_
|
|
+ $CC $CFLAGS -o conftest conftest.c -lbz2 > /dev/null 2>/dev/null
|
|
+ if test $? -eq 0; then
|
|
+ echo "-- OS supports bzip2 - linking in bzip2"
|
|
+ D_USE_BZ2="-DUSE_BZIP2"
|
|
+ L_BZ2="${BZLF} -lbz2"
|
|
+ else
|
|
+ echo "-- Either bzlib.h or libbz2.a not found - no bzip2"
|
|
+ fi
|
|
fi
|
|
fi
|
|
|
|
diff -Naur a/unix/unix.c b/unix/unix.c
|
|
--- a/unix/unix.c 2009-01-23 23:31:26.000000000 +0000
|
|
+++ b/unix/unix.c 2019-12-02 01:49:39.894641004 +0000
|
|
@@ -30,6 +30,9 @@
|
|
#define UNZIP_INTERNAL
|
|
#include "unzip.h"
|
|
|
|
+#include <iconv.h>
|
|
+#include <langinfo.h>
|
|
+
|
|
#ifdef SCO_XENIX
|
|
# define SYSNDIR
|
|
#else /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */
|
|
@@ -1096,10 +1099,41 @@
|
|
#ifndef MTS
|
|
|
|
/****************************/
|
|
+/* Function CloseError() */
|
|
+/***************************/
|
|
+
|
|
+int CloseError(__G)
|
|
+ __GDEF
|
|
+{
|
|
+ int errval = PK_OK;
|
|
+
|
|
+ if (fclose(G.outfile) < 0) {
|
|
+ switch (errno) {
|
|
+ case ENOSPC:
|
|
+ /* Do we need this on fileio.c? */
|
|
+ Info(slide, 0x4a1, ((char *)slide, "%s: write error (disk full?). Continue? (y/n/^C) ",
|
|
+ FnFilter1(G.filename)));
|
|
+ fgets(G.answerbuf, 9, stdin);
|
|
+ if (*G.answerbuf == 'y') /* stop writing to this file */
|
|
+ G.disk_full = 1; /* pass to next */
|
|
+ else
|
|
+ G.disk_full = 2; /* no: exit program */
|
|
+
|
|
+ errval = PK_DISK;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ errval = PK_WARN;
|
|
+ }
|
|
+ }
|
|
+ return errval;
|
|
+} /* End of CloseError() */
|
|
+
|
|
+/****************************/
|
|
/* Function close_outfile() */
|
|
/****************************/
|
|
|
|
-void close_outfile(__G) /* GRR: change to return PK-style warning level */
|
|
+int close_outfile(__G)
|
|
__GDEF
|
|
{
|
|
union {
|
|
@@ -1108,6 +1142,7 @@
|
|
} zt;
|
|
ulg z_uidgid[2];
|
|
int have_uidgid_flg;
|
|
+ int errval = PK_OK;
|
|
|
|
have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid);
|
|
|
|
@@ -1141,16 +1176,16 @@
|
|
Info(slide, 0x201, ((char *)slide,
|
|
"warning: symbolic link (%s) failed: mem alloc overflow\n",
|
|
FnFilter1(G.filename)));
|
|
- fclose(G.outfile);
|
|
- return;
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+ return errval ? errval : PK_WARN;
|
|
}
|
|
|
|
if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {
|
|
Info(slide, 0x201, ((char *)slide,
|
|
"warning: symbolic link (%s) failed: no mem\n",
|
|
FnFilter1(G.filename)));
|
|
- fclose(G.outfile);
|
|
- return;
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+ return errval ? errval : PK_WARN;
|
|
}
|
|
slnk_entry->next = NULL;
|
|
slnk_entry->targetlen = ucsize;
|
|
@@ -1174,10 +1209,10 @@
|
|
"warning: symbolic link (%s) failed\n",
|
|
FnFilter1(G.filename)));
|
|
free(slnk_entry);
|
|
- fclose(G.outfile);
|
|
- return;
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+ return errval ? errval : PK_WARN;
|
|
}
|
|
- fclose(G.outfile); /* close "link" file for good... */
|
|
+ errval = CloseError(G.outfile, G.filename); /* close "link" file for good... */
|
|
slnk_entry->target[ucsize] = '\0';
|
|
if (QCOND2)
|
|
Info(slide, 0, ((char *)slide, "-> %s ",
|
|
@@ -1188,7 +1223,7 @@
|
|
else
|
|
G.slink_head = slnk_entry;
|
|
G.slink_last = slnk_entry;
|
|
- return;
|
|
+ return errval;
|
|
}
|
|
#endif /* SYMLINKS */
|
|
|
|
@@ -1201,7 +1236,7 @@
|
|
#endif
|
|
|
|
#if (defined(NO_FCHOWN))
|
|
- fclose(G.outfile);
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
#endif
|
|
|
|
/* if -X option was specified and we have UID/GID info, restore it */
|
|
@@ -1227,7 +1262,7 @@
|
|
}
|
|
|
|
#if (!defined(NO_FCHOWN) && defined(NO_FCHMOD))
|
|
- fclose(G.outfile);
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
#endif
|
|
|
|
#if (!defined(NO_FCHOWN) && !defined(NO_FCHMOD))
|
|
@@ -1239,7 +1274,7 @@
|
|
if (fchmod(fileno(G.outfile), filtattr(__G__ G.pInfo->file_attr)))
|
|
perror("fchmod (file attributes) error");
|
|
|
|
- fclose(G.outfile);
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
#endif /* !NO_FCHOWN && !NO_FCHMOD */
|
|
|
|
/* skip restoring time stamps on user's request */
|
|
@@ -1267,6 +1302,7 @@
|
|
#endif
|
|
#endif /* NO_FCHOWN || NO_FCHMOD */
|
|
|
|
+ return errval;
|
|
} /* end function close_outfile() */
|
|
|
|
#endif /* !MTS */
|
|
@@ -1874,3 +1910,104 @@
|
|
}
|
|
}
|
|
#endif /* QLZIP */
|
|
+
|
|
+
|
|
+typedef struct {
|
|
+ char *local_charset;
|
|
+ char *archive_charset;
|
|
+} CHARSET_MAP;
|
|
+
|
|
+/* A mapping of local <-> archive charsets used by default to convert filenames
|
|
+ * of DOS/Windows Zip archives. Currently very basic. */
|
|
+static CHARSET_MAP dos_charset_map[] = {
|
|
+ { "ANSI_X3.4-1968", "CP850" },
|
|
+ { "ISO-8859-1", "CP850" },
|
|
+ { "CP1252", "CP850" },
|
|
+ { "UTF-8", "CP866" },
|
|
+ { "KOI8-R", "CP866" },
|
|
+ { "KOI8-U", "CP866" },
|
|
+ { "ISO-8859-5", "CP866" }
|
|
+};
|
|
+
|
|
+char OEM_CP[MAX_CP_NAME] = "";
|
|
+char ISO_CP[MAX_CP_NAME] = "";
|
|
+
|
|
+/* Try to guess the default value of OEM_CP based on the current locale.
|
|
+ * ISO_CP is left alone for now. */
|
|
+void init_conversion_charsets()
|
|
+{
|
|
+ const char *local_charset;
|
|
+ int i;
|
|
+
|
|
+ /* Make a guess only if OEM_CP not already set. */
|
|
+ if(*OEM_CP == '\0') {
|
|
+ local_charset = nl_langinfo(CODESET);
|
|
+ for(i = 0; i < sizeof(dos_charset_map)/sizeof(CHARSET_MAP); i++)
|
|
+ if(!strcasecmp(local_charset, dos_charset_map[i].local_charset)) {
|
|
+ strncpy(OEM_CP, dos_charset_map[i].archive_charset,
|
|
+ MAX_CP_NAME - 1);
|
|
+
|
|
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Convert a string from one encoding to the current locale using iconv().
|
|
+ * Be as non-intrusive as possible. If error is encountered during covertion
|
|
+ * just leave the string intact. */
|
|
+static void charset_to_intern(char *string, char *from_charset)
|
|
+{
|
|
+ iconv_t cd;
|
|
+ char *s,*d, *buf;
|
|
+ size_t slen, dlen, buflen;
|
|
+ const char *local_charset;
|
|
+
|
|
+ if(*from_charset == '\0')
|
|
+ return;
|
|
+
|
|
+ buf = NULL;
|
|
+ local_charset = nl_langinfo(CODESET);
|
|
+
|
|
+ if((cd = iconv_open(local_charset, from_charset)) == (iconv_t)-1)
|
|
+ return;
|
|
+
|
|
+ slen = strlen(string);
|
|
+ s = string;
|
|
+
|
|
+ /* Make sure OUTBUFSIZ + 1 never ends up smaller than FILNAMSIZ
|
|
+ * as this function also gets called with G.outbuf in fileio.c
|
|
+ */
|
|
+ buflen = FILNAMSIZ;
|
|
+ if (OUTBUFSIZ + 1 < FILNAMSIZ)
|
|
+ {
|
|
+ buflen = OUTBUFSIZ + 1;
|
|
+ }
|
|
+
|
|
+ d = buf = malloc(buflen);
|
|
+ if(!d)
|
|
+ goto cleanup;
|
|
+
|
|
+ bzero(buf,buflen);
|
|
+ dlen = buflen - 1;
|
|
+
|
|
+ if(iconv(cd, &s, &slen, &d, &dlen) == (size_t)-1)
|
|
+ goto cleanup;
|
|
+ strncpy(string, buf, buflen);
|
|
+
|
|
+ cleanup:
|
|
+ free(buf);
|
|
+ iconv_close(cd);
|
|
+}
|
|
+
|
|
+/* Convert a string from OEM_CP to the current locale charset. */
|
|
+inline void oem_intern(char *string)
|
|
+{
|
|
+ charset_to_intern(string, OEM_CP);
|
|
+}
|
|
+
|
|
+/* Convert a string from ISO_CP to the current locale charset. */
|
|
+inline void iso_intern(char *string)
|
|
+{
|
|
+ charset_to_intern(string, ISO_CP);
|
|
+}
|
|
diff -Naur a/unix/unix.c.orig b/unix/unix.c.orig
|
|
--- a/unix/unix.c.orig 1970-01-01 01:00:00.000000000 +0100
|
|
+++ b/unix/unix.c.orig 2019-12-01 23:53:08.675401658 +0000
|
|
@@ -0,0 +1,1909 @@
|
|
+/*
|
|
+ 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
|
|
+*/
|
|
+/*---------------------------------------------------------------------------
|
|
+
|
|
+ unix.c
|
|
+
|
|
+ Unix-specific routines for use with Info-ZIP's UnZip 5.41 and later.
|
|
+
|
|
+ Contains: readdir()
|
|
+ do_wild() <-- generic enough to put in fileio.c?
|
|
+ mapattr()
|
|
+ mapname()
|
|
+ checkdir()
|
|
+ mkdir()
|
|
+ close_outfile()
|
|
+ defer_dir_attribs()
|
|
+ set_direc_attribs()
|
|
+ stamp_file()
|
|
+ version()
|
|
+
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+
|
|
+#define UNZIP_INTERNAL
|
|
+#include "unzip.h"
|
|
+
|
|
+#ifdef SCO_XENIX
|
|
+# define SYSNDIR
|
|
+#else /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */
|
|
+# if defined(__convexc__) || defined(SYSV) || defined(CRAY) || defined(BSD4_4)
|
|
+# define DIRENT
|
|
+# endif
|
|
+#endif
|
|
+#if defined(_AIX) || defined(__mpexl)
|
|
+# define DIRENT
|
|
+#endif
|
|
+#ifdef COHERENT
|
|
+# if defined(_I386) || (defined(__COHERENT__) && (__COHERENT__ >= 0x420))
|
|
+# define DIRENT
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifdef _POSIX_VERSION
|
|
+# ifndef DIRENT
|
|
+# define DIRENT
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifdef DIRENT
|
|
+# include <dirent.h>
|
|
+#else
|
|
+# ifdef SYSV
|
|
+# ifdef SYSNDIR
|
|
+# include <sys/ndir.h>
|
|
+# else
|
|
+# include <ndir.h>
|
|
+# endif
|
|
+# else /* !SYSV */
|
|
+# ifndef NO_SYSDIR
|
|
+# include <sys/dir.h>
|
|
+# endif
|
|
+# endif /* ?SYSV */
|
|
+# ifndef dirent
|
|
+# define dirent direct
|
|
+# endif
|
|
+#endif /* ?DIRENT */
|
|
+
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+typedef struct uxdirattr { /* struct for holding unix style directory */
|
|
+ struct uxdirattr *next; /* info until can be sorted and set at end */
|
|
+ char *fn; /* filename of directory */
|
|
+ union {
|
|
+ iztimes t3; /* mtime, atime, ctime */
|
|
+ ztimbuf t2; /* modtime, actime */
|
|
+ } u;
|
|
+ unsigned perms; /* same as min_info.file_attr */
|
|
+ int have_uidgid; /* flag */
|
|
+ ulg uidgid[2];
|
|
+ char fnbuf[1]; /* buffer stub for directory name */
|
|
+} uxdirattr;
|
|
+#define UxAtt(d) ((uxdirattr *)d) /* typecast shortcut */
|
|
+#endif /* SET_DIR_ATTRIB */
|
|
+
|
|
+#ifdef ACORN_FTYPE_NFS
|
|
+/* Acorn bits for NFS filetyping */
|
|
+typedef struct {
|
|
+ uch ID[2];
|
|
+ uch size[2];
|
|
+ uch ID_2[4];
|
|
+ uch loadaddr[4];
|
|
+ uch execaddr[4];
|
|
+ uch attr[4];
|
|
+} RO_extra_block;
|
|
+
|
|
+#endif /* ACORN_FTYPE_NFS */
|
|
+
|
|
+/* static int created_dir; */ /* used in mapname(), checkdir() */
|
|
+/* static int renamed_fullpath; */ /* ditto */
|
|
+
|
|
+static unsigned filtattr OF((__GPRO__ unsigned perms));
|
|
+
|
|
+
|
|
+/*****************************/
|
|
+/* Strings used multiple */
|
|
+/* times in unix.c */
|
|
+/*****************************/
|
|
+
|
|
+#ifndef MTS
|
|
+/* messages of code for setting file/directory attributes */
|
|
+static ZCONST char CannotSetItemUidGid[] =
|
|
+ "warning: cannot set UID %lu and/or GID %lu for %s\n %s\n";
|
|
+static ZCONST char CannotSetUidGid[] =
|
|
+ " (warning) cannot set UID %lu and/or GID %lu\n %s";
|
|
+static ZCONST char CannotSetItemTimestamps[] =
|
|
+ "warning: cannot set modif./access times for %s\n %s\n";
|
|
+static ZCONST char CannotSetTimestamps[] =
|
|
+ " (warning) cannot set modif./access times\n %s";
|
|
+#endif /* !MTS */
|
|
+
|
|
+
|
|
+#ifndef SFX
|
|
+#ifdef NO_DIR /* for AT&T 3B1 */
|
|
+
|
|
+#define opendir(path) fopen(path,"r")
|
|
+#define closedir(dir) fclose(dir)
|
|
+typedef FILE DIR;
|
|
+typedef struct zdir {
|
|
+ FILE *dirhandle;
|
|
+ struct dirent *entry;
|
|
+} DIR
|
|
+DIR *opendir OF((ZCONST char *dirspec));
|
|
+void closedir OF((DIR *dirp));
|
|
+struct dirent *readdir OF((DIR *dirp));
|
|
+
|
|
+DIR *opendir(dirspec)
|
|
+ ZCONST char *dirspec;
|
|
+{
|
|
+ DIR *dirp;
|
|
+
|
|
+ if ((dirp = malloc(sizeof(DIR)) != NULL) {
|
|
+ if ((dirp->dirhandle = fopen(dirspec, "r")) == NULL) {
|
|
+ free(dirp);
|
|
+ dirp = NULL;
|
|
+ }
|
|
+ }
|
|
+ return dirp;
|
|
+}
|
|
+
|
|
+void closedir(dirp)
|
|
+ DIR *dirp;
|
|
+{
|
|
+ fclose(dirp->dirhandle);
|
|
+ free(dirp);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Apparently originally by Rich Salz.
|
|
+ * Cleaned up and modified by James W. Birdsall.
|
|
+ */
|
|
+struct dirent *readdir(dirp)
|
|
+ DIR *dirp;
|
|
+{
|
|
+
|
|
+ if (dirp == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ for (;;)
|
|
+ if (fread(&(dirp->entry), sizeof (struct dirent), 1,
|
|
+ dirp->dirhandle) == 0)
|
|
+ return (struct dirent *)NULL;
|
|
+ else if ((dirp->entry).d_ino)
|
|
+ return &(dirp->entry);
|
|
+
|
|
+} /* end function readdir() */
|
|
+
|
|
+#endif /* NO_DIR */
|
|
+
|
|
+
|
|
+/**********************/
|
|
+/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */
|
|
+/**********************/
|
|
+
|
|
+char *do_wild(__G__ wildspec)
|
|
+ __GDEF
|
|
+ ZCONST char *wildspec; /* only used first time on a given dir */
|
|
+{
|
|
+/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in unxcfg.h:
|
|
+ static DIR *wild_dir = (DIR *)NULL;
|
|
+ static ZCONST char *wildname;
|
|
+ static char *dirname, matchname[FILNAMSIZ];
|
|
+ static int notfirstcall=FALSE, have_dirname, dirnamelen;
|
|
+*/
|
|
+ struct dirent *file;
|
|
+
|
|
+ /* Even when we're just returning wildspec, we *always* do so in
|
|
+ * matchname[]--calling routine is allowed to append four characters
|
|
+ * to the returned string, and wildspec may be a pointer to argv[].
|
|
+ */
|
|
+ if (!G.notfirstcall) { /* first call: must initialize everything */
|
|
+ G.notfirstcall = TRUE;
|
|
+
|
|
+ if (!iswild(wildspec)) {
|
|
+ strncpy(G.matchname, wildspec, FILNAMSIZ);
|
|
+ G.matchname[FILNAMSIZ-1] = '\0';
|
|
+ G.have_dirname = FALSE;
|
|
+ G.wild_dir = NULL;
|
|
+ return G.matchname;
|
|
+ }
|
|
+
|
|
+ /* break the wildspec into a directory part and a wildcard filename */
|
|
+ if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) {
|
|
+ G.dirname = ".";
|
|
+ G.dirnamelen = 1;
|
|
+ G.have_dirname = FALSE;
|
|
+ G.wildname = wildspec;
|
|
+ } else {
|
|
+ ++G.wildname; /* point at character after '/' */
|
|
+ G.dirnamelen = G.wildname - wildspec;
|
|
+ if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) {
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "warning: cannot allocate wildcard buffers\n"));
|
|
+ strncpy(G.matchname, wildspec, FILNAMSIZ);
|
|
+ G.matchname[FILNAMSIZ-1] = '\0';
|
|
+ return G.matchname; /* but maybe filespec was not a wildcard */
|
|
+ }
|
|
+ strncpy(G.dirname, wildspec, G.dirnamelen);
|
|
+ G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */
|
|
+ G.have_dirname = TRUE;
|
|
+ }
|
|
+
|
|
+ if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) {
|
|
+ while ((file = readdir((DIR *)G.wild_dir)) !=
|
|
+ (struct dirent *)NULL) {
|
|
+ Trace((stderr, "do_wild: readdir returns %s\n",
|
|
+ FnFilter1(file->d_name)));
|
|
+ if (file->d_name[0] == '.' && G.wildname[0] != '.')
|
|
+ continue; /* Unix: '*' and '?' do not match leading dot */
|
|
+ if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/
|
|
+ /* skip "." and ".." directory entries */
|
|
+ strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) {
|
|
+ Trace((stderr, "do_wild: match() succeeds\n"));
|
|
+ if (G.have_dirname) {
|
|
+ strcpy(G.matchname, G.dirname);
|
|
+ strcpy(G.matchname+G.dirnamelen, file->d_name);
|
|
+ } else
|
|
+ strcpy(G.matchname, file->d_name);
|
|
+ return G.matchname;
|
|
+ }
|
|
+ }
|
|
+ /* if we get to here directory is exhausted, so close it */
|
|
+ closedir((DIR *)G.wild_dir);
|
|
+ G.wild_dir = (zvoid *)NULL;
|
|
+ }
|
|
+ Trace((stderr, "do_wild: opendir(%s) returns NULL\n",
|
|
+ FnFilter1(G.dirname)));
|
|
+
|
|
+ /* return the raw wildspec in case that works (e.g., directory not
|
|
+ * searchable, but filespec was not wild and file is readable) */
|
|
+ strncpy(G.matchname, wildspec, FILNAMSIZ);
|
|
+ G.matchname[FILNAMSIZ-1] = '\0';
|
|
+ return G.matchname;
|
|
+ }
|
|
+
|
|
+ /* last time through, might have failed opendir but returned raw wildspec */
|
|
+ if ((DIR *)G.wild_dir == (DIR *)NULL) {
|
|
+ G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */
|
|
+ if (G.have_dirname)
|
|
+ free(G.dirname);
|
|
+ return (char *)NULL;
|
|
+ }
|
|
+
|
|
+ /* If we've gotten this far, we've read and matched at least one entry
|
|
+ * successfully (in a previous call), so dirname has been copied into
|
|
+ * matchname already.
|
|
+ */
|
|
+ while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) {
|
|
+ Trace((stderr, "do_wild: readdir returns %s\n",
|
|
+ FnFilter1(file->d_name)));
|
|
+ if (file->d_name[0] == '.' && G.wildname[0] != '.')
|
|
+ continue; /* Unix: '*' and '?' do not match leading dot */
|
|
+ if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */
|
|
+ Trace((stderr, "do_wild: match() succeeds\n"));
|
|
+ if (G.have_dirname) {
|
|
+ /* strcpy(G.matchname, G.dirname); */
|
|
+ strcpy(G.matchname+G.dirnamelen, file->d_name);
|
|
+ } else
|
|
+ strcpy(G.matchname, file->d_name);
|
|
+ return G.matchname;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ closedir((DIR *)G.wild_dir); /* at least one entry read; nothing left */
|
|
+ G.wild_dir = (zvoid *)NULL;
|
|
+ G.notfirstcall = FALSE; /* reset for new wildspec */
|
|
+ if (G.have_dirname)
|
|
+ free(G.dirname);
|
|
+ return (char *)NULL;
|
|
+
|
|
+} /* end function do_wild() */
|
|
+
|
|
+#endif /* !SFX */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifndef S_ISUID
|
|
+# define S_ISUID 0004000 /* set user id on execution */
|
|
+#endif
|
|
+#ifndef S_ISGID
|
|
+# define S_ISGID 0002000 /* set group id on execution */
|
|
+#endif
|
|
+#ifndef S_ISVTX
|
|
+# define S_ISVTX 0001000 /* save swapped text even after use */
|
|
+#endif
|
|
+
|
|
+/************************/
|
|
+/* Function filtattr() */
|
|
+/************************/
|
|
+/* This is used to clear or keep the SUID and SGID bits on file permissions.
|
|
+ * It's possible that a file in an archive could have one of these bits set
|
|
+ * and, unknown to the person unzipping, could allow others to execute the
|
|
+ * file as the user or group. The new option -K bypasses this check.
|
|
+ */
|
|
+
|
|
+static unsigned filtattr(__G__ perms)
|
|
+ __GDEF
|
|
+ unsigned perms;
|
|
+{
|
|
+ /* keep setuid/setgid/tacky perms? */
|
|
+ if (!uO.K_flag)
|
|
+ perms &= ~(S_ISUID | S_ISGID | S_ISVTX);
|
|
+
|
|
+ return (0xffff & perms);
|
|
+} /* end function filtattr() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/**********************/
|
|
+/* Function mapattr() */
|
|
+/**********************/
|
|
+
|
|
+int mapattr(__G)
|
|
+ __GDEF
|
|
+{
|
|
+ int r;
|
|
+ ulg tmp = G.crec.external_file_attributes;
|
|
+
|
|
+ G.pInfo->file_attr = 0;
|
|
+ /* initialized to 0 for check in "default" branch below... */
|
|
+
|
|
+ switch (G.pInfo->hostnum) {
|
|
+ case AMIGA_:
|
|
+ tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */
|
|
+ G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);
|
|
+ break;
|
|
+ case THEOS_:
|
|
+ tmp &= 0xF1FFFFFFL;
|
|
+ if ((tmp & 0xF0000000L) != 0x40000000L)
|
|
+ tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */
|
|
+ else
|
|
+ tmp &= 0x41FFFFFFL; /* leave directory bit as set */
|
|
+ /* fall through! */
|
|
+ case UNIX_:
|
|
+ case VMS_:
|
|
+ case ACORN_:
|
|
+ case ATARI_:
|
|
+ case ATHEOS_:
|
|
+ case BEOS_:
|
|
+ case QDOS_:
|
|
+ case TANDEM_:
|
|
+ r = FALSE;
|
|
+ G.pInfo->file_attr = (unsigned)(tmp >> 16);
|
|
+ if (G.pInfo->file_attr == 0 && G.extra_field) {
|
|
+ /* Some (non-Info-ZIP) implementations of Zip for Unix and
|
|
+ * VMS (and probably others ??) leave 0 in the upper 16-bit
|
|
+ * part of the external_file_attributes field. Instead, they
|
|
+ * store file permission attributes in some extra field.
|
|
+ * As a work-around, we search for the presence of one of
|
|
+ * these extra fields and fall back to the MSDOS compatible
|
|
+ * part of external_file_attributes if one of the known
|
|
+ * e.f. types has been detected.
|
|
+ * Later, we might implement extraction of the permission
|
|
+ * bits from the VMS extra field. But for now, the work-around
|
|
+ * should be sufficient to provide "readable" extracted files.
|
|
+ * (For ASI Unix e.f., an experimental remap of the e.f.
|
|
+ * mode value IS already provided!)
|
|
+ */
|
|
+ ush ebID;
|
|
+ unsigned ebLen;
|
|
+ uch *ef = G.extra_field;
|
|
+ unsigned ef_len = G.crec.extra_field_length;
|
|
+
|
|
+ while (!r && ef_len >= EB_HEADSIZE) {
|
|
+ ebID = makeword(ef);
|
|
+ ebLen = (unsigned)makeword(ef+EB_LEN);
|
|
+ if (ebLen > (ef_len - EB_HEADSIZE))
|
|
+ /* discoverd some e.f. inconsistency! */
|
|
+ break;
|
|
+ switch (ebID) {
|
|
+ case EF_ASIUNIX:
|
|
+ if (ebLen >= (EB_ASI_MODE+2)) {
|
|
+ G.pInfo->file_attr =
|
|
+ (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));
|
|
+ /* force stop of loop: */
|
|
+ ef_len = (ebLen + EB_HEADSIZE);
|
|
+ break;
|
|
+ }
|
|
+ /* else: fall through! */
|
|
+ case EF_PKVMS:
|
|
+ /* "found nondecypherable e.f. with perm. attr" */
|
|
+ r = TRUE;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ ef_len -= (ebLen + EB_HEADSIZE);
|
|
+ ef += (ebLen + EB_HEADSIZE);
|
|
+ }
|
|
+ }
|
|
+ if (!r) {
|
|
+#ifdef SYMLINKS
|
|
+ /* Check if the file is a (POSIX-compatible) symbolic link.
|
|
+ * We restrict symlink support to those "made-by" hosts that
|
|
+ * are known to support symbolic links.
|
|
+ */
|
|
+ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&
|
|
+ SYMLINK_HOST(G.pInfo->hostnum);
|
|
+#endif
|
|
+ return 0;
|
|
+ }
|
|
+ /* fall through! */
|
|
+ /* all remaining cases: expand MSDOS read-only bit into write perms */
|
|
+ case FS_FAT_:
|
|
+ /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the
|
|
+ * Unix attributes in the upper 16 bits of the external attributes
|
|
+ * field, just like Info-ZIP's Zip for Unix. We try to use that
|
|
+ * value, after a check for consistency with the MSDOS attribute
|
|
+ * bits (see below).
|
|
+ */
|
|
+ G.pInfo->file_attr = (unsigned)(tmp >> 16);
|
|
+ /* fall through! */
|
|
+ case FS_HPFS_:
|
|
+ case FS_NTFS_:
|
|
+ case MAC_:
|
|
+ case TOPS20_:
|
|
+ default:
|
|
+ /* Ensure that DOS subdir bit is set when the entry's name ends
|
|
+ * in a '/'. Some third-party Zip programs fail to set the subdir
|
|
+ * bit for directory entries.
|
|
+ */
|
|
+ if ((tmp & 0x10) == 0) {
|
|
+ extent fnlen = strlen(G.filename);
|
|
+ if (fnlen > 0 && G.filename[fnlen-1] == '/')
|
|
+ tmp |= 0x10;
|
|
+ }
|
|
+ /* read-only bit --> write perms; subdir bit --> dir exec bit */
|
|
+ tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4;
|
|
+ if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) {
|
|
+ /* keep previous G.pInfo->file_attr setting, when its "owner"
|
|
+ * part appears to be consistent with DOS attribute flags!
|
|
+ */
|
|
+#ifdef SYMLINKS
|
|
+ /* Entries "made by FS_FAT_" could have been zipped on a
|
|
+ * system that supports POSIX-style symbolic links.
|
|
+ */
|
|
+ G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&
|
|
+ (G.pInfo->hostnum == FS_FAT_);
|
|
+#endif
|
|
+ return 0;
|
|
+ }
|
|
+ G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);
|
|
+ break;
|
|
+ } /* end switch (host-OS-created-by) */
|
|
+
|
|
+ /* for originating systems with no concept of "group," "other," "system": */
|
|
+ umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */
|
|
+ G.pInfo->file_attr &= ~tmp;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+} /* end function mapattr() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/************************/
|
|
+/* Function mapname() */
|
|
+/************************/
|
|
+
|
|
+int mapname(__G__ renamed)
|
|
+ __GDEF
|
|
+ int renamed;
|
|
+/*
|
|
+ * returns:
|
|
+ * MPN_OK - no problem detected
|
|
+ * MPN_INF_TRUNC - caution (truncated filename)
|
|
+ * MPN_INF_SKIP - info "skip entry" (dir doesn't exist)
|
|
+ * MPN_ERR_SKIP - error -> skip entry
|
|
+ * MPN_ERR_TOOLONG - error -> path is too long
|
|
+ * MPN_NOMEM - error (memory allocation failed) -> skip entry
|
|
+ * [also MPN_VOL_LABEL, MPN_CREATED_DIR]
|
|
+ */
|
|
+{
|
|
+ char pathcomp[FILNAMSIZ]; /* path-component buffer */
|
|
+ char *pp, *cp=(char *)NULL; /* character pointers */
|
|
+ char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */
|
|
+#ifdef ACORN_FTYPE_NFS
|
|
+ char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */
|
|
+ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */
|
|
+#endif
|
|
+ int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */
|
|
+ int error = MPN_OK;
|
|
+ register unsigned workch; /* hold the character being tested */
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Initialize various pointers and counters and stuff.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (G.pInfo->vollabel)
|
|
+ return MPN_VOL_LABEL; /* can't set disk volume labels in Unix */
|
|
+
|
|
+ /* can create path as long as not just freshening, or if user told us */
|
|
+ G.create_dirs = (!uO.fflag || renamed);
|
|
+
|
|
+ G.created_dir = FALSE; /* not yet */
|
|
+
|
|
+ /* user gave full pathname: don't prepend rootpath */
|
|
+ G.renamed_fullpath = (renamed && (*G.filename == '/'));
|
|
+
|
|
+ if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)
|
|
+ return MPN_NOMEM; /* initialize path buffer, unless no memory */
|
|
+
|
|
+ *pathcomp = '\0'; /* initialize translation buffer */
|
|
+ pp = pathcomp; /* point to translation buffer */
|
|
+ if (uO.jflag) /* junking directories */
|
|
+ cp = (char *)strrchr(G.filename, '/');
|
|
+ if (cp == (char *)NULL) /* no '/' or not junking dirs */
|
|
+ cp = G.filename; /* point to internal zipfile-member pathname */
|
|
+ else
|
|
+ ++cp; /* point to start of last component of path */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Begin main loop through characters in filename.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ while ((workch = (uch)*cp++) != 0) {
|
|
+
|
|
+ switch (workch) {
|
|
+ case '/': /* can assume -j flag not given */
|
|
+ *pp = '\0';
|
|
+ if (strcmp(pathcomp, ".") == 0) {
|
|
+ /* don't bother appending "./" to the path */
|
|
+ *pathcomp = '\0';
|
|
+ } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) {
|
|
+ /* "../" dir traversal detected, skip over it */
|
|
+ *pathcomp = '\0';
|
|
+ killed_ddot = TRUE; /* set "show message" flag */
|
|
+ }
|
|
+ /* when path component is not empty, append it now */
|
|
+ if (*pathcomp != '\0' &&
|
|
+ ((error = checkdir(__G__ pathcomp, APPEND_DIR))
|
|
+ & MPN_MASK) > MPN_INF_TRUNC)
|
|
+ return error;
|
|
+ pp = pathcomp; /* reset conversion buffer for next piece */
|
|
+ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */
|
|
+ break;
|
|
+
|
|
+#ifdef __CYGWIN__ /* Cygwin runs on Win32, apply FAT/NTFS filename rules */
|
|
+ case ':': /* drive spec not stored, so no colon allowed */
|
|
+ case '\\': /* '\\' may come as normal filename char (not */
|
|
+ case '<': /* dir sep char!) from unix-like file system */
|
|
+ case '>': /* no redirection symbols allowed either */
|
|
+ case '|': /* no pipe signs allowed */
|
|
+ case '"': /* no double quotes allowed */
|
|
+ case '?': /* no wildcards allowed */
|
|
+ case '*':
|
|
+ *pp++ = '_'; /* these rules apply equally to FAT and NTFS */
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ case ';': /* VMS version (or DEC-20 attrib?) */
|
|
+ lastsemi = pp;
|
|
+ *pp++ = ';'; /* keep for now; remove VMS ";##" */
|
|
+ break; /* later, if requested */
|
|
+
|
|
+#ifdef ACORN_FTYPE_NFS
|
|
+ case ',': /* NFS filetype extension */
|
|
+ lastcomma = pp;
|
|
+ *pp++ = ','; /* keep for now; may need to remove */
|
|
+ break; /* later, if requested */
|
|
+#endif
|
|
+
|
|
+#ifdef MTS
|
|
+ case ' ': /* change spaces to underscore under */
|
|
+ *pp++ = '_'; /* MTS; leave as spaces under Unix */
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ default:
|
|
+ /* disable control character filter when requested,
|
|
+ * else allow 8-bit characters (e.g. UTF-8) in filenames:
|
|
+ */
|
|
+ if (uO.cflxflag ||
|
|
+ (isprint(workch) || (128 <= workch && workch <= 254)))
|
|
+ *pp++ = (char)workch;
|
|
+ } /* end switch */
|
|
+
|
|
+ } /* end while loop */
|
|
+
|
|
+ /* Show warning when stripping insecure "parent dir" path components */
|
|
+ if (killed_ddot && QCOND2) {
|
|
+ Info(slide, 0, ((char *)slide,
|
|
+ "warning: skipped \"../\" path component(s) in %s\n",
|
|
+ FnFilter1(G.filename)));
|
|
+ if (!(error & ~MPN_MASK))
|
|
+ error = (error & MPN_MASK) | PK_WARN;
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Report if directory was created (and no file to create: filename ended
|
|
+ in '/'), check name to be sure it exists, and combine path and name be-
|
|
+ fore exiting.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (G.filename[strlen(G.filename) - 1] == '/') {
|
|
+ checkdir(__G__ G.filename, GETPATH);
|
|
+ if (G.created_dir) {
|
|
+ if (QCOND2) {
|
|
+ Info(slide, 0, ((char *)slide, " creating: %s\n",
|
|
+ FnFilter1(G.filename)));
|
|
+ }
|
|
+#ifndef NO_CHMOD
|
|
+ /* Filter out security-relevant attributes bits. */
|
|
+ G.pInfo->file_attr = filtattr(__G__ G.pInfo->file_attr);
|
|
+ /* When extracting non-UNIX directories or when extracting
|
|
+ * without UID/GID restoration or SGID preservation, any
|
|
+ * SGID flag inherited from the parent directory should be
|
|
+ * maintained to allow files extracted into this new folder
|
|
+ * to inherit the GID setting from the parent directory.
|
|
+ */
|
|
+ if (G.pInfo->hostnum != UNIX_ || !(uO.X_flag || uO.K_flag)) {
|
|
+ /* preserve SGID bit when inherited from parent dir */
|
|
+ if (!SSTAT(G.filename, &G.statbuf)) {
|
|
+ G.pInfo->file_attr |= G.statbuf.st_mode & S_ISGID;
|
|
+ } else {
|
|
+ perror("Could not read directory attributes");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* set approx. dir perms (make sure can still read/write in dir) */
|
|
+ if (chmod(G.filename, G.pInfo->file_attr | 0700))
|
|
+ perror("chmod (directory attributes) error");
|
|
+#endif
|
|
+ /* set dir time (note trailing '/') */
|
|
+ return (error & ~MPN_MASK) | MPN_CREATED_DIR;
|
|
+ }
|
|
+ /* dir existed already; don't look for data to extract */
|
|
+ return (error & ~MPN_MASK) | MPN_INF_SKIP;
|
|
+ }
|
|
+
|
|
+ *pp = '\0'; /* done with pathcomp: terminate it */
|
|
+
|
|
+ /* if not saving them, remove VMS version numbers (appended ";###") */
|
|
+ if (!uO.V_flag && lastsemi) {
|
|
+ pp = lastsemi + 1;
|
|
+ while (isdigit((uch)(*pp)))
|
|
+ ++pp;
|
|
+ if (*pp == '\0') /* only digits between ';' and end: nuke */
|
|
+ *lastsemi = '\0';
|
|
+ }
|
|
+
|
|
+ /* On UNIX (and compatible systems), "." and ".." are reserved for
|
|
+ * directory navigation and cannot be used as regular file names.
|
|
+ * These reserved one-dot and two-dot names are mapped to "_" and "__".
|
|
+ */
|
|
+ if (strcmp(pathcomp, ".") == 0)
|
|
+ *pathcomp = '_';
|
|
+ else if (strcmp(pathcomp, "..") == 0)
|
|
+ strcpy(pathcomp, "__");
|
|
+
|
|
+#ifdef ACORN_FTYPE_NFS
|
|
+ /* translate Acorn filetype information if asked to do so */
|
|
+ if (uO.acorn_nfs_ext &&
|
|
+ (ef_spark = (RO_extra_block *)
|
|
+ getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))
|
|
+ != (RO_extra_block *)NULL)
|
|
+ {
|
|
+ /* file *must* have a RISC OS extra field */
|
|
+ long ft = (long)makelong(ef_spark->loadaddr);
|
|
+ /*32-bit*/
|
|
+ if (lastcomma) {
|
|
+ pp = lastcomma + 1;
|
|
+ while (isxdigit((uch)(*pp))) ++pp;
|
|
+ if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */
|
|
+ }
|
|
+ if ((ft & 1<<31)==0) ft=0x000FFD00;
|
|
+ sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF);
|
|
+ }
|
|
+#endif /* ACORN_FTYPE_NFS */
|
|
+
|
|
+ if (*pathcomp == '\0') {
|
|
+ Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n",
|
|
+ FnFilter1(G.filename)));
|
|
+ return (error & ~MPN_MASK) | MPN_ERR_SKIP;
|
|
+ }
|
|
+
|
|
+ checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */
|
|
+ checkdir(__G__ G.filename, GETPATH);
|
|
+
|
|
+ return error;
|
|
+
|
|
+} /* end function mapname() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#if 0 /*========== NOTES ==========*/
|
|
+
|
|
+ extract-to dir: a:path/
|
|
+ buildpath: path1/path2/ ... (NULL-terminated)
|
|
+ pathcomp: filename
|
|
+
|
|
+ mapname():
|
|
+ loop over chars in zipfile member name
|
|
+ checkdir(path component, COMPONENT | CREATEDIR) --> map as required?
|
|
+ (d:/tmp/unzip/) (disk:[tmp.unzip.)
|
|
+ (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.)
|
|
+ (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.)
|
|
+ finally add filename itself and check for existence? (could use with rename)
|
|
+ (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir)
|
|
+ checkdir(name, GETPATH) --> copy path to name and free space
|
|
+
|
|
+#endif /* 0 */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/***********************/
|
|
+/* Function checkdir() */
|
|
+/***********************/
|
|
+
|
|
+int checkdir(__G__ pathcomp, flag)
|
|
+ __GDEF
|
|
+ char *pathcomp;
|
|
+ int flag;
|
|
+/*
|
|
+ * returns:
|
|
+ * MPN_OK - no problem detected
|
|
+ * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename
|
|
+ * MPN_INF_SKIP - path doesn't exist, not allowed to create
|
|
+ * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path
|
|
+ * exists and is not a directory, but is supposed to be
|
|
+ * MPN_ERR_TOOLONG - path is too long
|
|
+ * MPN_NOMEM - can't allocate memory for filename buffers
|
|
+ */
|
|
+{
|
|
+ /* static int rootlen = 0; */ /* length of rootpath */
|
|
+ /* static char *rootpath; */ /* user's "extract-to" directory */
|
|
+ /* static char *buildpath; */ /* full path (so far) to extracted file */
|
|
+ /* static char *end; */ /* pointer to end of buildpath ('\0') */
|
|
+
|
|
+# define FN_MASK 7
|
|
+# define FUNCTION (flag & FN_MASK)
|
|
+
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ APPEND_DIR: append the path component to the path being built and check
|
|
+ for its existence. If doesn't exist and we are creating directories, do
|
|
+ so for this one; else signal success or error as appropriate.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (FUNCTION == APPEND_DIR) {
|
|
+ int too_long = FALSE;
|
|
+#ifdef SHORT_NAMES
|
|
+ char *old_end = end;
|
|
+#endif
|
|
+
|
|
+ Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp)));
|
|
+ while ((*G.end = *pathcomp++) != '\0')
|
|
+ ++G.end;
|
|
+#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */
|
|
+ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */
|
|
+ *(G.end = old_end + FILENAME_MAX) = '\0';
|
|
+#endif
|
|
+
|
|
+ /* GRR: could do better check, see if overrunning buffer as we go:
|
|
+ * check end-buildpath after each append, set warning variable if
|
|
+ * within 20 of FILNAMSIZ; then if var set, do careful check when
|
|
+ * appending. Clear variable when begin new path. */
|
|
+
|
|
+ /* next check: need to append '/', at least one-char name, '\0' */
|
|
+ if ((G.end-G.buildpath) > FILNAMSIZ-3)
|
|
+ too_long = TRUE; /* check if extracting dir? */
|
|
+ if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */
|
|
+ if (!G.create_dirs) { /* told not to create (freshening) */
|
|
+ free(G.buildpath);
|
|
+ return MPN_INF_SKIP; /* path doesn't exist: nothing to do */
|
|
+ }
|
|
+ if (too_long) {
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ "checkdir error: path too long: %s\n",
|
|
+ FnFilter1(G.buildpath)));
|
|
+ free(G.buildpath);
|
|
+ /* no room for filenames: fatal */
|
|
+ return MPN_ERR_TOOLONG;
|
|
+ }
|
|
+ if (mkdir(G.buildpath, 0777) == -1) { /* create the directory */
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ "checkdir error: cannot create %s\n\
|
|
+ %s\n\
|
|
+ unable to process %s.\n",
|
|
+ FnFilter2(G.buildpath),
|
|
+ strerror(errno),
|
|
+ FnFilter1(G.filename)));
|
|
+ free(G.buildpath);
|
|
+ /* path didn't exist, tried to create, failed */
|
|
+ return MPN_ERR_SKIP;
|
|
+ }
|
|
+ G.created_dir = TRUE;
|
|
+ } else if (!S_ISDIR(G.statbuf.st_mode)) {
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ "checkdir error: %s exists but is not directory\n\
|
|
+ unable to process %s.\n",
|
|
+ FnFilter2(G.buildpath), FnFilter1(G.filename)));
|
|
+ free(G.buildpath);
|
|
+ /* path existed but wasn't dir */
|
|
+ return MPN_ERR_SKIP;
|
|
+ }
|
|
+ if (too_long) {
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ "checkdir error: path too long: %s\n", FnFilter1(G.buildpath)));
|
|
+ free(G.buildpath);
|
|
+ /* no room for filenames: fatal */
|
|
+ return MPN_ERR_TOOLONG;
|
|
+ }
|
|
+ *G.end++ = '/';
|
|
+ *G.end = '\0';
|
|
+ Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath)));
|
|
+ return MPN_OK;
|
|
+
|
|
+ } /* end if (FUNCTION == APPEND_DIR) */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ GETPATH: copy full path to the string pointed at by pathcomp, and free
|
|
+ G.buildpath.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (FUNCTION == GETPATH) {
|
|
+ strcpy(pathcomp, G.buildpath);
|
|
+ Trace((stderr, "getting and freeing path [%s]\n",
|
|
+ FnFilter1(pathcomp)));
|
|
+ free(G.buildpath);
|
|
+ G.buildpath = G.end = (char *)NULL;
|
|
+ return MPN_OK;
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ APPEND_NAME: assume the path component is the filename; append it and
|
|
+ return without checking for existence.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (FUNCTION == APPEND_NAME) {
|
|
+#ifdef SHORT_NAMES
|
|
+ char *old_end = end;
|
|
+#endif
|
|
+
|
|
+ Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
|
|
+ while ((*G.end = *pathcomp++) != '\0') {
|
|
+ ++G.end;
|
|
+#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */
|
|
+ if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */
|
|
+ *(G.end = old_end + FILENAME_MAX) = '\0';
|
|
+#endif
|
|
+ if ((G.end-G.buildpath) >= FILNAMSIZ) {
|
|
+ *--G.end = '\0';
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "checkdir warning: path too long; truncating\n\
|
|
+ %s\n -> %s\n",
|
|
+ FnFilter1(G.filename), FnFilter2(G.buildpath)));
|
|
+ return MPN_INF_TRUNC; /* filename truncated */
|
|
+ }
|
|
+ }
|
|
+ Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath)));
|
|
+ /* could check for existence here, prompt for new name... */
|
|
+ return MPN_OK;
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ INIT: allocate and initialize buffer space for the file currently being
|
|
+ extracted. If file was renamed with an absolute path, don't prepend the
|
|
+ extract-to path.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+/* GRR: for VMS and TOPS-20, add up to 13 to strlen */
|
|
+
|
|
+ if (FUNCTION == INIT) {
|
|
+ Trace((stderr, "initializing buildpath to "));
|
|
+#ifdef ACORN_FTYPE_NFS
|
|
+ if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+
|
|
+ (uO.acorn_nfs_ext ? 5 : 1)))
|
|
+#else
|
|
+ if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1))
|
|
+#endif
|
|
+ == (char *)NULL)
|
|
+ return MPN_NOMEM;
|
|
+ if ((G.rootlen > 0) && !G.renamed_fullpath) {
|
|
+ strcpy(G.buildpath, G.rootpath);
|
|
+ G.end = G.buildpath + G.rootlen;
|
|
+ } else {
|
|
+ *G.buildpath = '\0';
|
|
+ G.end = G.buildpath;
|
|
+ }
|
|
+ Trace((stderr, "[%s]\n", FnFilter1(G.buildpath)));
|
|
+ return MPN_OK;
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ ROOT: if appropriate, store the path in rootpath and create it if
|
|
+ necessary; else assume it's a zipfile member and return. This path
|
|
+ segment gets used in extracting all members from every zipfile specified
|
|
+ on the command line.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#if (!defined(SFX) || defined(SFX_EXDIR))
|
|
+ if (FUNCTION == ROOT) {
|
|
+ Trace((stderr, "initializing root path to [%s]\n",
|
|
+ FnFilter1(pathcomp)));
|
|
+ if (pathcomp == (char *)NULL) {
|
|
+ G.rootlen = 0;
|
|
+ return MPN_OK;
|
|
+ }
|
|
+ if (G.rootlen > 0) /* rootpath was already set, nothing to do */
|
|
+ return MPN_OK;
|
|
+ if ((G.rootlen = strlen(pathcomp)) > 0) {
|
|
+ char *tmproot;
|
|
+
|
|
+ if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) {
|
|
+ G.rootlen = 0;
|
|
+ return MPN_NOMEM;
|
|
+ }
|
|
+ strcpy(tmproot, pathcomp);
|
|
+ if (tmproot[G.rootlen-1] == '/') {
|
|
+ tmproot[--G.rootlen] = '\0';
|
|
+ }
|
|
+ if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||
|
|
+ !S_ISDIR(G.statbuf.st_mode)))
|
|
+ { /* path does not exist */
|
|
+ if (!G.create_dirs /* || iswild(tmproot) */ ) {
|
|
+ free(tmproot);
|
|
+ G.rootlen = 0;
|
|
+ /* skip (or treat as stored file) */
|
|
+ return MPN_INF_SKIP;
|
|
+ }
|
|
+ /* create the directory (could add loop here scanning tmproot
|
|
+ * to create more than one level, but why really necessary?) */
|
|
+ if (mkdir(tmproot, 0777) == -1) {
|
|
+ Info(slide, 1, ((char *)slide,
|
|
+ "checkdir: cannot create extraction directory: %s\n\
|
|
+ %s\n",
|
|
+ FnFilter1(tmproot), strerror(errno)));
|
|
+ free(tmproot);
|
|
+ G.rootlen = 0;
|
|
+ /* path didn't exist, tried to create, and failed: */
|
|
+ /* file exists, or 2+ subdir levels required */
|
|
+ return MPN_ERR_SKIP;
|
|
+ }
|
|
+ }
|
|
+ tmproot[G.rootlen++] = '/';
|
|
+ tmproot[G.rootlen] = '\0';
|
|
+ if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {
|
|
+ free(tmproot);
|
|
+ G.rootlen = 0;
|
|
+ return MPN_NOMEM;
|
|
+ }
|
|
+ Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath)));
|
|
+ }
|
|
+ return MPN_OK;
|
|
+ }
|
|
+#endif /* !SFX || SFX_EXDIR */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ END: free rootpath, immediately prior to program exit.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (FUNCTION == END) {
|
|
+ Trace((stderr, "freeing rootpath\n"));
|
|
+ if (G.rootlen > 0) {
|
|
+ free(G.rootpath);
|
|
+ G.rootlen = 0;
|
|
+ }
|
|
+ return MPN_OK;
|
|
+ }
|
|
+
|
|
+ return MPN_INVALID; /* should never reach */
|
|
+
|
|
+} /* end function checkdir() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifdef NO_MKDIR
|
|
+
|
|
+/********************/
|
|
+/* Function mkdir() */
|
|
+/********************/
|
|
+
|
|
+int mkdir(path, mode)
|
|
+ ZCONST char *path;
|
|
+ int mode; /* ignored */
|
|
+/*
|
|
+ * returns: 0 - successful
|
|
+ * -1 - failed (errno not set, however)
|
|
+ */
|
|
+{
|
|
+ char command[FILNAMSIZ+40]; /* buffer for system() call */
|
|
+
|
|
+ /* GRR 930416: added single quotes around path to avoid bug with
|
|
+ * creating directories with ampersands in name; not yet tested */
|
|
+ sprintf(command, "IFS=\" \t\n\" /bin/mkdir '%s' 2>/dev/null", path);
|
|
+ if (system(command))
|
|
+ return -1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#endif /* NO_MKDIR */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#if (!defined(MTS) || defined(SET_DIR_ATTRIB))
|
|
+static int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2]));
|
|
+
|
|
+static int get_extattribs(__G__ pzt, z_uidgid)
|
|
+ __GDEF
|
|
+ iztimes *pzt;
|
|
+ ulg z_uidgid[2];
|
|
+{
|
|
+/*---------------------------------------------------------------------------
|
|
+ Convert from MSDOS-format local time and date to Unix-format 32-bit GMT
|
|
+ time: adjust base year from 1980 to 1970, do usual conversions from
|
|
+ yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-
|
|
+ light savings time differences. If we have a Unix extra field, however,
|
|
+ we're laughing: both mtime and atime are ours. On the other hand, we
|
|
+ then have to check for restoration of UID/GID.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+ int have_uidgid_flg;
|
|
+ unsigned eb_izux_flg;
|
|
+
|
|
+ eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,
|
|
+ G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
|
|
+#ifdef IZ_CHECK_TZ
|
|
+ (G.tz_is_valid ? pzt : NULL),
|
|
+#else
|
|
+ pzt,
|
|
+#endif
|
|
+ z_uidgid) : 0);
|
|
+ if (eb_izux_flg & EB_UT_FL_MTIME) {
|
|
+ TTrace((stderr, "\nget_extattribs: Unix e.f. modif. time = %ld\n",
|
|
+ pzt->mtime));
|
|
+ } else {
|
|
+ pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
|
|
+ }
|
|
+ if (eb_izux_flg & EB_UT_FL_ATIME) {
|
|
+ TTrace((stderr, "get_extattribs: Unix e.f. access time = %ld\n",
|
|
+ pzt->atime));
|
|
+ } else {
|
|
+ pzt->atime = pzt->mtime;
|
|
+ TTrace((stderr, "\nget_extattribs: modification/access times = %ld\n",
|
|
+ pzt->mtime));
|
|
+ }
|
|
+
|
|
+ /* if -X option was specified and we have UID/GID info, restore it */
|
|
+ have_uidgid_flg =
|
|
+#ifdef RESTORE_UIDGID
|
|
+ (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));
|
|
+#else
|
|
+ 0;
|
|
+#endif
|
|
+ return have_uidgid_flg;
|
|
+}
|
|
+#endif /* !MTS || SET_DIR_ATTRIB */
|
|
+
|
|
+
|
|
+
|
|
+#ifndef MTS
|
|
+
|
|
+/****************************/
|
|
+/* Function CloseError() */
|
|
+/***************************/
|
|
+
|
|
+int CloseError(__G)
|
|
+ __GDEF
|
|
+{
|
|
+ int errval = PK_OK;
|
|
+
|
|
+ if (fclose(G.outfile) < 0) {
|
|
+ switch (errno) {
|
|
+ case ENOSPC:
|
|
+ /* Do we need this on fileio.c? */
|
|
+ Info(slide, 0x4a1, ((char *)slide, "%s: write error (disk full?). Continue? (y/n/^C) ",
|
|
+ FnFilter1(G.filename)));
|
|
+ fgets(G.answerbuf, 9, stdin);
|
|
+ if (*G.answerbuf == 'y') /* stop writing to this file */
|
|
+ G.disk_full = 1; /* pass to next */
|
|
+ else
|
|
+ G.disk_full = 2; /* no: exit program */
|
|
+
|
|
+ errval = PK_DISK;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ errval = PK_WARN;
|
|
+ }
|
|
+ }
|
|
+ return errval;
|
|
+} /* End of CloseError() */
|
|
+
|
|
+/****************************/
|
|
+/* Function close_outfile() */
|
|
+/****************************/
|
|
+
|
|
+int close_outfile(__G)
|
|
+ __GDEF
|
|
+{
|
|
+ union {
|
|
+ iztimes t3; /* mtime, atime, ctime */
|
|
+ ztimbuf t2; /* modtime, actime */
|
|
+ } zt;
|
|
+ ulg z_uidgid[2];
|
|
+ int have_uidgid_flg;
|
|
+ int errval = PK_OK;
|
|
+
|
|
+ have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid);
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ If symbolic links are supported, allocate storage for a symlink control
|
|
+ structure, put the uncompressed "data" and other required info in it, and
|
|
+ add the structure to the "deferred symlinks" chain. Since we know it's a
|
|
+ symbolic link to start with, we shouldn't have to worry about overflowing
|
|
+ unsigned ints with unsigned longs.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef SYMLINKS
|
|
+ if (G.symlnk) {
|
|
+ extent ucsize = (extent)G.lrec.ucsize;
|
|
+# ifdef SET_SYMLINK_ATTRIBS
|
|
+ extent attribsize = sizeof(unsigned) +
|
|
+ (have_uidgid_flg ? sizeof(z_uidgid) : 0);
|
|
+# else
|
|
+ extent attribsize = 0;
|
|
+# endif
|
|
+ /* size of the symlink entry is the sum of
|
|
+ * (struct size (includes 1st '\0') + 1 additional trailing '\0'),
|
|
+ * system specific attribute data size (might be 0),
|
|
+ * and the lengths of name and link target.
|
|
+ */
|
|
+ extent slnk_entrysize = (sizeof(slinkentry) + 1) + attribsize +
|
|
+ ucsize + strlen(G.filename);
|
|
+ slinkentry *slnk_entry;
|
|
+
|
|
+ if (slnk_entrysize < ucsize) {
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "warning: symbolic link (%s) failed: mem alloc overflow\n",
|
|
+ FnFilter1(G.filename)));
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+ return errval ? errval : PK_WARN;
|
|
+ }
|
|
+
|
|
+ if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "warning: symbolic link (%s) failed: no mem\n",
|
|
+ FnFilter1(G.filename)));
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+ return errval ? errval : PK_WARN;
|
|
+ }
|
|
+ slnk_entry->next = NULL;
|
|
+ slnk_entry->targetlen = ucsize;
|
|
+ slnk_entry->attriblen = attribsize;
|
|
+# ifdef SET_SYMLINK_ATTRIBS
|
|
+ memcpy(slnk_entry->buf, &(G.pInfo->file_attr),
|
|
+ sizeof(unsigned));
|
|
+ if (have_uidgid_flg)
|
|
+ memcpy(slnk_entry->buf + 4, z_uidgid, sizeof(z_uidgid));
|
|
+# endif
|
|
+ slnk_entry->target = slnk_entry->buf + slnk_entry->attriblen;
|
|
+ slnk_entry->fname = slnk_entry->target + ucsize + 1;
|
|
+ strcpy(slnk_entry->fname, G.filename);
|
|
+
|
|
+ /* move back to the start of the file to re-read the "link data" */
|
|
+ rewind(G.outfile);
|
|
+
|
|
+ if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize)
|
|
+ {
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "warning: symbolic link (%s) failed\n",
|
|
+ FnFilter1(G.filename)));
|
|
+ free(slnk_entry);
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+ return errval ? errval : PK_WARN;
|
|
+ }
|
|
+ errval = CloseError(G.outfile, G.filename); /* close "link" file for good... */
|
|
+ slnk_entry->target[ucsize] = '\0';
|
|
+ if (QCOND2)
|
|
+ Info(slide, 0, ((char *)slide, "-> %s ",
|
|
+ FnFilter1(slnk_entry->target)));
|
|
+ /* add this symlink record to the list of deferred symlinks */
|
|
+ if (G.slink_last != NULL)
|
|
+ G.slink_last->next = slnk_entry;
|
|
+ else
|
|
+ G.slink_head = slnk_entry;
|
|
+ G.slink_last = slnk_entry;
|
|
+ return errval;
|
|
+ }
|
|
+#endif /* SYMLINKS */
|
|
+
|
|
+#ifdef QLZIP
|
|
+ if (G.extra_field) {
|
|
+ static void qlfix OF((__GPRO__ uch *ef_ptr, unsigned ef_len));
|
|
+
|
|
+ qlfix(__G__ G.extra_field, G.lrec.extra_field_length);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+#if (defined(NO_FCHOWN))
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+#endif
|
|
+
|
|
+ /* if -X option was specified and we have UID/GID info, restore it */
|
|
+ if (have_uidgid_flg
|
|
+ /* check that both uid and gid values fit into their data sizes */
|
|
+ && ((ulg)(uid_t)(z_uidgid[0]) == z_uidgid[0])
|
|
+ && ((ulg)(gid_t)(z_uidgid[1]) == z_uidgid[1])) {
|
|
+ TTrace((stderr, "close_outfile: restoring Unix UID/GID info\n"));
|
|
+#if (defined(NO_FCHOWN))
|
|
+ if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))
|
|
+#else
|
|
+ if (fchown(fileno(G.outfile), (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))
|
|
+#endif
|
|
+ {
|
|
+ if (uO.qflag)
|
|
+ Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid,
|
|
+ z_uidgid[0], z_uidgid[1], FnFilter1(G.filename),
|
|
+ strerror(errno)));
|
|
+ else
|
|
+ Info(slide, 0x201, ((char *)slide, CannotSetUidGid,
|
|
+ z_uidgid[0], z_uidgid[1], strerror(errno)));
|
|
+ }
|
|
+ }
|
|
+
|
|
+#if (!defined(NO_FCHOWN) && defined(NO_FCHMOD))
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+#endif
|
|
+
|
|
+#if (!defined(NO_FCHOWN) && !defined(NO_FCHMOD))
|
|
+/*---------------------------------------------------------------------------
|
|
+ Change the file permissions from default ones to those stored in the
|
|
+ zipfile.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (fchmod(fileno(G.outfile), filtattr(__G__ G.pInfo->file_attr)))
|
|
+ perror("fchmod (file attributes) error");
|
|
+
|
|
+ errval = CloseError(G.outfile, G.filename);
|
|
+#endif /* !NO_FCHOWN && !NO_FCHMOD */
|
|
+
|
|
+ /* skip restoring time stamps on user's request */
|
|
+ if (uO.D_flag <= 1) {
|
|
+ /* set the file's access and modification times */
|
|
+ if (utime(G.filename, &(zt.t2))) {
|
|
+ if (uO.qflag)
|
|
+ Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps,
|
|
+ FnFilter1(G.filename), strerror(errno)));
|
|
+ else
|
|
+ Info(slide, 0x201, ((char *)slide, CannotSetTimestamps,
|
|
+ strerror(errno)));
|
|
+ }
|
|
+ }
|
|
+
|
|
+#if (defined(NO_FCHOWN) || defined(NO_FCHMOD))
|
|
+/*---------------------------------------------------------------------------
|
|
+ Change the file permissions from default ones to those stored in the
|
|
+ zipfile.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifndef NO_CHMOD
|
|
+ if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr)))
|
|
+ perror("chmod (file attributes) error");
|
|
+#endif
|
|
+#endif /* NO_FCHOWN || NO_FCHMOD */
|
|
+
|
|
+ return errval;
|
|
+} /* end function close_outfile() */
|
|
+
|
|
+#endif /* !MTS */
|
|
+
|
|
+
|
|
+#if (defined(SYMLINKS) && defined(SET_SYMLINK_ATTRIBS))
|
|
+int set_symlnk_attribs(__G__ slnk_entry)
|
|
+ __GDEF
|
|
+ slinkentry *slnk_entry;
|
|
+{
|
|
+ if (slnk_entry->attriblen > 0) {
|
|
+# if (!defined(NO_LCHOWN))
|
|
+ if (slnk_entry->attriblen > sizeof(unsigned)) {
|
|
+ ulg *z_uidgid_p = (zvoid *)(slnk_entry->buf + sizeof(unsigned));
|
|
+ /* check that both uid and gid values fit into their data sizes */
|
|
+ if (((ulg)(uid_t)(z_uidgid_p[0]) == z_uidgid_p[0]) &&
|
|
+ ((ulg)(gid_t)(z_uidgid_p[1]) == z_uidgid_p[1])) {
|
|
+ TTrace((stderr,
|
|
+ "set_symlnk_attribs: restoring Unix UID/GID info for\n\
|
|
+ %s\n",
|
|
+ FnFilter1(slnk_entry->fname)));
|
|
+ if (lchown(slnk_entry->fname,
|
|
+ (uid_t)z_uidgid_p[0], (gid_t)z_uidgid_p[1]))
|
|
+ {
|
|
+ Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid,
|
|
+ z_uidgid_p[0], z_uidgid_p[1], FnFilter1(slnk_entry->fname),
|
|
+ strerror(errno)));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+# endif /* !NO_LCHOWN */
|
|
+# if (!defined(NO_LCHMOD))
|
|
+ TTrace((stderr,
|
|
+ "set_symlnk_attribs: restoring Unix attributes for\n %s\n",
|
|
+ FnFilter1(slnk_entry->fname)));
|
|
+ if (lchmod(slnk_entry->fname,
|
|
+ filtattr(__G__ *(unsigned *)(zvoid *)slnk_entry->buf)))
|
|
+ perror("lchmod (file attributes) error");
|
|
+# endif /* !NO_LCHMOD */
|
|
+ }
|
|
+ /* currently, no error propagation... */
|
|
+ return PK_OK;
|
|
+} /* end function set_symlnk_attribs() */
|
|
+#endif /* SYMLINKS && SET_SYMLINK_ATTRIBS */
|
|
+
|
|
+
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+/* messages of code for setting directory attributes */
|
|
+# ifndef NO_CHMOD
|
|
+ static ZCONST char DirlistChmodFailed[] =
|
|
+ "warning: cannot set permissions for %s\n %s\n";
|
|
+# endif
|
|
+
|
|
+
|
|
+int defer_dir_attribs(__G__ pd)
|
|
+ __GDEF
|
|
+ direntry **pd;
|
|
+{
|
|
+ uxdirattr *d_entry;
|
|
+
|
|
+ d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename));
|
|
+ *pd = (direntry *)d_entry;
|
|
+ if (d_entry == (uxdirattr *)NULL) {
|
|
+ return PK_MEM;
|
|
+ }
|
|
+ d_entry->fn = d_entry->fnbuf;
|
|
+ strcpy(d_entry->fn, G.filename);
|
|
+
|
|
+ d_entry->perms = G.pInfo->file_attr;
|
|
+
|
|
+ d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3),
|
|
+ d_entry->uidgid);
|
|
+ return PK_OK;
|
|
+} /* end function defer_dir_attribs() */
|
|
+
|
|
+
|
|
+int set_direc_attribs(__G__ d)
|
|
+ __GDEF
|
|
+ direntry *d;
|
|
+{
|
|
+ int errval = PK_OK;
|
|
+
|
|
+ if (UxAtt(d)->have_uidgid &&
|
|
+ /* check that both uid and gid values fit into their data sizes */
|
|
+ ((ulg)(uid_t)(UxAtt(d)->uidgid[0]) == UxAtt(d)->uidgid[0]) &&
|
|
+ ((ulg)(gid_t)(UxAtt(d)->uidgid[1]) == UxAtt(d)->uidgid[1]) &&
|
|
+ chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0],
|
|
+ (gid_t)UxAtt(d)->uidgid[1]))
|
|
+ {
|
|
+ Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid,
|
|
+ UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn),
|
|
+ strerror(errno)));
|
|
+ if (!errval)
|
|
+ errval = PK_WARN;
|
|
+ }
|
|
+ /* Skip restoring directory time stamps on user' request. */
|
|
+ if (uO.D_flag <= 0) {
|
|
+ /* restore directory timestamps */
|
|
+ if (utime(d->fn, &UxAtt(d)->u.t2)) {
|
|
+ Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps,
|
|
+ FnFilter1(d->fn), strerror(errno)));
|
|
+ if (!errval)
|
|
+ errval = PK_WARN;
|
|
+ }
|
|
+ }
|
|
+#ifndef NO_CHMOD
|
|
+ if (chmod(d->fn, UxAtt(d)->perms)) {
|
|
+ Info(slide, 0x201, ((char *)slide, DirlistChmodFailed,
|
|
+ FnFilter1(d->fn), strerror(errno)));
|
|
+ if (!errval)
|
|
+ errval = PK_WARN;
|
|
+ }
|
|
+#endif /* !NO_CHMOD */
|
|
+ return errval;
|
|
+} /* end function set_direc_attribs() */
|
|
+
|
|
+#endif /* SET_DIR_ATTRIB */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifdef TIMESTAMP
|
|
+
|
|
+/***************************/
|
|
+/* Function stamp_file() */
|
|
+/***************************/
|
|
+
|
|
+int stamp_file(fname, modtime)
|
|
+ ZCONST char *fname;
|
|
+ time_t modtime;
|
|
+{
|
|
+ ztimbuf tp;
|
|
+
|
|
+ tp.modtime = tp.actime = modtime;
|
|
+ return (utime(fname, &tp));
|
|
+
|
|
+} /* end function stamp_file() */
|
|
+
|
|
+#endif /* TIMESTAMP */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifndef SFX
|
|
+
|
|
+/************************/
|
|
+/* Function version() */
|
|
+/************************/
|
|
+
|
|
+void version(__G)
|
|
+ __GDEF
|
|
+{
|
|
+#if (defined(__GNUC__) && defined(NX_CURRENT_COMPILER_RELEASE))
|
|
+ char cc_namebuf[40];
|
|
+ char cc_versbuf[40];
|
|
+#else
|
|
+#if (defined(__SUNPRO_C))
|
|
+ char cc_versbuf[17];
|
|
+#else
|
|
+#if (defined(__HP_cc) || defined(__IBMC__))
|
|
+ char cc_versbuf[25];
|
|
+#else
|
|
+#if (defined(__DECC_VER))
|
|
+ char cc_versbuf[17];
|
|
+ int cc_verstyp;
|
|
+#else
|
|
+#if (defined(CRAY) && defined(_RELEASE))
|
|
+ char cc_versbuf[40];
|
|
+#endif /* (CRAY && _RELEASE) */
|
|
+#endif /* __DECC_VER */
|
|
+#endif /* __HP_cc || __IBMC__ */
|
|
+#endif /* __SUNPRO_C */
|
|
+#endif /* (__GNUC__ && NX_CURRENT_COMPILER_RELEASE) */
|
|
+
|
|
+#if ((defined(CRAY) || defined(cray)) && defined(_UNICOS))
|
|
+ char os_namebuf[40];
|
|
+#else
|
|
+#if defined(__NetBSD__)
|
|
+ char os_namebuf[40];
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+ /* Pyramid, NeXT have problems with huge macro expansion, too: no Info() */
|
|
+ sprintf((char *)slide, LoadFarString(CompiledWith),
|
|
+
|
|
+#ifdef __GNUC__
|
|
+# ifdef NX_CURRENT_COMPILER_RELEASE
|
|
+ (sprintf(cc_namebuf, "NeXT DevKit %d.%02d ",
|
|
+ NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100),
|
|
+ cc_namebuf),
|
|
+ (strlen(__VERSION__) > 8)? "(gcc)" :
|
|
+ (sprintf(cc_versbuf, "(gcc %s)", __VERSION__), cc_versbuf),
|
|
+# else
|
|
+ "gcc ", __VERSION__,
|
|
+# endif
|
|
+#else
|
|
+#if defined(__SUNPRO_C)
|
|
+ "Sun C ", (sprintf(cc_versbuf, "version %x", __SUNPRO_C), cc_versbuf),
|
|
+#else
|
|
+#if (defined(__HP_cc))
|
|
+ "HP C ",
|
|
+ (((__HP_cc% 100) == 0) ?
|
|
+ (sprintf(cc_versbuf, "version A.%02d.%02d",
|
|
+ (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100))) :
|
|
+ (sprintf(cc_versbuf, "version A.%02d.%02d.%02d",
|
|
+ (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100), (__HP_cc% 100))),
|
|
+ cc_versbuf),
|
|
+#else
|
|
+#if (defined(__DECC_VER))
|
|
+ "DEC C ",
|
|
+ (sprintf(cc_versbuf, "%c%d.%d-%03d",
|
|
+ ((cc_verstyp = (__DECC_VER / 10000) % 10) == 6 ? 'T' :
|
|
+ (cc_verstyp == 8 ? 'S' : 'V')),
|
|
+ __DECC_VER / 10000000,
|
|
+ (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000),
|
|
+ cc_versbuf),
|
|
+#else
|
|
+#if defined(CRAY) && defined(_RELEASE)
|
|
+ "cc ", (sprintf(cc_versbuf, "version %d", _RELEASE), cc_versbuf),
|
|
+#else
|
|
+#ifdef __IBMC__
|
|
+ "IBM C ",
|
|
+ (sprintf(cc_versbuf, "version %d.%d.%d",
|
|
+ (__IBMC__ / 100), ((__IBMC__ / 10) % 10), (__IBMC__ % 10)),
|
|
+ cc_versbuf),
|
|
+#else
|
|
+#ifdef __VERSION__
|
|
+# ifndef IZ_CC_NAME
|
|
+# define IZ_CC_NAME "cc "
|
|
+# endif
|
|
+ IZ_CC_NAME, __VERSION__
|
|
+#else
|
|
+# ifndef IZ_CC_NAME
|
|
+# define IZ_CC_NAME "cc"
|
|
+# endif
|
|
+ IZ_CC_NAME, "",
|
|
+#endif /* ?__VERSION__ */
|
|
+#endif /* ?__IBMC__ */
|
|
+#endif /* ?(CRAY && _RELEASE) */
|
|
+#endif /* ?__DECC_VER */
|
|
+#endif /* ?__HP_cc */
|
|
+#endif /* ?__SUNPRO_C */
|
|
+#endif /* ?__GNUC__ */
|
|
+
|
|
+#ifndef IZ_OS_NAME
|
|
+# define IZ_OS_NAME "Unix"
|
|
+#endif
|
|
+ IZ_OS_NAME,
|
|
+
|
|
+#if defined(sgi) || defined(__sgi)
|
|
+ " (Silicon Graphics IRIX)",
|
|
+#else
|
|
+#ifdef sun
|
|
+# ifdef sparc
|
|
+# ifdef __SVR4
|
|
+ " (Sun SPARC/Solaris)",
|
|
+# else /* may or may not be SunOS */
|
|
+ " (Sun SPARC)",
|
|
+# endif
|
|
+# else
|
|
+# if defined(sun386) || defined(i386)
|
|
+ " (Sun 386i)",
|
|
+# else
|
|
+# if defined(mc68020) || defined(__mc68020__)
|
|
+ " (Sun 3)",
|
|
+# else /* mc68010 or mc68000: Sun 2 or earlier */
|
|
+ " (Sun 2)",
|
|
+# endif
|
|
+# endif
|
|
+# endif
|
|
+#else
|
|
+#ifdef __hpux
|
|
+ " (HP-UX)",
|
|
+#else
|
|
+#ifdef __osf__
|
|
+ " (DEC OSF/1)",
|
|
+#else
|
|
+#ifdef _AIX
|
|
+ " (IBM AIX)",
|
|
+#else
|
|
+#ifdef aiws
|
|
+ " (IBM RT/AIX)",
|
|
+#else
|
|
+#if defined(CRAY) || defined(cray)
|
|
+# ifdef _UNICOS
|
|
+ (sprintf(os_namebuf, " (Cray UNICOS release %d)", _UNICOS), os_namebuf),
|
|
+# else
|
|
+ " (Cray UNICOS)",
|
|
+# endif
|
|
+#else
|
|
+#if defined(uts) || defined(UTS)
|
|
+ " (Amdahl UTS)",
|
|
+#else
|
|
+#ifdef NeXT
|
|
+# ifdef mc68000
|
|
+ " (NeXTStep/black)",
|
|
+# else
|
|
+ " (NeXTStep for Intel)",
|
|
+# endif
|
|
+#else /* the next dozen or so are somewhat order-dependent */
|
|
+#ifdef LINUX
|
|
+# ifdef __ELF__
|
|
+ " (Linux ELF)",
|
|
+# else
|
|
+ " (Linux a.out)",
|
|
+# endif
|
|
+#else
|
|
+#ifdef MINIX
|
|
+ " (Minix)",
|
|
+#else
|
|
+#ifdef M_UNIX
|
|
+ " (SCO Unix)",
|
|
+#else
|
|
+#ifdef M_XENIX
|
|
+ " (SCO Xenix)",
|
|
+#else
|
|
+#ifdef __NetBSD__
|
|
+# ifdef NetBSD0_8
|
|
+ (sprintf(os_namebuf, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')),
|
|
+ os_namebuf),
|
|
+# else
|
|
+# ifdef NetBSD0_9
|
|
+ (sprintf(os_namebuf, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')),
|
|
+ os_namebuf),
|
|
+# else
|
|
+# ifdef NetBSD1_0
|
|
+ (sprintf(os_namebuf, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')),
|
|
+ os_namebuf),
|
|
+# else
|
|
+ (BSD4_4 == 0.5)? " (NetBSD before 0.9)" : " (NetBSD 1.1 or later)",
|
|
+# endif
|
|
+# endif
|
|
+# endif
|
|
+#else
|
|
+#ifdef __FreeBSD__
|
|
+ (BSD4_4 == 0.5)? " (FreeBSD 1.x)" : " (FreeBSD 2.0 or later)",
|
|
+#else
|
|
+#ifdef __bsdi__
|
|
+ (BSD4_4 == 0.5)? " (BSD/386 1.0)" : " (BSD/386 1.1 or later)",
|
|
+#else
|
|
+#ifdef __386BSD__
|
|
+ (BSD4_4 == 1)? " (386BSD, post-4.4 release)" : " (386BSD)",
|
|
+#else
|
|
+#ifdef __CYGWIN__
|
|
+ " (Cygwin)",
|
|
+#else
|
|
+#if defined(i686) || defined(__i686) || defined(__i686__)
|
|
+ " (Intel 686)",
|
|
+#else
|
|
+#if defined(i586) || defined(__i586) || defined(__i586__)
|
|
+ " (Intel 586)",
|
|
+#else
|
|
+#if defined(i486) || defined(__i486) || defined(__i486__)
|
|
+ " (Intel 486)",
|
|
+#else
|
|
+#if defined(i386) || defined(__i386) || defined(__i386__)
|
|
+ " (Intel 386)",
|
|
+#else
|
|
+#ifdef pyr
|
|
+ " (Pyramid)",
|
|
+#else
|
|
+#ifdef ultrix
|
|
+# ifdef mips
|
|
+ " (DEC/MIPS)",
|
|
+# else
|
|
+# ifdef vax
|
|
+ " (DEC/VAX)",
|
|
+# else /* __alpha? */
|
|
+ " (DEC/Alpha)",
|
|
+# endif
|
|
+# endif
|
|
+#else
|
|
+#ifdef gould
|
|
+ " (Gould)",
|
|
+#else
|
|
+#ifdef MTS
|
|
+ " (MTS)",
|
|
+#else
|
|
+#ifdef __convexc__
|
|
+ " (Convex)",
|
|
+#else
|
|
+#ifdef __QNX__
|
|
+ " (QNX 4)",
|
|
+#else
|
|
+#ifdef __QNXNTO__
|
|
+ " (QNX Neutrino)",
|
|
+#else
|
|
+#ifdef Lynx
|
|
+ " (LynxOS)",
|
|
+#else
|
|
+#ifdef __APPLE__
|
|
+# ifdef __i386__
|
|
+ " Mac OS X Intel i32",
|
|
+# else
|
|
+# ifdef __ppc__
|
|
+ " Mac OS X PowerPC",
|
|
+# else
|
|
+# ifdef __ppc64__
|
|
+ " Mac OS X PowerPC64",
|
|
+# else
|
|
+ " Mac OS X",
|
|
+# endif /* __ppc64__ */
|
|
+# endif /* __ppc__ */
|
|
+# endif /* __i386__ */
|
|
+#else
|
|
+ "",
|
|
+#endif /* Apple */
|
|
+#endif /* Lynx */
|
|
+#endif /* QNX Neutrino */
|
|
+#endif /* QNX 4 */
|
|
+#endif /* Convex */
|
|
+#endif /* MTS */
|
|
+#endif /* Gould */
|
|
+#endif /* DEC */
|
|
+#endif /* Pyramid */
|
|
+#endif /* 386 */
|
|
+#endif /* 486 */
|
|
+#endif /* 586 */
|
|
+#endif /* 686 */
|
|
+#endif /* Cygwin */
|
|
+#endif /* 386BSD */
|
|
+#endif /* BSDI BSD/386 */
|
|
+#endif /* NetBSD */
|
|
+#endif /* FreeBSD */
|
|
+#endif /* SCO Xenix */
|
|
+#endif /* SCO Unix */
|
|
+#endif /* Minix */
|
|
+#endif /* Linux */
|
|
+#endif /* NeXT */
|
|
+#endif /* Amdahl */
|
|
+#endif /* Cray */
|
|
+#endif /* RT/AIX */
|
|
+#endif /* AIX */
|
|
+#endif /* OSF/1 */
|
|
+#endif /* HP-UX */
|
|
+#endif /* Sun */
|
|
+#endif /* SGI */
|
|
+
|
|
+#ifdef __DATE__
|
|
+ " on ", __DATE__
|
|
+#else
|
|
+ "", ""
|
|
+#endif
|
|
+ );
|
|
+
|
|
+ (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);
|
|
+
|
|
+} /* end function version() */
|
|
+
|
|
+#endif /* !SFX */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifdef QLZIP
|
|
+
|
|
+struct qdirect {
|
|
+ long d_length __attribute__ ((packed)); /* file length */
|
|
+ unsigned char d_access __attribute__ ((packed)); /* file access type */
|
|
+ unsigned char d_type __attribute__ ((packed)); /* file type */
|
|
+ long d_datalen __attribute__ ((packed)); /* data length */
|
|
+ long d_reserved __attribute__ ((packed));/* Unused */
|
|
+ short d_szname __attribute__ ((packed)); /* size of name */
|
|
+ char d_name[36] __attribute__ ((packed));/* name area */
|
|
+ long d_update __attribute__ ((packed)); /* last update */
|
|
+ long d_refdate __attribute__ ((packed));
|
|
+ long d_backup __attribute__ ((packed)); /* EOD */
|
|
+};
|
|
+
|
|
+#define LONGID "QDOS02"
|
|
+#define EXTRALEN (sizeof(struct qdirect) + 8)
|
|
+#define JBLONGID "QZHD"
|
|
+#define JBEXTRALEN (sizeof(jbextra) - 4 * sizeof(char))
|
|
+
|
|
+typedef struct {
|
|
+ char eb_header[4] __attribute__ ((packed)); /* place_holder */
|
|
+ char longid[8] __attribute__ ((packed));
|
|
+ struct qdirect header __attribute__ ((packed));
|
|
+} qdosextra;
|
|
+
|
|
+typedef struct {
|
|
+ char eb_header[4]; /* place_holder */
|
|
+ char longid[4];
|
|
+ struct qdirect header;
|
|
+} jbextra;
|
|
+
|
|
+
|
|
+
|
|
+/* The following two functions SH() and LG() convert big-endian short
|
|
+ * and long numbers into native byte order. They are some kind of
|
|
+ * counterpart to the generic UnZip's makeword() and makelong() functions.
|
|
+ */
|
|
+static ush SH(ush val)
|
|
+{
|
|
+ uch swapbuf[2];
|
|
+
|
|
+ swapbuf[1] = (uch)(val & 0xff);
|
|
+ swapbuf[0] = (uch)(val >> 8);
|
|
+ return (*(ush *)swapbuf);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+static ulg LG(ulg val)
|
|
+{
|
|
+ /* convert the big-endian unsigned long number `val' to the machine
|
|
+ * dependent representation
|
|
+ */
|
|
+ ush swapbuf[2];
|
|
+
|
|
+ swapbuf[1] = SH((ush)(val & 0xffff));
|
|
+ swapbuf[0] = SH((ush)(val >> 16));
|
|
+ return (*(ulg *)swapbuf);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+static void qlfix(__G__ ef_ptr, ef_len)
|
|
+ __GDEF
|
|
+ uch *ef_ptr;
|
|
+ unsigned ef_len;
|
|
+{
|
|
+ while (ef_len >= EB_HEADSIZE)
|
|
+ {
|
|
+ unsigned eb_id = makeword(EB_ID + ef_ptr);
|
|
+ unsigned eb_len = makeword(EB_LEN + ef_ptr);
|
|
+
|
|
+ if (eb_len > (ef_len - EB_HEADSIZE)) {
|
|
+ /* discovered some extra field inconsistency! */
|
|
+ Trace((stderr,
|
|
+ "qlfix: block length %u > rest ef_size %u\n", eb_len,
|
|
+ ef_len - EB_HEADSIZE));
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (eb_id) {
|
|
+ case EF_QDOS:
|
|
+ {
|
|
+ struct _ntc_
|
|
+ {
|
|
+ long id;
|
|
+ long dlen;
|
|
+ } ntc;
|
|
+ long dlen = 0;
|
|
+
|
|
+ qdosextra *extra = (qdosextra *)ef_ptr;
|
|
+ jbextra *jbp = (jbextra *)ef_ptr;
|
|
+
|
|
+ if (!strncmp(extra->longid, LONGID, strlen(LONGID)))
|
|
+ {
|
|
+ if (eb_len != EXTRALEN)
|
|
+ if (uO.qflag)
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "warning: invalid length in Qdos field for %s\n",
|
|
+ FnFilter1(G.filename)));
|
|
+ else
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "warning: invalid length in Qdos field"));
|
|
+
|
|
+ if (extra->header.d_type)
|
|
+ {
|
|
+ dlen = extra->header.d_datalen;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID)))
|
|
+ {
|
|
+ if (eb_len != JBEXTRALEN)
|
|
+ if (uO.qflag)
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "warning: invalid length in QZ field for %s\n",
|
|
+ FnFilter1(G.filename)));
|
|
+ else
|
|
+ Info(slide, 0x201, ((char *)slide,
|
|
+ "warning: invalid length in QZ field"));
|
|
+ if (jbp->header.d_type)
|
|
+ {
|
|
+ dlen = jbp->header.d_datalen;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((long)LG(dlen) > 0)
|
|
+ {
|
|
+ zfseeko(G.outfile, -8, SEEK_END);
|
|
+ fread(&ntc, 8, 1, G.outfile);
|
|
+ if (ntc.id != *(long *)"XTcc")
|
|
+ {
|
|
+ ntc.id = *(long *)"XTcc";
|
|
+ ntc.dlen = dlen;
|
|
+ fwrite (&ntc, 8, 1, G.outfile);
|
|
+ }
|
|
+ Info(slide, 0x201, ((char *)slide, "QData = %d", LG(dlen)));
|
|
+ }
|
|
+ return; /* finished, cancel further extra field scanning */
|
|
+ }
|
|
+
|
|
+ default:
|
|
+ Trace((stderr,"qlfix: unknown extra field block, ID=%d\n",
|
|
+ eb_id));
|
|
+ }
|
|
+
|
|
+ /* Skip this extra field block */
|
|
+ ef_ptr += (eb_len + EB_HEADSIZE);
|
|
+ ef_len -= (eb_len + EB_HEADSIZE);
|
|
+ }
|
|
+}
|
|
+#endif /* QLZIP */
|
|
diff -Naur a/unix/unxcfg.h b/unix/unxcfg.h
|
|
--- a/unix/unxcfg.h 2009-04-16 19:36:12.000000000 +0100
|
|
+++ b/unix/unxcfg.h 2019-12-02 01:49:39.894641004 +0000
|
|
@@ -227,4 +227,30 @@
|
|
/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */
|
|
/* and notfirstcall are used by do_wild(). */
|
|
|
|
+
|
|
+#define MAX_CP_NAME 25 + 1
|
|
+
|
|
+#ifdef SETLOCALE
|
|
+# undef SETLOCALE
|
|
+#endif
|
|
+#define SETLOCALE(category, locale) setlocale(category, locale)
|
|
+#include <locale.h>
|
|
+
|
|
+#ifdef _ISO_INTERN
|
|
+# undef _ISO_INTERN
|
|
+#endif
|
|
+#define _ISO_INTERN(str1) iso_intern(str1)
|
|
+
|
|
+#ifdef _OEM_INTERN
|
|
+# undef _OEM_INTERN
|
|
+#endif
|
|
+#ifndef IZ_OEM2ISO_ARRAY
|
|
+# define IZ_OEM2ISO_ARRAY
|
|
+#endif
|
|
+#define _OEM_INTERN(str1) oem_intern(str1)
|
|
+
|
|
+void iso_intern(char *);
|
|
+void oem_intern(char *);
|
|
+void init_conversion_charsets(void);
|
|
+
|
|
#endif /* !__unxcfg_h */
|
|
diff -Naur a/unix/unxcfg.h.orig b/unix/unxcfg.h.orig
|
|
--- a/unix/unxcfg.h.orig 1970-01-01 01:00:00.000000000 +0100
|
|
+++ b/unix/unxcfg.h.orig 2009-04-16 19:36:12.000000000 +0100
|
|
@@ -0,0 +1,230 @@
|
|
+/*
|
|
+ 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
|
|
+*/
|
|
+/*---------------------------------------------------------------------------
|
|
+ Unix specific configuration section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifndef __unxcfg_h
|
|
+#define __unxcfg_h
|
|
+
|
|
+
|
|
+/* LARGE FILE SUPPORT - 10/6/04 EG */
|
|
+/* This needs to be set before the includes so they set the right sizes */
|
|
+
|
|
+#if (defined(NO_LARGE_FILE_SUPPORT) && defined(LARGE_FILE_SUPPORT))
|
|
+# undef LARGE_FILE_SUPPORT
|
|
+#endif
|
|
+
|
|
+/* Automatically set ZIP64_SUPPORT if LFS */
|
|
+#ifdef LARGE_FILE_SUPPORT
|
|
+# if (!defined(NO_ZIP64_SUPPORT) && !defined(ZIP64_SUPPORT))
|
|
+# define ZIP64_SUPPORT
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* NO_ZIP64_SUPPORT takes preceedence over ZIP64_SUPPORT */
|
|
+#if defined(NO_ZIP64_SUPPORT) && defined(ZIP64_SUPPORT)
|
|
+# undef ZIP64_SUPPORT
|
|
+#endif
|
|
+
|
|
+#ifdef LARGE_FILE_SUPPORT
|
|
+ /* 64-bit Large File Support */
|
|
+
|
|
+ /* The following Large File Summit (LFS) defines turn on large file support
|
|
+ on Linux (probably 2.4 or later kernel) and many other unixen */
|
|
+
|
|
+ /* These have to be before any include that sets types so the large file
|
|
+ versions of the types are set in the includes */
|
|
+
|
|
+# define _LARGEFILE_SOURCE /* some OSes need this for fseeko */
|
|
+# define _LARGEFILE64_SOURCE
|
|
+# define _FILE_OFFSET_BITS 64 /* select default interface as 64 bit */
|
|
+# define _LARGE_FILES /* some OSes need this for 64-bit off_t */
|
|
+# define __USE_LARGEFILE64
|
|
+#endif /* LARGE_FILE_SUPPORT */
|
|
+
|
|
+
|
|
+#include <sys/types.h> /* off_t, time_t, dev_t, ... */
|
|
+#include <sys/stat.h>
|
|
+
|
|
+#ifdef NO_OFF_T
|
|
+ typedef long zoff_t;
|
|
+#else
|
|
+ typedef off_t zoff_t;
|
|
+#endif
|
|
+#define ZOFF_T_DEFINED
|
|
+typedef struct stat z_stat;
|
|
+#define Z_STAT_DEFINED
|
|
+
|
|
+#ifndef COHERENT
|
|
+# include <fcntl.h> /* O_BINARY for open() w/o CR/LF translation */
|
|
+#else /* COHERENT */
|
|
+# ifdef _I386
|
|
+# include <fcntl.h> /* Coherent 4.0.x, Mark Williams C */
|
|
+# else
|
|
+# include <sys/fcntl.h> /* Coherent 3.10, Mark Williams C */
|
|
+# endif
|
|
+# define SHORT_SYMS
|
|
+# ifndef __COHERENT__ /* Coherent 4.2 has tzset() */
|
|
+# define tzset settz
|
|
+# endif
|
|
+#endif /* ?COHERENT */
|
|
+
|
|
+#ifndef NO_PARAM_H
|
|
+# ifdef NGROUPS_MAX
|
|
+# undef NGROUPS_MAX /* SCO bug: defined again in <sys/param.h> */
|
|
+# endif
|
|
+# ifdef BSD
|
|
+# define TEMP_BSD /* may be defined again in <sys/param.h> */
|
|
+# undef BSD
|
|
+# endif
|
|
+# include <sys/param.h> /* conflict with <sys/types.h>, some systems? */
|
|
+# ifdef TEMP_BSD
|
|
+# undef TEMP_BSD
|
|
+# ifndef BSD
|
|
+# define BSD
|
|
+# endif
|
|
+# endif
|
|
+#endif /* !NO_PARAM_H */
|
|
+
|
|
+#ifdef __osf__
|
|
+# define DIRENT
|
|
+# ifdef BSD
|
|
+# undef BSD
|
|
+# endif
|
|
+#endif /* __osf__ */
|
|
+
|
|
+#ifdef __CYGWIN__
|
|
+# include <unistd.h>
|
|
+# define DIRENT
|
|
+# define HAVE_TERMIOS_H
|
|
+# ifndef timezone
|
|
+# define timezone _timezone
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifdef BSD
|
|
+# include <sys/time.h>
|
|
+# include <sys/timeb.h>
|
|
+# if (defined(_AIX) || defined(__GLIBC__) || defined(__GNU__))
|
|
+# include <time.h>
|
|
+# endif
|
|
+#else
|
|
+# include <time.h>
|
|
+ struct tm *gmtime(), *localtime();
|
|
+#endif
|
|
+
|
|
+#if (defined(BSD4_4) || (defined(SYSV) && defined(MODERN)))
|
|
+# include <unistd.h> /* this includes utime.h on SGIs */
|
|
+# if (defined(BSD4_4) || defined(linux) || defined(__GLIBC__))
|
|
+# include <utime.h>
|
|
+# define GOT_UTIMBUF
|
|
+# endif
|
|
+# if (!defined(GOT_UTIMBUF) && (defined(__hpux) || defined(__SUNPRO_C)))
|
|
+# include <utime.h>
|
|
+# define GOT_UTIMBUF
|
|
+# endif
|
|
+# if (!defined(GOT_UTIMBUF) && defined(__GNU__))
|
|
+# include <utime.h>
|
|
+# define GOT_UTIMBUF
|
|
+# endif
|
|
+#endif
|
|
+#if (defined(__DGUX__) && !defined(GOT_UTIMBUF))
|
|
+ /* DG/UX requires this because of a non-standard struct utimebuf */
|
|
+# include <utime.h>
|
|
+# define GOT_UTIMBUF
|
|
+#endif
|
|
+
|
|
+#if (defined(V7) || defined(pyr_bsd))
|
|
+# define strchr index
|
|
+# define strrchr rindex
|
|
+#endif
|
|
+#ifdef V7
|
|
+# define O_RDONLY 0
|
|
+# define O_WRONLY 1
|
|
+# define O_RDWR 2
|
|
+#endif
|
|
+
|
|
+#if defined(NO_UNICODE_SUPPORT) && defined(UNICODE_SUPPORT)
|
|
+ /* disable Unicode (UTF-8) support when requested */
|
|
+# undef UNICODE_SUPPORT
|
|
+#endif
|
|
+
|
|
+#if (defined(_MBCS) && defined(NO_MBCS))
|
|
+ /* disable MBCS support when requested */
|
|
+# undef _MBCS
|
|
+#endif
|
|
+
|
|
+#if (!defined(NO_SETLOCALE) && !defined(_MBCS))
|
|
+# if (!defined(UNICODE_SUPPORT) || !defined(UTF8_MAYBE_NATIVE))
|
|
+ /* enable setlocale here, unless this happens later for UTF-8 and/or
|
|
+ * MBCS support */
|
|
+# include <locale.h>
|
|
+# ifndef SETLOCALE
|
|
+# define SETLOCALE(category, locale) setlocale(category, locale)
|
|
+# endif
|
|
+# endif
|
|
+#endif
|
|
+#ifndef NO_SETLOCALE
|
|
+# if (!defined(NO_WORKING_ISPRINT) && !defined(HAVE_WORKING_ISPRINT))
|
|
+ /* enable "enhanced" unprintable chars detection in fnfilter() */
|
|
+# define HAVE_WORKING_ISPRINT
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifdef MINIX
|
|
+# include <stdio.h>
|
|
+#endif
|
|
+#if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP))
|
|
+# define NO_STRNICMP
|
|
+#endif
|
|
+#ifndef DATE_FORMAT
|
|
+# define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */
|
|
+#endif
|
|
+#define lenEOL 1
|
|
+#ifdef EBCDIC
|
|
+# define PutNativeEOL *q++ = '\n';
|
|
+#else
|
|
+# define PutNativeEOL *q++ = native(LF);
|
|
+#endif
|
|
+#define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols)
|
|
+#define SCREENWIDTH 80
|
|
+#define SCREENLWRAP 1
|
|
+#define USE_EF_UT_TIME
|
|
+#if (!defined(NO_LCHOWN) || !defined(NO_LCHMOD))
|
|
+# define SET_SYMLINK_ATTRIBS
|
|
+#endif
|
|
+#ifdef MTS
|
|
+# ifdef SET_DIR_ATTRIB
|
|
+# undef SET_DIR_ATTRIB
|
|
+# endif
|
|
+#else /* !MTS */
|
|
+# define SET_DIR_ATTRIB
|
|
+# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) /* GRR 970513 */
|
|
+# define TIMESTAMP
|
|
+# endif
|
|
+# define RESTORE_UIDGID
|
|
+#endif /* ?MTS */
|
|
+
|
|
+/* Static variables that we have to add to Uz_Globs: */
|
|
+#define SYSTEM_SPECIFIC_GLOBALS \
|
|
+ int created_dir, renamed_fullpath;\
|
|
+ char *rootpath, *buildpath, *end;\
|
|
+ ZCONST char *wildname;\
|
|
+ char *dirname, matchname[FILNAMSIZ];\
|
|
+ int rootlen, have_dirname, dirnamelen, notfirstcall;\
|
|
+ zvoid *wild_dir;
|
|
+
|
|
+/* created_dir, and renamed_fullpath are used by both mapname() and */
|
|
+/* checkdir(). */
|
|
+/* rootlen, rootpath, buildpath and end are used by checkdir(). */
|
|
+/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */
|
|
+/* and notfirstcall are used by do_wild(). */
|
|
+
|
|
+#endif /* !__unxcfg_h */
|
|
diff -Naur a/unzip.c b/unzip.c
|
|
--- a/unzip.c 2009-04-16 19:26:52.000000000 +0100
|
|
+++ b/unzip.c 2019-12-02 01:49:39.895641007 +0000
|
|
@@ -327,11 +327,21 @@
|
|
-2 just filenames but allow -h/-t/-z -l long Unix \"ls -l\" format\n\
|
|
-v verbose, multi-page format\n";
|
|
|
|
+#ifndef UNIX
|
|
static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
|
|
-h print header line -t print totals for listed files or for all\n\
|
|
-z print zipfile comment -T print file times in sortable decimal format\
|
|
\n -C be case-insensitive %s\
|
|
-x exclude filenames that follow from listing\n";
|
|
+#else /* UNIX */
|
|
+static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
|
|
+ -h print header line -t print totals for listed files or for all\n\
|
|
+ -z print zipfile comment %c-T%c print file times in sortable decimal format\
|
|
+\n %c-C%c be case-insensitive %s\
|
|
+ -x exclude filenames that follow from listing\n\
|
|
+ -O CHARSET specify a character encoding for DOS, Windows and OS/2 archives\n\
|
|
+ -I CHARSET specify a character encoding for UNIX and other archives\n";
|
|
+#endif /* !UNIX */
|
|
#ifdef MORE
|
|
static ZCONST char Far ZipInfoUsageLine4[] =
|
|
" -M page output through built-in \"more\"\n";
|
|
@@ -665,6 +675,17 @@
|
|
-U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\
|
|
-C match filenames case-insensitively -L make (some) names \
|
|
lowercase\n %-42s -V retain VMS version numbers\n%s";
|
|
+#elif (defined UNIX)
|
|
+static ZCONST char Far UnzipUsageLine4[] = "\
|
|
+modifiers:\n\
|
|
+ -n never overwrite existing files -q quiet mode (-qq => quieter)\n\
|
|
+ -o overwrite files WITHOUT prompting -a auto-convert any text files\n\
|
|
+ -j junk paths (do not make directories) -aa treat ALL files as text\n\
|
|
+ -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\
|
|
+ -C match filenames case-insensitively -L make (some) names \
|
|
+lowercase\n %-42s -V retain VMS version numbers\n%s\
|
|
+ -O CHARSET specify a character encoding for DOS, Windows and OS/2 archives\n\
|
|
+ -I CHARSET specify a character encoding for UNIX and other archives\n\n";
|
|
#else /* !VMS */
|
|
static ZCONST char Far UnzipUsageLine4[] = "\
|
|
modifiers:\n\
|
|
@@ -803,6 +824,10 @@
|
|
#endif /* UNICODE_SUPPORT */
|
|
|
|
|
|
+#ifdef UNIX
|
|
+ init_conversion_charsets();
|
|
+#endif
|
|
+
|
|
#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
|
|
extern void DebugMalloc(void);
|
|
|
|
@@ -1336,6 +1361,11 @@
|
|
argc = *pargc;
|
|
argv = *pargv;
|
|
|
|
+#ifdef UNIX
|
|
+ extern char OEM_CP[MAX_CP_NAME];
|
|
+ extern char ISO_CP[MAX_CP_NAME];
|
|
+#endif
|
|
+
|
|
while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
|
|
s = *argv + 1;
|
|
while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */
|
|
@@ -1517,6 +1547,37 @@
|
|
}
|
|
break;
|
|
#endif /* MACOS */
|
|
+#ifdef UNIX
|
|
+ case ('I'):
|
|
+ if (negative) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: encodings can't be negated"));
|
|
+ return(PK_PARAM);
|
|
+ } else {
|
|
+ if(*s) { /* Handle the -Icharset case */
|
|
+ /* Assume that charsets can't start with a dash to spot arguments misuse */
|
|
+ if(*s == '-') {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: a valid character encoding should follow the -I argument"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ strncpy(ISO_CP, s, MAX_CP_NAME - 1);
|
|
+ ISO_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ } else { /* -I charset */
|
|
+ ++argv;
|
|
+ if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: a valid character encoding should follow the -I argument"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ s = *argv;
|
|
+ strncpy(ISO_CP, s, MAX_CP_NAME - 1);
|
|
+ ISO_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ }
|
|
+ while(*(++s)); /* No params straight after charset name */
|
|
+ }
|
|
+ break;
|
|
+#endif /* ?UNIX */
|
|
case ('j'): /* junk pathnames/directory structure */
|
|
if (negative)
|
|
uO.jflag = FALSE, negative = 0;
|
|
@@ -1592,6 +1653,37 @@
|
|
} else
|
|
++uO.overwrite_all;
|
|
break;
|
|
+#ifdef UNIX
|
|
+ case ('O'):
|
|
+ if (negative) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: encodings can't be negated"));
|
|
+ return(PK_PARAM);
|
|
+ } else {
|
|
+ if(*s) { /* Handle the -Ocharset case */
|
|
+ /* Assume that charsets can't start with a dash to spot arguments misuse */
|
|
+ if(*s == '-') {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: a valid character encoding should follow the -I argument"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ strncpy(OEM_CP, s, MAX_CP_NAME - 1);
|
|
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ } else { /* -O charset */
|
|
+ ++argv;
|
|
+ if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: a valid character encoding should follow the -O argument"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ s = *argv;
|
|
+ strncpy(OEM_CP, s, MAX_CP_NAME - 1);
|
|
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ }
|
|
+ while(*(++s)); /* No params straight after charset name */
|
|
+ }
|
|
+ break;
|
|
+#endif /* ?UNIX */
|
|
case ('p'): /* pipes: extract to stdout, no messages */
|
|
if (negative) {
|
|
uO.cflag = FALSE;
|
|
diff -Naur a/unzip.c.orig b/unzip.c.orig
|
|
--- a/unzip.c.orig 1970-01-01 01:00:00.000000000 +0100
|
|
+++ b/unzip.c.orig 2009-04-16 19:26:52.000000000 +0100
|
|
@@ -0,0 +1,2655 @@
|
|
+/*
|
|
+ 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
|
|
+*/
|
|
+/*---------------------------------------------------------------------------
|
|
+
|
|
+ unzip.c
|
|
+
|
|
+ UnZip - a zipfile extraction utility. See below for make instructions, or
|
|
+ read the comments in Makefile and the various Contents files for more de-
|
|
+ tailed explanations. To report a bug, submit a *complete* description via
|
|
+ //www.info-zip.org/zip-bug.html; include machine type, operating system and
|
|
+ version, compiler and version, and reasonably detailed error messages or
|
|
+ problem report. To join Info-ZIP, see the instructions in README.
|
|
+
|
|
+ UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
|
|
+ which in turn was almost a complete rewrite of version 3.x. For a detailed
|
|
+ revision history, see UnzpHist.zip at quest.jpl.nasa.gov. For a list of
|
|
+ the many (near infinite) contributors, see "CONTRIBS" in the UnZip source
|
|
+ distribution.
|
|
+
|
|
+ UnZip 6.0 adds support for archives larger than 4 GiB using the Zip64
|
|
+ extensions as well as support for Unicode information embedded per the
|
|
+ latest zip standard additions.
|
|
+
|
|
+ ---------------------------------------------------------------------------
|
|
+
|
|
+ [from original zipinfo.c]
|
|
+
|
|
+ This program reads great gobs of totally nifty information, including the
|
|
+ central directory stuff, from ZIP archives ("zipfiles" for short). It
|
|
+ started as just a testbed for fooling with zipfiles, but at this point it
|
|
+ is actually a useful utility. It also became the basis for the rewrite of
|
|
+ UnZip (3.16 -> 4.0), using the central directory for processing rather than
|
|
+ the individual (local) file headers.
|
|
+
|
|
+ As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.
|
|
+ If the executable is named "unzip" (or "unzip.exe", depending), it behaves
|
|
+ like UnZip by default; if it is named "zipinfo" or "ii", it behaves like
|
|
+ ZipInfo. The ZipInfo behavior may also be triggered by use of unzip's -Z
|
|
+ option; for example, "unzip -Z [zipinfo_options] archive.zip".
|
|
+
|
|
+ Another dandy product from your buddies at Newtware!
|
|
+
|
|
+ Author: Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/
|
|
+ 23 August 1990 -> April 1997
|
|
+
|
|
+ ---------------------------------------------------------------------------
|
|
+
|
|
+ Version: unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga,
|
|
+ Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS,
|
|
+ AtheOS, BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS, Tandem NSK, Theos
|
|
+ and TOPS-20.
|
|
+
|
|
+ Copyrights: see accompanying file "LICENSE" in UnZip source distribution.
|
|
+ (This software is free but NOT IN THE PUBLIC DOMAIN.)
|
|
+
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+
|
|
+
|
|
+#define __UNZIP_C /* identifies this source module */
|
|
+#define UNZIP_INTERNAL
|
|
+#include "unzip.h" /* includes, typedefs, macros, prototypes, etc. */
|
|
+#include "crypt.h"
|
|
+#include "unzvers.h"
|
|
+
|
|
+#ifndef WINDLL /* The WINDLL port uses windll/windll.c instead... */
|
|
+
|
|
+/***************************/
|
|
+/* Local type declarations */
|
|
+/***************************/
|
|
+
|
|
+#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
|
|
+typedef struct _sign_info
|
|
+ {
|
|
+ struct _sign_info *previous;
|
|
+ void (*sighandler)(int);
|
|
+ int sigtype;
|
|
+ } savsigs_info;
|
|
+#endif
|
|
+
|
|
+/*******************/
|
|
+/* Local Functions */
|
|
+/*******************/
|
|
+
|
|
+#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
|
|
+static int setsignalhandler OF((__GPRO__ savsigs_info **p_savedhandler_chain,
|
|
+ int signal_type, void (*newhandler)(int)));
|
|
+#endif
|
|
+#ifndef SFX
|
|
+static void help_extended OF((__GPRO));
|
|
+static void show_version_info OF((__GPRO));
|
|
+#endif
|
|
+
|
|
+
|
|
+/*************/
|
|
+/* Constants */
|
|
+/*************/
|
|
+
|
|
+#include "consts.h" /* all constant global variables are in here */
|
|
+ /* (non-constant globals were moved to globals.c) */
|
|
+
|
|
+/* constant local variables: */
|
|
+
|
|
+#ifndef SFX
|
|
+#ifndef _WIN32_WCE /* Win CE does not support environment variables */
|
|
+ static ZCONST char Far EnvUnZip[] = ENV_UNZIP;
|
|
+ static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2;
|
|
+ static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO;
|
|
+ static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2;
|
|
+#ifdef RISCOS
|
|
+ static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS;
|
|
+#endif /* RISCOS */
|
|
+ static ZCONST char Far NoMemEnvArguments[] =
|
|
+ "envargs: cannot get memory for arguments";
|
|
+#endif /* !_WIN32_WCE */
|
|
+ static ZCONST char Far CmdLineParamTooLong[] =
|
|
+ "error: command line parameter #%d exceeds internal size limit\n";
|
|
+#endif /* !SFX */
|
|
+
|
|
+#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
|
|
+ static ZCONST char Far CantSaveSigHandler[] =
|
|
+ "error: cannot save signal handler settings\n";
|
|
+#endif
|
|
+
|
|
+#if (!defined(SFX) || defined(SFX_EXDIR))
|
|
+ static ZCONST char Far NotExtracting[] =
|
|
+ "caution: not extracting; -d ignored\n";
|
|
+ static ZCONST char Far MustGiveExdir[] =
|
|
+ "error: must specify directory to which to extract with -d option\n";
|
|
+ static ZCONST char Far OnlyOneExdir[] =
|
|
+ "error: -d option used more than once (only one exdir allowed)\n";
|
|
+#endif
|
|
+#if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR))
|
|
+ static ZCONST char Far UTF8EscapeUnSupp[] =
|
|
+ "warning: -U \"escape all non-ASCII UTF-8 chars\" is not supported\n";
|
|
+#endif
|
|
+
|
|
+#if CRYPT
|
|
+ static ZCONST char Far MustGivePasswd[] =
|
|
+ "error: must give decryption password with -P option\n";
|
|
+#endif
|
|
+
|
|
+#ifndef SFX
|
|
+ static ZCONST char Far Zfirst[] =
|
|
+ "error: -Z must be first option for ZipInfo mode (check UNZIP variable?)\n";
|
|
+#endif
|
|
+static ZCONST char Far InvalidOptionsMsg[] = "error:\
|
|
+ -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
|
|
+static ZCONST char Far IgnoreOOptionMsg[] =
|
|
+ "caution: both -n and -o specified; ignoring -o\n";
|
|
+
|
|
+/* usage() strings */
|
|
+#ifndef SFX
|
|
+#ifdef VMS
|
|
+ static ZCONST char Far Example3[] = "vms.c";
|
|
+ static ZCONST char Far Example2[] = " unzip \"-V\" foo \"Bar\"\
|
|
+ (Quote names to preserve case, unless SET PROC/PARS=EXT)\n";
|
|
+#else /* !VMS */
|
|
+ static ZCONST char Far Example3[] = "ReadMe";
|
|
+#ifdef RISCOS
|
|
+ static ZCONST char Far Example2[] =
|
|
+" unzip foo -d RAM:$ => extract all files from foo into RAMDisc\n";
|
|
+#else /* !RISCOS */
|
|
+#if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE)))
|
|
+ static ZCONST char Far Example2[] =
|
|
+ ""; /* no room: too many local3[] items */
|
|
+#else /* !OS2 */
|
|
+#ifdef MACOS
|
|
+ static ZCONST char Far Example2[] = ""; /* not needed */
|
|
+#else /* !MACOS */
|
|
+ static ZCONST char Far Example2[] = " \
|
|
+ unzip -p foo | more => send contents of foo.zip via pipe into program more\n";
|
|
+#endif /* ?MACOS */
|
|
+#endif /* ?OS2 */
|
|
+#endif /* ?RISCOS */
|
|
+#endif /* ?VMS */
|
|
+
|
|
+/* local1[]: command options */
|
|
+#if defined(TIMESTAMP)
|
|
+ static ZCONST char Far local1[] =
|
|
+ " -T timestamp archive to latest";
|
|
+#else /* !TIMESTAMP */
|
|
+ static ZCONST char Far local1[] = "";
|
|
+#endif /* ?TIMESTAMP */
|
|
+
|
|
+/* local2[] and local3[]: modifier options */
|
|
+#ifdef DOS_FLX_H68_OS2_W32
|
|
+#ifdef FLEXOS
|
|
+ static ZCONST char Far local2[] = "";
|
|
+#else
|
|
+ static ZCONST char Far local2[] =
|
|
+ " -$ label removables (-$$ => fixed disks)";
|
|
+#endif
|
|
+#ifdef OS2
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local3[] = "\
|
|
+ -X restore ACLs if supported -s spaces in filenames => '_'\n\
|
|
+ -M pipe through \"more\" pager\n";
|
|
+#else
|
|
+ static ZCONST char Far local3[] = " \
|
|
+ -X restore ACLs if supported -s spaces in filenames => '_'\n\n";
|
|
+#endif /* ?MORE */
|
|
+#else /* !OS2 */
|
|
+#ifdef WIN32
|
|
+#ifdef NTSD_EAS
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local3[] = "\
|
|
+ -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\
|
|
+ -M pipe through \"more\" pager\n";
|
|
+#else
|
|
+ static ZCONST char Far local3[] = " \
|
|
+ -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\n";
|
|
+#endif /* ?MORE */
|
|
+#else /* !NTSD_EAS */
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local3[] = "\
|
|
+ -M pipe through \"more\" pager \
|
|
+ -s spaces in filenames => '_'\n\n";
|
|
+#else
|
|
+ static ZCONST char Far local3[] = " \
|
|
+ -s spaces in filenames => '_'\n\n";
|
|
+#endif /* ?MORE */
|
|
+#endif /* ?NTSD_EAS */
|
|
+#else /* !WIN32 */
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local3[] = " -\
|
|
+M pipe through \"more\" pager -s spaces in filenames => '_'\n\n";
|
|
+#else
|
|
+ static ZCONST char Far local3[] = "\
|
|
+ -s spaces in filenames => '_'\n";
|
|
+#endif
|
|
+#endif /* ?WIN32 */
|
|
+#endif /* ?OS2 || ?WIN32 */
|
|
+#else /* !DOS_FLX_OS2_W32 */
|
|
+#ifdef VMS
|
|
+ static ZCONST char Far local2[] = " -X restore owner/ACL protection info";
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local3[] = "\
|
|
+ -Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\
|
|
+ --D restore dir (-D: no) timestamps -M pipe through \"more\" pager\n\
|
|
+ (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\
|
|
+\n\n";
|
|
+#else
|
|
+ static ZCONST char Far local3[] = "\n\
|
|
+ -Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\
|
|
+ --D restore dir (-D: no) timestamps\n\
|
|
+ (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\
|
|
+\n\n";
|
|
+#endif
|
|
+#else /* !VMS */
|
|
+#ifdef ATH_BEO_UNX
|
|
+ static ZCONST char Far local2[] = " -X restore UID/GID info";
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local3[] = "\
|
|
+ -K keep setuid/setgid/tacky permissions -M pipe through \"more\" pager\n";
|
|
+#else
|
|
+ static ZCONST char Far local3[] = "\
|
|
+ -K keep setuid/setgid/tacky permissions\n";
|
|
+#endif
|
|
+#else /* !ATH_BEO_UNX */
|
|
+#ifdef TANDEM
|
|
+ static ZCONST char Far local2[] = "\
|
|
+ -X restore Tandem User ID -r remove file extensions\n\
|
|
+ -b create 'C' (180) text files ";
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local3[] = " \
|
|
+ -M pipe through \"more\" pager\n";
|
|
+#else
|
|
+ static ZCONST char Far local3[] = "\n";
|
|
+#endif
|
|
+#else /* !TANDEM */
|
|
+#ifdef AMIGA
|
|
+ static ZCONST char Far local2[] = " -N restore comments as filenotes";
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local3[] = " \
|
|
+ -M pipe through \"more\" pager\n";
|
|
+#else
|
|
+ static ZCONST char Far local3[] = "\n";
|
|
+#endif
|
|
+#else /* !AMIGA */
|
|
+#ifdef MACOS
|
|
+ static ZCONST char Far local2[] = " -E show Mac info during extraction";
|
|
+ static ZCONST char Far local3[] = " \
|
|
+ -i ignore filenames in mac extra info -J junk (ignore) Mac extra info\n\
|
|
+\n";
|
|
+#else /* !MACOS */
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far local2[] = " -M pipe through \"more\" pager";
|
|
+ static ZCONST char Far local3[] = "\n";
|
|
+#else
|
|
+ static ZCONST char Far local2[] = ""; /* Atari, Mac, CMS/MVS etc. */
|
|
+ static ZCONST char Far local3[] = "";
|
|
+#endif
|
|
+#endif /* ?MACOS */
|
|
+#endif /* ?AMIGA */
|
|
+#endif /* ?TANDEM */
|
|
+#endif /* ?ATH_BEO_UNX */
|
|
+#endif /* ?VMS */
|
|
+#endif /* ?DOS_FLX_OS2_W32 */
|
|
+#endif /* !SFX */
|
|
+
|
|
+#ifndef NO_ZIPINFO
|
|
+#ifdef VMS
|
|
+ static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")";
|
|
+#else
|
|
+ static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")";
|
|
+#endif
|
|
+
|
|
+static ZCONST char Far ZipInfoUsageLine1[] = "\
|
|
+ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\
|
|
+\n\
|
|
+List name, date/time, attribute, size, compression method, etc., about files\n\
|
|
+in list (excluding those in xlist) contained in the specified .zip archive(s).\
|
|
+\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\
|
|
+ usage: zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\
|
|
+ or: unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n";
|
|
+
|
|
+static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\
|
|
+ listing-format options: -s short Unix \"ls -l\" format (def.)\n\
|
|
+ -1 filenames ONLY, one per line -m medium Unix \"ls -l\" format\n\
|
|
+ -2 just filenames but allow -h/-t/-z -l long Unix \"ls -l\" format\n\
|
|
+ -v verbose, multi-page format\n";
|
|
+
|
|
+static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
|
|
+ -h print header line -t print totals for listed files or for all\n\
|
|
+ -z print zipfile comment -T print file times in sortable decimal format\
|
|
+\n -C be case-insensitive %s\
|
|
+ -x exclude filenames that follow from listing\n";
|
|
+#ifdef MORE
|
|
+ static ZCONST char Far ZipInfoUsageLine4[] =
|
|
+ " -M page output through built-in \"more\"\n";
|
|
+#else /* !MORE */
|
|
+ static ZCONST char Far ZipInfoUsageLine4[] = "";
|
|
+#endif /* ?MORE */
|
|
+#endif /* !NO_ZIPINFO */
|
|
+
|
|
+#ifdef BETA
|
|
+# ifdef VMSCLI
|
|
+ /* BetaVersion[] is also used in vms/cmdline.c: do not make it static */
|
|
+ ZCONST char Far BetaVersion[] = "%s\
|
|
+ THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
|
|
+# else
|
|
+ static ZCONST char Far BetaVersion[] = "%s\
|
|
+ THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifdef SFX
|
|
+# ifdef VMSCLI
|
|
+ /* UnzipSFXBanner[] is also used in vms/cmdline.c: do not make it static */
|
|
+ ZCONST char Far UnzipSFXBanner[] =
|
|
+# else
|
|
+ static ZCONST char Far UnzipSFXBanner[] =
|
|
+# endif
|
|
+ "UnZipSFX %d.%d%d%s of %s, by Info-ZIP (http://www.info-zip.org).\n";
|
|
+# ifdef SFX_EXDIR
|
|
+ static ZCONST char Far UnzipSFXOpts[] =
|
|
+ "Valid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCL%sV%s.\n";
|
|
+# else
|
|
+ static ZCONST char Far UnzipSFXOpts[] =
|
|
+ "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n";
|
|
+# endif
|
|
+#else /* !SFX */
|
|
+ static ZCONST char Far CompileOptions[] =
|
|
+ "UnZip special compilation options:\n";
|
|
+ static ZCONST char Far CompileOptFormat[] = " %s\n";
|
|
+#ifndef _WIN32_WCE /* Win CE does not support environment variables */
|
|
+ static ZCONST char Far EnvOptions[] =
|
|
+ "\nUnZip and ZipInfo environment options:\n";
|
|
+ static ZCONST char Far EnvOptFormat[] = "%16s: %.1024s\n";
|
|
+#endif
|
|
+ static ZCONST char Far None[] = "[none]";
|
|
+# ifdef ACORN_FTYPE_NFS
|
|
+ static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS";
|
|
+# endif
|
|
+# ifdef ASM_CRC
|
|
+ static ZCONST char Far AsmCRC[] = "ASM_CRC";
|
|
+# endif
|
|
+# ifdef ASM_INFLATECODES
|
|
+ static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES";
|
|
+# endif
|
|
+# ifdef CHECK_VERSIONS
|
|
+ static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS";
|
|
+# endif
|
|
+# ifdef COPYRIGHT_CLEAN
|
|
+ static ZCONST char Far Copyright_Clean[] =
|
|
+ "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)";
|
|
+# endif
|
|
+# ifdef DEBUG
|
|
+ static ZCONST char Far UDebug[] = "DEBUG";
|
|
+# endif
|
|
+# ifdef DEBUG_TIME
|
|
+ static ZCONST char Far DebugTime[] = "DEBUG_TIME";
|
|
+# endif
|
|
+# ifdef DLL
|
|
+ static ZCONST char Far Dll[] = "DLL";
|
|
+# endif
|
|
+# ifdef DOSWILD
|
|
+ static ZCONST char Far DosWild[] = "DOSWILD";
|
|
+# endif
|
|
+# ifdef LZW_CLEAN
|
|
+ static ZCONST char Far LZW_Clean[] =
|
|
+ "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)";
|
|
+# endif
|
|
+# ifndef MORE
|
|
+ static ZCONST char Far No_More[] = "NO_MORE";
|
|
+# endif
|
|
+# ifdef NO_ZIPINFO
|
|
+ static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO";
|
|
+# endif
|
|
+# ifdef NTSD_EAS
|
|
+ static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS";
|
|
+# endif
|
|
+# if defined(WIN32) && defined(NO_W32TIMES_IZFIX)
|
|
+ static ZCONST char Far W32NoIZTimeFix[] = "NO_W32TIMES_IZFIX";
|
|
+# endif
|
|
+# ifdef OLD_THEOS_EXTRA
|
|
+ static ZCONST char Far OldTheosExtra[] =
|
|
+ "OLD_THEOS_EXTRA (handle also old Theos port extra field)";
|
|
+# endif
|
|
+# ifdef OS2_EAS
|
|
+ static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS";
|
|
+# endif
|
|
+# ifdef QLZIP
|
|
+ static ZCONST char Far SMSExFldOnUnix[] = "QLZIP";
|
|
+# endif
|
|
+# ifdef REENTRANT
|
|
+ static ZCONST char Far Reentrant[] = "REENTRANT";
|
|
+# endif
|
|
+# ifdef REGARGS
|
|
+ static ZCONST char Far RegArgs[] = "REGARGS";
|
|
+# endif
|
|
+# ifdef RETURN_CODES
|
|
+ static ZCONST char Far Return_Codes[] = "RETURN_CODES";
|
|
+# endif
|
|
+# ifdef SET_DIR_ATTRIB
|
|
+ static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB";
|
|
+# endif
|
|
+# ifdef SYMLINKS
|
|
+ static ZCONST char Far SymLinkSupport[] =
|
|
+ "SYMLINKS (symbolic links supported, if RTL and file system permit)";
|
|
+# endif
|
|
+# ifdef TIMESTAMP
|
|
+ static ZCONST char Far TimeStamp[] = "TIMESTAMP";
|
|
+# endif
|
|
+# ifdef UNIXBACKUP
|
|
+ static ZCONST char Far UnixBackup[] = "UNIXBACKUP";
|
|
+# endif
|
|
+# ifdef USE_EF_UT_TIME
|
|
+ static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME";
|
|
+# endif
|
|
+# ifndef LZW_CLEAN
|
|
+ static ZCONST char Far Use_Unshrink[] =
|
|
+ "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)";
|
|
+# endif
|
|
+# ifndef COPYRIGHT_CLEAN
|
|
+ static ZCONST char Far Use_Smith_Code[] =
|
|
+ "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)";
|
|
+# endif
|
|
+# ifdef USE_DEFLATE64
|
|
+ static ZCONST char Far Use_Deflate64[] =
|
|
+ "USE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported)";
|
|
+# endif
|
|
+# ifdef UNICODE_SUPPORT
|
|
+# ifdef UTF8_MAYBE_NATIVE
|
|
+# ifdef UNICODE_WCHAR
|
|
+ /* direct native UTF-8 check AND charset transform via wchar_t */
|
|
+ static ZCONST char Far Use_Unicode[] =
|
|
+ "UNICODE_SUPPORT [wide-chars, char coding: %s] (handle UTF-8 paths)";
|
|
+# else
|
|
+ /* direct native UTF-8 check, only */
|
|
+ static ZCONST char Far Use_Unicode[] =
|
|
+ "UNICODE_SUPPORT [char coding: %s] (handle UTF-8 paths)";
|
|
+# endif
|
|
+ static ZCONST char Far SysChUTF8[] = "UTF-8";
|
|
+ static ZCONST char Far SysChOther[] = "other";
|
|
+# else /* !UTF8_MAYBE_NATIVE */
|
|
+ /* charset transform via wchar_t, no native UTF-8 support */
|
|
+ static ZCONST char Far Use_Unicode[] =
|
|
+ "UNICODE_SUPPORT [wide-chars] (handle UTF-8 paths)";
|
|
+# endif /* ?UTF8_MAYBE_NATIVE */
|
|
+# endif /* UNICODE_SUPPORT */
|
|
+# ifdef _MBCS
|
|
+ static ZCONST char Far Have_MBCS_Support[] =
|
|
+ "MBCS-support (multibyte character support, MB_CUR_MAX = %u)";
|
|
+# endif
|
|
+# ifdef MULT_VOLUME
|
|
+ static ZCONST char Far Use_MultiVol[] =
|
|
+ "MULT_VOLUME (multi-volume archives supported)";
|
|
+# endif
|
|
+# ifdef LARGE_FILE_SUPPORT
|
|
+ static ZCONST char Far Use_LFS[] =
|
|
+ "LARGE_FILE_SUPPORT (large files over 2 GiB supported)";
|
|
+# endif
|
|
+# ifdef ZIP64_SUPPORT
|
|
+ static ZCONST char Far Use_Zip64[] =
|
|
+ "ZIP64_SUPPORT (archives using Zip64 for large files supported)";
|
|
+# endif
|
|
+# if (defined(__DJGPP__) && (__DJGPP__ >= 2))
|
|
+# ifdef USE_DJGPP_ENV
|
|
+ static ZCONST char Far Use_DJGPP_Env[] = "USE_DJGPP_ENV";
|
|
+# endif
|
|
+# ifdef USE_DJGPP_GLOB
|
|
+ static ZCONST char Far Use_DJGPP_Glob[] = "USE_DJGPP_GLOB";
|
|
+# endif
|
|
+# endif /* __DJGPP__ && (__DJGPP__ >= 2) */
|
|
+# ifdef USE_VFAT
|
|
+ static ZCONST char Far Use_VFAT_support[] = "USE_VFAT";
|
|
+# endif
|
|
+# ifdef USE_ZLIB
|
|
+ static ZCONST char Far UseZlib[] =
|
|
+ "USE_ZLIB (compiled with version %s; using version %s)";
|
|
+# endif
|
|
+# ifdef USE_BZIP2
|
|
+ static ZCONST char Far UseBZip2[] =
|
|
+ "USE_BZIP2 (PKZIP 4.6+, using bzip2 lib version %s)";
|
|
+# endif
|
|
+# ifdef VMS_TEXT_CONV
|
|
+ static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV";
|
|
+# endif
|
|
+# ifdef VMSCLI
|
|
+ static ZCONST char Far VmsCLI[] = "VMSCLI";
|
|
+# endif
|
|
+# ifdef VMSWILD
|
|
+ static ZCONST char Far VmsWild[] = "VMSWILD";
|
|
+# endif
|
|
+# ifdef WILD_STOP_AT_DIR
|
|
+ static ZCONST char Far WildStopAtDir[] = "WILD_STOP_AT_DIR";
|
|
+# endif
|
|
+# if CRYPT
|
|
+# ifdef PASSWD_FROM_STDIN
|
|
+ static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN";
|
|
+# endif
|
|
+ static ZCONST char Far Decryption[] =
|
|
+ " [decryption, version %d.%d%s of %s]\n";
|
|
+ static ZCONST char Far CryptDate[] = CR_VERSION_DATE;
|
|
+# endif
|
|
+# ifndef __RSXNT__
|
|
+# ifdef __EMX__
|
|
+ static ZCONST char Far EnvEMX[] = "EMX";
|
|
+ static ZCONST char Far EnvEMXOPT[] = "EMXOPT";
|
|
+# endif
|
|
+# if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
|
|
+ static ZCONST char Far EnvGO32[] = "GO32";
|
|
+ static ZCONST char Far EnvGO32TMP[] = "GO32TMP";
|
|
+# endif
|
|
+# endif /* !__RSXNT__ */
|
|
+
|
|
+#ifdef VMS
|
|
+/* UnzipUsageLine1[] is also used in vms/cmdline.c: do not make it static */
|
|
+ ZCONST char Far UnzipUsageLine1[] = "\
|
|
+UnZip %d.%d%d%s of %s, by Info-ZIP. For more details see: unzip -v.\n\n";
|
|
+# ifdef COPYRIGHT_CLEAN
|
|
+ static ZCONST char Far UnzipUsageLine1v[] = "\
|
|
+UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\
|
|
+bug reports using http://www.info-zip.org/zip-bug.html; see README for details.\
|
|
+\n\n";
|
|
+# else
|
|
+ static ZCONST char Far UnzipUsageLine1v[] = "\
|
|
+UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\
|
|
+Send bug reports using //www.info-zip.org/zip-bug.html; see README for details.\
|
|
+\n\n";
|
|
+# endif /* ?COPYRIGHT_CLEAN */
|
|
+#else /* !VMS */
|
|
+# ifdef COPYRIGHT_CLEAN
|
|
+ static ZCONST char Far UnzipUsageLine1[] = "\
|
|
+UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\
|
|
+bug reports using http://www.info-zip.org/zip-bug.html; see README for details.\
|
|
+\n\n";
|
|
+# else
|
|
+ static ZCONST char Far UnzipUsageLine1[] = "\
|
|
+UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\
|
|
+Send bug reports using //www.info-zip.org/zip-bug.html; see README for details.\
|
|
+\n\n";
|
|
+# endif /* ?COPYRIGHT_CLEAN */
|
|
+# define UnzipUsageLine1v UnzipUsageLine1
|
|
+#endif /* ?VMS */
|
|
+
|
|
+static ZCONST char Far UnzipUsageLine2v[] = "\
|
|
+Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ;\
|
|
+\nsee ftp://ftp.info-zip.org/pub/infozip/UnZip.html for other sites.\
|
|
+\n\n";
|
|
+
|
|
+#ifdef MACOS
|
|
+static ZCONST char Far UnzipUsageLine2[] = "\
|
|
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \
|
|
+ Default action is to extract files in list, to exdir;\n\
|
|
+ file[.zip] may be a wildcard. %s\n";
|
|
+#else /* !MACOS */
|
|
+#ifdef VM_CMS
|
|
+static ZCONST char Far UnzipUsageLine2[] = "\
|
|
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \
|
|
+ Default action is to extract files in list, except those in xlist, to disk fm;\
|
|
+\n file[.zip] may be a wildcard. %s\n";
|
|
+#else /* !VM_CMS */
|
|
+static ZCONST char Far UnzipUsageLine2[] = "\
|
|
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
|
|
+ Default action is to extract files in list, except those in xlist, to exdir;\n\
|
|
+ file[.zip] may be a wildcard. %s\n";
|
|
+#endif /* ?VM_CMS */
|
|
+#endif /* ?MACOS */
|
|
+
|
|
+#ifdef NO_ZIPINFO
|
|
+# define ZIPINFO_MODE_OPTION ""
|
|
+ static ZCONST char Far ZipInfoMode[] =
|
|
+ "(ZipInfo mode is disabled in this version.)";
|
|
+#else
|
|
+# define ZIPINFO_MODE_OPTION "[-Z] "
|
|
+ static ZCONST char Far ZipInfoMode[] =
|
|
+ "-Z => ZipInfo mode (\"unzip -Z\" for usage).";
|
|
+#endif /* ?NO_ZIPINFO */
|
|
+
|
|
+#ifdef VMS
|
|
+ static ZCONST char Far VMSusageLine2b[] = "\
|
|
+=> define foreign command symbol in LOGIN.COM: $ unzip :== $dev:[dir]unzip.exe\
|
|
+\n";
|
|
+#endif
|
|
+
|
|
+#ifdef MACOS
|
|
+static ZCONST char Far UnzipUsageLine3[] = "\n\
|
|
+ -d extract files into exdir -l list files (short format)\n\
|
|
+ -f freshen existing files, create none -t test compressed archive data\n\
|
|
+ -u update files, create if necessary -z display archive comment only\n\
|
|
+ -v list verbosely/show version info %s\n";
|
|
+#else /* !MACOS */
|
|
+#ifdef VM_CMS
|
|
+static ZCONST char Far UnzipUsageLine3[] = "\n\
|
|
+ -p extract files to pipe, no messages -l list files (short format)\n\
|
|
+ -f freshen existing files, create none -t test compressed archive data\n\
|
|
+ -u update files, create if necessary -z display archive comment only\n\
|
|
+ -v list verbosely/show version info %s\n\
|
|
+ -x exclude files that follow (in xlist) -d extract files onto disk fm\n";
|
|
+#else /* !VM_CMS */
|
|
+static ZCONST char Far UnzipUsageLine3[] = "\n\
|
|
+ -p extract files to pipe, no messages -l list files (short format)\n\
|
|
+ -f freshen existing files, create none -t test compressed archive data\n\
|
|
+ -u update files, create if necessary -z display archive comment only\n\
|
|
+ -v list verbosely/show version info %s\n\
|
|
+ -x exclude files that follow (in xlist) -d extract files into exdir\n";
|
|
+#endif /* ?VM_CMS */
|
|
+#endif /* ?MACOS */
|
|
+
|
|
+/* There is not enough space on a standard 80x25 Windows console screen for
|
|
+ * the additional line advertising the UTF-8 debugging options. This may
|
|
+ * eventually also be the case for other ports. Probably, the -U option need
|
|
+ * not be shown on the introductory screen at all. [Chr. Spieler, 2008-02-09]
|
|
+ *
|
|
+ * Likely, other advanced options should be moved to an extended help page and
|
|
+ * the option to list that page put here. [E. Gordon, 2008-3-16]
|
|
+ */
|
|
+#if (defined(UNICODE_SUPPORT) && !defined(WIN32))
|
|
+#ifdef VMS
|
|
+static ZCONST char Far UnzipUsageLine4[] = "\
|
|
+modifiers:\n\
|
|
+ -n never overwrite or make a new version of an existing file\n\
|
|
+ -o always make a new version (-oo: overwrite original) of an existing file\n\
|
|
+ -q quiet mode (-qq => quieter) -a auto-convert any text files\n\
|
|
+ -j junk paths (do not make directories) -aa treat ALL files as text\n\
|
|
+ -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\
|
|
+ -C match filenames case-insensitively -L make (some) names \
|
|
+lowercase\n %-42s -V retain VMS version numbers\n%s";
|
|
+#else /* !VMS */
|
|
+static ZCONST char Far UnzipUsageLine4[] = "\
|
|
+modifiers:\n\
|
|
+ -n never overwrite existing files -q quiet mode (-qq => quieter)\n\
|
|
+ -o overwrite files WITHOUT prompting -a auto-convert any text files\n\
|
|
+ -j junk paths (do not make directories) -aa treat ALL files as text\n\
|
|
+ -U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields\n\
|
|
+ -C match filenames case-insensitively -L make (some) names \
|
|
+lowercase\n %-42s -V retain VMS version numbers\n%s";
|
|
+#endif /* ?VMS */
|
|
+#else /* !UNICODE_SUPPORT */
|
|
+#ifdef VMS
|
|
+static ZCONST char Far UnzipUsageLine4[] = "\
|
|
+modifiers:\n\
|
|
+ -n never overwrite or make a new version of an existing file\n\
|
|
+ -o always make a new version (-oo: overwrite original) of an existing file\n\
|
|
+ -q quiet mode (-qq => quieter) -a auto-convert any text files\n\
|
|
+ -j junk paths (do not make directories) -aa treat ALL files as text\n\
|
|
+ -C match filenames case-insensitively -L make (some) names \
|
|
+lowercase\n %-42s -V retain VMS version numbers\n%s";
|
|
+#else /* !VMS */
|
|
+static ZCONST char Far UnzipUsageLine4[] = "\
|
|
+modifiers:\n\
|
|
+ -n never overwrite existing files -q quiet mode (-qq => quieter)\n\
|
|
+ -o overwrite files WITHOUT prompting -a auto-convert any text files\n\
|
|
+ -j junk paths (do not make directories) -aa treat ALL files as text\n\
|
|
+ -C match filenames case-insensitively -L make (some) names \
|
|
+lowercase\n %-42s -V retain VMS version numbers\n%s";
|
|
+#endif /* ?VMS */
|
|
+#endif /* ?UNICODE_SUPPORT */
|
|
+
|
|
+static ZCONST char Far UnzipUsageLine5[] = "\
|
|
+See \"unzip -hh\" or unzip.txt for more help. Examples:\n\
|
|
+ unzip data1 -x joe => extract all files except joe from zipfile data1.zip\n\
|
|
+%s\
|
|
+ unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n";
|
|
+#endif /* ?SFX */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*****************************/
|
|
+/* main() / UzpMain() stub */
|
|
+/*****************************/
|
|
+
|
|
+int MAIN(argc, argv) /* return PK-type error code (except under VMS) */
|
|
+ int argc;
|
|
+ char *argv[];
|
|
+{
|
|
+ int r;
|
|
+
|
|
+ CONSTRUCTGLOBALS();
|
|
+ r = unzip(__G__ argc, argv);
|
|
+ DESTROYGLOBALS();
|
|
+ RETURN(r);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*******************************/
|
|
+/* Primary UnZip entry point */
|
|
+/*******************************/
|
|
+
|
|
+int unzip(__G__ argc, argv)
|
|
+ __GDEF
|
|
+ int argc;
|
|
+ char *argv[];
|
|
+{
|
|
+#ifndef NO_ZIPINFO
|
|
+ char *p;
|
|
+#endif
|
|
+#if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX))
|
|
+ int i;
|
|
+#endif
|
|
+ int retcode, error=FALSE;
|
|
+#ifndef NO_EXCEPT_SIGNALS
|
|
+#ifdef REENTRANT
|
|
+ savsigs_info *oldsighandlers = NULL;
|
|
+# define SET_SIGHANDLER(sigtype, newsighandler) \
|
|
+ if ((retcode = setsignalhandler(__G__ &oldsighandlers, (sigtype), \
|
|
+ (newsighandler))) > PK_WARN) \
|
|
+ goto cleanup_and_exit
|
|
+#else
|
|
+# define SET_SIGHANDLER(sigtype, newsighandler) \
|
|
+ signal((sigtype), (newsighandler))
|
|
+#endif
|
|
+#endif /* NO_EXCEPT_SIGNALS */
|
|
+
|
|
+ /* initialize international char support to the current environment */
|
|
+ SETLOCALE(LC_CTYPE, "");
|
|
+
|
|
+#ifdef UNICODE_SUPPORT
|
|
+ /* see if can use UTF-8 Unicode locale */
|
|
+# ifdef UTF8_MAYBE_NATIVE
|
|
+ {
|
|
+ char *codeset;
|
|
+# if !(defined(NO_NL_LANGINFO) || defined(NO_LANGINFO_H))
|
|
+ /* get the codeset (character set encoding) currently used */
|
|
+# include <langinfo.h>
|
|
+
|
|
+ codeset = nl_langinfo(CODESET);
|
|
+# else /* NO_NL_LANGINFO || NO_LANGINFO_H */
|
|
+ /* query the current locale setting for character classification */
|
|
+ codeset = setlocale(LC_CTYPE, NULL);
|
|
+ if (codeset != NULL) {
|
|
+ /* extract the codeset portion of the locale name */
|
|
+ codeset = strchr(codeset, '.');
|
|
+ if (codeset != NULL) ++codeset;
|
|
+ }
|
|
+# endif /* ?(NO_NL_LANGINFO || NO_LANGINFO_H) */
|
|
+ /* is the current codeset UTF-8 ? */
|
|
+ if ((codeset != NULL) && (strcmp(codeset, "UTF-8") == 0)) {
|
|
+ /* successfully found UTF-8 char coding */
|
|
+ G.native_is_utf8 = TRUE;
|
|
+ } else {
|
|
+ /* Current codeset is not UTF-8 or cannot be determined. */
|
|
+ G.native_is_utf8 = FALSE;
|
|
+ }
|
|
+ /* Note: At least for UnZip, trying to change the process codeset to
|
|
+ * UTF-8 does not work. For the example Linux setup of the
|
|
+ * UnZip maintainer, a successful switch to "en-US.UTF-8"
|
|
+ * resulted in garbage display of all non-basic ASCII characters.
|
|
+ */
|
|
+ }
|
|
+# endif /* UTF8_MAYBE_NATIVE */
|
|
+
|
|
+ /* initialize Unicode */
|
|
+ G.unicode_escape_all = 0;
|
|
+ G.unicode_mismatch = 0;
|
|
+
|
|
+ G.unipath_version = 0;
|
|
+ G.unipath_checksum = 0;
|
|
+ G.unipath_filename = NULL;
|
|
+#endif /* UNICODE_SUPPORT */
|
|
+
|
|
+
|
|
+#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
|
|
+ extern void DebugMalloc(void);
|
|
+
|
|
+ atexit(DebugMalloc);
|
|
+#endif
|
|
+
|
|
+#ifdef MALLOC_WORK
|
|
+ /* The following (rather complex) expression determines the allocation
|
|
+ size of the decompression work area. It simulates what the
|
|
+ combined "union" and "struct" declaration of the "static" work
|
|
+ area reservation achieves automatically at compile time.
|
|
+ Any decent compiler should evaluate this expression completely at
|
|
+ compile time and provide constants to the zcalloc() call.
|
|
+ (For better readability, some subexpressions are encapsulated
|
|
+ in temporarly defined macros.)
|
|
+ */
|
|
+# define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch))
|
|
+# define UZ_NUMOF_CHUNKS \
|
|
+ (unsigned)(((WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK > HSIZE) ? \
|
|
+ (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK : HSIZE)
|
|
+ G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK);
|
|
+# undef UZ_SLIDE_CHUNK
|
|
+# undef UZ_NUMOF_CHUNKS
|
|
+ G.area.shrink.Parent = (shrint *)G.area.Slide;
|
|
+ G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE));
|
|
+ G.area.shrink.Stack = G.area.Slide +
|
|
+ (sizeof(shrint) + sizeof(uch))*(HSIZE);
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Set signal handler for restoring echo, warn of zipfile corruption, etc.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+#ifndef NO_EXCEPT_SIGNALS
|
|
+#ifdef SIGINT
|
|
+ SET_SIGHANDLER(SIGINT, handler);
|
|
+#endif
|
|
+#ifdef SIGTERM /* some systems really have no SIGTERM */
|
|
+ SET_SIGHANDLER(SIGTERM, handler);
|
|
+#endif
|
|
+#if defined(SIGABRT) && !(defined(AMIGA) && defined(__SASC))
|
|
+ SET_SIGHANDLER(SIGABRT, handler);
|
|
+#endif
|
|
+#ifdef SIGBREAK
|
|
+ SET_SIGHANDLER(SIGBREAK, handler);
|
|
+#endif
|
|
+#ifdef SIGBUS
|
|
+ SET_SIGHANDLER(SIGBUS, handler);
|
|
+#endif
|
|
+#ifdef SIGILL
|
|
+ SET_SIGHANDLER(SIGILL, handler);
|
|
+#endif
|
|
+#ifdef SIGSEGV
|
|
+ SET_SIGHANDLER(SIGSEGV, handler);
|
|
+#endif
|
|
+#endif /* NO_EXCEPT_SIGNALS */
|
|
+
|
|
+#if (defined(WIN32) && defined(__RSXNT__))
|
|
+ for (i = 0 ; i < argc; i++) {
|
|
+ _ISO_INTERN(argv[i]);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Macintosh initialization code.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef MACOS
|
|
+ {
|
|
+ int a;
|
|
+
|
|
+ for (a = 0; a < 4; ++a)
|
|
+ G.rghCursor[a] = GetCursor(a+128);
|
|
+ G.giCursor = 0;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ NetWare initialization code.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef NLM
|
|
+ InitUnZipConsole();
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Acorn RISC OS initialization code.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef RISCOS
|
|
+ set_prefix();
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Theos initialization code.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef THEOS
|
|
+ /* The easiest way found to force creation of libraries when selected
|
|
+ * members are to be unzipped. Explicitly add libraries names to the
|
|
+ * arguments list before the first member of the library.
|
|
+ */
|
|
+ if (! _setargv(&argc, &argv)) {
|
|
+ Info(slide, 0x401, ((char *)slide, "cannot process argv\n"));
|
|
+ retcode = PK_MEM;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Sanity checks. Commentary by Otis B. Driftwood and Fiorello:
|
|
+
|
|
+ D: It's all right. That's in every contract. That's what they
|
|
+ call a sanity clause.
|
|
+
|
|
+ F: Ha-ha-ha-ha-ha. You can't fool me. There ain't no Sanity
|
|
+ Claus.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef DEBUG
|
|
+# ifdef LARGE_FILE_SUPPORT
|
|
+ /* test if we can support large files - 10/6/04 EG */
|
|
+ if (sizeof(zoff_t) < 8) {
|
|
+ Info(slide, 0x401, ((char *)slide, "LARGE_FILE_SUPPORT set but not supported\n"));
|
|
+ retcode = PK_BADERR;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+ /* test if we can show 64-bit values */
|
|
+ {
|
|
+ zoff_t z = ~(zoff_t)0; /* z should be all 1s now */
|
|
+ char *sz;
|
|
+
|
|
+ sz = FmZofft(z, FZOFFT_HEX_DOT_WID, "X");
|
|
+ if ((sz[0] != 'F') || (strlen(sz) != 16))
|
|
+ {
|
|
+ z = 0;
|
|
+ }
|
|
+
|
|
+ /* shift z so only MSB is set */
|
|
+ z <<= 63;
|
|
+ sz = FmZofft(z, FZOFFT_HEX_DOT_WID, "X");
|
|
+ if ((sz[0] != '8') || (strlen(sz) != 16))
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "Can't show 64-bit values correctly\n"));
|
|
+ retcode = PK_BADERR;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+ }
|
|
+# endif /* LARGE_FILE_SUPPORT */
|
|
+
|
|
+ /* 2004-11-30 SMS.
|
|
+ Test the NEXTBYTE macro for proper operation.
|
|
+ */
|
|
+ {
|
|
+ int test_char;
|
|
+ static uch test_buf[2] = { 'a', 'b' };
|
|
+
|
|
+ G.inptr = test_buf;
|
|
+ G.incnt = 1;
|
|
+
|
|
+ test_char = NEXTBYTE; /* Should get 'a'. */
|
|
+ if (test_char == 'a')
|
|
+ {
|
|
+ test_char = NEXTBYTE; /* Should get EOF, not 'b'. */
|
|
+ }
|
|
+ if (test_char != EOF)
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "NEXTBYTE macro failed. Try compiling with ALT_NEXTBYTE defined?"));
|
|
+
|
|
+ retcode = PK_BADERR;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+ }
|
|
+#endif /* DEBUG */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ First figure out if we're running in UnZip mode or ZipInfo mode, and put
|
|
+ the appropriate environment-variable options into the queue. Then rip
|
|
+ through any command-line options lurking about...
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef SFX
|
|
+ G.argv0 = argv[0];
|
|
+#if (defined(OS2) || defined(WIN32))
|
|
+ G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */
|
|
+#else
|
|
+ G.zipfn = G.argv0;
|
|
+#endif
|
|
+
|
|
+#ifdef VMSCLI
|
|
+ {
|
|
+ ulg status = vms_unzip_cmdline(&argc, &argv);
|
|
+ if (!(status & 1)) {
|
|
+ retcode = (int)status;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+ }
|
|
+#endif /* VMSCLI */
|
|
+
|
|
+ uO.zipinfo_mode = FALSE;
|
|
+ error = uz_opts(__G__ &argc, &argv); /* UnZipSFX call only */
|
|
+
|
|
+#else /* !SFX */
|
|
+
|
|
+#ifdef RISCOS
|
|
+ /* get the extensions to swap from environment */
|
|
+ getRISCOSexts(ENV_UNZIPEXTS);
|
|
+#endif
|
|
+
|
|
+#ifdef MSDOS
|
|
+ /* extract MKS extended argument list from environment (before envargs!) */
|
|
+ mksargs(&argc, &argv);
|
|
+#endif
|
|
+
|
|
+#ifdef VMSCLI
|
|
+ {
|
|
+ ulg status = vms_unzip_cmdline(&argc, &argv);
|
|
+ if (!(status & 1)) {
|
|
+ retcode = (int)status;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+ }
|
|
+#endif /* VMSCLI */
|
|
+
|
|
+ G.noargs = (argc == 1); /* no options, no zipfile, no anything */
|
|
+
|
|
+#ifndef NO_ZIPINFO
|
|
+ for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) {
|
|
+ if (*p == DIR_END
|
|
+#ifdef DIR_END2
|
|
+ || *p == DIR_END2
|
|
+#endif
|
|
+ )
|
|
+ break;
|
|
+ }
|
|
+ ++p;
|
|
+
|
|
+#ifdef THEOS
|
|
+ if (strncmp(p, "ZIPINFO.",8) == 0 || strstr(p, ".ZIPINFO:") != NULL ||
|
|
+ strncmp(p, "II.",3) == 0 || strstr(p, ".II:") != NULL ||
|
|
+#else
|
|
+ if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 ||
|
|
+ STRNICMP(p, "ii", 2) == 0 ||
|
|
+#endif
|
|
+ (argc > 1 && strncmp(argv[1], "-Z", 2) == 0))
|
|
+ {
|
|
+ uO.zipinfo_mode = TRUE;
|
|
+#ifndef _WIN32_WCE /* Win CE does not support environment variables */
|
|
+ if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvZipInfo),
|
|
+ LoadFarStringSmall2(EnvZipInfo2))) != PK_OK)
|
|
+ perror(LoadFarString(NoMemEnvArguments));
|
|
+#endif
|
|
+ } else
|
|
+#endif /* !NO_ZIPINFO */
|
|
+ {
|
|
+ uO.zipinfo_mode = FALSE;
|
|
+#ifndef _WIN32_WCE /* Win CE does not support environment variables */
|
|
+ if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvUnZip),
|
|
+ LoadFarStringSmall2(EnvUnZip2))) != PK_OK)
|
|
+ perror(LoadFarString(NoMemEnvArguments));
|
|
+#endif
|
|
+ }
|
|
+
|
|
+ if (!error) {
|
|
+ /* Check the length of all passed command line parameters.
|
|
+ * Command arguments might get sent through the Info() message
|
|
+ * system, which uses the sliding window area as string buffer.
|
|
+ * As arguments may additionally get fed through one of the FnFilter
|
|
+ * macros, we require all command line arguments to be shorter than
|
|
+ * WSIZE/4 (and ca. 2 standard line widths for fixed message text).
|
|
+ */
|
|
+ for (i = 1 ; i < argc; i++) {
|
|
+ if (strlen(argv[i]) > ((WSIZE>>2) - 160)) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(CmdLineParamTooLong), i));
|
|
+ retcode = PK_PARAM;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+ }
|
|
+#ifndef NO_ZIPINFO
|
|
+ if (uO.zipinfo_mode)
|
|
+ error = zi_opts(__G__ &argc, &argv);
|
|
+ else
|
|
+#endif /* !NO_ZIPINFO */
|
|
+ error = uz_opts(__G__ &argc, &argv);
|
|
+ }
|
|
+
|
|
+#endif /* ?SFX */
|
|
+
|
|
+ if ((argc < 0) || error) {
|
|
+ retcode = error;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Now get the zipfile name from the command line and then process any re-
|
|
+ maining options and file specifications.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef DOS_FLX_H68_NLM_OS2_W32
|
|
+ /* convert MSDOS-style 'backward slash' directory separators to Unix-style
|
|
+ * 'forward slashes' for user's convenience (include zipfile name itself)
|
|
+ */
|
|
+#ifdef SFX
|
|
+ for (G.pfnames = argv, i = argc; i > 0; --i) {
|
|
+#else
|
|
+ /* argc does not include the zipfile specification */
|
|
+ for (G.pfnames = argv, i = argc+1; i > 0; --i) {
|
|
+#endif
|
|
+#ifdef __human68k__
|
|
+ extern char *_toslash(char *);
|
|
+ _toslash(*G.pfnames);
|
|
+#else /* !__human68k__ */
|
|
+ char *q = *G.pfnames;
|
|
+
|
|
+ while (*q != '\0') {
|
|
+ if (*q == '\\')
|
|
+ *q = '/';
|
|
+ INCSTR(q);
|
|
+ }
|
|
+#endif /* ?__human68k__ */
|
|
+ ++G.pfnames;
|
|
+ }
|
|
+#endif /* DOS_FLX_H68_NLM_OS2_W32 */
|
|
+
|
|
+#ifndef SFX
|
|
+ G.wildzipfn = *argv++;
|
|
+#endif
|
|
+
|
|
+#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */
|
|
+
|
|
+ G.filespecs = argc;
|
|
+ G.xfilespecs = 0;
|
|
+
|
|
+ if (argc > 0) {
|
|
+ char **pp = argv-1;
|
|
+
|
|
+ G.pfnames = argv;
|
|
+ while (*++pp)
|
|
+ if (strcmp(*pp, "-x") == 0) {
|
|
+ if (pp > argv) {
|
|
+ *pp = 0; /* terminate G.pfnames */
|
|
+ G.filespecs = pp - G.pfnames;
|
|
+ } else {
|
|
+ G.pfnames = (char **)fnames; /* defaults */
|
|
+ G.filespecs = 0;
|
|
+ }
|
|
+ G.pxnames = pp + 1; /* excluded-names ptr: _after_ -x */
|
|
+ G.xfilespecs = argc - G.filespecs - 1;
|
|
+ break; /* skip rest of args */
|
|
+ }
|
|
+ G.process_all_files = FALSE;
|
|
+ } else
|
|
+ G.process_all_files = TRUE; /* for speed */
|
|
+
|
|
+#else /* !SFX || SFX_EXDIR */ /* check for -x or -d */
|
|
+
|
|
+ G.filespecs = argc;
|
|
+ G.xfilespecs = 0;
|
|
+
|
|
+ if (argc > 0) {
|
|
+ int in_files=FALSE, in_xfiles=FALSE;
|
|
+ char **pp = argv-1;
|
|
+
|
|
+ G.process_all_files = FALSE;
|
|
+ G.pfnames = argv;
|
|
+ while (*++pp) {
|
|
+ Trace((stderr, "pp - argv = %d\n", pp-argv));
|
|
+#ifdef CMS_MVS
|
|
+ if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) {
|
|
+#else
|
|
+ if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) {
|
|
+#endif
|
|
+ int firstarg = (pp == argv);
|
|
+
|
|
+ uO.exdir = (*pp) + 2;
|
|
+ if (in_files) { /* ... zipfile ... -d exdir ... */
|
|
+ *pp = (char *)NULL; /* terminate G.pfnames */
|
|
+ G.filespecs = pp - G.pfnames;
|
|
+ in_files = FALSE;
|
|
+ } else if (in_xfiles) {
|
|
+ *pp = (char *)NULL; /* terminate G.pxnames */
|
|
+ G.xfilespecs = pp - G.pxnames;
|
|
+ /* "... -x xlist -d exdir": nothing left */
|
|
+ }
|
|
+ /* first check for "-dexdir", then for "-d exdir" */
|
|
+ if (*uO.exdir == '\0') {
|
|
+ if (*++pp)
|
|
+ uO.exdir = *pp;
|
|
+ else {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(MustGiveExdir)));
|
|
+ /* don't extract here by accident */
|
|
+ retcode = PK_PARAM;
|
|
+ goto cleanup_and_exit;
|
|
+ }
|
|
+ }
|
|
+ if (firstarg) { /* ... zipfile -d exdir ... */
|
|
+ if (pp[1]) {
|
|
+ G.pfnames = pp + 1; /* argv+2 */
|
|
+ G.filespecs = argc - (G.pfnames-argv); /* for now... */
|
|
+ } else {
|
|
+ G.process_all_files = TRUE;
|
|
+ G.pfnames = (char **)fnames; /* GRR: necessary? */
|
|
+ G.filespecs = 0; /* GRR: necessary? */
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ } else if (!in_xfiles) {
|
|
+ if (strcmp(*pp, "-x") == 0) {
|
|
+ in_xfiles = TRUE;
|
|
+ if (pp == G.pfnames) {
|
|
+ G.pfnames = (char **)fnames; /* defaults */
|
|
+ G.filespecs = 0;
|
|
+ } else if (in_files) {
|
|
+ *pp = 0; /* terminate G.pfnames */
|
|
+ G.filespecs = pp - G.pfnames; /* adjust count */
|
|
+ in_files = FALSE;
|
|
+ }
|
|
+ G.pxnames = pp + 1; /* excluded-names ptr starts after -x */
|
|
+ G.xfilespecs = argc - (G.pxnames-argv); /* anything left */
|
|
+ } else
|
|
+ in_files = TRUE;
|
|
+ }
|
|
+ }
|
|
+ } else
|
|
+ G.process_all_files = TRUE; /* for speed */
|
|
+
|
|
+ if (uO.exdir != (char *)NULL && !G.extract_flag) /* -d ignored */
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting)));
|
|
+#endif /* ?(SFX && !SFX_EXDIR) */
|
|
+
|
|
+#ifdef UNICODE_SUPPORT
|
|
+ /* set Unicode-escape-all if option -U used */
|
|
+ if (uO.U_flag == 1)
|
|
+# ifdef UNICODE_WCHAR
|
|
+ G.unicode_escape_all = TRUE;
|
|
+# else
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(UTF8EscapeUnSupp)));
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Okey dokey, we have everything we need to get started. Let's roll.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ retcode = process_zipfiles(__G);
|
|
+
|
|
+cleanup_and_exit:
|
|
+#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
|
|
+ /* restore all signal handlers back to their state at function entry */
|
|
+ while (oldsighandlers != NULL) {
|
|
+ savsigs_info *thissigsav = oldsighandlers;
|
|
+
|
|
+ signal(thissigsav->sigtype, thissigsav->sighandler);
|
|
+ oldsighandlers = thissigsav->previous;
|
|
+ free(thissigsav);
|
|
+ }
|
|
+#endif
|
|
+#if (defined(MALLOC_WORK) && !defined(REENTRANT))
|
|
+ if (G.area.Slide != (uch *)NULL) {
|
|
+ free(G.area.Slide);
|
|
+ G.area.Slide = (uch *)NULL;
|
|
+ }
|
|
+#endif
|
|
+#if (defined(MSDOS) && !defined(SFX) && !defined(WINDLL))
|
|
+ if (retcode != PK_OK)
|
|
+ check_for_windows("UnZip");
|
|
+#endif
|
|
+ return(retcode);
|
|
+
|
|
+} /* end main()/unzip() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
|
|
+/*******************************/
|
|
+/* Function setsignalhandler() */
|
|
+/*******************************/
|
|
+
|
|
+static int setsignalhandler(__G__ p_savedhandler_chain, signal_type,
|
|
+ newhandler)
|
|
+ __GDEF
|
|
+ savsigs_info **p_savedhandler_chain;
|
|
+ int signal_type;
|
|
+ void (*newhandler)(int);
|
|
+{
|
|
+ savsigs_info *savsig;
|
|
+
|
|
+ savsig = malloc(sizeof(savsigs_info));
|
|
+ if (savsig == NULL) {
|
|
+ /* error message and break */
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(CantSaveSigHandler)));
|
|
+ return PK_MEM;
|
|
+ }
|
|
+ savsig->sigtype = signal_type;
|
|
+ savsig->sighandler = signal(SIGINT, newhandler);
|
|
+ if (savsig->sighandler == SIG_ERR) {
|
|
+ free(savsig);
|
|
+ } else {
|
|
+ savsig->previous = *p_savedhandler_chain;
|
|
+ *p_savedhandler_chain = savsig;
|
|
+ }
|
|
+ return PK_OK;
|
|
+
|
|
+} /* end function setsignalhandler() */
|
|
+
|
|
+#endif /* REENTRANT && !NO_EXCEPT_SIGNALS */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/**********************/
|
|
+/* Function uz_opts() */
|
|
+/**********************/
|
|
+
|
|
+int uz_opts(__G__ pargc, pargv)
|
|
+ __GDEF
|
|
+ int *pargc;
|
|
+ char ***pargv;
|
|
+{
|
|
+ char **argv, *s;
|
|
+ int argc, c, error=FALSE, negative=0, showhelp=0;
|
|
+
|
|
+
|
|
+ argc = *pargc;
|
|
+ argv = *pargv;
|
|
+
|
|
+ while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
|
|
+ s = *argv + 1;
|
|
+ while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */
|
|
+#ifdef CMS_MVS
|
|
+ switch (tolower(c))
|
|
+#else
|
|
+ switch (c)
|
|
+#endif
|
|
+ {
|
|
+ case ('-'):
|
|
+ ++negative;
|
|
+ break;
|
|
+#ifdef RISCOS
|
|
+ case ('/'):
|
|
+ if (negative) { /* negative not allowed with -/ swap */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: must give extensions list"));
|
|
+ return(PK_PARAM); /* don't extract here by accident */
|
|
+ }
|
|
+ exts2swap = s; /* override Unzip$Exts */
|
|
+ s += strlen(s);
|
|
+ break;
|
|
+#endif
|
|
+ case ('a'):
|
|
+ if (negative) {
|
|
+ uO.aflag = MAX(uO.aflag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.aflag;
|
|
+ break;
|
|
+#if (defined(DLL) && defined(API_DOC))
|
|
+ case ('A'): /* extended help for API */
|
|
+ APIhelp(__G__ argc, argv);
|
|
+ *pargc = -1; /* signal to exit successfully */
|
|
+ return 0;
|
|
+#endif
|
|
+ case ('b'):
|
|
+ if (negative) {
|
|
+#if (defined(TANDEM) || defined(VMS))
|
|
+ uO.bflag = MAX(uO.bflag-negative,0);
|
|
+#endif
|
|
+ negative = 0; /* do nothing: "-b" is default */
|
|
+ } else {
|
|
+#ifdef VMS
|
|
+ if (uO.aflag == 0)
|
|
+ ++uO.bflag;
|
|
+#endif
|
|
+#ifdef TANDEM
|
|
+ ++uO.bflag;
|
|
+#endif
|
|
+ uO.aflag = 0;
|
|
+ }
|
|
+ break;
|
|
+#ifdef UNIXBACKUP
|
|
+ case ('B'): /* -B: back up existing files */
|
|
+ if (negative)
|
|
+ uO.B_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.B_flag = TRUE;
|
|
+ break;
|
|
+#endif
|
|
+ case ('c'):
|
|
+ if (negative) {
|
|
+ uO.cflag = FALSE, negative = 0;
|
|
+#ifdef NATIVE
|
|
+ uO.aflag = 0;
|
|
+#endif
|
|
+ } else {
|
|
+ uO.cflag = TRUE;
|
|
+#ifdef NATIVE
|
|
+ uO.aflag = 2; /* so you can read it on the screen */
|
|
+#endif
|
|
+#ifdef DLL
|
|
+ if (G.redirect_text)
|
|
+ G.redirect_data = 2;
|
|
+#endif
|
|
+ }
|
|
+ break;
|
|
+#ifndef CMS_MVS
|
|
+ case ('C'): /* -C: match filenames case-insensitively */
|
|
+ if (negative)
|
|
+ uO.C_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.C_flag = TRUE;
|
|
+ break;
|
|
+#endif /* !CMS_MVS */
|
|
+#if (!defined(SFX) || defined(SFX_EXDIR))
|
|
+ case ('d'):
|
|
+ if (negative) { /* negative not allowed with -d exdir */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(MustGiveExdir)));
|
|
+ return(PK_PARAM); /* don't extract here by accident */
|
|
+ }
|
|
+ if (uO.exdir != (char *)NULL) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(OnlyOneExdir)));
|
|
+ return(PK_PARAM); /* GRR: stupid restriction? */
|
|
+ } else {
|
|
+ /* first check for "-dexdir", then for "-d exdir" */
|
|
+ uO.exdir = s;
|
|
+ if (*uO.exdir == '\0') {
|
|
+ if (argc > 1) {
|
|
+ --argc;
|
|
+ uO.exdir = *++argv;
|
|
+ if (*uO.exdir == '-') {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(MustGiveExdir)));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ /* else uO.exdir points at extraction dir */
|
|
+ } else {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(MustGiveExdir)));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ }
|
|
+ /* uO.exdir now points at extraction dir (-dexdir or
|
|
+ * -d exdir); point s at end of exdir to avoid mis-
|
|
+ * interpretation of exdir characters as more options
|
|
+ */
|
|
+ if (*s != 0)
|
|
+ while (*++s != 0)
|
|
+ ;
|
|
+ }
|
|
+ break;
|
|
+#endif /* !SFX || SFX_EXDIR */
|
|
+#if (!defined(NO_TIMESTAMPS))
|
|
+ case ('D'): /* -D: Skip restoring dir (or any) timestamp. */
|
|
+ if (negative) {
|
|
+ uO.D_flag = MAX(uO.D_flag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ uO.D_flag++;
|
|
+ break;
|
|
+#endif /* (!NO_TIMESTAMPS) */
|
|
+ case ('e'): /* just ignore -e, -x options (extract) */
|
|
+ break;
|
|
+#ifdef MACOS
|
|
+ case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
|
|
+ if( negative ) {
|
|
+ uO.E_flag = FALSE, negative = 0;
|
|
+ } else {
|
|
+ uO.E_flag = TRUE;
|
|
+ }
|
|
+ break;
|
|
+#endif /* MACOS */
|
|
+ case ('f'): /* "freshen" (extract only newer files) */
|
|
+ if (negative)
|
|
+ uO.fflag = uO.uflag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.fflag = uO.uflag = TRUE;
|
|
+ break;
|
|
+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
|
|
+ case ('F'): /* Acorn filetype & NFS extension handling */
|
|
+ if (negative)
|
|
+ uO.acorn_nfs_ext = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.acorn_nfs_ext = TRUE;
|
|
+ break;
|
|
+#endif /* RISCOS || ACORN_FTYPE_NFS */
|
|
+ case ('h'): /* just print help message and quit */
|
|
+ if (showhelp == 0) {
|
|
+#ifndef SFX
|
|
+ if (*s == 'h')
|
|
+ showhelp = 2;
|
|
+ else
|
|
+#endif /* !SFX */
|
|
+ {
|
|
+ showhelp = 1;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+#ifdef MACOS
|
|
+ case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
|
|
+ if( negative ) {
|
|
+ uO.i_flag = FALSE, negative = 0;
|
|
+ } else {
|
|
+ uO.i_flag = TRUE;
|
|
+ }
|
|
+ break;
|
|
+#endif /* MACOS */
|
|
+ case ('j'): /* junk pathnames/directory structure */
|
|
+ if (negative)
|
|
+ uO.jflag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.jflag = TRUE;
|
|
+ break;
|
|
+#if (defined(ATH_BEO) || defined(MACOS))
|
|
+ case ('J'): /* Junk AtheOS, BeOS or MacOS file attributes */
|
|
+ if( negative ) {
|
|
+ uO.J_flag = FALSE, negative = 0;
|
|
+ } else {
|
|
+ uO.J_flag = TRUE;
|
|
+ }
|
|
+ break;
|
|
+#endif /* ATH_BEO || MACOS */
|
|
+#ifdef ATH_BEO_UNX
|
|
+ case ('K'):
|
|
+ if (negative) {
|
|
+ uO.K_flag = FALSE, negative = 0;
|
|
+ } else {
|
|
+ uO.K_flag = TRUE;
|
|
+ }
|
|
+ break;
|
|
+#endif /* ATH_BEO_UNX */
|
|
+#ifndef SFX
|
|
+ case ('l'):
|
|
+ if (negative) {
|
|
+ uO.vflag = MAX(uO.vflag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.vflag;
|
|
+ break;
|
|
+#endif /* !SFX */
|
|
+#ifndef CMS_MVS
|
|
+ case ('L'): /* convert (some) filenames to lowercase */
|
|
+ if (negative) {
|
|
+ uO.L_flag = MAX(uO.L_flag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.L_flag;
|
|
+ break;
|
|
+#endif /* !CMS_MVS */
|
|
+#ifdef MORE
|
|
+#ifdef CMS_MVS
|
|
+ case ('m'):
|
|
+#endif
|
|
+ case ('M'): /* send all screen output through "more" fn. */
|
|
+/* GRR: eventually check for numerical argument => height */
|
|
+ if (negative)
|
|
+ G.M_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ G.M_flag = TRUE;
|
|
+ break;
|
|
+#endif /* MORE */
|
|
+ case ('n'): /* don't overwrite any files */
|
|
+ if (negative)
|
|
+ uO.overwrite_none = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.overwrite_none = TRUE;
|
|
+ break;
|
|
+#ifdef AMIGA
|
|
+ case ('N'): /* restore comments as filenotes */
|
|
+ if (negative)
|
|
+ uO.N_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.N_flag = TRUE;
|
|
+ break;
|
|
+#endif /* AMIGA */
|
|
+ case ('o'): /* OK to overwrite files without prompting */
|
|
+ if (negative) {
|
|
+ uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.overwrite_all;
|
|
+ break;
|
|
+ case ('p'): /* pipes: extract to stdout, no messages */
|
|
+ if (negative) {
|
|
+ uO.cflag = FALSE;
|
|
+ uO.qflag = MAX(uO.qflag-999,0);
|
|
+ negative = 0;
|
|
+ } else {
|
|
+ uO.cflag = TRUE;
|
|
+ uO.qflag += 999;
|
|
+ }
|
|
+ break;
|
|
+#if CRYPT
|
|
+ /* GRR: yes, this is highly insecure, but dozens of people
|
|
+ * have pestered us for this, so here we go... */
|
|
+ case ('P'):
|
|
+ if (negative) { /* negative not allowed with -P passwd */
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(MustGivePasswd)));
|
|
+ return(PK_PARAM); /* don't extract here by accident */
|
|
+ }
|
|
+ if (uO.pwdarg != (char *)NULL) {
|
|
+/*
|
|
+ GRR: eventually support multiple passwords?
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(OnlyOnePasswd)));
|
|
+ return(PK_PARAM);
|
|
+ */
|
|
+ } else {
|
|
+ /* first check for "-Ppasswd", then for "-P passwd" */
|
|
+ uO.pwdarg = s;
|
|
+ if (*uO.pwdarg == '\0') {
|
|
+ if (argc > 1) {
|
|
+ --argc;
|
|
+ uO.pwdarg = *++argv;
|
|
+ if (*uO.pwdarg == '-') {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(MustGivePasswd)));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ /* else pwdarg points at decryption password */
|
|
+ } else {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ LoadFarString(MustGivePasswd)));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ }
|
|
+ /* pwdarg now points at decryption password (-Ppasswd or
|
|
+ * -P passwd); point s at end of passwd to avoid mis-
|
|
+ * interpretation of passwd characters as more options
|
|
+ */
|
|
+ if (*s != 0)
|
|
+ while (*++s != 0)
|
|
+ ;
|
|
+ }
|
|
+ break;
|
|
+#endif /* CRYPT */
|
|
+ case ('q'): /* quiet: fewer comments/messages */
|
|
+ if (negative) {
|
|
+ uO.qflag = MAX(uO.qflag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.qflag;
|
|
+ break;
|
|
+#ifdef QDOS
|
|
+ case ('Q'): /* QDOS flags */
|
|
+ qlflag ^= strtol(s, &s, 10);
|
|
+ break; /* we XOR this as we can config qlflags */
|
|
+#endif
|
|
+#ifdef TANDEM
|
|
+ case ('r'): /* remove file extensions */
|
|
+ if (negative)
|
|
+ uO.rflag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.rflag = TRUE;
|
|
+ break;
|
|
+#endif /* TANDEM */
|
|
+#ifdef DOS_FLX_NLM_OS2_W32
|
|
+ case ('s'): /* spaces in filenames: allow by default */
|
|
+ if (negative)
|
|
+ uO.sflag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.sflag = TRUE;
|
|
+ break;
|
|
+#endif /* DOS_FLX_NLM_OS2_W32 */
|
|
+#ifdef VMS
|
|
+ /* VMS: extract "text" files in Stream_LF format (-a[a]) */
|
|
+ case ('S'):
|
|
+ if (negative)
|
|
+ uO.S_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.S_flag = TRUE;
|
|
+ break;
|
|
+#endif /* VMS */
|
|
+ case ('t'):
|
|
+ if (negative)
|
|
+ uO.tflag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.tflag = TRUE;
|
|
+ break;
|
|
+#ifdef TIMESTAMP
|
|
+ case ('T'):
|
|
+ if (negative)
|
|
+ uO.T_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.T_flag = TRUE;
|
|
+ break;
|
|
+#endif
|
|
+ case ('u'): /* update (extract only new and newer files) */
|
|
+ if (negative)
|
|
+ uO.uflag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.uflag = TRUE;
|
|
+ break;
|
|
+#ifdef UNICODE_SUPPORT
|
|
+ case ('U'): /* escape UTF-8, or disable UTF-8 support */
|
|
+ if (negative) {
|
|
+ uO.U_flag = MAX(uO.U_flag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ uO.U_flag++;
|
|
+ break;
|
|
+#else /* !UNICODE_SUPPORT */
|
|
+#ifndef CMS_MVS
|
|
+ case ('U'): /* obsolete; to be removed in version 6.0 */
|
|
+ if (negative)
|
|
+ uO.L_flag = TRUE, negative = 0;
|
|
+ else
|
|
+ uO.L_flag = FALSE;
|
|
+ break;
|
|
+#endif /* !CMS_MVS */
|
|
+#endif /* ?UNICODE_SUPPORT */
|
|
+#ifndef SFX
|
|
+ case ('v'): /* verbose */
|
|
+ if (negative) {
|
|
+ uO.vflag = MAX(uO.vflag-negative,0);
|
|
+ negative = 0;
|
|
+ } else if (uO.vflag)
|
|
+ ++uO.vflag;
|
|
+ else
|
|
+ uO.vflag = 2;
|
|
+ break;
|
|
+#endif /* !SFX */
|
|
+#ifndef CMS_MVS
|
|
+ case ('V'): /* Version (retain VMS/DEC-20 file versions) */
|
|
+ if (negative)
|
|
+ uO.V_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.V_flag = TRUE;
|
|
+ break;
|
|
+#endif /* !CMS_MVS */
|
|
+#ifdef WILD_STOP_AT_DIR
|
|
+ case ('W'): /* Wildcard interpretation (stop at '/'?) */
|
|
+ if (negative)
|
|
+ uO.W_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.W_flag = TRUE;
|
|
+ break;
|
|
+#endif /* WILD_STOP_AT_DIR */
|
|
+ case ('x'): /* extract: default */
|
|
+#ifdef SFX
|
|
+ /* when 'x' is the only option in this argument, and the
|
|
+ * next arg is not an option, assume this initiates an
|
|
+ * exclusion list (-x xlist): terminate option-scanning
|
|
+ * and leave uz_opts with argv still pointing to "-x";
|
|
+ * the xlist is processed later
|
|
+ */
|
|
+ if (s - argv[0] == 2 && *s == '\0' &&
|
|
+ argc > 1 && argv[1][0] != '-') {
|
|
+ /* break out of nested loops without "++argv;--argc" */
|
|
+ goto opts_done;
|
|
+ }
|
|
+#endif /* SFX */
|
|
+ break;
|
|
+#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))
|
|
+ case ('X'): /* restore owner/protection info (need privs?) */
|
|
+ if (negative) {
|
|
+ uO.X_flag = MAX(uO.X_flag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.X_flag;
|
|
+ break;
|
|
+#endif /* RESTORE_UIDGID || RESTORE_ACL */
|
|
+#ifdef VMS
|
|
+ case ('Y'): /* Treat ".nnn" as ";nnn" version. */
|
|
+ if (negative)
|
|
+ uO.Y_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.Y_flag = TRUE;
|
|
+ break;
|
|
+#endif /* VMS */
|
|
+ case ('z'): /* display only the archive comment */
|
|
+ if (negative) {
|
|
+ uO.zflag = MAX(uO.zflag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.zflag;
|
|
+ break;
|
|
+#ifndef SFX
|
|
+ case ('Z'): /* should have been first option (ZipInfo) */
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
|
|
+ error = TRUE;
|
|
+ break;
|
|
+#endif /* !SFX */
|
|
+#ifdef VMS
|
|
+ case ('2'): /* Force ODS2-compliant names. */
|
|
+ if (negative)
|
|
+ uO.ods2_flag = FALSE, negative = 0;
|
|
+ else
|
|
+ uO.ods2_flag = TRUE;
|
|
+ break;
|
|
+#endif /* VMS */
|
|
+#ifdef DOS_H68_OS2_W32
|
|
+ case ('$'):
|
|
+ if (negative) {
|
|
+ uO.volflag = MAX(uO.volflag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.volflag;
|
|
+ break;
|
|
+#endif /* DOS_H68_OS2_W32 */
|
|
+#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))
|
|
+ case (':'): /* allow "parent dir" path components */
|
|
+ if (negative) {
|
|
+ uO.ddotflag = MAX(uO.ddotflag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.ddotflag;
|
|
+ break;
|
|
+#endif /* !RISCOS && !CMS_MVS && !TANDEM */
|
|
+#ifdef UNIX
|
|
+ case ('^'): /* allow control chars in filenames */
|
|
+ if (negative) {
|
|
+ uO.cflxflag = MAX(uO.cflxflag-negative,0);
|
|
+ negative = 0;
|
|
+ } else
|
|
+ ++uO.cflxflag;
|
|
+ break;
|
|
+#endif /* UNIX */
|
|
+ default:
|
|
+ error = TRUE;
|
|
+ break;
|
|
+
|
|
+ } /* end switch */
|
|
+ } /* end while (not end of argument string) */
|
|
+ } /* end while (not done with switches) */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Check for nonsensical combinations of options.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef SFX
|
|
+opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */
|
|
+#endif
|
|
+
|
|
+ if (showhelp > 0) { /* just print help message and quit */
|
|
+ *pargc = -1;
|
|
+#ifndef SFX
|
|
+ if (showhelp == 2) {
|
|
+ help_extended(__G);
|
|
+ return PK_OK;
|
|
+ } else
|
|
+#endif /* !SFX */
|
|
+ {
|
|
+ return USAGE(PK_OK);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((uO.cflag && (uO.tflag || uO.uflag)) ||
|
|
+ (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))
|
|
+ {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));
|
|
+ error = TRUE;
|
|
+ }
|
|
+ if (uO.aflag > 2)
|
|
+ uO.aflag = 2;
|
|
+#ifdef VMS
|
|
+ if (uO.bflag > 2)
|
|
+ uO.bflag = 2;
|
|
+ /* Clear -s flag when converting text files. */
|
|
+ if (uO.aflag <= 0)
|
|
+ uO.S_flag = 0;
|
|
+#endif /* VMS */
|
|
+ if (uO.overwrite_all && uO.overwrite_none) {
|
|
+ Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
|
|
+ uO.overwrite_all = FALSE;
|
|
+ }
|
|
+#ifdef MORE
|
|
+ if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func. useless */
|
|
+ G.M_flag = 0;
|
|
+#endif
|
|
+
|
|
+#ifdef SFX
|
|
+ if (error)
|
|
+#else
|
|
+ if ((argc-- == 0) || error)
|
|
+#endif
|
|
+ {
|
|
+ *pargc = argc;
|
|
+ *pargv = argv;
|
|
+#ifndef SFX
|
|
+ if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */
|
|
+ show_version_info(__G);
|
|
+ return PK_OK;
|
|
+ }
|
|
+ if (!G.noargs && !error)
|
|
+ error = TRUE; /* had options (not -h or -v) but no zipfile */
|
|
+#endif /* !SFX */
|
|
+ return USAGE(error);
|
|
+ }
|
|
+
|
|
+#ifdef SFX
|
|
+ /* print our banner unless we're being fairly quiet */
|
|
+ if (uO.qflag < 2)
|
|
+ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
|
|
+ UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
|
|
+ LoadFarStringSmall(VersionDate)));
|
|
+#ifdef BETA
|
|
+ /* always print the beta warning: no unauthorized distribution!! */
|
|
+ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
|
|
+ "SFX"));
|
|
+#endif
|
|
+#endif /* SFX */
|
|
+
|
|
+ if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
|
|
+#ifdef TIMESTAMP
|
|
+ || uO.T_flag
|
|
+#endif
|
|
+ )
|
|
+ G.extract_flag = FALSE;
|
|
+ else
|
|
+ G.extract_flag = TRUE;
|
|
+
|
|
+ *pargc = argc;
|
|
+ *pargv = argv;
|
|
+ return PK_OK;
|
|
+
|
|
+} /* end function uz_opts() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/********************/
|
|
+/* Function usage() */
|
|
+/********************/
|
|
+
|
|
+#ifdef SFX
|
|
+# ifdef VMS
|
|
+# define LOCAL "X.\n\
|
|
+(Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)"
|
|
+# endif
|
|
+# ifdef UNIX
|
|
+# define LOCAL "X"
|
|
+# endif
|
|
+# ifdef DOS_OS2_W32
|
|
+# define LOCAL "s$"
|
|
+# endif
|
|
+# if (defined(FLEXOS) || defined(NLM))
|
|
+# define LOCAL "s"
|
|
+# endif
|
|
+# ifdef AMIGA
|
|
+# define LOCAL "N"
|
|
+# endif
|
|
+ /* Default for all other systems: */
|
|
+# ifndef LOCAL
|
|
+# define LOCAL ""
|
|
+# endif
|
|
+
|
|
+# ifndef NO_TIMESTAMP
|
|
+# ifdef MORE
|
|
+# define SFXOPT1 "DM"
|
|
+# else
|
|
+# define SFXOPT1 "D"
|
|
+# endif
|
|
+# else
|
|
+# ifdef MORE
|
|
+# define SFXOPT1 "M"
|
|
+# else
|
|
+# define SFXOPT1 ""
|
|
+# endif
|
|
+# endif
|
|
+
|
|
+int usage(__G__ error) /* return PK-type error code */
|
|
+ __GDEF
|
|
+ int error;
|
|
+{
|
|
+ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
|
|
+ UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
|
|
+ LoadFarStringSmall(VersionDate)));
|
|
+ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts),
|
|
+ SFXOPT1, LOCAL));
|
|
+#ifdef BETA
|
|
+ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
|
|
+ "SFX"));
|
|
+#endif
|
|
+
|
|
+ if (error)
|
|
+ return PK_PARAM;
|
|
+ else
|
|
+ return PK_COOL; /* just wanted usage screen: no error */
|
|
+
|
|
+} /* end function usage() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#else /* !SFX */
|
|
+# ifdef VMS
|
|
+# define QUOT '\"'
|
|
+# define QUOTS "\""
|
|
+# else
|
|
+# define QUOT ' '
|
|
+# define QUOTS ""
|
|
+# endif
|
|
+
|
|
+int usage(__G__ error) /* return PK-type error code */
|
|
+ __GDEF
|
|
+ int error;
|
|
+{
|
|
+ int flag = (error? 1 : 0);
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Print either ZipInfo usage or UnZip usage, depending on incantation.
|
|
+ (Strings must be no longer than 512 bytes for Turbo C, apparently.)
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ if (uO.zipinfo_mode) {
|
|
+
|
|
+#ifndef NO_ZIPINFO
|
|
+
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1),
|
|
+ ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
|
|
+ LoadFarStringSmall(VersionDate),
|
|
+ LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS));
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2)));
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3),
|
|
+ LoadFarStringSmall(ZipInfoUsageLine4)));
|
|
+#ifdef VMS
|
|
+ Info(slide, flag, ((char *)slide, "\n\
|
|
+You must quote non-lowercase options and filespecs, unless SET PROC/PARSE=EXT.\
|
|
+\n"));
|
|
+#endif
|
|
+
|
|
+#endif /* !NO_ZIPINFO */
|
|
+
|
|
+ } else { /* UnZip mode */
|
|
+
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1),
|
|
+ UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
|
|
+ LoadFarStringSmall(VersionDate)));
|
|
+#ifdef BETA
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", ""));
|
|
+#endif
|
|
+
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2),
|
|
+ ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode)));
|
|
+#ifdef VMS
|
|
+ if (!error) /* maybe no command-line tail found; show extra help */
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b)));
|
|
+#endif
|
|
+
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3),
|
|
+ LoadFarStringSmall(local1)));
|
|
+
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4),
|
|
+ LoadFarStringSmall(local2), LoadFarStringSmall2(local3)));
|
|
+
|
|
+ /* This is extra work for SMALL_MEM, but it will work since
|
|
+ * LoadFarStringSmall2 uses the same buffer. Remember, this
|
|
+ * is a hack. */
|
|
+ Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5),
|
|
+ LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3),
|
|
+ LoadFarStringSmall2(Example3)));
|
|
+
|
|
+ } /* end if (uO.zipinfo_mode) */
|
|
+
|
|
+ if (error)
|
|
+ return PK_PARAM;
|
|
+ else
|
|
+ return PK_COOL; /* just wanted usage screen: no error */
|
|
+
|
|
+} /* end function usage() */
|
|
+
|
|
+#endif /* ?SFX */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifndef SFX
|
|
+
|
|
+/* Print extended help to stdout. */
|
|
+static void help_extended(__G)
|
|
+ __GDEF
|
|
+{
|
|
+ extent i; /* counter for help array */
|
|
+
|
|
+ /* help array */
|
|
+ static ZCONST char *text[] = {
|
|
+ "",
|
|
+ "Extended Help for UnZip",
|
|
+ "",
|
|
+ "See the UnZip Manual for more detailed help",
|
|
+ "",
|
|
+ "",
|
|
+ "UnZip lists and extracts files in zip archives. The default action is to",
|
|
+ "extract zipfile entries to the current directory, creating directories as",
|
|
+ "needed. With appropriate options, UnZip lists the contents of archives",
|
|
+ "instead.",
|
|
+ "",
|
|
+ "Basic unzip command line:",
|
|
+ " unzip [-Z] options archive[.zip] [file ...] [-x xfile ...] [-d exdir]",
|
|
+ "",
|
|
+ "Some examples:",
|
|
+ " unzip -l foo.zip - list files in short format in archive foo.zip",
|
|
+ "",
|
|
+ " unzip -t foo - test the files in archive foo",
|
|
+ "",
|
|
+ " unzip -Z foo - list files using more detailed zipinfo format",
|
|
+ "",
|
|
+ " unzip foo - unzip the contents of foo in current dir",
|
|
+ "",
|
|
+ " unzip -a foo - unzip foo and convert text files to local OS",
|
|
+ "",
|
|
+ "If unzip is run in zipinfo mode, a more detailed list of archive contents",
|
|
+ "is provided. The -Z option sets zipinfo mode and changes the available",
|
|
+ "options.",
|
|
+ "",
|
|
+ "Basic zipinfo command line:",
|
|
+ " zipinfo options archive[.zip] [file ...] [-x xfile ...]",
|
|
+ " unzip -Z options archive[.zip] [file ...] [-x xfile ...]",
|
|
+ "",
|
|
+ "Below, Mac OS refers to Mac OS before Mac OS X. Mac OS X is a Unix based",
|
|
+ "port and is referred to as Unix Apple.",
|
|
+ "",
|
|
+ "",
|
|
+ "unzip options:",
|
|
+ " -Z Switch to zipinfo mode. Must be first option.",
|
|
+ " -hh Display extended help.",
|
|
+ " -A [OS/2, Unix DLL] Print extended help for DLL.",
|
|
+ " -c Extract files to stdout/screen. As -p but include names. Also,",
|
|
+ " -a allowed and EBCDIC conversions done if needed.",
|
|
+ " -f Freshen by extracting only if older file on disk.",
|
|
+ " -l List files using short form.",
|
|
+ " -p Extract files to pipe (stdout). Only file data is output and all",
|
|
+ " files extracted in binary mode (as stored).",
|
|
+ " -t Test archive files.",
|
|
+ " -T Set timestamp on archive(s) to that of newest file. Similar to",
|
|
+ " zip -o but faster.",
|
|
+ " -u Update existing older files on disk as -f and extract new files.",
|
|
+ " -v Use verbose list format. If given alone as unzip -v show version",
|
|
+ " information. Also can be added to other list commands for more",
|
|
+ " verbose output.",
|
|
+ " -z Display only archive comment.",
|
|
+ "",
|
|
+ "unzip modifiers:",
|
|
+ " -a Convert text files to local OS format. Convert line ends, EOF",
|
|
+ " marker, and from or to EBCDIC character set as needed.",
|
|
+ " -b Treat all files as binary. [Tandem] Force filecode 180 ('C').",
|
|
+ " [VMS] Autoconvert binary files. -bb forces convert of all files.",
|
|
+ " -B [UNIXBACKUP compile option enabled] Save a backup copy of each",
|
|
+ " overwritten file in foo~ or foo~99999 format.",
|
|
+ " -C Use case-insensitive matching.",
|
|
+ " -D Skip restoration of timestamps for extracted directories. On VMS this",
|
|
+ " is on by default and -D essentially becames -DD.",
|
|
+ " -DD Skip restoration of timestamps for all entries.",
|
|
+ " -E [MacOS (not Unix Apple)] Display contents of MacOS extra field during",
|
|
+ " restore.",
|
|
+ " -F [Acorn] Suppress removal of NFS filetype extension. [Non-Acorn if",
|
|
+ " ACORN_FTYPE_NFS] Translate filetype and append to name.",
|
|
+ " -i [MacOS] Ignore filenames in MacOS extra field. Instead, use name in",
|
|
+ " standard header.",
|
|
+ " -j Junk paths and deposit all files in extraction directory.",
|
|
+ " -J [BeOS] Junk file attributes. [MacOS] Ignore MacOS specific info.",
|
|
+ " -K [AtheOS, BeOS, Unix] Restore SUID/SGID/Tacky file attributes.",
|
|
+ " -L Convert to lowercase any names from uppercase only file system.",
|
|
+ " -LL Convert all files to lowercase.",
|
|
+ " -M Pipe all output through internal pager similar to Unix more(1).",
|
|
+ " -n Never overwrite existing files. Skip extracting that file, no prompt.",
|
|
+ " -N [Amiga] Extract file comments as Amiga filenotes.",
|
|
+ " -o Overwrite existing files without prompting. Useful with -f. Use with",
|
|
+ " care.",
|
|
+ " -P p Use password p to decrypt files. THIS IS INSECURE! Some OS show",
|
|
+ " command line to other users.",
|
|
+ " -q Perform operations quietly. The more q (as in -qq) the quieter.",
|
|
+ " -s [OS/2, NT, MS-DOS] Convert spaces in filenames to underscores.",
|
|
+ " -S [VMS] Convert text files (-a, -aa) into Stream_LF format.",
|
|
+ " -U [UNICODE enabled] Show non-local characters as #Uxxxx or #Lxxxxxx ASCII",
|
|
+ " text escapes where x is hex digit. [Old] -U used to leave names",
|
|
+ " uppercase if created on MS-DOS, VMS, etc. See -L.",
|
|
+ " -UU [UNICODE enabled] Disable use of stored UTF-8 paths. Note that UTF-8",
|
|
+ " paths stored as native local paths are still processed as Unicode.",
|
|
+ " -V Retain VMS file version numbers.",
|
|
+ " -W [Only if WILD_STOP_AT_DIR] Modify pattern matching so ? and * do not",
|
|
+ " match directory separator /, but ** does. Allows matching at specific",
|
|
+ " directory levels.",
|
|
+ " -X [VMS, Unix, OS/2, NT, Tandem] Restore UICs and ACL entries under VMS,",
|
|
+ " or UIDs/GIDs under Unix, or ACLs under certain network-enabled",
|
|
+ " versions of OS/2, or security ACLs under Windows NT. Can require",
|
|
+ " user privileges.",
|
|
+ " -XX [NT] Extract NT security ACLs after trying to enable additional",
|
|
+ " system privileges.",
|
|
+ " -Y [VMS] Treat archived name endings of .nnn as VMS version numbers.",
|
|
+ " -$ [MS-DOS, OS/2, NT] Restore volume label if extraction medium is",
|
|
+ " removable. -$$ allows fixed media (hard drives) to be labeled.",
|
|
+ " -/ e [Acorn] Use e as extension list.",
|
|
+ " -: [All but Acorn, VM/CMS, MVS, Tandem] Allow extract archive members into",
|
|
+ " locations outside of current extraction root folder. This allows",
|
|
+ " paths such as ../foo to be extracted above the current extraction",
|
|
+ " directory, which can be a security problem.",
|
|
+ " -^ [Unix] Allow control characters in names of extracted entries. Usually",
|
|
+ " this is not a good thing and should be avoided.",
|
|
+ " -2 [VMS] Force unconditional conversion of names to ODS-compatible names.",
|
|
+ " Default is to exploit destination file system, preserving cases and",
|
|
+ " extended name characters on ODS5 and applying ODS2 filtering on ODS2.",
|
|
+ "",
|
|
+ "",
|
|
+ "Wildcards:",
|
|
+ " Internally unzip supports the following wildcards:",
|
|
+ " ? (or %% or #, depending on OS) matches any single character",
|
|
+ " * matches any number of characters, including zero",
|
|
+ " [list] matches char in list (regex), can do range [ac-f], all but [!bf]",
|
|
+ " If port supports [], must escape [ as [[]",
|
|
+ " For shells that expand wildcards, escape (\\* or \"*\") so unzip can recurse.",
|
|
+ "",
|
|
+ "Include and Exclude:",
|
|
+ " -i pattern pattern ... include files that match a pattern",
|
|
+ " -x pattern pattern ... exclude files that match a pattern",
|
|
+ " Patterns are paths with optional wildcards and match paths as stored in",
|
|
+ " archive. Exclude and include lists end at next option or end of line.",
|
|
+ " unzip archive -x pattern pattern ...",
|
|
+ "",
|
|
+ "Multi-part (split) archives (archives created as a set of split files):",
|
|
+ " Currently split archives are not readable by unzip. A workaround is",
|
|
+ " to use zip to convert the split archive to a single-file archive and",
|
|
+ " use unzip on that. See the manual page for Zip 3.0 or later.",
|
|
+ "",
|
|
+ "Streaming (piping into unzip):",
|
|
+ " Currently unzip does not support streaming. The funzip utility can be",
|
|
+ " used to process the first entry in a stream.",
|
|
+ " cat archive | funzip",
|
|
+ "",
|
|
+ "Testing archives:",
|
|
+ " -t test contents of archive",
|
|
+ " This can be modified using -q for quieter operation, and -qq for even",
|
|
+ " quieter operation.",
|
|
+ "",
|
|
+ "Unicode:",
|
|
+ " If compiled with Unicode support, unzip automatically handles archives",
|
|
+ " with Unicode entries. Currently Unicode on Win32 systems is limited.",
|
|
+ " Characters not in the current character set are shown as ASCII escapes",
|
|
+ " in the form #Uxxxx where the Unicode character number fits in 16 bits,",
|
|
+ " or #Lxxxxxx where it doesn't, where x is the ASCII character for a hex",
|
|
+ " digit.",
|
|
+ "",
|
|
+ "",
|
|
+ "zipinfo options (these are used in zipinfo mode (unzip -Z ...)):",
|
|
+ " -1 List names only, one per line. No headers/trailers. Good for scripts.",
|
|
+ " -2 List names only as -1, but include headers, trailers, and comments.",
|
|
+ " -s List archive entries in short Unix ls -l format. Default list format.",
|
|
+ " -m List in long Unix ls -l format. As -s, but includes compression %.",
|
|
+ " -l List in long Unix ls -l format. As -m, but compression in bytes.",
|
|
+ " -v List zipfile information in verbose, multi-page format.",
|
|
+ " -h List header line. Includes archive name, actual size, total files.",
|
|
+ " -M Pipe all output through internal pager similar to Unix more(1) command.",
|
|
+ " -t List totals for files listed or for all files. Includes uncompressed",
|
|
+ " and compressed sizes, and compression factors.",
|
|
+ " -T Print file dates and times in a sortable decimal format (yymmdd.hhmmss)",
|
|
+ " Default date and time format is a more human-readable version.",
|
|
+ " -U [UNICODE] If entry has a UTF-8 Unicode path, display any characters",
|
|
+ " not in current character set as text #Uxxxx and #Lxxxxxx escapes",
|
|
+ " representing the Unicode character number of the character in hex.",
|
|
+ " -UU [UNICODE] Disable use of any UTF-8 path information.",
|
|
+ " -z Include archive comment if any in listing.",
|
|
+ "",
|
|
+ "",
|
|
+ "funzip stream extractor:",
|
|
+ " funzip extracts the first member in an archive to stdout. Typically",
|
|
+ " used to unzip the first member of a stream or pipe. If a file argument",
|
|
+ " is given, read from that file instead of stdin.",
|
|
+ "",
|
|
+ "funzip command line:",
|
|
+ " funzip [-password] [input[.zip|.gz]]",
|
|
+ "",
|
|
+ "",
|
|
+ "unzipsfx self extractor:",
|
|
+ " Self-extracting archives made with unzipsfx are no more (or less)",
|
|
+ " portable across different operating systems than unzip executables.",
|
|
+ " In general, a self-extracting archive made on a particular Unix system,",
|
|
+ " for example, will only self-extract under the same flavor of Unix.",
|
|
+ " Regular unzip may still be used to extract embedded archive however.",
|
|
+ "",
|
|
+ "unzipsfx command line:",
|
|
+ " <unzipsfx+archive_filename> [-options] [file(s) ... [-x xfile(s) ...]]",
|
|
+ "",
|
|
+ "unzipsfx options:",
|
|
+ " -c, -p - Output to pipe. (See above for unzip.)",
|
|
+ " -f, -u - Freshen and Update, as for unzip.",
|
|
+ " -t - Test embedded archive. (Can be used to list contents.)",
|
|
+ " -z - Print archive comment. (See unzip above.)",
|
|
+ "",
|
|
+ "unzipsfx modifiers:",
|
|
+ " Most unzip modifiers are supported. These include",
|
|
+ " -a - Convert text files.",
|
|
+ " -n - Never overwrite.",
|
|
+ " -o - Overwrite without prompting.",
|
|
+ " -q - Quiet operation.",
|
|
+ " -C - Match names case-insensitively.",
|
|
+ " -j - Junk paths.",
|
|
+ " -V - Keep version numbers.",
|
|
+ " -s - Convert spaces to underscores.",
|
|
+ " -$ - Restore volume label.",
|
|
+ "",
|
|
+ "If unzipsfx compiled with SFX_EXDIR defined, -d option also available:",
|
|
+ " -d exd - Extract to directory exd.",
|
|
+ "By default, all files extracted to current directory. This option",
|
|
+ "forces extraction to specified directory.",
|
|
+ "",
|
|
+ "See unzipsfx manual page for more information.",
|
|
+ ""
|
|
+ };
|
|
+
|
|
+ for (i = 0; i < sizeof(text)/sizeof(char *); i++)
|
|
+ {
|
|
+ Info(slide, 0, ((char *)slide, "%s\n", text[i]));
|
|
+ }
|
|
+} /* end function help_extended() */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+#ifndef _WIN32_WCE /* Win CE does not support environment variables */
|
|
+#if (!defined(MODERN) || defined(NO_STDLIB_H))
|
|
+/* Declare getenv() to be sure (might be missing in some environments) */
|
|
+extern char *getenv();
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+/********************************/
|
|
+/* Function show_version_info() */
|
|
+/********************************/
|
|
+
|
|
+static void show_version_info(__G)
|
|
+ __GDEF
|
|
+{
|
|
+ if (uO.qflag > 3) /* "unzip -vqqqq" */
|
|
+ Info(slide, 0, ((char *)slide, "%d\n",
|
|
+ (UZ_MAJORVER*100 + UZ_MINORVER*10 + UZ_PATCHLEVEL)));
|
|
+ else {
|
|
+#ifndef _WIN32_WCE /* Win CE does not support environment variables */
|
|
+ char *envptr;
|
|
+#endif
|
|
+ int numopts = 0;
|
|
+
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v),
|
|
+ UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
|
|
+ LoadFarStringSmall(VersionDate)));
|
|
+ Info(slide, 0, ((char *)slide,
|
|
+ LoadFarString(UnzipUsageLine2v)));
|
|
+ version(__G);
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions)));
|
|
+#ifdef ACORN_FTYPE_NFS
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(AcornFtypeNFS)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef ASM_CRC
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(AsmCRC)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef ASM_INFLATECODES
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(AsmInflateCodes)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef CHECK_VERSIONS
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Check_Versions)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef COPYRIGHT_CLEAN
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Copyright_Clean)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef DEBUG
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(UDebug)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef DEBUG_TIME
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(DebugTime)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef DLL
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Dll)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef DOSWILD
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(DosWild)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef LZW_CLEAN
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(LZW_Clean)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifndef MORE
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(No_More)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef NO_ZIPINFO
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(No_ZipInfo)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef NTSD_EAS
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(NTSDExtAttrib)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#if defined(WIN32) && defined(NO_W32TIMES_IZFIX)
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(W32NoIZTimeFix)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef OLD_THEOS_EXTRA
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(OldTheosExtra)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef OS2_EAS
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(OS2ExtAttrib)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef QLZIP
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(SMSExFldOnUnix)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef REENTRANT
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Reentrant)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef REGARGS
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(RegArgs)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef RETURN_CODES
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Return_Codes)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(SetDirAttrib)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef SYMLINKS
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(SymLinkSupport)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef TIMESTAMP
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(TimeStamp)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef UNIXBACKUP
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(UnixBackup)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef USE_EF_UT_TIME
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_EF_UT_time)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifndef COPYRIGHT_CLEAN
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_Smith_Code)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifndef LZW_CLEAN
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_Unshrink)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef USE_DEFLATE64
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_Deflate64)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef UNICODE_SUPPORT
|
|
+# ifdef UTF8_MAYBE_NATIVE
|
|
+ sprintf((char *)(slide+256), LoadFarStringSmall(Use_Unicode),
|
|
+ LoadFarStringSmall2(G.native_is_utf8 ? SysChUTF8 : SysChOther));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ (char *)(slide+256)));
|
|
+# else
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_Unicode)));
|
|
+# endif
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef _MBCS
|
|
+ sprintf((char *)(slide+256), LoadFarStringSmall(Have_MBCS_Support),
|
|
+ (unsigned int)MB_CUR_MAX);
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ (char *)(slide+256)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef MULT_VOLUME
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_MultiVol)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef LARGE_FILE_SUPPORT
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_LFS)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef ZIP64_SUPPORT
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_Zip64)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#if (defined(__DJGPP__) && (__DJGPP__ >= 2))
|
|
+# ifdef USE_DJGPP_ENV
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_DJGPP_Env)));
|
|
+ ++numopts;
|
|
+# endif
|
|
+# ifdef USE_DJGPP_GLOB
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_DJGPP_Glob)));
|
|
+ ++numopts;
|
|
+# endif
|
|
+#endif /* __DJGPP__ && (__DJGPP__ >= 2) */
|
|
+#ifdef USE_VFAT
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(Use_VFAT_support)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef USE_ZLIB
|
|
+ sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib),
|
|
+ ZLIB_VERSION, zlibVersion());
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ (char *)(slide+256)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef USE_BZIP2
|
|
+ sprintf((char *)(slide+256), LoadFarStringSmall(UseBZip2),
|
|
+ BZ2_bzlibVersion());
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ (char *)(slide+256)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef VMS_TEXT_CONV
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(VmsTextConv)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef VMSCLI
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(VmsCLI)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef VMSWILD
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(VmsWild)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#ifdef WILD_STOP_AT_DIR
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(WildStopAtDir)));
|
|
+ ++numopts;
|
|
+#endif
|
|
+#if CRYPT
|
|
+# ifdef PASSWD_FROM_STDIN
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(PasswdStdin)));
|
|
+# endif
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(Decryption),
|
|
+ CR_MAJORVER, CR_MINORVER, CR_BETA_VER,
|
|
+ LoadFarStringSmall(CryptDate)));
|
|
+ ++numopts;
|
|
+#endif /* CRYPT */
|
|
+ if (numopts == 0)
|
|
+ Info(slide, 0, ((char *)slide,
|
|
+ LoadFarString(CompileOptFormat),
|
|
+ LoadFarStringSmall(None)));
|
|
+
|
|
+#ifndef _WIN32_WCE /* Win CE does not support environment variables */
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions)));
|
|
+ envptr = getenv(LoadFarStringSmall(EnvUnZip));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvUnZip),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+ envptr = getenv(LoadFarStringSmall(EnvUnZip2));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvUnZip2),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+ envptr = getenv(LoadFarStringSmall(EnvZipInfo));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvZipInfo),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+ envptr = getenv(LoadFarStringSmall(EnvZipInfo2));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvZipInfo2),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+#ifndef __RSXNT__
|
|
+#ifdef __EMX__
|
|
+ envptr = getenv(LoadFarStringSmall(EnvEMX));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvEMX),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+ envptr = getenv(LoadFarStringSmall(EnvEMXOPT));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvEMXOPT),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+#endif /* __EMX__ */
|
|
+#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
|
|
+ envptr = getenv(LoadFarStringSmall(EnvGO32));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvGO32),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+ envptr = getenv(LoadFarStringSmall(EnvGO32TMP));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvGO32TMP),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+#endif /* __GO32__ && !(__DJGPP__ >= 2) */
|
|
+#endif /* !__RSXNT__ */
|
|
+#ifdef RISCOS
|
|
+ envptr = getenv(LoadFarStringSmall(EnvUnZipExts));
|
|
+ Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
|
|
+ LoadFarStringSmall(EnvUnZipExts),
|
|
+ (envptr == (char *)NULL || *envptr == 0)?
|
|
+ LoadFarStringSmall2(None) : envptr));
|
|
+#endif /* RISCOS */
|
|
+#endif /* !_WIN32_WCE */
|
|
+ }
|
|
+} /* end function show_version() */
|
|
+
|
|
+#endif /* !SFX */
|
|
+#endif /* !WINDLL */
|
|
diff -Naur a/unzpriv.h b/unzpriv.h
|
|
--- a/unzpriv.h 2009-04-20 00:59:26.000000000 +0100
|
|
+++ b/unzpriv.h 2019-12-02 01:05:52.857702371 +0000
|
|
@@ -1211,6 +1211,7 @@
|
|
# ifdef UNICODE_WCHAR
|
|
# if !(defined(_WIN32_WCE) || defined(POCKET_UNZIP))
|
|
# include <wchar.h>
|
|
+# include <wctype.h>
|
|
# endif
|
|
# endif
|
|
# ifndef _MBCS /* no need to include <locale.h> twice, see below */
|
|
@@ -1806,6 +1807,8 @@
|
|
#define EB_NTSD_VERSION 4 /* offset of NTSD version byte */
|
|
#define EB_NTSD_MAX_VER (0) /* maximum version # we know how to handle */
|
|
|
|
+#define EB_PKVMS_MINLEN 4 /* minimum data length of PKVMS extra block */
|
|
+
|
|
#define EB_ASI_CRC32 0 /* offset of ASI Unix field's crc32 checksum */
|
|
#define EB_ASI_MODE 4 /* offset of ASI Unix permission mode field */
|
|
|
|
@@ -2393,6 +2396,12 @@
|
|
char *fnfilter OF((ZCONST char *raw, uch *space,
|
|
extent size));
|
|
|
|
+# if defined( UNICODE_SUPPORT) && defined( _MBCS)
|
|
+wchar_t *fnfilterw OF((ZCONST wchar_t *src, wchar_t *dst,
|
|
+ extent siz));
|
|
+#endif
|
|
+
|
|
+
|
|
/*---------------------------------------------------------------------------
|
|
Decompression functions:
|
|
---------------------------------------------------------------------------*/
|
|
@@ -2604,7 +2613,7 @@
|
|
int SetFileSize OF((FILE *file, zusz_t filesize)); /* local */
|
|
#endif
|
|
#ifndef MTS /* macro in MTS */
|
|
- void close_outfile OF((__GPRO)); /* local */
|
|
+ int close_outfile OF((__GPRO)); /* local */
|
|
#endif
|
|
#ifdef SET_SYMLINK_ATTRIBS
|
|
int set_symlnk_attribs OF((__GPRO__ slinkentry *slnk_entry)); /* local */
|
|
@@ -3008,7 +3017,7 @@
|
|
!(((islochdr) || (isuxatt)) && \
|
|
((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \
|
|
(hostnum) == FS_HPFS_ || \
|
|
- ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \
|
|
+ ((hostnum) == FS_NTFS_ /* && (hostver) == 50 */ )) { \
|
|
_OEM_INTERN((string)); \
|
|
} else { \
|
|
_ISO_INTERN((string)); \
|
|
diff -Naur a/unzpriv.h.orig b/unzpriv.h.orig
|
|
--- a/unzpriv.h.orig 1970-01-01 01:00:00.000000000 +0100
|
|
+++ b/unzpriv.h.orig 2019-12-02 01:04:10.077348607 +0000
|
|
@@ -0,0 +1,3125 @@
|
|
+/*
|
|
+ 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
|
|
+*/
|
|
+/*---------------------------------------------------------------------------
|
|
+
|
|
+ unzpriv.h
|
|
+
|
|
+ This header file contains private (internal) macros, typedefs, prototypes
|
|
+ and global-variable declarations used by all of the UnZip source files.
|
|
+ In a prior life it was part of the main unzip.h header, but now it is only
|
|
+ included by that header if UNZIP_INTERNAL is defined.
|
|
+
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+
|
|
+
|
|
+#ifndef __unzpriv_h /* prevent multiple inclusions */
|
|
+#define __unzpriv_h
|
|
+
|
|
+/* First thing: Signal all following code that we compile UnZip utilities! */
|
|
+#ifndef UNZIP
|
|
+# define UNZIP
|
|
+#endif
|
|
+
|
|
+/* GRR 960204: MORE defined here in preparation for removal altogether */
|
|
+#ifndef MORE
|
|
+# ifndef RISCOS
|
|
+# define MORE
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* fUnZip should never need to be reentrant */
|
|
+#ifdef FUNZIP
|
|
+# ifdef REENTRANT
|
|
+# undef REENTRANT
|
|
+# endif
|
|
+# ifdef DLL
|
|
+# undef DLL
|
|
+# endif
|
|
+# ifdef SFX /* fUnZip is NOT the sfx stub! */
|
|
+# undef SFX
|
|
+# endif
|
|
+# ifdef USE_BZIP2 /* fUnZip does not support bzip2 decompression */
|
|
+# undef USE_BZIP2
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(USE_ZLIB) && !defined(HAVE_ZL_INFLAT64) && !defined(NO_DEFLATE64))
|
|
+ /* zlib does not (yet?) provide Deflate64(tm) support */
|
|
+# define NO_DEFLATE64
|
|
+#endif
|
|
+
|
|
+#ifdef NO_DEFLATE64
|
|
+ /* disable support for Deflate64(tm) */
|
|
+# ifdef USE_DEFLATE64
|
|
+# undef USE_DEFLATE64
|
|
+# endif
|
|
+#else
|
|
+ /* enable Deflate64(tm) support unless compiling for SFX stub */
|
|
+# if (!defined(USE_DEFLATE64) && !defined(SFX))
|
|
+# define USE_DEFLATE64
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* disable bzip2 support for SFX stub, unless explicitly requested */
|
|
+#if (defined(SFX) && !defined(BZIP2_SFX) && defined(USE_BZIP2))
|
|
+# undef USE_BZIP2
|
|
+#endif
|
|
+
|
|
+#if (defined(NO_VMS_TEXT_CONV) || defined(VMS))
|
|
+# ifdef VMS_TEXT_CONV
|
|
+# undef VMS_TEXT_CONV
|
|
+# endif
|
|
+#else
|
|
+# if (!defined(VMS_TEXT_CONV) && !defined(SFX))
|
|
+# define VMS_TEXT_CONV
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* Enable -B option per default on specific systems, to allow backing up
|
|
+ * files that would be overwritten.
|
|
+ * (This list of systems must be kept in sync with the list of systems
|
|
+ * that add the B_flag to the UzpOpts structure, see unzip.h.)
|
|
+ */
|
|
+#if (!defined(NO_UNIXBACKUP) && !defined(UNIXBACKUP))
|
|
+# if defined(UNIX) || defined(OS2) || defined(WIN32)
|
|
+# define UNIXBACKUP
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(DLL) && !defined(REENTRANT))
|
|
+# define REENTRANT
|
|
+#endif
|
|
+
|
|
+#if (!defined(DYNAMIC_CRC_TABLE) && !defined(FUNZIP))
|
|
+# define DYNAMIC_CRC_TABLE
|
|
+#endif
|
|
+
|
|
+#if (defined(DYNAMIC_CRC_TABLE) && !defined(REENTRANT))
|
|
+# ifndef DYNALLOC_CRCTAB
|
|
+# define DYNALLOC_CRCTAB
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ OS-dependent configuration for UnZip internals
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+/* Some compiler distributions for Win32/i386 systems try to emulate
|
|
+ * a Unix (POSIX-compatible) environment.
|
|
+ */
|
|
+#if (defined(WIN32) && defined(UNIX))
|
|
+ /* UnZip does not support merging both ports in a single executable. */
|
|
+# if (defined(FORCE_WIN32_OVER_UNIX) && defined(FORCE_UNIX_OVER_WIN32))
|
|
+ /* conflicting choice requests -> we prefer the Win32 environment */
|
|
+# undef FORCE_UNIX_OVER_WIN32
|
|
+# endif
|
|
+# ifdef FORCE_WIN32_OVER_UNIX
|
|
+ /* native Win32 support was explicitly requested... */
|
|
+# undef UNIX
|
|
+# else
|
|
+ /* use the POSIX (Unix) emulation features by default... */
|
|
+# undef WIN32
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* bad or (occasionally?) missing stddef.h: */
|
|
+#if (defined(M_XENIX) || defined(DNIX))
|
|
+# define NO_STDDEF_H
|
|
+#endif
|
|
+
|
|
+#if (defined(M_XENIX) && !defined(M_UNIX)) /* SCO Xenix only, not SCO Unix */
|
|
+# define SCO_XENIX
|
|
+# define NO_LIMITS_H /* no limits.h, but MODERN defined */
|
|
+# define NO_UID_GID /* no uid_t/gid_t */
|
|
+# define size_t int
|
|
+#endif
|
|
+
|
|
+#ifdef realix /* Modcomp Real/IX, real-time SysV.3 variant */
|
|
+# define SYSV
|
|
+# define NO_UID_GID /* no uid_t/gid_t */
|
|
+#endif
|
|
+
|
|
+#if (defined(_AIX) && !defined(_ALL_SOURCE))
|
|
+# define _ALL_SOURCE
|
|
+#endif
|
|
+
|
|
+#if defined(apollo) /* defines __STDC__ */
|
|
+# define NO_STDLIB_H
|
|
+#endif
|
|
+
|
|
+#ifdef DNIX
|
|
+# define SYSV
|
|
+# define SHORT_NAMES /* 14-char limitation on path components */
|
|
+/* # define FILENAME_MAX 14 */
|
|
+# define FILENAME_MAX NAME_MAX /* GRR: experiment */
|
|
+#endif
|
|
+
|
|
+#if (defined(SYSTEM_FIVE) || defined(__SYSTEM_FIVE))
|
|
+# ifndef SYSV
|
|
+# define SYSV
|
|
+# endif
|
|
+#endif /* SYSTEM_FIVE || __SYSTEM_FIVE */
|
|
+#if (defined(M_SYSV) || defined(M_SYS5))
|
|
+# ifndef SYSV
|
|
+# define SYSV
|
|
+# endif
|
|
+#endif /* M_SYSV || M_SYS5 */
|
|
+/* __SVR4 and __svr4__ catch Solaris on at least some combos of compiler+OS */
|
|
+#if (defined(__SVR4) || defined(__svr4__) || defined(sgi) || defined(__hpux))
|
|
+# ifndef SYSV
|
|
+# define SYSV
|
|
+# endif
|
|
+#endif /* __SVR4 || __svr4__ || sgi || __hpux */
|
|
+#if (defined(LINUX) || defined(__QNX__))
|
|
+# ifndef SYSV
|
|
+# define SYSV
|
|
+# endif
|
|
+#endif /* LINUX || __QNX__ */
|
|
+
|
|
+#if (defined(ultrix) || defined(__ultrix) || defined(bsd4_2))
|
|
+# if (!defined(BSD) && !defined(SYSV))
|
|
+# define BSD
|
|
+# endif
|
|
+#endif /* ultrix || __ultrix || bsd4_2 */
|
|
+#if (defined(sun) || defined(pyr) || defined(CONVEX))
|
|
+# if (!defined(BSD) && !defined(SYSV))
|
|
+# define BSD
|
|
+# endif
|
|
+#endif /* sun || pyr || CONVEX */
|
|
+
|
|
+#ifdef pyr /* Pyramid: has BSD and AT&T "universes" */
|
|
+# ifdef BSD
|
|
+# define pyr_bsd
|
|
+# define USE_STRINGS_H /* instead of more common string.h */
|
|
+# define ZMEM /* ZMEM now uses bcopy/bzero: not in AT&T universe */
|
|
+# endif /* (AT&T memcpy claimed to be very slow, though) */
|
|
+# define DECLARE_ERRNO
|
|
+#endif /* pyr */
|
|
+
|
|
+/* stat() bug for Borland, VAX C RTL, and Atari ST MiNT on TOS
|
|
+ * filesystems: returns 0 for wildcards! (returns 0xffffffff on Minix
|
|
+ * filesystem or `U:' drive under Atari MiNT.) Watcom C was previously
|
|
+ * included on this list; it would be good to know what version the problem
|
|
+ * was fixed at, if it did exist. */
|
|
+#if (defined(__TURBOC__) && !defined(WIN32))
|
|
+/*# define WILD_STAT_BUG*/
|
|
+#endif
|
|
+#if (defined(VMS) || defined(__MINT__))
|
|
+# define WILD_STAT_BUG
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ OS-dependent includes
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ API (DLL) section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef DLL
|
|
+# define MAIN UZ_EXP UzpMain /* was UzpUnzip */
|
|
+# ifdef OS2DLL
|
|
+# undef Info
|
|
+# define REDIRECTC(c) varputchar(__G__ c)
|
|
+# define REDIRECTPRINT(buf,size) varmessage(__G__ buf, size)
|
|
+# define FINISH_REDIRECT() finish_REXX_redirect(__G)
|
|
+# else
|
|
+# define REDIRECTC(c)
|
|
+# define REDIRECTPRINT(buf,size) 0
|
|
+# define FINISH_REDIRECT() close_redirect(__G)
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Acorn RISCOS section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef RISCOS
|
|
+# include "acorn/riscos.h"
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Amiga section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef AMIGA
|
|
+# include "amiga/amiga.h"
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ AOS/VS section (somewhat similar to Unix, apparently):
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef AOS_VS
|
|
+# ifdef __FILEIO_C
|
|
+# include "aosvs/aosvs.h"
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Atari ST section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef ATARI
|
|
+# include <time.h>
|
|
+# include <stat.h>
|
|
+# include <fcntl.h>
|
|
+# include <limits.h>
|
|
+# define SYMLINKS
|
|
+# define EXE_EXTENSION ".tos"
|
|
+# ifndef DATE_FORMAT
|
|
+# define DATE_FORMAT DF_DMY
|
|
+# endif
|
|
+# define DIR_END '/'
|
|
+# define INT_SPRINTF
|
|
+# define timezone _timezone
|
|
+# define lenEOL 2
|
|
+# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);}
|
|
+# undef SHORT_NAMES
|
|
+# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
|
|
+# define TIMESTAMP
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ AtheOS section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef __ATHEOS__
|
|
+# include "atheos/athcfg.h"
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ BeOS section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef __BEOS__
|
|
+# include "beos/beocfg.h"
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Human68k/X680x0 section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef __human68k__
|
|
+ /* DO NOT DEFINE DOS_OS2 HERE! If Human68k is so much */
|
|
+ /* like MS-DOS and/or OS/2, create DOS_H68_OS2 macro. */
|
|
+# if (!defined(_MBCS) && !defined(NO_MBCS))
|
|
+ /* enable MBCS support by default for this system */
|
|
+# define _MBCS
|
|
+# endif
|
|
+# if (defined(_MBCS) && defined(NO_MBCS))
|
|
+ /* disable MBCS support when explicitely requested */
|
|
+# undef _MBCS
|
|
+# endif
|
|
+# include <time.h>
|
|
+# include <fcntl.h>
|
|
+# include <io.h>
|
|
+# include <conio.h>
|
|
+# include <sys/stat.h>
|
|
+# ifdef HAVE_MBSTRING_H
|
|
+# include <mbstring.h>
|
|
+# endif
|
|
+# ifdef HAVE_MBCTYPE_H
|
|
+# include <mbctype.h>
|
|
+# else
|
|
+# ifndef _ismbblead
|
|
+# define _ismbblead(c) (0x80 <= (c) && ((c) < 0xa0 || 0xe0 <= (c)))
|
|
+# endif
|
|
+# endif
|
|
+# ifndef DATE_FORMAT
|
|
+# define DATE_FORMAT DF_YMD /* Japanese standard */
|
|
+# endif
|
|
+# define lenEOL 1
|
|
+# define PutNativeEOL *q++ = native(LF);
|
|
+# define INT_SPRINTF
|
|
+# define SYMLINKS
|
|
+# ifdef SFX
|
|
+# define MAIN main_sfx
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Mac section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef MACOS
|
|
+# include "maccfg.h"
|
|
+#endif /* MACOS */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ MS-DOS, OS/2, FLEXOS section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef WINDLL
|
|
+# ifdef MORE
|
|
+# undef MORE
|
|
+# endif
|
|
+# ifdef OS2_EAS
|
|
+# undef OS2_EAS
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__)))
|
|
+# ifndef MSC
|
|
+# define MSC /* This should work for older MSC, too! */
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(MSDOS) || defined(OS2) || defined(FLEXOS))
|
|
+# include <sys/types.h> /* off_t, time_t, dev_t, ... */
|
|
+# include <sys/stat.h>
|
|
+# include <io.h> /* lseek(), open(), setftime(), dup(), creat() */
|
|
+# include <time.h> /* localtime() */
|
|
+# include <fcntl.h> /* O_BINARY for open() w/o CR/LF translation */
|
|
+
|
|
+# ifdef OS2 /* defined for all OS/2 compilers */
|
|
+# include "os2/os2cfg.h"
|
|
+# else
|
|
+# ifdef FLEXOS
|
|
+# include "flexos/flxcfg.h"
|
|
+# else
|
|
+# include "msdos/doscfg.h"
|
|
+# endif
|
|
+# endif
|
|
+
|
|
+# if (defined(_MSC_VER) && (_MSC_VER == 700) && !defined(GRR))
|
|
+ /*
|
|
+ * ARGH. MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not
|
|
+ * 1970 Jan 1 00:00. So we have to diddle time_t's appropriately: add or
|
|
+ * subtract 70 years' worth of seconds; i.e., number of days times 86400;
|
|
+ * i.e., (70*365 regular days + 17 leap days + 1 1899 day) * 86400 ==
|
|
+ * (25550 + 17 + 1) * 86400 == 2209075200 seconds. We know time_t is an
|
|
+ * unsigned long (ulg) on the only system with this bug.
|
|
+ */
|
|
+# define TIMET_TO_NATIVE(x) (x) += (ulg)2209075200L;
|
|
+# define NATIVE_TO_TIMET(x) (x) -= (ulg)2209075200L;
|
|
+# endif
|
|
+# if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0450))
|
|
+# define timezone _timezone
|
|
+# endif
|
|
+# if (defined(__GO32__) || defined(FLEXOS))
|
|
+# define DIR_END '/'
|
|
+# else
|
|
+# define DIR_END '\\' /* OS uses '\\' as directory separator */
|
|
+# define DIR_END2 '/' /* also check for '/' (RTL may convert) */
|
|
+# endif
|
|
+# ifdef DATE_FORMAT
|
|
+# undef DATE_FORMAT
|
|
+# endif
|
|
+# define DATE_FORMAT dateformat()
|
|
+# define lenEOL 2
|
|
+# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);}
|
|
+# if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))
|
|
+# define USE_EF_UT_TIME
|
|
+# endif
|
|
+#endif /* MSDOS || OS2 || FLEXOS */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ MTS section (piggybacks UNIX, I think):
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef MTS
|
|
+# include <sys/types.h> /* off_t, time_t, dev_t, ... */
|
|
+# include <sys/stat.h>
|
|
+# include <sys/file.h> /* MTS uses this instead of fcntl.h */
|
|
+# include <timeb.h>
|
|
+# include <time.h>
|
|
+# include <unix.h> /* some important non-ANSI routines */
|
|
+# define mkdir(s,n) (-1) /* no "make directory" capability */
|
|
+# define EBCDIC /* set EBCDIC conversion on */
|
|
+# define NO_STRNICMP /* unzip's is as good the one in MTS */
|
|
+# define USE_FWRITE
|
|
+# define close_outfile() fclose(G.outfile) /* can't set time on files */
|
|
+# define umask(n) /* don't have umask() on MTS */
|
|
+# define FOPWT "w" /* open file for writing in TEXT mode */
|
|
+# ifndef DATE_FORMAT
|
|
+# define DATE_FORMAT DF_MDY
|
|
+# endif
|
|
+# define lenEOL 1
|
|
+# define PutNativeEOL *q++ = native(LF);
|
|
+#endif /* MTS */
|
|
+
|
|
+ /*---------------------------------------------------------------------------
|
|
+ Novell Netware NLM section
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef NLM
|
|
+# include "netware/nlmcfg.h"
|
|
+#endif
|
|
+
|
|
+ /*---------------------------------------------------------------------------
|
|
+ QDOS section
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef QDOS
|
|
+# define DIRENT
|
|
+# include <fcntl.h>
|
|
+# include <unistd.h>
|
|
+# include <sys/stat.h>
|
|
+# include <time.h>
|
|
+# include "qdos/izqdos.h"
|
|
+# ifndef DATE_FORMAT
|
|
+# define DATE_FORMAT DF_MDY
|
|
+# endif
|
|
+# define lenEOL 1
|
|
+# define PutNativeEOL *q++ = native(LF);
|
|
+# define DIR_END '_'
|
|
+# define RETURN QReturn
|
|
+# undef PATH_MAX
|
|
+# define PATH_MAX 36
|
|
+# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
|
|
+# define TIMESTAMP
|
|
+# endif
|
|
+# define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols)
|
|
+# define SCREENWIDTH 80
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Tandem NSK section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef TANDEM
|
|
+# include "tandem.h"
|
|
+# include <fcntl.h>
|
|
+# ifndef __INT32
|
|
+ /* We are compiling with non-WIDE memory model, int = 16 bits */
|
|
+# ifndef INT_16BIT
|
|
+# define INT_16BIT /* report "int" size is 16-bit to inflate setup */
|
|
+# endif
|
|
+# ifdef USE_DEFLATE64
|
|
+ /* Following required for 64k WSIZE of Deflate64 support */
|
|
+# define MED_MEM /* else OUTBUFSIZ is 64K and fails in do_string */
|
|
+# define INBUFSIZ 8192 /* but larger buffer for real OSes */
|
|
+# endif
|
|
+# endif
|
|
+ /* use a single LF delimiter so that writes to 101 text files work */
|
|
+# define PutNativeEOL *q++ = native(LF);
|
|
+# define lenEOL 1
|
|
+# ifndef DATE_FORMAT
|
|
+# define DATE_FORMAT DF_DMY
|
|
+# endif
|
|
+# define SCREENLINES 25
|
|
+ /* USE_EF_UT_TIME is set in tandem.h */
|
|
+# define RESTORE_UIDGID
|
|
+# define NO_STRNICMP
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ THEOS section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef THEOS
|
|
+# include "theos/thscfg.h"
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ TOPS-20 section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef TOPS20
|
|
+# include <sys/types.h> /* off_t, time_t, dev_t, ... */
|
|
+# include <sys/stat.h>
|
|
+# include <sys/param.h>
|
|
+# include <sys/time.h>
|
|
+# include <sys/timeb.h>
|
|
+# include <sys/file.h>
|
|
+# include <timex.h>
|
|
+# include <monsym.h> /* get amazing monsym() macro */
|
|
+ extern int open(), close(), read();
|
|
+ extern int stat(), unlink(), jsys(), fcntl();
|
|
+ extern long lseek(), dup(), creat();
|
|
+# define strchr index /* GRR: necessary? */
|
|
+# define strrchr rindex
|
|
+# define REALLY_SHORT_SYMS
|
|
+# define NO_MKDIR
|
|
+# ifndef HAVE_STRNICMP
|
|
+# define NO_STRNICMP /* probably not provided by TOPS20 C RTL */
|
|
+# endif
|
|
+# define DIR_BEG '<'
|
|
+# define DIR_END '>'
|
|
+# define DIR_EXT ".directory"
|
|
+# ifndef DATE_FORMAT
|
|
+# define DATE_FORMAT DF_MDY
|
|
+# endif
|
|
+# define EXE_EXTENSION ".exe" /* just a guess... */
|
|
+#endif /* TOPS20 */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Unix section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef UNIX
|
|
+# include "unix/unxcfg.h"
|
|
+#endif /* UNIX */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ VM/CMS and MVS section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef CMS_MVS
|
|
+# include "vmmvs.h"
|
|
+# define CLOSE_INFILE() close_infile(__G)
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ VMS section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef VMS
|
|
+# include "vms/vmscfg.h"
|
|
+#endif /* VMS */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Win32 (Windows 95/NT) section:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#if (defined(WIN32) && !defined(POCKET_UNZIP) && !defined(_WIN32_WCE))
|
|
+# include "win32/w32cfg.h"
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Win32 Windows CE section (also POCKET_UNZIP)
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#if (defined(_WIN32_WCE) || defined(POCKET_UNZIP))
|
|
+# include "wince/wcecfg.h"
|
|
+#endif
|
|
+
|
|
+
|
|
+
|
|
+/* ----------------------------------------------------------------------------
|
|
+ MUST BE AFTER LARGE FILE INCLUDES
|
|
+ ---------------------------------------------------------------------------- */
|
|
+/* This stuff calls in types and messes up large file includes. It needs to
|
|
+ go after large file defines in local includes.
|
|
+ I am guessing that moving them here probably broke some ports, but hey.
|
|
+ 10/31/2004 EG */
|
|
+/* ----------------------------------------------------------------------------
|
|
+ Common includes
|
|
+ ---------------------------------------------------------------------------- */
|
|
+
|
|
+/* Some ports apply specific adjustments which must be in effect before
|
|
+ reading the "standard" include headers.
|
|
+ */
|
|
+
|
|
+#ifdef EFT
|
|
+# define Z_OFF_T off_t /* Amdahl UTS nonsense ("extended file types") */
|
|
+#else
|
|
+#if (defined(UNIX) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64))
|
|
+# define Z_OFF_T off_t /* 64bit offsets to support 2GB < zipfile size < 4GB */
|
|
+#else
|
|
+# define Z_OFF_T long
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+#ifndef ZOFF_T_DEFINED
|
|
+ typedef Z_OFF_T zoff_t;
|
|
+# define ZOFF_T_DEFINED
|
|
+#endif
|
|
+#ifndef Z_STAT_DEFINED
|
|
+ typedef struct stat z_stat;
|
|
+# define Z_STAT_DEFINED
|
|
+#endif
|
|
+
|
|
+#ifndef MINIX /* Minix needs it after all the other includes (?) */
|
|
+# include <stdio.h>
|
|
+#endif
|
|
+
|
|
+#include <ctype.h> /* skip for VMS, to use tolower() function? */
|
|
+#include <errno.h> /* used in mapname() */
|
|
+#ifdef USE_STRINGS_H
|
|
+# include <strings.h> /* strcpy, strcmp, memcpy, index/rindex, etc. */
|
|
+#else
|
|
+# include <string.h> /* strcpy, strcmp, memcpy, strchr/strrchr, etc. */
|
|
+#endif
|
|
+#if (defined(MODERN) && !defined(NO_LIMITS_H))
|
|
+# include <limits.h> /* MAX/MIN constant symbols for system types... */
|
|
+#endif
|
|
+
|
|
+/* this include must be down here for SysV.4, for some reason... */
|
|
+#include <signal.h> /* used in unzip.c, fileio.c */
|
|
+
|
|
+
|
|
+#ifdef MODERN
|
|
+# ifndef NO_STDDEF_H
|
|
+# include <stddef.h>
|
|
+# endif
|
|
+# ifndef NO_STDLIB_H
|
|
+# include <stdlib.h> /* standard library prototypes, malloc(), etc. */
|
|
+# endif
|
|
+ typedef size_t extent;
|
|
+#else /* !MODERN */
|
|
+# ifndef AOS_VS /* mostly modern? */
|
|
+ Z_OFF_T lseek();
|
|
+# ifdef VAXC /* not fully modern, but has stdlib.h and void */
|
|
+# include <stdlib.h>
|
|
+# else
|
|
+ char *malloc();
|
|
+# endif /* ?VAXC */
|
|
+# endif /* !AOS_VS */
|
|
+ typedef unsigned int extent;
|
|
+#endif /* ?MODERN */
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*************/
|
|
+/* Defines */
|
|
+/*************/
|
|
+
|
|
+#define UNZIP_BZ2VERS 46
|
|
+#ifdef ZIP64_SUPPORT
|
|
+# ifdef USE_BZIP2
|
|
+# define UNZIP_VERSION UNZIP_BZ2VERS
|
|
+# else
|
|
+# define UNZIP_VERSION 45
|
|
+# endif
|
|
+#else
|
|
+#ifdef USE_DEFLATE64
|
|
+# define UNZIP_VERSION 21 /* compatible with PKUNZIP 4.0 */
|
|
+#else
|
|
+# define UNZIP_VERSION 20 /* compatible with PKUNZIP 2.0 */
|
|
+#endif
|
|
+#endif
|
|
+#define VMS_UNZIP_VERSION 42 /* if OS-needed-to-extract is VMS: can do */
|
|
+
|
|
+#if (defined(MSDOS) || defined(OS2))
|
|
+# define DOS_OS2
|
|
+#endif
|
|
+
|
|
+#if (defined(OS2) || defined(WIN32))
|
|
+# define OS2_W32
|
|
+#endif
|
|
+
|
|
+#if (defined(DOS_OS2) || defined(WIN32))
|
|
+# define DOS_OS2_W32
|
|
+# define DOS_W32_OS2 /* historical: don't use */
|
|
+#endif
|
|
+
|
|
+#if (defined(DOS_OS2_W32) || defined(__human68k__))
|
|
+# define DOS_H68_OS2_W32
|
|
+#endif
|
|
+
|
|
+#if (defined(DOS_OS2) || defined(FLEXOS))
|
|
+# define DOS_FLX_OS2
|
|
+#endif
|
|
+
|
|
+#if (defined(DOS_OS2_W32) || defined(FLEXOS))
|
|
+# define DOS_FLX_OS2_W32
|
|
+#endif
|
|
+
|
|
+#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))
|
|
+# define DOS_FLX_H68_OS2_W32
|
|
+#endif
|
|
+
|
|
+#if (defined(DOS_FLX_OS2) || defined(NLM))
|
|
+# define DOS_FLX_NLM_OS2
|
|
+#endif
|
|
+
|
|
+#if (defined(DOS_FLX_OS2_W32) || defined(NLM))
|
|
+# define DOS_FLX_NLM_OS2_W32
|
|
+#endif
|
|
+
|
|
+#if (defined(DOS_FLX_H68_OS2_W32) || defined(NLM))
|
|
+# define DOS_FLX_H68_NLM_OS2_W32
|
|
+#endif
|
|
+
|
|
+#if (defined(TOPS20) || defined(VMS))
|
|
+# define T20_VMS
|
|
+#endif
|
|
+
|
|
+#if (defined(MSDOS) || defined(T20_VMS))
|
|
+# define DOS_T20_VMS
|
|
+#endif
|
|
+
|
|
+#if (defined(__ATHEOS__) || defined(__BEOS__))
|
|
+# define ATH_BEO
|
|
+#endif
|
|
+
|
|
+#if (defined(ATH_BEO) || defined(UNIX))
|
|
+# define ATH_BEO_UNX
|
|
+#endif
|
|
+
|
|
+#if (defined(ATH_BEO_UNX) || defined(THEOS))
|
|
+# define ATH_BEO_THS_UNX
|
|
+#endif
|
|
+
|
|
+/* clean up with a few defaults */
|
|
+#ifndef DIR_END
|
|
+# define DIR_END '/' /* last char before program name or filename */
|
|
+#endif
|
|
+#ifndef DATE_FORMAT
|
|
+# ifdef DATEFMT_ISO_DEFAULT
|
|
+# define DATE_FORMAT DF_YMD /* defaults to invariant ISO-style */
|
|
+# else
|
|
+# define DATE_FORMAT DF_MDY /* defaults to US convention */
|
|
+# endif
|
|
+#endif
|
|
+#ifndef DATE_SEPCHAR
|
|
+# define DATE_SEPCHAR '-'
|
|
+#endif
|
|
+#ifndef CLOSE_INFILE
|
|
+# define CLOSE_INFILE() close(G.zipfd)
|
|
+#endif
|
|
+#ifndef RETURN
|
|
+# define RETURN return /* only used in main() */
|
|
+#endif
|
|
+#ifndef EXIT
|
|
+# define EXIT exit
|
|
+#endif
|
|
+#ifndef USAGE
|
|
+# define USAGE(ret) usage(__G__ (ret)) /* used in unzip.c, zipinfo.c */
|
|
+#endif
|
|
+#ifndef TIMET_TO_NATIVE /* everybody but MSC 7.0 and Macintosh */
|
|
+# define TIMET_TO_NATIVE(x)
|
|
+# define NATIVE_TO_TIMET(x)
|
|
+#endif
|
|
+#ifndef STRNICMP
|
|
+# ifdef NO_STRNICMP
|
|
+# define STRNICMP zstrnicmp
|
|
+# else
|
|
+# define STRNICMP strnicmp
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+
|
|
+#if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_UNX) || defined(RISCOS))
|
|
+# ifndef HAVE_UNLINK
|
|
+# define HAVE_UNLINK
|
|
+# endif
|
|
+#endif
|
|
+#if (defined(AOS_VS) || defined(ATARI)) /* GRR: others? */
|
|
+# ifndef HAVE_UNLINK
|
|
+# define HAVE_UNLINK
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* OS-specific exceptions to the "ANSI <--> INT_SPRINTF" rule */
|
|
+
|
|
+#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF))
|
|
+# if (defined(SYSV) || defined(CONVEX) || defined(NeXT) || defined(BSD4_4))
|
|
+# define INT_SPRINTF /* sprintf() returns int: SysVish/Posix */
|
|
+# endif
|
|
+# if (defined(DOS_FLX_NLM_OS2_W32) || defined(VMS) || defined(AMIGA))
|
|
+# define INT_SPRINTF /* sprintf() returns int: ANSI */
|
|
+# endif
|
|
+# if (defined(ultrix) || defined(__ultrix)) /* Ultrix 4.3 and newer */
|
|
+# if (defined(POSIX) || defined(__POSIX))
|
|
+# define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */
|
|
+# endif
|
|
+# ifdef __GNUC__
|
|
+# define PCHAR_SPRINTF /* undetermined actual return value */
|
|
+# endif
|
|
+# endif
|
|
+# if (defined(__osf__) || defined(_AIX) || defined(CMS_MVS) || defined(THEOS))
|
|
+# define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */
|
|
+# endif
|
|
+# if defined(sun)
|
|
+# define PCHAR_SPRINTF /* sprintf() returns char *: SunOS cc *and* gcc */
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* defaults that we hope will take care of most machines in the future */
|
|
+
|
|
+#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF))
|
|
+# ifdef __STDC__
|
|
+# define INT_SPRINTF /* sprintf() returns int: ANSI */
|
|
+# endif
|
|
+# ifndef INT_SPRINTF
|
|
+# define PCHAR_SPRINTF /* sprintf() returns char *: BSDish */
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#define MSG_STDERR(f) (f & 1) /* bit 0: 0 = stdout, 1 = stderr */
|
|
+#define MSG_INFO(f) ((f & 6) == 0) /* bits 1 and 2: 0 = info */
|
|
+#define MSG_WARN(f) ((f & 6) == 2) /* bits 1 and 2: 1 = warning */
|
|
+#define MSG_ERROR(f) ((f & 6) == 4) /* bits 1 and 2: 2 = error */
|
|
+#define MSG_FATAL(f) ((f & 6) == 6) /* bits 1 and 2: (3 = fatal error) */
|
|
+#define MSG_ZFN(f) (f & 0x0008) /* bit 3: 1 = print zipfile name */
|
|
+#define MSG_FN(f) (f & 0x0010) /* bit 4: 1 = print filename */
|
|
+#define MSG_LNEWLN(f) (f & 0x0020) /* bit 5: 1 = leading newline if !SOL */
|
|
+#define MSG_TNEWLN(f) (f & 0x0040) /* bit 6: 1 = trailing newline if !SOL */
|
|
+#define MSG_MNEWLN(f) (f & 0x0080) /* bit 7: 1 = trailing NL for prompts */
|
|
+/* the following are subject to change */
|
|
+#define MSG_NO_WGUI(f) (f & 0x0100) /* bit 8: 1 = skip if Windows GUI */
|
|
+#define MSG_NO_AGUI(f) (f & 0x0200) /* bit 9: 1 = skip if Acorn GUI */
|
|
+#define MSG_NO_DLL2(f) (f & 0x0400) /* bit 10: 1 = skip if OS/2 DLL */
|
|
+#define MSG_NO_NDLL(f) (f & 0x0800) /* bit 11: 1 = skip if WIN32 DLL */
|
|
+#define MSG_NO_WDLL(f) (f & 0x1000) /* bit 12: 1 = skip if Windows DLL */
|
|
+
|
|
+#if (defined(MORE) && !defined(SCREENLINES))
|
|
+# ifdef DOS_FLX_NLM_OS2_W32
|
|
+# define SCREENLINES 25 /* can be (should be) a function instead */
|
|
+# else
|
|
+# define SCREENLINES 24 /* VT-100s are assumed to be minimal hardware */
|
|
+# endif
|
|
+#endif
|
|
+#if (defined(MORE) && !defined(SCREENSIZE))
|
|
+# ifndef SCREENWIDTH
|
|
+# define SCREENSIZE(scrrows, scrcols) { \
|
|
+ if ((scrrows) != NULL) *(scrrows) = SCREENLINES; }
|
|
+# else
|
|
+# define SCREENSIZE(scrrows, scrcols) { \
|
|
+ if ((scrrows) != NULL) *(scrrows) = SCREENLINES; \
|
|
+ if ((scrcols) != NULL) *(scrcols) = SCREENWIDTH; }
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(__16BIT__) || defined(MED_MEM) || defined(SMALL_MEM))
|
|
+# define DIR_BLKSIZ 64 /* number of directory entries per block
|
|
+ * (should fit in 4096 bytes, usually) */
|
|
+#else
|
|
+# define DIR_BLKSIZ 16384 /* use more memory, to reduce long-range seeks */
|
|
+#endif
|
|
+
|
|
+#ifndef WSIZE
|
|
+# ifdef USE_DEFLATE64
|
|
+# define WSIZE 65536L /* window size--must be a power of two, and */
|
|
+# else /* at least 64K for PKZip's deflate64 method */
|
|
+# define WSIZE 0x8000 /* window size--must be a power of two, and */
|
|
+# endif /* at least 32K for zip's deflate method */
|
|
+#endif
|
|
+
|
|
+#ifdef __16BIT__
|
|
+# ifndef INT_16BIT
|
|
+# define INT_16BIT /* on 16-bit systems int size is 16 bits */
|
|
+# endif
|
|
+#else
|
|
+# define nearmalloc malloc
|
|
+# define nearfree free
|
|
+# if (!defined(__IBMC__) || !defined(OS2))
|
|
+# ifndef near
|
|
+# define near
|
|
+# endif
|
|
+# ifndef far
|
|
+# define far
|
|
+# endif
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(DYNALLOC_CRCTAB) && !defined(DYNAMIC_CRC_TABLE))
|
|
+# undef DYNALLOC_CRCTAB
|
|
+#endif
|
|
+
|
|
+#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))
|
|
+# undef DYNALLOC_CRCTAB /* not safe with reentrant code */
|
|
+#endif
|
|
+
|
|
+#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB))
|
|
+# ifdef DYNALLOC_CRCTAB
|
|
+# undef DYNALLOC_CRCTAB
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(USE_ZLIB) && defined(ASM_CRC))
|
|
+# undef ASM_CRC
|
|
+#endif
|
|
+
|
|
+#ifdef USE_ZLIB
|
|
+# ifdef IZ_CRC_BE_OPTIMIZ
|
|
+# undef IZ_CRC_BE_OPTIMIZ
|
|
+# endif
|
|
+# ifdef IZ_CRC_LE_OPTIMIZ
|
|
+# undef IZ_CRC_LE_OPTIMIZ
|
|
+# endif
|
|
+#endif
|
|
+#if (!defined(IZ_CRC_BE_OPTIMIZ) && !defined(IZ_CRC_LE_OPTIMIZ))
|
|
+# ifdef IZ_CRCOPTIM_UNFOLDTBL
|
|
+# undef IZ_CRCOPTIM_UNFOLDTBL
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifndef INBUFSIZ
|
|
+# if (defined(MED_MEM) || defined(SMALL_MEM))
|
|
+# define INBUFSIZ 2048 /* works for MS-DOS small model */
|
|
+# else
|
|
+# define INBUFSIZ 8192 /* larger buffers for real OSes */
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(INT_16BIT) && (defined(USE_DEFLATE64) || lenEOL > 1))
|
|
+ /* For environments using 16-bit integers OUTBUFSIZ must be limited to
|
|
+ * less than 64k (do_string() uses "unsigned" in calculations involving
|
|
+ * OUTBUFSIZ). This is achieved by defining MED_MEM when WSIZE = 64k (aka
|
|
+ * Deflate64 support enabled) or EOL markers contain multiple characters.
|
|
+ * (The rule gets applied AFTER the default rule for INBUFSIZ because it
|
|
+ * is not neccessary to reduce INBUFSIZE in this case.)
|
|
+ */
|
|
+# if (!defined(SMALL_MEM) && !defined(MED_MEM))
|
|
+# define MED_MEM
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* Logic for case of small memory, length of EOL > 1: if OUTBUFSIZ == 2048,
|
|
+ * OUTBUFSIZ>>1 == 1024 and OUTBUFSIZ>>7 == 16; therefore rawbuf is 1008 bytes
|
|
+ * and transbuf 1040 bytes. Have room for 32 extra EOL chars; 1008/32 == 31.5
|
|
+ * chars/line, smaller than estimated 35-70 characters per line for C source
|
|
+ * and normal text. Hence difference is sufficient for most "average" files.
|
|
+ * (Argument scales for larger OUTBUFSIZ.)
|
|
+ */
|
|
+#ifdef SMALL_MEM /* i.e., 16-bit OSes: MS-DOS, OS/2 1.x, etc. */
|
|
+# define LoadFarString(x) fLoadFarString(__G__ (x))
|
|
+# define LoadFarStringSmall(x) fLoadFarStringSmall(__G__ (x))
|
|
+# define LoadFarStringSmall2(x) fLoadFarStringSmall2(__G__ (x))
|
|
+# if (defined(_MSC_VER) && (_MSC_VER >= 600))
|
|
+# define zfstrcpy(dest, src) _fstrcpy((dest), (src))
|
|
+# define zfstrcmp(s1, s2) _fstrcmp((s1), (s2))
|
|
+# endif
|
|
+# if !(defined(SFX) || defined(FUNZIP))
|
|
+# if (defined(_MSC_VER))
|
|
+# define zfmalloc(sz) _fmalloc((sz))
|
|
+# define zffree(x) _ffree(x)
|
|
+# endif
|
|
+# if (defined(__TURBOC__))
|
|
+# include <alloc.h>
|
|
+# define zfmalloc(sz) farmalloc((unsigned long)(sz))
|
|
+# define zffree(x) farfree(x)
|
|
+# endif
|
|
+# endif /* !(SFX || FUNZIP) */
|
|
+# ifndef Far
|
|
+# define Far far /* __far only works for MSC 6.00, not 6.0a or Borland */
|
|
+# endif
|
|
+# define OUTBUFSIZ INBUFSIZ
|
|
+# if (lenEOL == 1)
|
|
+# define RAWBUFSIZ (OUTBUFSIZ>>1)
|
|
+# else
|
|
+# define RAWBUFSIZ ((OUTBUFSIZ>>1) - (OUTBUFSIZ>>7))
|
|
+# endif
|
|
+# define TRANSBUFSIZ (OUTBUFSIZ-RAWBUFSIZ)
|
|
+ typedef short shrint; /* short/int or "shrink int" (unshrink) */
|
|
+#else
|
|
+# define zfstrcpy(dest, src) strcpy((dest), (src))
|
|
+# define zfstrcmp(s1, s2) strcmp((s1), (s2))
|
|
+# define zfmalloc malloc
|
|
+# define zffree(x) free(x)
|
|
+# ifdef QDOS
|
|
+# define LoadFarString(x) Qstrfix(x) /* fix up _ for '.' */
|
|
+# define LoadFarStringSmall(x) Qstrfix(x)
|
|
+# define LoadFarStringSmall2(x) Qstrfix(x)
|
|
+# else
|
|
+# define LoadFarString(x) (char *)(x)
|
|
+# define LoadFarStringSmall(x) (char *)(x)
|
|
+# define LoadFarStringSmall2(x) (char *)(x)
|
|
+# endif
|
|
+# ifdef MED_MEM
|
|
+# define OUTBUFSIZ 0xFF80 /* can't malloc arrays of 0xFFE8 or more */
|
|
+# define TRANSBUFSIZ 0xFF80
|
|
+ typedef short shrint;
|
|
+# else
|
|
+# define OUTBUFSIZ (lenEOL*WSIZE) /* more efficient text conversion */
|
|
+# define TRANSBUFSIZ (lenEOL*OUTBUFSIZ)
|
|
+# ifdef AMIGA
|
|
+ typedef short shrint;
|
|
+# else
|
|
+ typedef int shrint; /* for efficiency/speed, we hope... */
|
|
+# endif
|
|
+# endif /* ?MED_MEM */
|
|
+# define RAWBUFSIZ OUTBUFSIZ
|
|
+#endif /* ?SMALL_MEM */
|
|
+
|
|
+#ifndef Far
|
|
+# define Far
|
|
+#endif
|
|
+
|
|
+#ifndef Cdecl
|
|
+# define Cdecl
|
|
+#endif
|
|
+
|
|
+#ifndef MAIN
|
|
+# define MAIN main
|
|
+#endif
|
|
+
|
|
+#ifdef SFX /* disable some unused features for SFX executables */
|
|
+# ifndef NO_ZIPINFO
|
|
+# define NO_ZIPINFO
|
|
+# endif
|
|
+# ifdef TIMESTAMP
|
|
+# undef TIMESTAMP
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifdef SFX
|
|
+# ifdef CHEAP_SFX_AUTORUN
|
|
+# ifndef NO_SFX_EXDIR
|
|
+# define NO_SFX_EXDIR
|
|
+# endif
|
|
+# endif
|
|
+# ifndef NO_SFX_EXDIR
|
|
+# ifndef SFX_EXDIR
|
|
+# define SFX_EXDIR
|
|
+# endif
|
|
+# else
|
|
+# ifdef SFX_EXDIR
|
|
+# undef SFX_EXDIR
|
|
+# endif
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* user may have defined both by accident... NOTIMESTAMP takes precedence */
|
|
+#if (defined(TIMESTAMP) && defined(NOTIMESTAMP))
|
|
+# undef TIMESTAMP
|
|
+#endif
|
|
+
|
|
+#if (!defined(COPYRIGHT_CLEAN) && !defined(USE_SMITH_CODE))
|
|
+# define COPYRIGHT_CLEAN
|
|
+#endif
|
|
+
|
|
+/* The LZW patent is expired worldwide since 2004-Jul-07, so USE_UNSHRINK
|
|
+ * is now enabled by default. See unshrink.c.
|
|
+ */
|
|
+#if (!defined(LZW_CLEAN) && !defined(USE_UNSHRINK))
|
|
+# define USE_UNSHRINK
|
|
+#endif
|
|
+
|
|
+#ifndef O_BINARY
|
|
+# define O_BINARY 0
|
|
+#endif
|
|
+
|
|
+#ifndef PIPE_ERROR
|
|
+# ifndef EPIPE
|
|
+# define EPIPE -1
|
|
+# endif
|
|
+# define PIPE_ERROR (errno == EPIPE)
|
|
+#endif
|
|
+
|
|
+/* File operations--use "b" for binary if allowed or fixed length 512 on VMS */
|
|
+#ifdef VMS
|
|
+# define FOPR "r","ctx=stm"
|
|
+# define FOPM "r+","ctx=stm","rfm=fix","mrs=512"
|
|
+# define FOPW "w","ctx=stm","rfm=fix","mrs=512"
|
|
+# define FOPWR "w+","ctx=stm","rfm=fix","mrs=512"
|
|
+#endif /* VMS */
|
|
+
|
|
+#ifdef CMS_MVS
|
|
+/* Binary files must be RECFM=F,LRECL=1 for ftell() to get correct pos */
|
|
+/* ...unless byteseek is used. Let's try that for a while. */
|
|
+# define FOPR "rb,byteseek"
|
|
+# define FOPM "r+b,byteseek"
|
|
+# ifdef MVS
|
|
+# define FOPW "wb,recfm=u,lrecl=32760,byteseek" /* New binary files */
|
|
+# define FOPWE "wb" /* Existing binary files */
|
|
+# define FOPWT "w,lrecl=133" /* New text files */
|
|
+# define FOPWTE "w" /* Existing text files */
|
|
+# else
|
|
+# define FOPW "wb,recfm=v,lrecl=32760"
|
|
+# define FOPWT "w"
|
|
+# endif
|
|
+#endif /* CMS_MVS */
|
|
+
|
|
+#ifdef TOPS20 /* TOPS-20 MODERN? You kidding? */
|
|
+# define FOPW "w8"
|
|
+#endif /* TOPS20 */
|
|
+
|
|
+/* Defaults when nothing special has been defined previously. */
|
|
+#ifdef MODERN
|
|
+# ifndef FOPR
|
|
+# define FOPR "rb"
|
|
+# endif
|
|
+# ifndef FOPM
|
|
+# define FOPM "r+b"
|
|
+# endif
|
|
+# ifndef FOPW
|
|
+# define FOPW "wb"
|
|
+# endif
|
|
+# ifndef FOPWT
|
|
+# define FOPWT "wt"
|
|
+# endif
|
|
+# ifndef FOPWR
|
|
+# define FOPWR "w+b"
|
|
+# endif
|
|
+#else /* !MODERN */
|
|
+# ifndef FOPR
|
|
+# define FOPR "r"
|
|
+# endif
|
|
+# ifndef FOPM
|
|
+# define FOPM "r+"
|
|
+# endif
|
|
+# ifndef FOPW
|
|
+# define FOPW "w"
|
|
+# endif
|
|
+# ifndef FOPWT
|
|
+# define FOPWT "w"
|
|
+# endif
|
|
+# ifndef FOPWR
|
|
+# define FOPWR "w+"
|
|
+# endif
|
|
+#endif /* ?MODERN */
|
|
+
|
|
+/*
|
|
+ * If <limits.h> exists on most systems, should include that, since it may
|
|
+ * define some or all of the following: NAME_MAX, PATH_MAX, _POSIX_NAME_MAX,
|
|
+ * _POSIX_PATH_MAX.
|
|
+ */
|
|
+#ifdef DOS_FLX_NLM_OS2_W32
|
|
+# include <limits.h>
|
|
+#endif
|
|
+
|
|
+/* 2008-07-22 SMS.
|
|
+ * Unfortunately, on VMS, <limits.h> exists, and is included by <stdlib.h>
|
|
+ * (so it's pretty much unavoidable), and it defines PATH_MAX to a fixed
|
|
+ * short value (256, correct only for older systems without ODS-5 support),
|
|
+ * rather than one based on the real RMS NAM[L] situation. So, we
|
|
+ * artificially undefine it here, to allow our better-defined _MAX_PATH
|
|
+ * (see vms/vmscfg.h) to be used.
|
|
+ */
|
|
+#ifdef VMS
|
|
+# undef PATH_MAX
|
|
+#endif
|
|
+
|
|
+#ifndef PATH_MAX
|
|
+# ifdef MAXPATHLEN
|
|
+# define PATH_MAX MAXPATHLEN /* in <sys/param.h> on some systems */
|
|
+# else
|
|
+# ifdef _MAX_PATH
|
|
+# define PATH_MAX _MAX_PATH
|
|
+# else
|
|
+# if FILENAME_MAX > 255
|
|
+# define PATH_MAX FILENAME_MAX /* used like PATH_MAX on some systems */
|
|
+# else
|
|
+# define PATH_MAX 1024
|
|
+# endif
|
|
+# endif /* ?_MAX_PATH */
|
|
+# endif /* ?MAXPATHLEN */
|
|
+#endif /* !PATH_MAX */
|
|
+
|
|
+/*
|
|
+ * buffer size required to hold the longest legal local filepath
|
|
+ * (including the trailing '\0')
|
|
+ */
|
|
+#define FILNAMSIZ PATH_MAX
|
|
+
|
|
+#ifdef UNICODE_SUPPORT
|
|
+# if !(defined(UTF8_MAYBE_NATIVE) || defined(UNICODE_WCHAR))
|
|
+# undef UNICODE_SUPPORT
|
|
+# endif
|
|
+#endif
|
|
+/* 2007-09-18 SMS.
|
|
+ * Include <locale.h> here if it will be needed later for Unicode.
|
|
+ * Otherwise, SETLOCALE may be defined here, and then defined again
|
|
+ * (differently) when <locale.h> is read later.
|
|
+ */
|
|
+#ifdef UNICODE_SUPPORT
|
|
+# ifdef UNICODE_WCHAR
|
|
+# if !(defined(_WIN32_WCE) || defined(POCKET_UNZIP))
|
|
+# include <wchar.h>
|
|
+# endif
|
|
+# endif
|
|
+# ifndef _MBCS /* no need to include <locale.h> twice, see below */
|
|
+# include <locale.h>
|
|
+# ifndef SETLOCALE
|
|
+# define SETLOCALE(category, locale) setlocale(category, locale)
|
|
+# endif
|
|
+# endif
|
|
+#endif /* UNICODE_SUPPORT */
|
|
+
|
|
+/* DBCS support for Info-ZIP (mainly for japanese (-: )
|
|
+ * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
|
|
+ */
|
|
+#ifdef _MBCS
|
|
+# include <locale.h>
|
|
+ /* Multi Byte Character Set */
|
|
+# define ___MBS_TMP_DEF char *___tmp_ptr;
|
|
+# define ___TMP_PTR ___tmp_ptr
|
|
+# ifndef CLEN
|
|
+# define NEED_UZMBCLEN
|
|
+# define CLEN(ptr) (int)uzmbclen((ZCONST unsigned char *)(ptr))
|
|
+# endif
|
|
+# ifndef PREINCSTR
|
|
+# define PREINCSTR(ptr) (ptr += CLEN(ptr))
|
|
+# endif
|
|
+# define POSTINCSTR(ptr) (___TMP_PTR=(char *)(ptr), PREINCSTR(ptr),___TMP_PTR)
|
|
+ char *plastchar OF((ZCONST char *ptr, extent len));
|
|
+# define lastchar(ptr, len) ((int)(unsigned)*plastchar(ptr, len))
|
|
+# ifndef MBSCHR
|
|
+# define NEED_UZMBSCHR
|
|
+# define MBSCHR(str,c) (char *)uzmbschr((ZCONST unsigned char *)(str), c)
|
|
+# endif
|
|
+# ifndef MBSRCHR
|
|
+# define NEED_UZMBSRCHR
|
|
+# define MBSRCHR(str,c) (char *)uzmbsrchr((ZCONST unsigned char *)(str), c)
|
|
+# endif
|
|
+# ifndef SETLOCALE
|
|
+# define SETLOCALE(category, locale) setlocale(category, locale)
|
|
+# endif
|
|
+#else /* !_MBCS */
|
|
+# define ___MBS_TMP_DEF
|
|
+# define ___TMP_PTR
|
|
+# define CLEN(ptr) 1
|
|
+# define PREINCSTR(ptr) (++(ptr))
|
|
+# define POSTINCSTR(ptr) ((ptr)++)
|
|
+# define plastchar(ptr, len) (&ptr[(len)-1])
|
|
+# define lastchar(ptr, len) (ptr[(len)-1])
|
|
+# define MBSCHR(str, c) strchr(str, c)
|
|
+# define MBSRCHR(str, c) strrchr(str, c)
|
|
+# ifndef SETLOCALE
|
|
+# define SETLOCALE(category, locale)
|
|
+# endif
|
|
+#endif /* ?_MBCS */
|
|
+#define INCSTR(ptr) PREINCSTR(ptr)
|
|
+
|
|
+
|
|
+#if (defined(MALLOC_WORK) && !defined(MY_ZCALLOC))
|
|
+ /* Any system without a special calloc function */
|
|
+# ifndef zcalloc
|
|
+# define zcalloc(items, size) \
|
|
+ (zvoid far *)calloc((unsigned)(items), (unsigned)(size))
|
|
+# endif
|
|
+# ifndef zcfree
|
|
+# define zcfree free
|
|
+# endif
|
|
+#endif /* MALLOC_WORK && !MY_ZCALLOC */
|
|
+
|
|
+#if (defined(CRAY) && defined(ZMEM))
|
|
+# undef ZMEM
|
|
+#endif
|
|
+
|
|
+#ifdef ZMEM
|
|
+# undef ZMEM
|
|
+# define memcmp(b1,b2,len) bcmp(b2,b1,len)
|
|
+# define memcpy(dest,src,len) bcopy(src,dest,len)
|
|
+# define memzero bzero
|
|
+#else
|
|
+# define memzero(dest,len) memset(dest,0,len)
|
|
+#endif
|
|
+
|
|
+#ifndef TRUE
|
|
+# define TRUE 1 /* sort of obvious */
|
|
+#endif
|
|
+#ifndef FALSE
|
|
+# define FALSE 0
|
|
+#endif
|
|
+
|
|
+#ifndef SEEK_SET
|
|
+# define SEEK_SET 0
|
|
+# define SEEK_CUR 1
|
|
+# define SEEK_END 2
|
|
+#endif
|
|
+
|
|
+#if (!defined(S_IEXEC) && defined(S_IXUSR))
|
|
+# define S_IEXEC S_IXUSR
|
|
+#endif
|
|
+
|
|
+#if (defined(UNIX) && defined(S_IFLNK) && !defined(MTS))
|
|
+# define SYMLINKS
|
|
+# ifndef S_ISLNK
|
|
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
|
+# endif
|
|
+#endif /* UNIX && S_IFLNK && !MTS */
|
|
+
|
|
+#ifndef S_ISDIR
|
|
+# ifdef CMS_MVS
|
|
+# define S_ISDIR(m) (FALSE)
|
|
+# else
|
|
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifndef IS_VOLID
|
|
+# define IS_VOLID(m) ((m) & 0x08)
|
|
+#endif
|
|
+
|
|
+/***********************************/
|
|
+/* LARGE_FILE_SUPPORT */
|
|
+/***********************************/
|
|
+/* This whole section lifted from Zip 3b tailor.h
|
|
+
|
|
+ * Types are in OS dependent headers (eg, w32cfg.h)
|
|
+ *
|
|
+ * LARGE_FILE_SUPPORT and ZIP64_SUPPORT are automatically
|
|
+ * set in OS dependent headers (for some ports) based on the port and compiler.
|
|
+ *
|
|
+ * Function prototypes are below as OF is defined earlier in this file
|
|
+ * but after OS dependent header is included.
|
|
+ *
|
|
+ * E. Gordon 9/21/2003
|
|
+ * Updated 1/28/2004
|
|
+ * Lifted and placed here 6/7/2004 - Myles Bennett
|
|
+ */
|
|
+#ifdef LARGE_FILE_SUPPORT
|
|
+ /* 64-bit Large File Support */
|
|
+
|
|
+/* ---------------------------- */
|
|
+
|
|
+# if defined(UNIX) || defined(VMS)
|
|
+
|
|
+ /* 64-bit stat functions */
|
|
+# define zstat stat
|
|
+# define zfstat fstat
|
|
+
|
|
+ /* 64-bit fseeko */
|
|
+# define zlseek lseek
|
|
+# define zfseeko fseeko
|
|
+
|
|
+ /* 64-bit ftello */
|
|
+# define zftello ftello
|
|
+
|
|
+ /* 64-bit fopen */
|
|
+# define zfopen fopen
|
|
+# define zfdopen fdopen
|
|
+
|
|
+# endif /* UNIX || VMS */
|
|
+
|
|
+/* ---------------------------- */
|
|
+
|
|
+# ifdef WIN32
|
|
+
|
|
+# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__LCC__)
|
|
+ /* MS C (VC), MinGW GCC port and LCC-32 use the MS C Runtime lib */
|
|
+
|
|
+ /* 64-bit stat functions */
|
|
+# define zstat _stati64
|
|
+# define zfstat _fstati64
|
|
+
|
|
+ /* 64-bit lseek */
|
|
+# define zlseek _lseeki64
|
|
+
|
|
+# if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
|
+ /* Beginning with VS 8.0 (Visual Studio 2005, MSC 14), the Microsoft
|
|
+ C rtl publishes its (previously internal) implmentations of
|
|
+ "fseeko" and "ftello" for 64-bit file offsets. */
|
|
+ /* 64-bit fseeko */
|
|
+# define zfseeko _fseeki64
|
|
+ /* 64-bit ftello */
|
|
+# define zftello _ftelli64
|
|
+
|
|
+# else /* not (defined(_MSC_VER) && (_MSC_VER >= 1400)) */
|
|
+
|
|
+# if defined(__MSVCRT_VERSION__) && (__MSVCRT_VERSION__ >= 0x800)
|
|
+ /* Up-to-date versions of MinGW define the macro __MSVCRT_VERSION__
|
|
+ to denote the version of the MS C rtl dll used for linking. When
|
|
+ configured to link against the runtime of MS Visual Studio 8 (or
|
|
+ newer), the built-in 64-bit fseek/ftell functions are available. */
|
|
+ /* 64-bit fseeko */
|
|
+# define zfseeko _fseeki64
|
|
+ /* 64-bit ftello */
|
|
+# define zftello _ftelli64
|
|
+
|
|
+# else /* !(defined(__MSVCRT_VERSION__) && (__MSVCRT_VERSION__>=0x800)) */
|
|
+ /* The version of the C runtime is lower than MSC 14 or unknown. */
|
|
+
|
|
+ /* The newest MinGW port contains built-in extensions to the MSC rtl
|
|
+ that provide fseeko and ftello, but our implementations will do
|
|
+ for now. */
|
|
+ /* 64-bit fseeko */
|
|
+ int zfseeko OF((FILE *, zoff_t, int));
|
|
+
|
|
+ /* 64-bit ftello */
|
|
+ zoff_t zftello OF((FILE *));
|
|
+
|
|
+# endif /* ? (__MSVCRT_VERSION__ >= 0x800) */
|
|
+# endif /* ? (_MSC_VER >= 1400) */
|
|
+
|
|
+ /* 64-bit fopen */
|
|
+# define zfopen fopen
|
|
+# define zfdopen fdopen
|
|
+
|
|
+# endif /* _MSC_VER || __MINGW__ || __LCC__ */
|
|
+
|
|
+# ifdef __CYGWIN__
|
|
+ /* CYGWIN GCC Posix emulator on Windows
|
|
+ (configuration not yet finished/tested) */
|
|
+
|
|
+ /* 64-bit stat functions */
|
|
+# define zstat _stati64
|
|
+# define zfstat _fstati64
|
|
+
|
|
+ /* 64-bit lseek */
|
|
+# define zlseek _lseeki64
|
|
+
|
|
+ /* 64-bit fseeko */
|
|
+# define zfseeko fseeko
|
|
+
|
|
+ /* 64-bit ftello */
|
|
+# define zftello ftello
|
|
+
|
|
+ /* 64-bit fopen */
|
|
+# define zfopen fopen
|
|
+# define zfdopen fdopen
|
|
+
|
|
+# endif
|
|
+# if defined(__WATCOMC__) || defined(__BORLANDC__)
|
|
+ /* WATCOM C and Borland C provide their own C runtime libraries,
|
|
+ but they are sufficiently compatible with MS CRTL. */
|
|
+
|
|
+ /* 64-bit stat functions */
|
|
+# define zstat _stati64
|
|
+# define zfstat _fstati64
|
|
+
|
|
+# ifdef __WATCOMC__
|
|
+ /* 64-bit lseek */
|
|
+# define zlseek _lseeki64
|
|
+# endif
|
|
+
|
|
+ /* 64-bit fseeko */
|
|
+ int zfseeko OF((FILE *, zoff_t, int));
|
|
+
|
|
+ /* 64-bit ftello */
|
|
+ zoff_t zftello OF((FILE *));
|
|
+
|
|
+ /* 64-bit fopen */
|
|
+# define zfopen fopen
|
|
+# define zfdopen fdopen
|
|
+
|
|
+# endif
|
|
+# ifdef __IBMC__
|
|
+ /* IBM C */
|
|
+
|
|
+ /* 64-bit stat functions */
|
|
+
|
|
+ /* 64-bit fseeko */
|
|
+
|
|
+ /* 64-bit ftello */
|
|
+
|
|
+ /* 64-bit fopen */
|
|
+
|
|
+# endif
|
|
+
|
|
+# endif /* WIN32 */
|
|
+
|
|
+#else
|
|
+ /* No Large File Support */
|
|
+
|
|
+# ifndef REGULUS /* returns the inode number on success(!)...argh argh argh */
|
|
+# define zstat stat
|
|
+# endif
|
|
+# define zfstat fstat
|
|
+# define zlseek lseek
|
|
+# define zfseeko fseek
|
|
+# define zftello ftell
|
|
+# define zfopen fopen
|
|
+# define zfdopen fdopen
|
|
+
|
|
+# if defined(UNIX) || defined(VMS) || defined(WIN32)
|
|
+ /* For these systems, implement "64bit file vs. 32bit prog" check */
|
|
+# ifndef DO_SAFECHECK_2GB
|
|
+# define DO_SAFECHECK_2GB
|
|
+# endif
|
|
+# endif
|
|
+
|
|
+#endif
|
|
+
|
|
+/* No "64bit file vs. 32bit prog" check for SFX stub, to save space */
|
|
+#if (defined(DO_SAFECHECK_2GB) && defined(SFX))
|
|
+# undef DO_SAFECHECK_2GB
|
|
+#endif
|
|
+
|
|
+#ifndef SSTAT
|
|
+# ifdef WILD_STAT_BUG
|
|
+# define SSTAT(path,pbuf) (iswild(path) || zstat(path,pbuf))
|
|
+# else
|
|
+# define SSTAT zstat
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+
|
|
+/* Default fzofft() format selection. */
|
|
+
|
|
+#ifndef FZOFFT_FMT
|
|
+
|
|
+# ifdef LARGE_FILE_SUPPORT
|
|
+# define FZOFFT_FMT "ll"
|
|
+# define FZOFFT_HEX_WID_VALUE "16"
|
|
+# else /* def LARGE_FILE_SUPPORT */
|
|
+# define FZOFFT_FMT "l"
|
|
+# define FZOFFT_HEX_WID_VALUE "8"
|
|
+# endif /* def LARGE_FILE_SUPPORT */
|
|
+
|
|
+#endif /* ndef FZOFFT_FMT */
|
|
+
|
|
+#define FZOFFT_HEX_WID ((char *) -1)
|
|
+#define FZOFFT_HEX_DOT_WID ((char *) -2)
|
|
+
|
|
+#define FZOFFT_NUM 4 /* Number of chambers. */
|
|
+#define FZOFFT_LEN 24 /* Number of characters/chamber. */
|
|
+
|
|
+
|
|
+#ifdef SHORT_SYMS /* Mark Williams C, ...? */
|
|
+# define extract_or_test_files xtr_or_tst_files
|
|
+# define extract_or_test_member xtr_or_tst_member
|
|
+#endif
|
|
+
|
|
+#ifdef REALLY_SHORT_SYMS /* TOPS-20 linker: first 6 chars */
|
|
+# define process_cdir_file_hdr XXpcdfh
|
|
+# define process_local_file_hdr XXplfh
|
|
+# define extract_or_test_files XXxotf /* necessary? */
|
|
+# define extract_or_test_member XXxotm /* necessary? */
|
|
+# define check_for_newer XXcfn
|
|
+# define overwrite_all XXoa
|
|
+# define process_all_files XXpaf
|
|
+# define extra_field XXef
|
|
+# define explode_lit8 XXel8
|
|
+# define explode_lit4 XXel4
|
|
+# define explode_nolit8 XXnl8
|
|
+# define explode_nolit4 XXnl4
|
|
+# define cpdist8 XXcpdist8
|
|
+# define inflate_codes XXic
|
|
+# define inflate_stored XXis
|
|
+# define inflate_fixed XXif
|
|
+# define inflate_dynamic XXid
|
|
+# define inflate_block XXib
|
|
+# define maxcodemax XXmax
|
|
+#endif
|
|
+
|
|
+#ifndef S_TIME_T_MAX /* max value of signed (>= 32-bit) time_t */
|
|
+# define S_TIME_T_MAX ((time_t)(ulg)0x7fffffffL)
|
|
+#endif
|
|
+#ifndef U_TIME_T_MAX /* max value of unsigned (>= 32-bit) time_t */
|
|
+# define U_TIME_T_MAX ((time_t)(ulg)0xffffffffL)
|
|
+#endif
|
|
+#ifdef DOSTIME_MINIMUM /* min DOSTIME value (1980-01-01) */
|
|
+# undef DOSTIME_MINIMUM
|
|
+#endif
|
|
+#define DOSTIME_MINIMUM ((ulg)0x00210000L)
|
|
+#ifdef DOSTIME_2038_01_18 /* approximate DOSTIME equivalent of */
|
|
+# undef DOSTIME_2038_01_18 /* the signed-32-bit time_t limit */
|
|
+#endif
|
|
+#define DOSTIME_2038_01_18 ((ulg)0x74320000L)
|
|
+
|
|
+#ifdef QDOS
|
|
+# define ZSUFX "_zip"
|
|
+# define ALT_ZSUFX ".zip"
|
|
+#else
|
|
+# ifdef RISCOS
|
|
+# define ZSUFX "/zip"
|
|
+# else
|
|
+# define ZSUFX ".zip"
|
|
+# endif
|
|
+# define ALT_ZSUFX ".ZIP" /* Unix-only so far (only case-sensitive fs) */
|
|
+#endif
|
|
+
|
|
+#define CENTRAL_HDR_SIG "\001\002" /* the infamous "PK" signature bytes, */
|
|
+#define LOCAL_HDR_SIG "\003\004" /* w/o "PK" (so unzip executable not */
|
|
+#define END_CENTRAL_SIG "\005\006" /* mistaken for zipfile itself) */
|
|
+#define EXTD_LOCAL_SIG "\007\010" /* [ASCII "\113" == EBCDIC "\080" ??] */
|
|
+
|
|
+/** internal-only return codes **/
|
|
+#define IZ_DIR 76 /* potential zipfile is a directory */
|
|
+/* special return codes for mapname() */
|
|
+#define MPN_OK 0 /* mapname successful */
|
|
+#define MPN_INF_TRUNC (1<<8) /* caution - filename truncated */
|
|
+#define MPN_INF_SKIP (2<<8) /* info - skipped because nothing to do */
|
|
+#define MPN_ERR_SKIP (3<<8) /* error - entry skipped */
|
|
+#define MPN_ERR_TOOLONG (4<<8) /* error - path too long */
|
|
+#define MPN_NOMEM (10<<8) /* error - out of memory, file skipped */
|
|
+#define MPN_CREATED_DIR (16<<8) /* directory created: set time & permission */
|
|
+#define MPN_VOL_LABEL (17<<8) /* volume label, but can't set on hard disk */
|
|
+#define MPN_INVALID (99<<8) /* internal logic error, should never reach */
|
|
+/* mask for internal mapname&checkdir return codes */
|
|
+#define MPN_MASK 0x7F00
|
|
+/* error code for extracting/testing extra field blocks */
|
|
+#define IZ_EF_TRUNC 79 /* local extra field truncated (PKZIP'd) */
|
|
+
|
|
+/* choice of activities for do_string() */
|
|
+#define SKIP 0 /* skip header block */
|
|
+#define DISPLAY 1 /* display archive comment (ASCII) */
|
|
+#define DISPL_8 5 /* display file comment (ext. ASCII) */
|
|
+#define DS_FN 2 /* read filename (ext. ASCII, chead) */
|
|
+#define DS_FN_C 2 /* read filename from central header */
|
|
+#define DS_FN_L 6 /* read filename from local header */
|
|
+#define EXTRA_FIELD 3 /* copy extra field into buffer */
|
|
+#define DS_EF 3
|
|
+#ifdef AMIGA
|
|
+# define FILENOTE 4 /* convert file comment to filenote */
|
|
+#endif
|
|
+#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
|
|
+# define CHECK_AUTORUN 7 /* copy command, display remainder */
|
|
+# define CHECK_AUTORUN_Q 8 /* copy command, skip remainder */
|
|
+#endif
|
|
+
|
|
+#define DOES_NOT_EXIST -1 /* return values for check_for_newer() */
|
|
+#define EXISTS_AND_OLDER 0
|
|
+#define EXISTS_AND_NEWER 1
|
|
+
|
|
+#define OVERWRT_QUERY 0 /* status values for G.overwrite_mode */
|
|
+#define OVERWRT_ALWAYS 1
|
|
+#define OVERWRT_NEVER 2
|
|
+
|
|
+#define IS_OVERWRT_ALL (G.overwrite_mode == OVERWRT_ALWAYS)
|
|
+#define IS_OVERWRT_NONE (G.overwrite_mode == OVERWRT_NEVER)
|
|
+
|
|
+#ifdef VMS
|
|
+ /* return codes for VMS-specific open_outfile() function */
|
|
+# define OPENOUT_OK 0 /* file openend normally */
|
|
+# define OPENOUT_FAILED 1 /* file open failed */
|
|
+# define OPENOUT_SKIPOK 2 /* file not opened, skip at error level OK */
|
|
+# define OPENOUT_SKIPWARN 3 /* file not opened, skip at error level WARN */
|
|
+#endif /* VMS */
|
|
+
|
|
+#define ROOT 0 /* checkdir() extract-to path: called once */
|
|
+#define INIT 1 /* allocate buildpath: called once per member */
|
|
+#define APPEND_DIR 2 /* append a dir comp.: many times per member */
|
|
+#define APPEND_NAME 3 /* append actual filename: once per member */
|
|
+#define GETPATH 4 /* retrieve the complete path and free it */
|
|
+#define END 5 /* free root path prior to exiting program */
|
|
+
|
|
+/* version_made_by codes (central dir): make sure these */
|
|
+/* are not defined on their respective systems!! */
|
|
+#define FS_FAT_ 0 /* filesystem used by MS-DOS, OS/2, Win32 */
|
|
+#define AMIGA_ 1
|
|
+#define VMS_ 2
|
|
+#define UNIX_ 3
|
|
+#define VM_CMS_ 4
|
|
+#define ATARI_ 5 /* what if it's a minix filesystem? [cjh] */
|
|
+#define FS_HPFS_ 6 /* filesystem used by OS/2 (and NT 3.x) */
|
|
+#define MAC_ 7 /* HFS filesystem used by MacOS */
|
|
+#define Z_SYSTEM_ 8
|
|
+#define CPM_ 9
|
|
+#define TOPS20_ 10
|
|
+#define FS_NTFS_ 11 /* filesystem used by Windows NT */
|
|
+#define QDOS_ 12
|
|
+#define ACORN_ 13 /* Archimedes Acorn RISC OS */
|
|
+#define FS_VFAT_ 14 /* filesystem used by Windows 95, NT */
|
|
+#define MVS_ 15
|
|
+#define BEOS_ 16 /* hybrid POSIX/database filesystem */
|
|
+#define TANDEM_ 17 /* Tandem NSK */
|
|
+#define THEOS_ 18 /* THEOS */
|
|
+#define MAC_OSX_ 19 /* Mac OS/X (Darwin) */
|
|
+#define ATHEOS_ 30 /* AtheOS */
|
|
+#define NUM_HOSTS 31 /* index of last system + 1 */
|
|
+/* don't forget to update zipinfo.c appropiately if NUM_HOSTS changes! */
|
|
+
|
|
+#define STORED 0 /* compression methods */
|
|
+#define SHRUNK 1
|
|
+#define REDUCED1 2
|
|
+#define REDUCED2 3
|
|
+#define REDUCED3 4
|
|
+#define REDUCED4 5
|
|
+#define IMPLODED 6
|
|
+#define TOKENIZED 7
|
|
+#define DEFLATED 8
|
|
+#define ENHDEFLATED 9
|
|
+#define DCLIMPLODED 10
|
|
+#define BZIPPED 12
|
|
+#define LZMAED 14
|
|
+#define IBMTERSED 18
|
|
+#define IBMLZ77ED 19
|
|
+#define WAVPACKED 97
|
|
+#define PPMDED 98
|
|
+#define NUM_METHODS 17 /* number of known method IDs */
|
|
+/* don't forget to update list.c (list_files()), extract.c and zipinfo.c
|
|
+ * appropriately if NUM_METHODS changes */
|
|
+
|
|
+/* (the PK-class error codes are public and have been moved into unzip.h) */
|
|
+
|
|
+#define DF_MDY 0 /* date format 10/26/91 (USA only) */
|
|
+#define DF_DMY 1 /* date format 26/10/91 (most of the world) */
|
|
+#define DF_YMD 2 /* date format 91/10/26 (a few countries) */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Extra-field block ID values and offset info.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+/* extra-field ID values, all little-endian: */
|
|
+#define EF_PKSZ64 0x0001 /* PKWARE's 64-bit filesize extensions */
|
|
+#define EF_AV 0x0007 /* PKWARE's authenticity verification */
|
|
+#define EF_EFS 0x0008 /* PKWARE's extended language encoding */
|
|
+#define EF_OS2 0x0009 /* OS/2 extended attributes */
|
|
+#define EF_PKW32 0x000a /* PKWARE's Win95/98/WinNT filetimes */
|
|
+#define EF_PKVMS 0x000c /* PKWARE's VMS */
|
|
+#define EF_PKUNIX 0x000d /* PKWARE's Unix */
|
|
+#define EF_PKFORK 0x000e /* PKWARE's future stream/fork descriptors */
|
|
+#define EF_PKPATCH 0x000f /* PKWARE's patch descriptor */
|
|
+#define EF_PKPKCS7 0x0014 /* PKWARE's PKCS#7 store for X.509 Certs */
|
|
+#define EF_PKFX509 0x0015 /* PKWARE's file X.509 Cert&Signature ID */
|
|
+#define EF_PKCX509 0x0016 /* PKWARE's central dir X.509 Cert ID */
|
|
+#define EF_PKENCRHD 0x0017 /* PKWARE's Strong Encryption header */
|
|
+#define EF_PKRMCTL 0x0018 /* PKWARE's Record Management Controls*/
|
|
+#define EF_PKLSTCS7 0x0019 /* PKWARE's PKCS#7 Encr. Recipient Cert List */
|
|
+#define EF_PKIBM 0x0065 /* PKWARE's IBM S/390 & AS/400 attributes */
|
|
+#define EF_PKIBM2 0x0066 /* PKWARE's IBM S/390 & AS/400 compr. attribs */
|
|
+#define EF_IZVMS 0x4d49 /* Info-ZIP's VMS ("IM") */
|
|
+#define EF_IZUNIX 0x5855 /* Info-ZIP's first Unix[1] ("UX") */
|
|
+#define EF_IZUNIX2 0x7855 /* Info-ZIP's second Unix[2] ("Ux") */
|
|
+#define EF_IZUNIX3 0x7875 /* Info-ZIP's newest Unix[3] ("ux") */
|
|
+#define EF_TIME 0x5455 /* universal timestamp ("UT") */
|
|
+#define EF_UNIPATH 0x7075 /* Info-ZIP Unicode Path ("up") */
|
|
+#define EF_UNICOMNT 0x6375 /* Info-ZIP Unicode Comment ("uc") */
|
|
+#define EF_MAC3 0x334d /* Info-ZIP's new Macintosh (= "M3") */
|
|
+#define EF_JLMAC 0x07c8 /* Johnny Lee's old Macintosh (= 1992) */
|
|
+#define EF_ZIPIT 0x2605 /* Thomas Brown's Macintosh (ZipIt) */
|
|
+#define EF_ZIPIT2 0x2705 /* T. Brown's Mac (ZipIt) v 1.3.8 and newer ? */
|
|
+#define EF_SMARTZIP 0x4d63 /* Mac SmartZip by Marco Bambini */
|
|
+#define EF_VMCMS 0x4704 /* Info-ZIP's VM/CMS ("\004G") */
|
|
+#define EF_MVS 0x470f /* Info-ZIP's MVS ("\017G") */
|
|
+#define EF_ACL 0x4c41 /* (OS/2) access control list ("AL") */
|
|
+#define EF_NTSD 0x4453 /* NT security descriptor ("SD") */
|
|
+#define EF_ATHEOS 0x7441 /* AtheOS ("At") */
|
|
+#define EF_BEOS 0x6542 /* BeOS ("Be") */
|
|
+#define EF_QDOS 0xfb4a /* SMS/QDOS ("J\373") */
|
|
+#define EF_AOSVS 0x5356 /* AOS/VS ("VS") */
|
|
+#define EF_SPARK 0x4341 /* David Pilling's Acorn/SparkFS ("AC") */
|
|
+#define EF_TANDEM 0x4154 /* Tandem NSK ("TA") */
|
|
+#define EF_THEOS 0x6854 /* Jean-Michel Dubois' Theos "Th" */
|
|
+#define EF_THEOSO 0x4854 /* old Theos port */
|
|
+#define EF_MD5 0x4b46 /* Fred Kantor's MD5 ("FK") */
|
|
+#define EF_ASIUNIX 0x756e /* ASi's Unix ("nu") */
|
|
+
|
|
+#define EB_HEADSIZE 4 /* length of extra field block header */
|
|
+#define EB_ID 0 /* offset of block ID in header */
|
|
+#define EB_LEN 2 /* offset of data length field in header */
|
|
+#define EB_UCSIZE_P 0 /* offset of ucsize field in compr. data */
|
|
+#define EB_CMPRHEADLEN 6 /* lenght of compression header */
|
|
+
|
|
+#define EB_UX_MINLEN 8 /* minimal "UX" field contains atime, mtime */
|
|
+#define EB_UX_FULLSIZE 12 /* full "UX" field (atime, mtime, uid, gid) */
|
|
+#define EB_UX_ATIME 0 /* offset of atime in "UX" extra field data */
|
|
+#define EB_UX_MTIME 4 /* offset of mtime in "UX" extra field data */
|
|
+#define EB_UX_UID 8 /* byte offset of UID in "UX" field data */
|
|
+#define EB_UX_GID 10 /* byte offset of GID in "UX" field data */
|
|
+
|
|
+#define EB_UX2_MINLEN 4 /* minimal "Ux" field contains UID/GID */
|
|
+#define EB_UX2_UID 0 /* byte offset of UID in "Ux" field data */
|
|
+#define EB_UX2_GID 2 /* byte offset of GID in "Ux" field data */
|
|
+#define EB_UX2_VALID (1 << 8) /* UID/GID present */
|
|
+
|
|
+#define EB_UX3_MINLEN 7 /* minimal "ux" field size (2-byte UID/GID) */
|
|
+
|
|
+#define EB_UT_MINLEN 1 /* minimal UT field contains Flags byte */
|
|
+#define EB_UT_FLAGS 0 /* byte offset of Flags field */
|
|
+#define EB_UT_TIME1 1 /* byte offset of 1st time value */
|
|
+#define EB_UT_FL_MTIME (1 << 0) /* mtime present */
|
|
+#define EB_UT_FL_ATIME (1 << 1) /* atime present */
|
|
+#define EB_UT_FL_CTIME (1 << 2) /* ctime present */
|
|
+
|
|
+#define EB_FLGS_OFFS 4 /* offset of flags area in generic compressed
|
|
+ extra field blocks (BEOS, MAC, and others) */
|
|
+#define EB_OS2_HLEN 4 /* size of OS2/ACL compressed data header */
|
|
+#define EB_BEOS_HLEN 5 /* length of BeOS&AtheOS e.f attribute header */
|
|
+#define EB_BE_FL_UNCMPR 0x01 /* "BeOS&AtheOS attribs uncompr." bit flag */
|
|
+#define EB_MAC3_HLEN 14 /* length of Mac3 attribute block header */
|
|
+#define EB_SMARTZIP_HLEN 64 /* fixed length of the SmartZip extra field */
|
|
+#define EB_M3_FL_DATFRK 0x01 /* "this entry is data fork" flag */
|
|
+#define EB_M3_FL_UNCMPR 0x04 /* "Mac3 attributes uncompressed" bit flag */
|
|
+#define EB_M3_FL_TIME64 0x08 /* "Mac3 time fields are 64 bit wide" flag */
|
|
+#define EB_M3_FL_NOUTC 0x10 /* "Mac3 timezone offset fields missing" flag */
|
|
+
|
|
+#define EB_NTSD_C_LEN 4 /* length of central NT security data */
|
|
+#define EB_NTSD_L_LEN 5 /* length of minimal local NT security data */
|
|
+#define EB_NTSD_VERSION 4 /* offset of NTSD version byte */
|
|
+#define EB_NTSD_MAX_VER (0) /* maximum version # we know how to handle */
|
|
+
|
|
+#define EB_PKVMS_MINLEN 4 /* minimum data length of PKVMS extra block */
|
|
+
|
|
+#define EB_ASI_CRC32 0 /* offset of ASI Unix field's crc32 checksum */
|
|
+#define EB_ASI_MODE 4 /* offset of ASI Unix permission mode field */
|
|
+
|
|
+#define EB_IZVMS_HLEN 12 /* length of IZVMS attribute block header */
|
|
+#define EB_IZVMS_FLGS 4 /* offset of compression type flag */
|
|
+#define EB_IZVMS_UCSIZ 6 /* offset of ucsize field in IZVMS header */
|
|
+#define EB_IZVMS_BCMASK 07 /* 3 bits for compression type */
|
|
+#define EB_IZVMS_BCSTOR 0 /* Stored */
|
|
+#define EB_IZVMS_BC00 1 /* 0byte -> 0bit compression */
|
|
+#define EB_IZVMS_BCDEFL 2 /* Deflated */
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ True sizes of the various headers (excluding their 4-byte signatures),
|
|
+ as defined by PKWARE--so it is not likely that these will ever change.
|
|
+ But if they do, make sure both these defines AND the typedefs below get
|
|
+ updated accordingly.
|
|
+
|
|
+ 12/27/2006
|
|
+ The Zip64 End Of Central Directory record is variable size and now
|
|
+ comes in two flavors, version 1 and the new version 2 that supports
|
|
+ central directory encryption. We only use the old fields at the
|
|
+ top of the Zip64 EOCDR, and this block is a fixed size still, but
|
|
+ need to be aware of the stuff following.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+#define LREC_SIZE 26 /* lengths of local file headers, central */
|
|
+#define CREC_SIZE 42 /* directory headers, end-of-central-dir */
|
|
+#define ECREC_SIZE 18 /* record, zip64 end-of-cent-dir locator */
|
|
+#define ECLOC64_SIZE 16 /* and zip64 end-of-central-dir record, */
|
|
+#define ECREC64_SIZE 52 /* respectively */
|
|
+
|
|
+#define MAX_BITS 13 /* used in unshrink() */
|
|
+#define HSIZE (1 << MAX_BITS) /* size of global work area */
|
|
+
|
|
+#define LF 10 /* '\n' on ASCII machines; must be 10 due to EBCDIC */
|
|
+#define CR 13 /* '\r' on ASCII machines; must be 13 due to EBCDIC */
|
|
+#define CTRLZ 26 /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */
|
|
+
|
|
+#ifdef EBCDIC
|
|
+# define foreign(c) ascii[(uch)(c)]
|
|
+# define native(c) ebcdic[(uch)(c)]
|
|
+# define NATIVE "EBCDIC"
|
|
+# define NOANSIFILT
|
|
+#endif
|
|
+
|
|
+#ifdef VMS
|
|
+# define ENV_UNZIP "UNZIP_OPTS" /* names of environment variables */
|
|
+# define ENV_ZIPINFO "ZIPINFO_OPTS"
|
|
+#endif /* VMS */
|
|
+#ifdef RISCOS
|
|
+# define ENV_UNZIP "Unzip$Options"
|
|
+# define ENV_ZIPINFO "Zipinfo$Options"
|
|
+# define ENV_UNZIPEXTS "Unzip$Exts"
|
|
+#endif /* RISCOS */
|
|
+#ifndef ENV_UNZIP
|
|
+# define ENV_UNZIP "UNZIP" /* the standard names */
|
|
+# define ENV_ZIPINFO "ZIPINFO"
|
|
+#endif
|
|
+#define ENV_UNZIP2 "UNZIPOPT" /* alternate names, for zip compat. */
|
|
+#define ENV_ZIPINFO2 "ZIPINFOOPT"
|
|
+
|
|
+#if (!defined(QQ) && !defined(NOQQ))
|
|
+# define QQ
|
|
+#endif
|
|
+
|
|
+#ifdef QQ /* Newtware version: no file */
|
|
+# define QCOND (!uO.qflag) /* comments with -vq or -vqq */
|
|
+#else /* Bill Davidsen version: no way to */
|
|
+# define QCOND (longhdr) /* kill file comments when listing */
|
|
+#endif
|
|
+
|
|
+#ifdef OLD_QQ
|
|
+# define QCOND2 (uO.qflag < 2)
|
|
+#else
|
|
+# define QCOND2 (!uO.qflag)
|
|
+#endif
|
|
+
|
|
+#ifdef WILD_STOP_AT_DIR
|
|
+# define __WDLPRO , int sepc
|
|
+# define __WDL , sepc
|
|
+# define __WDLDEF int sepc;
|
|
+# define WISEP , (uO.W_flag ? '/' : '\0')
|
|
+#else
|
|
+# define __WDLPRO
|
|
+# define __WDL
|
|
+# define __WDLDEF
|
|
+# define WISEP
|
|
+#endif
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/**************/
|
|
+/* Typedefs */
|
|
+/**************/
|
|
+
|
|
+#ifdef ZIP64_SUPPORT
|
|
+# ifndef Z_UINT8_DEFINED
|
|
+# if (defined(__GNUC__) || defined(__hpux) || defined(__SUNPRO_C))
|
|
+ typedef unsigned long long z_uint8;
|
|
+# else
|
|
+ typedef unsigned __int64 z_uint8;
|
|
+# endif
|
|
+# define Z_UINT8_DEFINED
|
|
+# endif
|
|
+#endif
|
|
+#ifndef Z_UINT4_DEFINED
|
|
+# if (defined(MODERN) && !defined(NO_LIMITS_H))
|
|
+# if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL))
|
|
+ typedef unsigned int z_uint4;
|
|
+# define Z_UINT4_DEFINED
|
|
+# else
|
|
+# if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL))
|
|
+ typedef unsigned long z_uint4;
|
|
+# define Z_UINT4_DEFINED
|
|
+# else
|
|
+# if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL))
|
|
+ typedef unsigned short z_uint4;
|
|
+# define Z_UINT4_DEFINED
|
|
+# endif
|
|
+# endif
|
|
+# endif
|
|
+# endif /* MODERN && !NO_LIMITS_H */
|
|
+#endif /* !Z_UINT4_DEFINED */
|
|
+#ifndef Z_UINT4_DEFINED
|
|
+ typedef ulg z_uint4;
|
|
+# define Z_UINT4_DEFINED
|
|
+#endif
|
|
+
|
|
+/* The following three user-defined unsigned integer types are used for
|
|
+ holding zipfile entities (required widths without / with Zip64 support):
|
|
+ a) sizes and offset of zipfile entries
|
|
+ (4 bytes / 8 bytes)
|
|
+ b) enumeration and counts of zipfile entries
|
|
+ (2 bytes / 8 bytes)
|
|
+ Remark: internally, we use 4 bytes for archive member counting in the
|
|
+ No-Zip64 case, because UnZip supports more than 64k entries for
|
|
+ classic Zip archives without Zip64 extensions.
|
|
+ c) enumeration and counts of zipfile volumes of multivolume archives
|
|
+ (2 bytes / 4 bytes)
|
|
+ */
|
|
+#ifdef ZIP64_SUPPORT
|
|
+ typedef z_uint8 zusz_t; /* zipentry sizes & offsets */
|
|
+ typedef z_uint8 zucn_t; /* archive entry counts */
|
|
+ typedef z_uint4 zuvl_t; /* multivolume numbers */
|
|
+# define MASK_ZUCN64 (~(zucn_t)0)
|
|
+/* In case we ever get to support an environment where z_uint8 may be WIDER
|
|
+ than 64 bit wide, we will have to apply a construct similar to
|
|
+ #define MASK_ZUCN64 (~(zucn_t)0 & (zucn_t)0xffffffffffffffffULL)
|
|
+ for the 64-bit mask.
|
|
+ */
|
|
+#else
|
|
+ typedef ulg zusz_t; /* zipentry sizes & offsets */
|
|
+ typedef unsigned int zucn_t; /* archive entry counts */
|
|
+ typedef unsigned short zuvl_t; /* multivolume numbers */
|
|
+# define MASK_ZUCN64 (~(zucn_t)0)
|
|
+#endif
|
|
+#define MASK_ZUCN16 ((zucn_t)0xFFFF)
|
|
+
|
|
+#ifdef NO_UID_GID
|
|
+# ifdef UID_USHORT
|
|
+ typedef unsigned short uid_t; /* TI SysV.3 */
|
|
+ typedef unsigned short gid_t;
|
|
+# else
|
|
+ typedef unsigned int uid_t; /* SCO Xenix */
|
|
+ typedef unsigned int gid_t;
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (defined(GOT_UTIMBUF) || defined(sgi) || defined(ATARI))
|
|
+ typedef struct utimbuf ztimbuf;
|
|
+#else
|
|
+ typedef struct ztimbuf {
|
|
+ time_t actime; /* new access time */
|
|
+ time_t modtime; /* new modification time */
|
|
+ } ztimbuf;
|
|
+#endif
|
|
+
|
|
+typedef struct iztimes {
|
|
+ time_t atime; /* new access time */
|
|
+ time_t mtime; /* new modification time */
|
|
+ time_t ctime; /* used for creation time; NOT same as st_ctime */
|
|
+} iztimes;
|
|
+
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ typedef struct direntry { /* head of system-specific struct holding */
|
|
+ struct direntry *next; /* defered directory attributes info */
|
|
+ char *fn; /* filename of directory */
|
|
+ char buf[1]; /* start of system-specific internal data */
|
|
+ } direntry;
|
|
+#endif /* SET_DIR_ATTRIB */
|
|
+
|
|
+#ifdef SYMLINKS
|
|
+ typedef struct slinkentry { /* info for deferred symlink creation */
|
|
+ struct slinkentry *next; /* pointer to next entry in chain */
|
|
+ extent targetlen; /* length of target filespec */
|
|
+ extent attriblen; /* length of system-specific attrib data */
|
|
+ char *target; /* pointer to target filespec */
|
|
+ char *fname; /* pointer to name of link */
|
|
+ char buf[1]; /* data/name/link buffer */
|
|
+ } slinkentry;
|
|
+#endif /* SYMLINKS */
|
|
+
|
|
+typedef struct min_info {
|
|
+ zoff_t offset;
|
|
+ zusz_t compr_size; /* compressed size (needed if extended header) */
|
|
+ zusz_t uncompr_size; /* uncompressed size (needed if extended header) */
|
|
+ ulg crc; /* crc (needed if extended header) */
|
|
+ zuvl_t diskstart; /* no of volume where this entry starts */
|
|
+ uch hostver;
|
|
+ uch hostnum;
|
|
+ unsigned file_attr; /* local flavor, as used by creat(), chmod()... */
|
|
+ unsigned encrypted : 1; /* file encrypted: decrypt before uncompressing */
|
|
+ unsigned ExtLocHdr : 1; /* use time instead of CRC for decrypt check */
|
|
+ unsigned textfile : 1; /* file is text (according to zip) */
|
|
+ unsigned textmode : 1; /* file is to be extracted as text */
|
|
+ unsigned lcflag : 1; /* convert filename to lowercase */
|
|
+ unsigned vollabel : 1; /* "file" is an MS-DOS volume (disk) label */
|
|
+#ifdef SYMLINKS
|
|
+ unsigned symlink : 1; /* file is a symbolic link */
|
|
+#endif
|
|
+ unsigned HasUxAtt : 1; /* crec ext_file_attr has Unix style mode bits */
|
|
+#ifdef UNICODE_SUPPORT
|
|
+ unsigned GPFIsUTF8: 1; /* crec gen_purpose_flag UTF-8 bit 11 is set */
|
|
+#endif
|
|
+#ifndef SFX
|
|
+ char Far *cfilname; /* central header version of filename */
|
|
+#endif
|
|
+} min_info;
|
|
+
|
|
+typedef struct VMStimbuf {
|
|
+ char *revdate; /* (both roughly correspond to Unix modtime/st_mtime) */
|
|
+ char *credate;
|
|
+} VMStimbuf;
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Zipfile work area declarations.
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef MALLOC_WORK
|
|
+ union work {
|
|
+ struct { /* unshrink(): */
|
|
+ shrint *Parent; /* pointer to (8192 * sizeof(shrint)) */
|
|
+ uch *value; /* pointer to 8KB char buffer */
|
|
+ uch *Stack; /* pointer to another 8KB char buffer */
|
|
+ } shrink;
|
|
+ uch *Slide; /* explode(), inflate(), unreduce() */
|
|
+ };
|
|
+#else /* !MALLOC_WORK */
|
|
+ union work {
|
|
+ struct { /* unshrink(): */
|
|
+ shrint Parent[HSIZE]; /* (8192 * sizeof(shrint)) == 16KB minimum */
|
|
+ uch value[HSIZE]; /* 8KB */
|
|
+ uch Stack[HSIZE]; /* 8KB */
|
|
+ } shrink; /* total = 32KB minimum; 80KB on Cray/Alpha */
|
|
+ uch Slide[WSIZE]; /* explode(), inflate(), unreduce() */
|
|
+ };
|
|
+#endif /* ?MALLOC_WORK */
|
|
+
|
|
+#define slide G.area.Slide
|
|
+
|
|
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
|
|
+# define redirSlide G.redirect_sldptr
|
|
+#else
|
|
+# define redirSlide G.area.Slide
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Zipfile layout declarations. If these headers ever change, make sure the
|
|
+ xxREC_SIZE defines (above) change with them!
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+ typedef uch local_byte_hdr[ LREC_SIZE ];
|
|
+# define L_VERSION_NEEDED_TO_EXTRACT_0 0
|
|
+# define L_VERSION_NEEDED_TO_EXTRACT_1 1
|
|
+# define L_GENERAL_PURPOSE_BIT_FLAG 2
|
|
+# define L_COMPRESSION_METHOD 4
|
|
+# define L_LAST_MOD_DOS_DATETIME 6
|
|
+# define L_CRC32 10
|
|
+# define L_COMPRESSED_SIZE 14
|
|
+# define L_UNCOMPRESSED_SIZE 18
|
|
+# define L_FILENAME_LENGTH 22
|
|
+# define L_EXTRA_FIELD_LENGTH 24
|
|
+
|
|
+ typedef uch cdir_byte_hdr[ CREC_SIZE ];
|
|
+# define C_VERSION_MADE_BY_0 0
|
|
+# define C_VERSION_MADE_BY_1 1
|
|
+# define C_VERSION_NEEDED_TO_EXTRACT_0 2
|
|
+# define C_VERSION_NEEDED_TO_EXTRACT_1 3
|
|
+# define C_GENERAL_PURPOSE_BIT_FLAG 4
|
|
+# define C_COMPRESSION_METHOD 6
|
|
+# define C_LAST_MOD_DOS_DATETIME 8
|
|
+# define C_CRC32 12
|
|
+# define C_COMPRESSED_SIZE 16
|
|
+# define C_UNCOMPRESSED_SIZE 20
|
|
+# define C_FILENAME_LENGTH 24
|
|
+# define C_EXTRA_FIELD_LENGTH 26
|
|
+# define C_FILE_COMMENT_LENGTH 28
|
|
+# define C_DISK_NUMBER_START 30
|
|
+# define C_INTERNAL_FILE_ATTRIBUTES 32
|
|
+# define C_EXTERNAL_FILE_ATTRIBUTES 34
|
|
+# define C_RELATIVE_OFFSET_LOCAL_HEADER 38
|
|
+
|
|
+ typedef uch ec_byte_rec[ ECREC_SIZE+4 ];
|
|
+/* define SIGNATURE 0 space-holder only */
|
|
+# define NUMBER_THIS_DISK 4
|
|
+# define NUM_DISK_WITH_START_CEN_DIR 6
|
|
+# define NUM_ENTRIES_CEN_DIR_THS_DISK 8
|
|
+# define TOTAL_ENTRIES_CENTRAL_DIR 10
|
|
+# define SIZE_CENTRAL_DIRECTORY 12
|
|
+# define OFFSET_START_CENTRAL_DIRECTORY 16
|
|
+# define ZIPFILE_COMMENT_LENGTH 20
|
|
+
|
|
+ typedef uch ec_byte_loc64[ ECLOC64_SIZE+4 ];
|
|
+# define NUM_DISK_START_EOCDR64 4
|
|
+# define OFFSET_START_EOCDR64 8
|
|
+# define NUM_THIS_DISK_LOC64 16
|
|
+
|
|
+ typedef uch ec_byte_rec64[ ECREC64_SIZE+4 ];
|
|
+# define ECREC64_LENGTH 4
|
|
+# define EC_VERSION_MADE_BY_0 12
|
|
+# define EC_VERSION_NEEDED_0 14
|
|
+# define NUMBER_THIS_DSK_REC64 16
|
|
+# define NUM_DISK_START_CEN_DIR64 20
|
|
+# define NUM_ENTRIES_CEN_DIR_THS_DISK64 24
|
|
+# define TOTAL_ENTRIES_CENTRAL_DIR64 32
|
|
+# define SIZE_CENTRAL_DIRECTORY64 40
|
|
+# define OFFSET_START_CENTRAL_DIRECT64 48
|
|
+
|
|
+
|
|
+/* The following structs are used to hold all header data of a zip entry.
|
|
+ Traditionally, the structs' layouts followed the data layout of the
|
|
+ corresponding zipfile header structures. However, the zipfile header
|
|
+ layouts were designed in the old ages of 16-bit CPUs, they are subject
|
|
+ to structure padding and/or alignment issues on newer systems with a
|
|
+ "natural word width" of more than 2 bytes.
|
|
+ Please note that the structure members are now reordered by size
|
|
+ (top-down), to prevent internal padding and optimize memory usage!
|
|
+ */
|
|
+ typedef struct local_file_header { /* LOCAL */
|
|
+ zusz_t csize;
|
|
+ zusz_t ucsize;
|
|
+ ulg last_mod_dos_datetime;
|
|
+ ulg crc32;
|
|
+ uch version_needed_to_extract[2];
|
|
+ ush general_purpose_bit_flag;
|
|
+ ush compression_method;
|
|
+ ush filename_length;
|
|
+ ush extra_field_length;
|
|
+ } local_file_hdr;
|
|
+
|
|
+ typedef struct central_directory_file_header { /* CENTRAL */
|
|
+ zusz_t csize;
|
|
+ zusz_t ucsize;
|
|
+ zusz_t relative_offset_local_header;
|
|
+ ulg last_mod_dos_datetime;
|
|
+ ulg crc32;
|
|
+ ulg external_file_attributes;
|
|
+ zuvl_t disk_number_start;
|
|
+ ush internal_file_attributes;
|
|
+ uch version_made_by[2];
|
|
+ uch version_needed_to_extract[2];
|
|
+ ush general_purpose_bit_flag;
|
|
+ ush compression_method;
|
|
+ ush filename_length;
|
|
+ ush extra_field_length;
|
|
+ ush file_comment_length;
|
|
+ } cdir_file_hdr;
|
|
+
|
|
+ typedef struct end_central_dir_record { /* END CENTRAL */
|
|
+ zusz_t size_central_directory;
|
|
+ zusz_t offset_start_central_directory;
|
|
+ zucn_t num_entries_centrl_dir_ths_disk;
|
|
+ zucn_t total_entries_central_dir;
|
|
+ zuvl_t number_this_disk;
|
|
+ zuvl_t num_disk_start_cdir;
|
|
+ int have_ecr64; /* valid Zip64 ecdir-record exists */
|
|
+ int is_zip64_archive; /* Zip64 ecdir-record is mandatory */
|
|
+ ush zipfile_comment_length;
|
|
+ } ecdir_rec;
|
|
+
|
|
+
|
|
+/* Huffman code lookup table entry--this entry is four bytes for machines
|
|
+ that have 16-bit pointers (e.g. PC's in the small or medium model).
|
|
+ Valid extra bits are 0..16. e == 31 is EOB (end of block), e == 32
|
|
+ means that v is a literal, 32 < e < 64 means that v is a pointer to
|
|
+ the next table, which codes (e & 31) bits, and lastly e == 99 indicates
|
|
+ an unused code. If a code with e == 99 is looked up, this implies an
|
|
+ error in the data. */
|
|
+
|
|
+struct huft {
|
|
+ uch e; /* number of extra bits or operation */
|
|
+ uch b; /* number of bits in this code or subcode */
|
|
+ union {
|
|
+ ush n; /* literal, length base, or distance base */
|
|
+ struct huft *t; /* pointer to next level of table */
|
|
+ } v;
|
|
+};
|
|
+
|
|
+
|
|
+typedef struct _APIDocStruct {
|
|
+ char *compare;
|
|
+ char *function;
|
|
+ char *syntax;
|
|
+ char *purpose;
|
|
+} APIDocStruct;
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/*************/
|
|
+/* Globals */
|
|
+/*************/
|
|
+
|
|
+#if (defined(OS2) && !defined(FUNZIP))
|
|
+# include "os2/os2data.h"
|
|
+#endif
|
|
+
|
|
+#include "globals.h"
|
|
+
|
|
+
|
|
+
|
|
+/*************************/
|
|
+/* Function Prototypes */
|
|
+/*************************/
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Functions in unzip.c (initialization routines):
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifndef WINDLL
|
|
+ int MAIN OF((int argc, char **argv));
|
|
+ int unzip OF((__GPRO__ int argc, char **argv));
|
|
+ int uz_opts OF((__GPRO__ int *pargc, char ***pargv));
|
|
+ int usage OF((__GPRO__ int error));
|
|
+#endif /* !WINDLL */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Functions in process.c (main driver routines):
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+int process_zipfiles OF((__GPRO));
|
|
+void free_G_buffers OF((__GPRO));
|
|
+/* static int do_seekable OF((__GPRO__ int lastchance)); */
|
|
+/* static int find_ecrec OF((__GPRO__ long searchlen)); */
|
|
+/* static int process_central_comment OF((__GPRO)); */
|
|
+int process_cdir_file_hdr OF((__GPRO));
|
|
+int process_local_file_hdr OF((__GPRO));
|
|
+int getZip64Data OF((__GPRO__ ZCONST uch *ef_buf,
|
|
+ unsigned ef_len));
|
|
+#ifdef UNICODE_SUPPORT
|
|
+ int getUnicodeData OF((__GPRO__ ZCONST uch *ef_buf,
|
|
+ unsigned ef_len));
|
|
+#endif
|
|
+unsigned ef_scan_for_izux OF((ZCONST uch *ef_buf, unsigned ef_len,
|
|
+ int ef_is_c, ulg dos_mdatetime,
|
|
+ iztimes *z_utim, ulg *z_uidgid));
|
|
+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
|
|
+ zvoid *getRISCOSexfield OF((ZCONST uch *ef_buf, unsigned ef_len));
|
|
+#endif
|
|
+
|
|
+#ifndef SFX
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Functions in zipinfo.c (`zipinfo-style' listing routines):
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifndef NO_ZIPINFO
|
|
+#ifndef WINDLL
|
|
+ int zi_opts OF((__GPRO__ int *pargc, char ***pargv));
|
|
+#endif
|
|
+void zi_end_central OF((__GPRO));
|
|
+int zipinfo OF((__GPRO));
|
|
+/* static int zi_long OF((__GPRO__ zusz_t *pEndprev)); */
|
|
+/* static int zi_short OF((__GPRO)); */
|
|
+/* static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez,
|
|
+ ZCONST time_t *modtimez, char *d_t_str));*/
|
|
+#endif /* !NO_ZIPINFO */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Functions in list.c (generic zipfile-listing routines):
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+int list_files OF((__GPRO));
|
|
+#ifdef TIMESTAMP
|
|
+ int get_time_stamp OF((__GPRO__ time_t *last_modtime,
|
|
+ ulg *nmember));
|
|
+#endif
|
|
+int ratio OF((zusz_t uc, zusz_t c));
|
|
+void fnprint OF((__GPRO));
|
|
+
|
|
+#endif /* !SFX */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Functions in fileio.c:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+int open_input_file OF((__GPRO));
|
|
+int open_outfile OF((__GPRO)); /* also vms.c */
|
|
+void undefer_input OF((__GPRO));
|
|
+void defer_leftover_input OF((__GPRO));
|
|
+unsigned readbuf OF((__GPRO__ char *buf, register unsigned len));
|
|
+int readbyte OF((__GPRO));
|
|
+int fillinbuf OF((__GPRO));
|
|
+int seek_zipf OF((__GPRO__ zoff_t abs_offset));
|
|
+#ifdef FUNZIP
|
|
+ int flush OF((__GPRO__ ulg size)); /* actually funzip.c */
|
|
+#else
|
|
+ int flush OF((__GPRO__ uch *buf, ulg size, int unshrink));
|
|
+#endif
|
|
+/* static int disk_error OF((__GPRO)); */
|
|
+void handler OF((int signal));
|
|
+time_t dos_to_unix_time OF((ulg dos_datetime));
|
|
+int check_for_newer OF((__GPRO__ char *filename)); /* os2,vmcms,vms */
|
|
+int do_string OF((__GPRO__ unsigned int length, int option));
|
|
+ush makeword OF((ZCONST uch *b));
|
|
+ulg makelong OF((ZCONST uch *sig));
|
|
+zusz_t makeint64 OF((ZCONST uch *sig));
|
|
+char *fzofft OF((__GPRO__ zoff_t val,
|
|
+ ZCONST char *pre, ZCONST char *post));
|
|
+#if (!defined(STR_TO_ISO) || defined(NEED_STR2ISO))
|
|
+ char *str2iso OF((char *dst, ZCONST char *src));
|
|
+#endif
|
|
+#if (!defined(STR_TO_OEM) || defined(NEED_STR2OEM))
|
|
+ char *str2oem OF((char *dst, ZCONST char *src));
|
|
+#endif
|
|
+#ifdef NO_STRNICMP
|
|
+ int zstrnicmp OF((register ZCONST char *s1,
|
|
+ register ZCONST char *s2,
|
|
+ register unsigned n));
|
|
+#endif
|
|
+#ifdef REGULUS
|
|
+ int zstat OF((ZCONST char *p, struct stat *s));
|
|
+#endif
|
|
+#ifdef ZMEM /* MUST be ifdef'd because of conflicts with the standard def. */
|
|
+ zvoid *memset OF((register zvoid *, register int, register unsigned int));
|
|
+ int memcmp OF((register ZCONST zvoid*, register ZCONST zvoid *,
|
|
+ register unsigned int));
|
|
+ zvoid *memcpy OF((register zvoid *, register ZCONST zvoid *,
|
|
+ register unsigned int));
|
|
+#endif
|
|
+#ifdef NEED_UZMBCLEN
|
|
+ extent uzmbclen OF((ZCONST unsigned char *ptr));
|
|
+#endif
|
|
+#ifdef NEED_UZMBSCHR
|
|
+ unsigned char *uzmbschr OF((ZCONST unsigned char *str, unsigned int c));
|
|
+#endif
|
|
+#ifdef NEED_UZMBSRCHR
|
|
+ unsigned char *uzmbsrchr OF((ZCONST unsigned char *str, unsigned int c));
|
|
+#endif
|
|
+#ifdef SMALL_MEM
|
|
+ char *fLoadFarString OF((__GPRO__ const char Far *sz));
|
|
+ char *fLoadFarStringSmall OF((__GPRO__ const char Far *sz));
|
|
+ char *fLoadFarStringSmall2 OF((__GPRO__ const char Far *sz));
|
|
+ #ifndef zfstrcpy
|
|
+ char Far * Far zfstrcpy OF((char Far *s1, const char Far *s2));
|
|
+ #endif
|
|
+ #if (!defined(SFX) && !defined(zfstrcmp))
|
|
+ int Far zfstrcmp OF((const char Far *s1, const char Far *s2));
|
|
+ #endif
|
|
+#endif
|
|
+
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Functions in extract.c:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+int extract_or_test_files OF((__GPRO));
|
|
+/* static int store_info OF((void)); */
|
|
+/* static int extract_or_test_member OF((__GPRO)); */
|
|
+/* static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); */
|
|
+/* static int test_OS2 OF((__GPRO__ uch *eb, unsigned eb_size)); */
|
|
+/* static int test_NT OF((__GPRO__ uch *eb, unsigned eb_size)); */
|
|
+#ifndef SFX
|
|
+ unsigned find_compr_idx OF((unsigned compr_methodnum));
|
|
+#endif
|
|
+int memextract OF((__GPRO__ uch *tgt, ulg tgtsize,
|
|
+ ZCONST uch *src, ulg srcsize));
|
|
+int memflush OF((__GPRO__ ZCONST uch *rawbuf, ulg size));
|
|
+#if (defined(VMS) || defined(VMS_TEXT_CONV))
|
|
+ uch *extract_izvms_block OF((__GPRO__ ZCONST uch *ebdata,
|
|
+ unsigned size, unsigned *retlen,
|
|
+ ZCONST uch *init, unsigned needlen));
|
|
+#endif
|
|
+char *fnfilter OF((ZCONST char *raw, uch *space,
|
|
+ extent size));
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Decompression functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#if (!defined(SFX) && !defined(FUNZIP))
|
|
+int explode OF((__GPRO)); /* explode.c */
|
|
+#endif
|
|
+int huft_free OF((struct huft *t)); /* inflate.c */
|
|
+int huft_build OF((__GPRO__ ZCONST unsigned *b, unsigned n,
|
|
+ unsigned s, ZCONST ush *d, ZCONST uch *e,
|
|
+ struct huft **t, unsigned *m));
|
|
+#ifdef USE_ZLIB
|
|
+ int UZinflate OF((__GPRO__ int is_defl64)); /* inflate.c */
|
|
+# define inflate_free(x) inflateEnd(&((Uz_Globs *)(&G))->dstrm)
|
|
+#else
|
|
+ int inflate OF((__GPRO__ int is_defl64)); /* inflate.c */
|
|
+ int inflate_free OF((__GPRO)); /* inflate.c */
|
|
+#endif /* ?USE_ZLIB */
|
|
+#if (!defined(SFX) && !defined(FUNZIP))
|
|
+#ifndef COPYRIGHT_CLEAN
|
|
+ int unreduce OF((__GPRO)); /* unreduce.c */
|
|
+/* static void LoadFollowers OF((__GPRO__ f_array *follower, uch *Slen));
|
|
+ * unreduce.c */
|
|
+#endif /* !COPYRIGHT_CLEAN */
|
|
+#ifndef LZW_CLEAN
|
|
+ int unshrink OF((__GPRO)); /* unshrink.c */
|
|
+/* static void partial_clear OF((__GPRO)); * unshrink.c */
|
|
+#endif /* !LZW_CLEAN */
|
|
+#endif /* !SFX && !FUNZIP */
|
|
+#ifdef USE_BZIP2
|
|
+ int UZbunzip2 OF((__GPRO)); /* extract.c */
|
|
+ void bz_internal_error OF((int bzerrcode)); /* ubz2err.c */
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Internal API functions (only included in DLL versions):
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef DLL
|
|
+ void setFileNotFound OF((__GPRO)); /* api.c */
|
|
+ int unzipToMemory OF((__GPRO__ char *zip, char *file,
|
|
+ UzpBuffer *retstr)); /* api.c */
|
|
+ int redirect_outfile OF((__GPRO)); /* api.c */
|
|
+ int writeToMemory OF((__GPRO__ ZCONST uch *rawbuf,
|
|
+ extent size)); /* api.c */
|
|
+ int close_redirect OF((__GPRO)); /* api.c */
|
|
+ /* this obsolescent entry point kept for compatibility: */
|
|
+ int UzpUnzip OF((int argc, char **argv));/* use UzpMain */
|
|
+#ifdef OS2DLL
|
|
+ int varmessage OF((__GPRO__ ZCONST uch *buf, ulg size));
|
|
+ int varputchar OF((__GPRO__ int c)); /* rexxapi.c */
|
|
+ int finish_REXX_redirect OF((__GPRO)); /* rexxapi.c */
|
|
+#endif
|
|
+#ifdef API_DOC
|
|
+ void APIhelp OF((__GPRO__ int argc, char **argv));
|
|
+#endif /* apihelp.c */
|
|
+#endif /* DLL */
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ MSDOS-only functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef MSDOS
|
|
+#if (!defined(FUNZIP) && !defined(SFX) && !defined(WINDLL))
|
|
+ void check_for_windows OF((ZCONST char *app)); /* msdos.c */
|
|
+#endif
|
|
+#if (defined(__GO32__) || defined(__EMX__))
|
|
+ unsigned _dos_getcountryinfo(void *); /* msdos.c */
|
|
+#if (!defined(__DJGPP__) || (__DJGPP__ < 2))
|
|
+ unsigned _dos_setftime(int, unsigned, unsigned); /* msdos.c */
|
|
+ unsigned _dos_setfileattr(const char *, unsigned); /* msdos.c */
|
|
+ unsigned _dos_creat(const char *, unsigned, int *); /* msdos.c */
|
|
+ void _dos_getdrive(unsigned *); /* msdos.c */
|
|
+ unsigned _dos_close(int); /* msdos.c */
|
|
+#endif /* !__DJGPP__ || (__DJGPP__ < 2) */
|
|
+#endif /* __GO32__ || __EMX__ */
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ OS/2-only functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef OS2 /* GetFileTime conflicts with something in Win32 header files */
|
|
+#if (defined(REENTRANT) && defined(USETHREADID))
|
|
+ ulg GetThreadId OF((void));
|
|
+#endif
|
|
+ int GetCountryInfo OF((void)); /* os2.c */
|
|
+ long GetFileTime OF((ZCONST char *name)); /* os2.c */
|
|
+/* static void SetPathAttrTimes OF((__GPRO__ int flags, int dir)); os2.c */
|
|
+/* static int SetEAs OF((__GPRO__ const char *path,
|
|
+ void *eablock)); os2.c */
|
|
+/* static int SetACL OF((__GPRO__ const char *path,
|
|
+ void *eablock)); os2.c */
|
|
+/* static int IsFileNameValid OF((const char *name)); os2.c */
|
|
+/* static void map2fat OF((char *pathcomp, char **pEndFAT)); os2.c */
|
|
+/* static int SetLongNameEA OF((char *name, char *longname)); os2.c */
|
|
+/* static void InitNLS OF((void)); os2.c */
|
|
+ int IsUpperNLS OF((int nChr)); /* os2.c */
|
|
+ int ToLowerNLS OF((int nChr)); /* os2.c */
|
|
+ void DebugMalloc OF((void)); /* os2.c */
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ QDOS-only functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef QDOS
|
|
+ int QMatch (uch, uch);
|
|
+ void QFilename (__GPRO__ char *);
|
|
+ char *Qstrfix (char *);
|
|
+ int QReturn (int zip_error);
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ TOPS20-only functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef TOPS20
|
|
+ int upper OF((char *s)); /* tops20.c */
|
|
+ int enquote OF((char *s)); /* tops20.c */
|
|
+ int dequote OF((char *s)); /* tops20.c */
|
|
+ int fnlegal OF(()); /* error if prototyped? */ /* tops20.c */
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ VM/CMS- and MVS-only functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef CMS_MVS
|
|
+ extent getVMMVSexfield OF((char *type, uch *ef_block, unsigned datalen));
|
|
+ FILE *vmmvs_open_infile OF((__GPRO)); /* vmmvs.c */
|
|
+ void close_infile OF((__GPRO)); /* vmmvs.c */
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ VMS-only functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef VMS
|
|
+ int check_format OF((__GPRO)); /* vms.c */
|
|
+/* int open_outfile OF((__GPRO)); * (see fileio.c) vms.c */
|
|
+/* int flush OF((__GPRO__ uch *rawbuf, unsigned size,
|
|
+ int final_flag)); * (see fileio.c) vms.c */
|
|
+ char *vms_msg_text OF((void)); /* vms.c */
|
|
+#ifdef RETURN_CODES
|
|
+ void return_VMS OF((__GPRO__ int zip_error)); /* vms.c */
|
|
+#else
|
|
+ void return_VMS OF((int zip_error)); /* vms.c */
|
|
+#endif
|
|
+#ifdef VMSCLI
|
|
+ ulg vms_unzip_cmdline OF((int *, char ***)); /* cmdline.c */
|
|
+ int VMSCLI_usage OF((__GPRO__ int error)); /* cmdline.c */
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ WIN32-only functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+#ifdef WIN32
|
|
+ int IsWinNT OF((void)); /* win32.c */
|
|
+#ifdef NTSD_EAS
|
|
+ void process_defer_NT OF((__GPRO)); /* win32.c */
|
|
+ int test_NTSD OF((__GPRO__ uch *eb, unsigned eb_size,
|
|
+ uch *eb_ucptr, ulg eb_ucsize)); /* win32.c */
|
|
+# define TEST_NTSD test_NTSD
|
|
+#endif
|
|
+#ifdef W32_STAT_BANDAID
|
|
+ int zstat_win32 OF((__W32STAT_GLOBALS__
|
|
+ const char *path, z_stat *buf)); /* win32.c */
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------------
|
|
+ Miscellaneous/shared functions:
|
|
+ ---------------------------------------------------------------------------*/
|
|
+
|
|
+Uz_Globs *globalsCtor OF((void)); /* globals.c */
|
|
+
|
|
+int envargs OF((int *Pargc, char ***Pargv,
|
|
+ ZCONST char *envstr, ZCONST char *envstr2));
|
|
+ /* envargs.c */
|
|
+void mksargs OF((int *argcp, char ***argvp)); /* envargs.c */
|
|
+
|
|
+int match OF((ZCONST char *s, ZCONST char *p,
|
|
+ int ic __WDLPRO)); /* match.c */
|
|
+int iswild OF((ZCONST char *p)); /* match.c */
|
|
+
|
|
+/* declarations of public CRC-32 functions have been moved into crc32.h
|
|
+ (free_crc_table(), get_crc_table(), crc32()) crc32.c */
|
|
+
|
|
+int dateformat OF((void)); /* local */
|
|
+char dateseparator OF((void)); /* local */
|
|
+#ifndef WINDLL
|
|
+ void version OF((__GPRO)); /* local */
|
|
+#endif
|
|
+int mapattr OF((__GPRO)); /* local */
|
|
+int mapname OF((__GPRO__ int renamed)); /* local */
|
|
+int checkdir OF((__GPRO__ char *pathcomp, int flag)); /* local */
|
|
+char *do_wild OF((__GPRO__ ZCONST char *wildzipfn)); /* local */
|
|
+char *GetLoadPath OF((__GPRO)); /* local */
|
|
+#if (defined(MORE) && (defined(ATH_BEO_UNX) || defined(QDOS) || defined(VMS)))
|
|
+ int screensize OF((int *tt_rows, int *tt_cols)); /* local */
|
|
+# if defined(VMS)
|
|
+ int screenlinewrap OF((void)); /* local */
|
|
+# endif
|
|
+#endif /* MORE && (ATH_BEO_UNX || QDOS || VMS) */
|
|
+#ifdef OS2_W32
|
|
+ int SetFileSize OF((FILE *file, zusz_t filesize)); /* local */
|
|
+#endif
|
|
+#ifndef MTS /* macro in MTS */
|
|
+ int close_outfile OF((__GPRO)); /* local */
|
|
+#endif
|
|
+#ifdef SET_SYMLINK_ATTRIBS
|
|
+ int set_symlnk_attribs OF((__GPRO__ slinkentry *slnk_entry)); /* local */
|
|
+#endif
|
|
+#ifdef SET_DIR_ATTRIB
|
|
+ int defer_dir_attribs OF((__GPRO__ direntry **pd)); /* local */
|
|
+ int set_direc_attribs OF((__GPRO__ direntry *d)); /* local */
|
|
+#endif
|
|
+#ifdef TIMESTAMP
|
|
+# ifdef WIN32
|
|
+ int stamp_file OF((__GPRO__
|
|
+ ZCONST char *fname, time_t modtime)); /* local */
|
|
+# else
|
|
+ int stamp_file OF((ZCONST char *fname, time_t modtime)); /* local */
|
|
+# endif
|
|
+#endif
|
|
+#ifdef NEED_ISO_OEM_INIT
|
|
+ void prepare_ISO_OEM_translat OF((__GPRO)); /* local */
|
|
+#endif
|
|
+#if (defined(MALLOC_WORK) && defined(MY_ZCALLOC))
|
|
+ zvoid far *zcalloc OF((unsigned int, unsigned int));
|
|
+ zvoid zcfree OF((zvoid far *));
|
|
+#endif /* MALLOC_WORK && MY_ZCALLOC */
|
|
+#ifdef SYSTEM_SPECIFIC_CTOR
|
|
+ void SYSTEM_SPECIFIC_CTOR OF((__GPRO)); /* local */
|
|
+#endif
|
|
+#ifdef SYSTEM_SPECIFIC_DTOR
|
|
+ void SYSTEM_SPECIFIC_DTOR OF((__GPRO)); /* local */
|
|
+#endif
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+/************/
|
|
+/* Macros */
|
|
+/************/
|
|
+
|
|
+#ifndef MAX
|
|
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
|
|
+#endif
|
|
+#ifndef MIN
|
|
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
+#endif
|
|
+
|
|
+#ifdef DEBUG
|
|
+# if (defined(THEOS) && defined(NO_BOGUS_SPC))
|
|
+# define NO_DEBUG_IN_MACROS
|
|
+# define Trace(x) _fprintf x
|
|
+# else
|
|
+# define Trace(x) fprintf x
|
|
+# endif
|
|
+#else
|
|
+# define Trace(x)
|
|
+#endif
|
|
+
|
|
+#ifdef DEBUG_TIME
|
|
+# define TTrace(x) fprintf x
|
|
+#else
|
|
+# define TTrace(x)
|
|
+#endif
|
|
+
|
|
+#ifdef NO_DEBUG_IN_MACROS
|
|
+# define MTrace(x)
|
|
+#else
|
|
+# define MTrace(x) Trace(x)
|
|
+#endif
|
|
+
|
|
+#if (defined(UNIX) || defined(T20_VMS)) /* generally old systems */
|
|
+# define ToLower(x) ((char)(isupper((int)x)? tolower((int)x) : x))
|
|
+#else
|
|
+# define ToLower tolower /* assumed "smart"; used in match() */
|
|
+#endif
|
|
+
|
|
+#ifdef USE_STRM_INPUT
|
|
+ /* ``Replace'' the unbuffered UNIX style I/O function with similar
|
|
+ * standard C functions from <stdio.h>.
|
|
+ */
|
|
+# define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd))
|
|
+# ifdef zlseek
|
|
+# undef zlseek
|
|
+# endif
|
|
+# define zlseek(fd,o,w) zfseeko((FILE *)(fd),(o),(w))
|
|
+# define close(fd) fclose((FILE *)(fd))
|
|
+#endif /* USE_STRM_INPUT */
|
|
+
|
|
+/* The return value of the Info() "macro function" is never checked in
|
|
+ * UnZip. Otherwise, to get the same behaviour as for (*G.message)(), the
|
|
+ * Info() definition for "FUNZIP" would have to be corrected:
|
|
+ * #define Info(buf,flag,sprf_arg) \
|
|
+ * (fputs((char *)(sprintf sprf_arg, (buf)), \
|
|
+ * (flag)&1? stderr : stdout) < 0)
|
|
+ */
|
|
+#ifndef Info /* may already have been defined for redirection */
|
|
+# ifdef FUNZIP
|
|
+# define Info(buf,flag,sprf_arg) \
|
|
+ fputs((char *)(sprintf sprf_arg, (buf)), (flag)&1? stderr : stdout)
|
|
+# else
|
|
+# ifdef INT_SPRINTF /* optimized version for "int sprintf()" flavour */
|
|
+# define Info(buf,flag,sprf_arg) \
|
|
+ (*G.message)((zvoid *)&G, (uch *)(buf), (ulg)sprintf sprf_arg, (flag))
|
|
+# else /* generic version, does not use sprintf() return value */
|
|
+# define Info(buf,flag,sprf_arg) \
|
|
+ (*G.message)((zvoid *)&G, (uch *)(buf), \
|
|
+ (ulg)(sprintf sprf_arg, strlen((char *)(buf))), (flag))
|
|
+# endif
|
|
+# endif
|
|
+#endif /* !Info */
|
|
+
|
|
+/* This wrapper macro around fzofft() is just defined to "hide" the
|
|
+ * argument needed to reference the global storage buffers.
|
|
+ */
|
|
+#define FmZofft(val, pre, post) fzofft(__G__ val, pre, post)
|
|
+
|
|
+/* The following macro wrappers around the fnfilter function are used many
|
|
+ * times to prepare archive entry names or name components for displaying
|
|
+ * listings and (warning/error) messages. They use sections in the upper half
|
|
+ * of 'slide' as buffer, since their output is normally fed through the
|
|
+ * Info() macro with 'slide' (the start of this area) as message buffer.
|
|
+ */
|
|
+#define FnFilter1(fname) \
|
|
+ fnfilter((fname), slide + (extent)(WSIZE>>1), (extent)(WSIZE>>2))
|
|
+#define FnFilter2(fname) \
|
|
+ fnfilter((fname), slide + (extent)((WSIZE>>1) + (WSIZE>>2)),\
|
|
+ (extent)(WSIZE>>2))
|
|
+
|
|
+#ifndef FUNZIP /* used only in inflate.c */
|
|
+# define MESSAGE(str,len,flag) (*G.message)((zvoid *)&G,(str),(len),(flag))
|
|
+#endif
|
|
+
|
|
+#if 0 /* Optimization: use the (const) result of crc32(0L,NULL,0) */
|
|
+# define CRCVAL_INITIAL crc32(0L, NULL, 0)
|
|
+#else
|
|
+# define CRCVAL_INITIAL 0L
|
|
+#endif
|
|
+
|
|
+#ifdef SYMLINKS
|
|
+ /* This macro defines the Zip "made by" hosts that are considered
|
|
+ to support storing symbolic link entries. */
|
|
+# define SYMLINK_HOST(hn) ((hn) == UNIX_ || (hn) == ATARI_ || \
|
|
+ (hn) == ATHEOS_ || (hn) == BEOS_ || (hn) == VMS_)
|
|
+#endif
|
|
+
|
|
+#ifndef TEST_NTSD /* "NTSD valid?" checking function */
|
|
+# define TEST_NTSD NULL /* ... is not available */
|
|
+#endif
|
|
+
|
|
+#define SKIP_(length) if(length&&((error=do_string(__G__ length,SKIP))!=0))\
|
|
+ {error_in_archive=error; if(error>1) return error;}
|
|
+
|
|
+/*
|
|
+ * Skip a variable-length field, and report any errors. Used in zipinfo.c
|
|
+ * and unzip.c in several functions.
|
|
+ *
|
|
+ * macro SKIP_(length)
|
|
+ * ush length;
|
|
+ * {
|
|
+ * if (length && ((error = do_string(length, SKIP)) != 0)) {
|
|
+ * error_in_archive = error; /-* might be warning *-/
|
|
+ * if (error > 1) /-* fatal *-/
|
|
+ * return (error);
|
|
+ * }
|
|
+ * }
|
|
+ *
|
|
+ */
|
|
+
|
|
+
|
|
+#ifdef FUNZIP
|
|
+# define FLUSH(w) flush(__G__ (ulg)(w))
|
|
+# define NEXTBYTE getc(G.in) /* redefined in crypt.h if full version */
|
|
+#else
|
|
+# define FLUSH(w) ((G.mem_mode) ? memflush(__G__ redirSlide,(ulg)(w)) \
|
|
+ : flush(__G__ redirSlide,(ulg)(w),0))
|
|
+# define NEXTBYTE (G.incnt-- > 0 ? (int)(*G.inptr++) : readbyte(__G))
|
|
+#endif
|
|
+
|
|
+
|
|
+#define READBITS(nbits,zdest) {if(nbits>G.bits_left) {int temp; G.zipeof=1;\
|
|
+ while (G.bits_left<=8*(int)(sizeof(G.bitbuf)-1) && (temp=NEXTBYTE)!=EOF) {\
|
|
+ G.bitbuf|=(ulg)temp<<G.bits_left; G.bits_left+=8; G.zipeof=0;}}\
|
|
+ zdest=(shrint)((unsigned)G.bitbuf&mask_bits[nbits]);G.bitbuf>>=nbits;\
|
|
+ G.bits_left-=nbits;}
|
|
+
|
|
+/*
|
|
+ * macro READBITS(nbits,zdest) * only used by unreduce and unshrink *
|
|
+ * {
|
|
+ * if (nbits > G.bits_left) { * fill G.bitbuf, 8*sizeof(ulg) bits *
|
|
+ * int temp;
|
|
+ *
|
|
+ * G.zipeof = 1;
|
|
+ * while (G.bits_left <= 8*(int)(sizeof(G.bitbuf)-1) &&
|
|
+ * (temp = NEXTBYTE) != EOF) {
|
|
+ * G.bitbuf |= (ulg)temp << G.bits_left;
|
|
+ * G.bits_left += 8;
|
|
+ * G.zipeof = 0;
|
|
+ * }
|
|
+ * }
|
|
+ * zdest = (shrint)((unsigned)G.bitbuf & mask_bits[nbits]);
|
|
+ * G.bitbuf >>= nbits;
|
|
+ * G.bits_left -= nbits;
|
|
+ * }
|
|
+ *
|
|
+ */
|
|
+
|
|
+
|
|
+/* GRR: should use StringLower for STRLOWER macro if possible */
|
|
+
|
|
+/*
|
|
+ * Copy the zero-terminated string in str1 into str2, converting any
|
|
+ * uppercase letters to lowercase as we go. str2 gets zero-terminated
|
|
+ * as well, of course. str1 and str2 may be the same character array.
|
|
+ */
|
|
+#ifdef _MBCS
|
|
+# define STRLOWER(str1, str2) \
|
|
+ { \
|
|
+ char *p, *q, c; unsigned i; \
|
|
+ p = (char *)(str1); \
|
|
+ q = (char *)(str2); \
|
|
+ while ((c = *p) != '\0') { \
|
|
+ if ((i = CLEN(p)) > 1) { \
|
|
+ while (i--) *q++ = *p++; \
|
|
+ } else { \
|
|
+ *q++ = (char)(isupper((int)(c))? tolower((int)(c)) : c); \
|
|
+ p++; \
|
|
+ } \
|
|
+ } \
|
|
+ *q = '\0'; \
|
|
+ }
|
|
+#else
|
|
+# define STRLOWER(str1, str2) \
|
|
+ { \
|
|
+ char *p, *q; \
|
|
+ p = (char *)(str1) - 1; \
|
|
+ q = (char *)(str2); \
|
|
+ while (*++p) \
|
|
+ *q++ = (char)(isupper((int)(*p))? tolower((int)(*p)) : *p); \
|
|
+ *q = '\0'; \
|
|
+ }
|
|
+#endif
|
|
+/*
|
|
+ * NOTES: This macro makes no assumptions about the characteristics of
|
|
+ * the tolower() function or macro (beyond its existence), nor does it
|
|
+ * make assumptions about the structure of the character set (i.e., it
|
|
+ * should work on EBCDIC machines, too). The fact that either or both
|
|
+ * of isupper() and tolower() may be macros has been taken into account;
|
|
+ * watch out for "side effects" (in the C sense) when modifying this
|
|
+ * macro.
|
|
+ */
|
|
+
|
|
+#ifndef foreign
|
|
+# define foreign(c) (c)
|
|
+#endif
|
|
+
|
|
+#ifndef native
|
|
+# define native(c) (c)
|
|
+# define A_TO_N(str1)
|
|
+#else
|
|
+# ifndef NATIVE
|
|
+# define NATIVE "native chars"
|
|
+# endif
|
|
+# define A_TO_N(str1) {register uch *p;\
|
|
+ for (p=(uch *)(str1); *p; p++) *p=native(*p);}
|
|
+#endif
|
|
+/*
|
|
+ * Translate the zero-terminated string in str1 from ASCII to the native
|
|
+ * character set. The translation is performed in-place and uses the
|
|
+ * "native" macro to translate each character.
|
|
+ *
|
|
+ * NOTE: Using the "native" macro means that is it the only part of unzip
|
|
+ * which knows which translation table (if any) is actually in use to
|
|
+ * produce the native character set. This makes adding new character set
|
|
+ * translation tables easy, insofar as all that is needed is an appropriate
|
|
+ * "native" macro definition and the translation table itself. Currently,
|
|
+ * the only non-ASCII native character set implemented is EBCDIC, but this
|
|
+ * may not always be so.
|
|
+ */
|
|
+
|
|
+
|
|
+/* default setup for internal codepage: assume ISO 8859-1 compatibility!! */
|
|
+#if (!defined(NATIVE) && !defined(CRTL_CP_IS_ISO) && !defined(CRTL_CP_IS_OEM))
|
|
+# define CRTL_CP_IS_ISO
|
|
+#endif
|
|
+
|
|
+
|
|
+/* Translate "extended ASCII" chars (OEM coding for DOS and OS/2; else
|
|
+ * ISO-8859-1 [ISO Latin 1, Win Ansi,...]) into the internal "native"
|
|
+ * code page. As with A_TO_N(), conversion is done in place.
|
|
+ */
|
|
+#ifndef _ISO_INTERN
|
|
+# ifdef CRTL_CP_IS_OEM
|
|
+# ifndef IZ_ISO2OEM_ARRAY
|
|
+# define IZ_ISO2OEM_ARRAY
|
|
+# endif
|
|
+# define _ISO_INTERN(str1) if (iso2oem) {register uch *p;\
|
|
+ for (p=(uch *)(str1); *p; p++)\
|
|
+ *p = native((*p & 0x80) ? iso2oem[*p & 0x7f] : *p);}
|
|
+# else
|
|
+# define _ISO_INTERN(str1) A_TO_N(str1)
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifndef _OEM_INTERN
|
|
+# ifdef CRTL_CP_IS_OEM
|
|
+# define _OEM_INTERN(str1) A_TO_N(str1)
|
|
+# else
|
|
+# ifndef IZ_OEM2ISO_ARRAY
|
|
+# define IZ_OEM2ISO_ARRAY
|
|
+# endif
|
|
+# define _OEM_INTERN(str1) if (oem2iso) {register uch *p;\
|
|
+ for (p=(uch *)(str1); *p; p++)\
|
|
+ *p = native((*p & 0x80) ? oem2iso[*p & 0x7f] : *p);}
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifndef STR_TO_ISO
|
|
+# ifdef CRTL_CP_IS_ISO
|
|
+# define STR_TO_ISO strcpy
|
|
+# else
|
|
+# define STR_TO_ISO str2iso
|
|
+# define NEED_STR2ISO
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#ifndef STR_TO_OEM
|
|
+# ifdef CRTL_CP_IS_OEM
|
|
+# define STR_TO_OEM strcpy
|
|
+# else
|
|
+# define STR_TO_OEM str2oem
|
|
+# define NEED_STR2OEM
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (!defined(INTERN_TO_ISO) && !defined(ASCII2ISO))
|
|
+# ifdef CRTL_CP_IS_OEM
|
|
+ /* know: "ASCII" is "OEM" */
|
|
+# define ASCII2ISO(c) \
|
|
+ ((((c) & 0x80) && oem2iso) ? oem2iso[(c) & 0x7f] : (c))
|
|
+# if (defined(NEED_STR2ISO) && !defined(CRYP_USES_OEM2ISO))
|
|
+# define CRYP_USES_OEM2ISO
|
|
+# endif
|
|
+# else
|
|
+ /* assume: "ASCII" is "ISO-ANSI" */
|
|
+# define ASCII2ISO(c) (c)
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+#if (!defined(INTERN_TO_OEM) && !defined(ASCII2OEM))
|
|
+# ifdef CRTL_CP_IS_OEM
|
|
+ /* know: "ASCII" is "OEM" */
|
|
+# define ASCII2OEM(c) (c)
|
|
+# else
|
|
+ /* assume: "ASCII" is "ISO-ANSI" */
|
|
+# define ASCII2OEM(c) \
|
|
+ ((((c) & 0x80) && iso2oem) ? iso2oem[(c) & 0x7f] : (c))
|
|
+# if (defined(NEED_STR2OEM) && !defined(CRYP_USES_ISO2OEM))
|
|
+# define CRYP_USES_ISO2OEM
|
|
+# endif
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+/* codepage conversion setup for testp() in crypt.c */
|
|
+#ifdef CRTL_CP_IS_ISO
|
|
+# ifndef STR_TO_CP2
|
|
+# define STR_TO_CP2 STR_TO_OEM
|
|
+# endif
|
|
+#else
|
|
+# ifdef CRTL_CP_IS_OEM
|
|
+# ifndef STR_TO_CP2
|
|
+# define STR_TO_CP2 STR_TO_ISO
|
|
+# endif
|
|
+# else /* native internal CP is neither ISO nor OEM */
|
|
+# ifndef STR_TO_CP1
|
|
+# define STR_TO_CP1 STR_TO_ISO
|
|
+# endif
|
|
+# ifndef STR_TO_CP2
|
|
+# define STR_TO_CP2 STR_TO_OEM
|
|
+# endif
|
|
+# endif
|
|
+#endif
|
|
+
|
|
+
|
|
+/* Convert filename (and file comment string) into "internal" charset.
|
|
+ * This macro assumes that Zip entry filenames are coded in OEM (IBM DOS)
|
|
+ * codepage when made on
|
|
+ * -> DOS (this includes 16-bit Windows 3.1) (FS_FAT_)
|
|
+ * -> OS/2 (FS_HPFS_)
|
|
+ * -> Win95/WinNT with Nico Mak's WinZip (FS_NTFS_ && hostver == "5.0")
|
|
+ * EXCEPTIONS:
|
|
+ * PKZIP for Windows 2.5, 2.6, and 4.0 flag their entries as "FS_FAT_", but
|
|
+ * the filename stored in the local header is coded in Windows ANSI (CP 1252
|
|
+ * resp. ISO 8859-1 on US and western Europe locale settings).
|
|
+ * Likewise, PKZIP for UNIX 2.51 flags its entries as "FS_FAT_", but the
|
|
+ * filenames stored in BOTH the local and the central header are coded
|
|
+ * in the local system's codepage (usually ANSI codings like ISO 8859-1).
|
|
+ *
|
|
+ * All other ports are assumed to code zip entry filenames in ISO 8859-1.
|
|
+ */
|
|
+#ifndef Ext_ASCII_TO_Native
|
|
+# define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \
|
|
+ if (((hostnum) == FS_FAT_ && \
|
|
+ !(((islochdr) || (isuxatt)) && \
|
|
+ ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \
|
|
+ (hostnum) == FS_HPFS_ || \
|
|
+ ((hostnum) == FS_NTFS_ /* && (hostver) == 50 */ )) { \
|
|
+ _OEM_INTERN((string)); \
|
|
+ } else { \
|
|
+ _ISO_INTERN((string)); \
|
|
+ }
|
|
+#endif
|
|
+
|
|
+
|
|
+
|
|
+/**********************/
|
|
+/* Global constants */
|
|
+/**********************/
|
|
+
|
|
+ extern ZCONST unsigned near mask_bits[17];
|
|
+ extern ZCONST char *fnames[2];
|
|
+
|
|
+#ifdef EBCDIC
|
|
+ extern ZCONST uch ebcdic[];
|
|
+#endif
|
|
+#ifdef IZ_ISO2OEM_ARRAY
|
|
+ extern ZCONST uch Far *iso2oem;
|
|
+ extern ZCONST uch Far iso2oem_850[];
|
|
+#endif
|
|
+#ifdef IZ_OEM2ISO_ARRAY
|
|
+ extern ZCONST uch Far *oem2iso;
|
|
+ extern ZCONST uch Far oem2iso_850[];
|
|
+#endif
|
|
+
|
|
+ extern ZCONST char Far VersionDate[];
|
|
+ extern ZCONST char Far CentSigMsg[];
|
|
+#ifndef SFX
|
|
+ extern ZCONST char Far EndSigMsg[];
|
|
+#endif
|
|
+ extern ZCONST char Far SeekMsg[];
|
|
+ extern ZCONST char Far FilenameNotMatched[];
|
|
+ extern ZCONST char Far ExclFilenameNotMatched[];
|
|
+ extern ZCONST char Far ReportMsg[];
|
|
+
|
|
+#ifndef SFX
|
|
+ extern ZCONST char Far Zipnfo[];
|
|
+ extern ZCONST char Far CompiledWith[];
|
|
+#endif /* !SFX */
|
|
+
|
|
+
|
|
+
|
|
+/***********************************/
|
|
+/* Global (shared?) RTL variables */
|
|
+/***********************************/
|
|
+
|
|
+#ifdef DECLARE_ERRNO
|
|
+ extern int errno;
|
|
+#endif
|
|
+
|
|
+/*---------------------------------------------------------------------
|
|
+ Unicode Support
|
|
+ 28 August 2005
|
|
+ ---------------------------------------------------------------------*/
|
|
+#if (defined(UNICODE_SUPPORT) && defined(UNICODE_WCHAR))
|
|
+
|
|
+ /* Default character when a zwchar too big for wchar_t */
|
|
+# define zwchar_to_wchar_t_default_char '_'
|
|
+
|
|
+ /* Default character string when wchar_t does not convert to mb */
|
|
+# define wide_to_mb_default_string "_"
|
|
+
|
|
+ /* wide character type */
|
|
+ typedef unsigned long zwchar;
|
|
+
|
|
+ /* UTF-8 related conversion functions, currently found in process.c */
|
|
+
|
|
+# if 0 /* currently unused */
|
|
+ /* check if string is all ASCII */
|
|
+ int is_ascii_string OF((ZCONST char *mbstring));
|
|
+# endif /* unused */
|
|
+
|
|
+ /* convert UTF-8 string to multi-byte string */
|
|
+ char *utf8_to_local_string OF((ZCONST char *utf8_string, int escape_all));
|
|
+
|
|
+ /* convert UTF-8 string to wide string */
|
|
+ zwchar *utf8_to_wide_string OF((ZCONST char *utf8_string));
|
|
+
|
|
+ /* convert wide string to multi-byte string */
|
|
+ char *wide_to_local_string OF((ZCONST zwchar *wide_string, int escape_all));
|
|
+
|
|
+# if 0 /* currently unused */
|
|
+ /* convert local string to multi-byte display string */
|
|
+ char *local_to_display_string OF((ZCONST char *local_string));
|
|
+# endif /* unused */
|
|
+
|
|
+ /* convert wide character to escape string */
|
|
+ char *wide_to_escape_string OF((unsigned long));
|
|
+
|
|
+# define utf8_to_escaped_string(utf8_string) \
|
|
+ utf8_to_local_string(utf8_string, TRUE)
|
|
+
|
|
+# if 0 /* currently unused */
|
|
+ /* convert escape string to wide character */
|
|
+ unsigned long escape_string_to_wide OF((ZCONST char *escape_string));
|
|
+
|
|
+ /* convert local to UTF-8 */
|
|
+ char *local_to_utf8_string OF ((ZCONST char *local_string));
|
|
+
|
|
+ /* convert local to wide string */
|
|
+ zwchar *local_to_wide_string OF ((ZCONST char *local_string));
|
|
+
|
|
+ /* convert wide string to UTF-8 */
|
|
+ char *wide_to_utf8_string OF((ZCONST zwchar *wide_string));
|
|
+# endif /* unused */
|
|
+
|
|
+#endif /* UNICODE_SUPPORT && UNICODE_WCHAR */
|
|
+
|
|
+
|
|
+#endif /* !__unzpriv_h */
|
|
diff -Naur a/zipinfo.c b/zipinfo.c
|
|
--- a/zipinfo.c 2009-02-08 17:04:30.000000000 +0000
|
|
+++ b/zipinfo.c 2019-12-02 01:49:39.895641007 +0000
|
|
@@ -457,6 +457,10 @@
|
|
int tflag_slm=TRUE, tflag_2v=FALSE;
|
|
int explicit_h=FALSE, explicit_t=FALSE;
|
|
|
|
+#ifdef UNIX
|
|
+ extern char OEM_CP[MAX_CP_NAME];
|
|
+ extern char ISO_CP[MAX_CP_NAME];
|
|
+#endif
|
|
|
|
#ifdef MACOS
|
|
uO.lflag = LFLAG; /* reset default on each call */
|
|
@@ -501,6 +505,37 @@
|
|
uO.lflag = 0;
|
|
}
|
|
break;
|
|
+#ifdef UNIX
|
|
+ case ('I'):
|
|
+ if (negative) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: encodings can't be negated"));
|
|
+ return(PK_PARAM);
|
|
+ } else {
|
|
+ if(*s) { /* Handle the -Icharset case */
|
|
+ /* Assume that charsets can't start with a dash to spot arguments misuse */
|
|
+ if(*s == '-') {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: a valid character encoding should follow the -I argument"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ strncpy(ISO_CP, s, MAX_CP_NAME - 1);
|
|
+ ISO_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ } else { /* -I charset */
|
|
+ ++argv;
|
|
+ if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: a valid character encoding should follow the -I argument"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ s = *argv;
|
|
+ strncpy(ISO_CP, s, MAX_CP_NAME - 1);
|
|
+ ISO_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ }
|
|
+ while(*(++s)); /* No params straight after charset name */
|
|
+ }
|
|
+ break;
|
|
+#endif /* ?UNIX */
|
|
case 'l': /* longer form of "ls -l" type listing */
|
|
if (negative)
|
|
uO.lflag = -2, negative = 0;
|
|
@@ -521,6 +556,37 @@
|
|
G.M_flag = TRUE;
|
|
break;
|
|
#endif
|
|
+#ifdef UNIX
|
|
+ case ('O'):
|
|
+ if (negative) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: encodings can't be negated"));
|
|
+ return(PK_PARAM);
|
|
+ } else {
|
|
+ if(*s) { /* Handle the -Ocharset case */
|
|
+ /* Assume that charsets can't start with a dash to spot arguments misuse */
|
|
+ if(*s == '-') {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: a valid character encoding should follow the -I argument"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ strncpy(OEM_CP, s, MAX_CP_NAME - 1);
|
|
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ } else { /* -O charset */
|
|
+ ++argv;
|
|
+ if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
|
|
+ Info(slide, 0x401, ((char *)slide,
|
|
+ "error: a valid character encoding should follow the -O argument"));
|
|
+ return(PK_PARAM);
|
|
+ }
|
|
+ s = *argv;
|
|
+ strncpy(OEM_CP, s, MAX_CP_NAME - 1);
|
|
+ OEM_CP[MAX_CP_NAME - 1] = '\0';
|
|
+ }
|
|
+ while(*(++s)); /* No params straight after charset name */
|
|
+ }
|
|
+ break;
|
|
+#endif /* ?UNIX */
|
|
case 's': /* default: shorter "ls -l" type listing */
|
|
if (negative)
|
|
uO.lflag = -2, negative = 0;
|
|
@@ -771,7 +837,7 @@
|
|
Info(slide, 0x401,
|
|
((char *)slide, LoadFarString(CentSigMsg), j));
|
|
Info(slide, 0x401,
|
|
- ((char *)slide, LoadFarString(ReportMsg)));
|
|
+ ((char *)slide,"%s", LoadFarString(ReportMsg)));
|
|
error_in_archive = PK_BADERR; /* sig not found */
|
|
break;
|
|
}
|
|
@@ -960,7 +1026,8 @@
|
|
&& (!G.ecrec.is_zip64_archive)
|
|
&& (memcmp(G.sig, end_central_sig, 4) != 0)
|
|
) { /* just to make sure again */
|
|
- Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
|
|
+ Info(slide, 0x401,
|
|
+ ((char *)slide,"%s", LoadFarString(EndSigMsg)));
|
|
error_in_archive = PK_WARN; /* didn't find sig */
|
|
}
|
|
|
|
@@ -1881,7 +1948,7 @@
|
|
#endif
|
|
int k, error, error_in_archive=PK_COOL;
|
|
unsigned hostnum, hostver, methid, methnum, xattr;
|
|
- char *p, workspace[12], attribs[16];
|
|
+ char *p, workspace[12], attribs[17];
|
|
char methbuf[5];
|
|
static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */
|
|
static ZCONST char Far os[NUM_HOSTS+1][4] = {
|
|
@@ -1921,7 +1988,19 @@
|
|
ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
|
|
methbuf[3] = dtype[dnum];
|
|
} else if (methnum >= NUM_METHODS) { /* unknown */
|
|
- sprintf(&methbuf[1], "%03u", G.crec.compression_method);
|
|
+ /* 2016-12-05 SMS.
|
|
+ * https://launchpad.net/bugs/1643750
|
|
+ * Unexpectedly large compression methods overflow
|
|
+ * &methbuf[]. Use the old, three-digit decimal format
|
|
+ * for values which fit. Otherwise, sacrifice the "u",
|
|
+ * and use four-digit hexadecimal.
|
|
+ */
|
|
+ if (G.crec.compression_method <= 999) {
|
|
+ sprintf( &methbuf[ 1], "%03u", G.crec.compression_method);
|
|
+ } else {
|
|
+ sprintf( &methbuf[ 0], "%04X", G.crec.compression_method);
|
|
+ }
|
|
+
|
|
}
|
|
|
|
for (k = 0; k < 15; ++k)
|