Archive-Unzip-Burst
view release on metacpan or search on metacpan
unzip-6.0/win32-experimental/unz60d10_w32wide-Unicode_patch.txt view on Meta::CPAN
+ &(d_entryw->Accft),
+ &(d_entryw->Creft))
+ : 0);
+ return PK_OK;
+} /* end function defer_dir_attribsw() */
+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
+
+
int set_direc_attribs(__G__ d)
__GDEF
direntry *d;
{
+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
+ /* Win9x does not support setting directory time stamps. */
+ return PK_OK;
+#else /* ! (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
int errval;
HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */
@@ -1320,6 +1604,107 @@
return errval;
+#endif /* ? (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */
} /* end function set_direc_attribs() */
+
+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
+int set_direc_attribsw(__G__ dw)
+ __GDEF
+ direntryw *dw;
+{
+ int errval;
+ HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */
+
+ /* Win9x does not support setting directory time stamps. */
+ if (!IsWinNT())
+ return PK_OK;
+
+ errval = PK_OK;
+
+ /* Skip restoring directory time stamps on user' request. */
+ if (uO.D_flag <= 0) {
+ /* Open a handle to the directory before processing extra fields;
+ we do this in case new security on file prevents us from updating
+ time stamps.
+ Although the WIN32 documentation recommends to use GENERIC_WRITE
+ access flag to create the handle for SetFileTime(), this is too
+ demanding for directories with the "read-only" attribute bit set.
+ So we use the more specific flag FILE_WRITE_ATTRIBUTES here to
+ request the minimum required access rights. (This problem is a
+ Windows bug that has been silently fixed in Windows XP SP2.) */
+ hFile = CreateFileW(dw->fnw, FILE_WRITE_ATTRIBUTES,
+ FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ }
+
+#ifdef NTSD_EAS
+ if (NtAtt(dw)->SDlen > 0) {
+ int err;
+
+ if (QCOND2) {
+ char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);
+ Info(slide, 1, ((char *)slide, " set attrib: %-22s ",
+ FnFilter1(fn)));
+ free(fn);
+ }
+
+ /* set NTFS SD extra fields */
+ err = SetSD(__G__ dw->fnw, NtAtt(dw)->perms,
+ NtAtt(dw)->buf, NtAtt(dw)->SDlen - EB_HEADSIZE);
+ if (err == IZ_EF_TRUNC) {
+ if (!QCOND2) {
+ char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);
+ Info(slide, 1, ((char *)slide, "%-22s ",
+ FnFilter1(fn)));
+ free(fn);
+ }
+ Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
+ NtAtt(dw)->SDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
+ } else if (QCOND2) {
+ Info(slide, 0, ((char *)slide, "\n"));
+ }
+ if (errval < err)
+ errval = err;
+ }
+#endif /* NTSD_EAS */
+
+ /* Skip restoring directory time stamps on user' request. */
+ if (uO.D_flag <= 0) {
+ if (hFile == INVALID_HANDLE_VALUE) {
+ char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);
+ Info(slide, 1, ((char *)slide,
+ "warning: CreateFile() error %d (set file times for %s)\n",
+ (int)GetLastError(), FnFilter1(fn)));
+ free(fn);
+ if (!errval)
+ errval = PK_WARN;
+ } else {
+ if (NtAtt(dw)->gotTime) {
+ FILETIME *pModft = (NtAtt(dw)->gotTime & EB_UT_FL_MTIME)
+ ? &(NtAtt(dw)->Modft) : NULL;
+ FILETIME *pAccft = (NtAtt(dw)->gotTime & EB_UT_FL_ATIME)
+ ? &(NtAtt(dw)->Accft) : NULL;
+ FILETIME *pCreft = (NtAtt(dw)->gotTime & EB_UT_FL_CTIME)
+ ? &(NtAtt(dw)->Creft) : NULL;
+
+ if (!SetFileTime(hFile, pCreft, pAccft, pModft)) {
+ char *fn = wchar_to_local_string(dw->fnw,
+ G.unicode_escape_all);
+ Info(slide, 0, ((char *)slide,
+ "warning: SetFileTime() for %s error %d\n",
+ FnFilter1(fn), (int)GetLastError()));
+ free(fn);
+ if (!errval)
+ errval = PK_WARN;
+ }
+ }
+ CloseHandle(hFile);
+ }
+ }
+
+ return errval;
+} /* end function set_direc_attribsw() */
+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
+
#endif /* SET_DIR_ATTRIB */
@@ -1419,5 +1804,5 @@
#endif
- if ((!strncmp(name, "//", 2) || !strncmp(name, "\\\\", 2)) &&
+ if ((!strncmp(name, "//", 2) || !strncmp(name,"\\\\", 2)) &&
(name[2] != '\0' && name[2] != '/' && name[2] != '\\')) {
/* GetFullPathname() and GetVolumeInformation() do not work
@@ -1467,4 +1852,63 @@
+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
+static int NTQueryVolInfoW(__GPRO__ const wchar_t *namew)
+{
+ /* static char lastRootPath[4] = ""; */
+ /* static int lastVolOldFAT; */
+ /* static int lastVolLocTim; */
+ wchar_t *tmp0w;
+ wchar_t tmp1w[MAX_PATH], tmp2w[MAX_PATH];
+ DWORD volSerNo, maxCompLen, fileSysFlags;
+
+ if ((!wcsncmp(namew, L"//", 2) || !wcsncmp(namew, L"\\\\", 2)) &&
+ (namew[2] != '\0' && namew[2] != '/' && namew[2] != '\\')) {
+ /* GetFullPathname() and GetVolumeInformation() do not work
+ * on UNC names. For now, we return "error".
+ * **FIXME**: check if UNC name is mapped to a drive letter
+ * and use mapped drive for volume info query.
+ */
+ return FALSE;
+ }
+ if (iswalpha(namew[0]) && (namew[1] == ':'))
+ tmp0w = (wchar_t *)namew;
+ else
+ {
+ if (!GetFullPathNameW(namew, MAX_PATH, tmp1w, &tmp0w))
+ return FALSE;
+ tmp0w = &tmp1w[0];
+ }
+ if (wcsncmp(G.lastRootPathw, tmp0w, 2) != 0) {
+ /* For speed, we skip repeated queries for the same device */
+ wcsncpy(G.lastRootPathw, tmp0w, 2); /* Build the root path name, */
+ G.lastRootPathw[2] = '/'; /* e.g. "A:/" */
+ G.lastRootPathw[3] = '\0';
unzip-6.0/win32-experimental/unz60d10_w32wide-Unicode_patch.txt view on Meta::CPAN
+ 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;
}
-} /* end function map2fat() */
+ return MPN_INVALID; /* should never reach */
+
+} /* end function checkdir() */
-/***********************/ /* Borrowed from os2.c for UnZip 5.1. */
-/* Function checkdir() */ /* Difference: no EA stuff */
-/***********************/ /* HPFS stuff works on NTFS too */
+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
-int checkdir(__G__ pathcomp, flag)
+/* WIN32 wide version */
+
+int checkdirw(__G__ pathcompw, flag)
__GDEF
- char *pathcomp;
+ wchar_t *pathcompw;
int flag;
/*
@@ -2126,16 +3345,20 @@
if (FUNCTION == APPEND_DIR) {
- char *p = pathcomp;
+ wchar_t *pw = pathcompw;
int too_long = FALSE;
-
- Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp)));
- while ((*G.endHPFS = *p++) != '\0') /* copy to HPFS filename */
- ++G.endHPFS;
- if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
- p = pathcomp;
- while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */
- ++G.endFAT;
+ char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);
+ char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
+ /* Could use G.filename from the standard path, but may
+ not work well on this port */
+ char *fn = wchar_to_local_string(G.unipath_widefilename, G.unicode_escape_all);
+
+ while ((*G.endHPFSw = *pw++) != '\0') /* copy to HPFS filename */
+ ++G.endHPFSw;
+ if (!IsVolumeOldFATw(__G__ G.buildpathHPFSw)) {
+ pw = pathcompw;
+ while ((*G.endFATw = *pw++) != '\0') /* copy to FAT filename, too */
+ ++G.endFATw;
} else
- map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */
+ map2fatw(pathcompw, &G.endFATw); /* map into FAT fn, update endFAT */
/* GRR: could do better check, see if overrunning buffer as we go:
@@ -2145,5 +3368,5 @@
/* next check: need to append '/', at least one-char name, '\0' */
- if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)
+ if ((G.endHPFSw-G.buildpathHPFSw) > FILNAMSIZ-3)
too_long = TRUE; /* check if extracting dir? */
#ifdef FIX_STAT_BUG
@@ -2153,8 +3376,11 @@
* than console. The code below attempts to work around this problem.
*/
- if (access(G.buildpathFAT, 0) != 0) {
+ if (_waccess(G.buildpathFATw, 0) != 0) {
if (!G.create_dirs) { /* told not to create (freshening) */
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
/* path doesn't exist: nothing to do */
return MPN_INF_SKIP;
@@ -2163,28 +3389,40 @@
Info(slide, 1, ((char *)slide,
"checkdir error: path too long: %s\n",
- FnFilter1(G.buildpathHPFS)));
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
+ FnFilter1(fn)));
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
/* no room for filenames: fatal */
return MPN_ERR_TOOLONG;
}
- if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
- Info(slide, 1, ((char *)slide,
- "checkdir error: cannot create %s\n\
- unable to process %s.\n",
- FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
- /* path didn't exist, tried to create, failed */
- return MPN_ERR_SKIP;
- }
- G.created_dir = TRUE;
+ {
+ int i = MKDIRW(G.buildpathFATw, 0777);
+ if (i == -1) { /* create the directory */
+ Info(slide, 1, ((char *)slide,
+ "checkdir error: cannot create %s\n\
+ unable to process %s.\n",
+ FnFilter2(buildpathFAT), FnFilter1(fn)));
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
+ /* path didn't exist, tried to create, failed */
+ return MPN_ERR_SKIP;
+ }
+ G.created_dir = TRUE;
+ }
}
#endif /* FIX_STAT_BUG */
- if (SSTAT(G.buildpathFAT, &G.statbuf)) /* path doesn't exist */
+ if (SSTATW(G.buildpathFATw, &G.statbuf)) /* path doesn't exist */
{
if (!G.create_dirs) { /* told not to create (freshening) */
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
/* path doesn't exist: nothing to do */
return MPN_INF_SKIP;
@@ -2193,28 +3431,41 @@
Info(slide, 1, ((char *)slide,
"checkdir error: path too long: %s\n",
- FnFilter1(G.buildpathHPFS)));
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
+ FnFilter1(buildpathHPFS)));
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
/* no room for filenames: fatal */
return MPN_ERR_TOOLONG;
}
- if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
- Info(slide, 1, ((char *)slide,
- "checkdir error: cannot create %s\n\
- unable to process %s.\n",
- FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
- /* path didn't exist, tried to create, failed */
- return MPN_ERR_SKIP;
- }
- G.created_dir = TRUE;
+ {
+ char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);
+ int i = MKDIRW(G.buildpathFATw, 0777);
+ if (i == -1) { /* create the directory */
+ Info(slide, 1, ((char *)slide,
+ "checkdir error: cannot create %s\n\
+ unable to process %s.\n",
+ FnFilter2(buildpathFAT), FnFilter1(fn)));
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
+ /* 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.buildpathFAT), FnFilter1(G.filename)));
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
+ FnFilter2(buildpathFAT), FnFilter1(fn)));
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
/* path existed but wasn't dir */
return MPN_ERR_SKIP;
@@ -2223,15 +3474,23 @@
Info(slide, 1, ((char *)slide,
"checkdir error: path too long: %s\n",
- FnFilter1(G.buildpathHPFS)));
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
+ FnFilter1(buildpathHPFS)));
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
/* no room for filenames: fatal */
return MPN_ERR_TOOLONG;
}
- *G.endHPFS++ = '/';
- *G.endFAT++ = '/';
- *G.endHPFS = *G.endFAT = '\0';
+ *G.endHPFSw++ = '/';
+ *G.endFATw++ = '/';
+ *G.endHPFSw = *G.endFATw = '\0';
Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now = [%s]\n",
- FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
+ FnFilter1(buildpathHPFS), FnFilter2(buildpathFAT)));
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ free(fn);
+ //free(G.buildpathHPFSw);
+ //free(G.buildpathFATw);
return MPN_OK;
@@ -2245,12 +3504,16 @@
if (FUNCTION == GETPATH) {
+ char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);
+ char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
Trace((stderr, "getting and freeing FAT path [%s]\n",
- FnFilter1(G.buildpathFAT)));
+ FnFilter1(buildpathFAT)));
Trace((stderr, "freeing HPFS path [%s]\n",
- FnFilter1(G.buildpathHPFS)));
- strcpy(pathcomp, G.buildpathFAT);
- free(G.buildpathFAT);
- free(G.buildpathHPFS);
- G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;
+ FnFilter1(buildpathHPFS)));
+ wcscpy(pathcompw, G.buildpathFATw);
+ free(buildpathFAT);
+ free(buildpathHPFS);
+ free(G.buildpathFATw);
+ free(G.buildpathHPFSw);
+ G.buildpathHPFSw = G.buildpathFATw = G.endHPFSw = G.endFATw = NULL;
return MPN_OK;
}
@@ -2262,6 +3525,8 @@
if (FUNCTION == APPEND_NAME) {
- char *p = pathcomp;
+ wchar_t *pw = pathcompw;
int error = MPN_OK;
+ char *pathcomp = wchar_to_local_string(pathcompw, G.unicode_escape_all);
+ char *fn = wchar_to_local_string(G.unipath_widefilename, G.unicode_escape_all);
Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
@@ -2270,16 +3535,19 @@
* for OS filename size limit overflow within the copy loop.
*/
- while ((*G.endHPFS = *p++) != '\0') { /* copy to HPFS filename */
- ++G.endHPFS;
+ while ((*G.endHPFSw = *pw++) != '\0') { /* copy to HPFS filename */
+ ++G.endHPFSw;
}
/* Now, check for OS filename size overflow. When detected, the
* mapped HPFS name is truncated and a warning message is shown.
*/
- if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {
- G.buildpathHPFS[FILNAMSIZ-1] = '\0';
+ if ((G.endHPFSw-G.buildpathHPFSw) >= FILNAMSIZ) {
+ char *buildpathHPFS;
+ G.buildpathHPFSw[FILNAMSIZ-1] = '\0';
+ buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
Info(slide, 1, ((char *)slide,
"checkdir warning: path too long; truncating\n \
%s\n -> %s\n",
- FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));
+ FnFilter1(fn), FnFilter2(buildpathHPFS)));
+ free(buildpathHPFS);
error = MPN_INF_TRUNC; /* filename truncated */
}
@@ -2289,12 +3557,12 @@
* within the following copy loop, either.
*/
- if (G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
+ if (G.pInfo->vollabel || !IsVolumeOldFATw(__G__ G.buildpathHPFSw)) {
/* copy to FAT filename, too */
- p = pathcomp;
- while ((*G.endFAT = *p++) != '\0')
- ++G.endFAT;
+ pw = pathcompw;
+ while ((*G.endFATw = *pw++) != '\0')
+ ++G.endFATw;
} else
/* map into FAT fn, update endFAT */
- map2fat(pathcomp, &G.endFAT);
+ map2fatw(pathcompw, &G.endFATw);
/* Check that the FAT path does not exceed the FILNAMSIZ limit, and
@@ -2305,8 +3573,16 @@
* has already happened.
*/
- if ((G.endFAT-G.buildpathFAT) >= FILNAMSIZ)
- G.buildpathFAT[FILNAMSIZ-1] = '\0';
- Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n",
- FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
+ if ((G.endFATw-G.buildpathFATw) >= FILNAMSIZ)
+ G.buildpathFATw[FILNAMSIZ-1] = '\0';
+ {
+ char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
+ char *buildpathFAT = wchar_to_local_string(G.buildpathFATw,G.unicode_escape_all);
+ Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n",
+ FnFilter1(buildpathHPFS), FnFilter2(buildpathFAT)));
+ free(buildpathHPFS);
+ free(buildpathFAT);
+ }
+ free(fn);
+ free(pathcomp);
return error; /* could check for existence, prompt for new name... */
@@ -2321,33 +3597,23 @@
if (FUNCTION == INIT) {
- Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
-#ifdef ACORN_FTYPE_NFS
- if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+
- (uO.acorn_nfs_ext ? 5 : 1)))
-#else
- if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1))
-#endif
+ Trace((stderr, "initializing buildpathHPFSw and buildpathFATw to "));
+ if ((G.buildpathHPFSw = (wchar_t *)malloc((G.fnlen+G.rootlen+1) * sizeof(wchar_t)))
== NULL)
return MPN_NOMEM;
-#ifdef ACORN_FTYPE_NFS
- if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+
- (uO.acorn_nfs_ext ? 5 : 1)))
-#else
- if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1))
-#endif
+ if ((G.buildpathFATw = (wchar_t *)malloc((G.fnlen+G.rootlen+1) * sizeof(wchar_t)))
== NULL) {
- free(G.buildpathHPFS);
+ free(G.buildpathHPFSw);
return MPN_NOMEM;
}
if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */
/* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
- if (G.renamed_fullpath && pathcomp[1] == ':')
- *G.buildpathHPFS = (char)ToLower(*pathcomp);
+ if (G.renamed_fullpath && pathcompw[1] == ':')
+ *G.buildpathHPFSw = (wchar_t)towlower(*pathcompw);
else if (!G.renamed_fullpath && G.rootlen > 1 &&
- G.rootpath[1] == ':')
- *G.buildpathHPFS = (char)ToLower(*G.rootpath);
+ G.rootpathw[1] == ':')
+ *G.buildpathHPFSw = (wchar_t)towlower(*G.rootpathw);
else {
- char tmpN[MAX_PATH], *tmpP;
- if (GetFullPathNameA(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH)
+ wchar_t tmpNw[MAX_PATH], *tmpPw;
+ if (GetFullPathNameW(L".", MAX_PATH, tmpNw, &tmpPw) > MAX_PATH)
{ /* by definition of MAX_PATH we should never get here */
Info(slide, 1, ((char *)slide,
@@ -2355,28 +3621,33 @@
return MPN_INF_TRUNC; /* can't get drive letter */
}
- G.nLabelDrive = *tmpN - 'a' + 1;
- *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');
+ G.nLabelDrive = (char)(*tmpNw - 'a' + 1);
+ *G.buildpathHPFSw = (wchar_t)(G.nLabelDrive - 1 + 'a');
}
- G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */
- if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */
+ G.nLabelDrive = (char)(*G.buildpathHPFSw - 'a' + 1); /* save for mapname() */
+ if (uO.volflag == 0 || *G.buildpathHPFSw < 'a' /* no labels/bogus? */
|| (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */
- free(G.buildpathHPFS);
- free(G.buildpathFAT);
+ free(G.buildpathHPFSw);
+ free(G.buildpathFATw);
return MPN_VOL_LABEL; /* skipping with message */
}
- *G.buildpathHPFS = '\0';
+ *G.buildpathHPFSw = '\0';
} else if (G.renamed_fullpath) /* pathcomp = valid data */
- strcpy(G.buildpathHPFS, pathcomp);
+ wcscpy(G.buildpathHPFSw, pathcompw);
else if (G.rootlen > 0)
- strcpy(G.buildpathHPFS, G.rootpath);
+ wcscpy(G.buildpathHPFSw, G.rootpathw);
else
- *G.buildpathHPFS = '\0';
- G.endHPFS = G.buildpathHPFS;
- G.endFAT = G.buildpathFAT;
- while ((*G.endFAT = *G.endHPFS) != '\0') {
- ++G.endFAT;
- ++G.endHPFS;
+ *G.buildpathHPFSw = '\0';
+ G.endHPFSw = G.buildpathHPFSw;
+ G.endFATw = G.buildpathFATw;
+ while ((*G.endFATw = *G.endHPFSw) != '\0') {
+ ++G.endFATw;
+ ++G.endHPFSw;
}
- Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS)));
+ {
+ char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);
+ Trace((stderr, "[%s]\n", FnFilter1(buildpathHPFS)));
+ free(buildpathHPFS);
+ }
+
return MPN_OK;
}
@@ -2395,7 +3666,9 @@
#if (!defined(SFX) || defined(SFX_EXDIR))
if (FUNCTION == ROOT) {
+ char *pathcomp = wchar_to_local_string(pathcompw, G.unicode_escape_all);
Trace((stderr, "initializing root path to [%s]\n",
FnFilter1(pathcomp)));
- if (pathcomp == NULL) {
+ free(pathcomp);
+ if (pathcompw == NULL) {
G.rootlen = 0;
return MPN_OK;
@@ -2403,17 +3676,17 @@
if (G.rootlen > 0) /* rootpath was already set, nothing to do */
return MPN_OK;
- if ((G.rootlen = strlen(pathcomp)) > 0) {
+ if ((G.rootlen = wcslen(pathcompw)) > 0) {
int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;
- char *tmproot;
+ wchar_t *tmprootw;
- if ((tmproot = (char *)malloc(G.rootlen+3)) == (char *)NULL) {
+ if ((tmprootw = (wchar_t *)malloc((G.rootlen+3) * sizeof(wchar_t))) == (wchar_t *)NULL) {
G.rootlen = 0;
return MPN_NOMEM;
}
- strcpy(tmproot, pathcomp);
- if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')
+ wcscpy(tmprootw, pathcompw);
+ if (iswalpha(tmprootw[0]) && tmprootw[1] == ':')
has_drive = TRUE; /* drive designator */
- if (tmproot[G.rootlen-1] == '/' || tmproot[G.rootlen-1] == '\\') {
- tmproot[--G.rootlen] = '\0';
+ if (tmprootw[G.rootlen-1] == '/' || tmprootw[G.rootlen-1] == '\\') {
+ tmprootw[--G.rootlen] = '\0';
had_trailing_pathsep = TRUE;
}
@@ -2422,9 +3695,9 @@
add_dot = TRUE; /* relative path: add '.' before '/' */
} else if (G.rootlen > 0) { /* need not check "x:." and "x:/" */
- if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
+ if (SSTATW(tmprootw, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
{
/* path does not exist */
if (!G.create_dirs /* || iswild(tmproot) */ ) {
- free(tmproot);
+ free(tmprootw);
G.rootlen = 0;
/* treat as stored file */
@@ -2433,12 +3706,15 @@
/* create directory (could add loop here scanning tmproot
* to create more than one level, but really necessary?) */
- if (MKDIR(tmproot, 0777) == -1) {
+ if (MKDIRW(tmprootw, 0777) == -1) {
+ char *tmproot = wchar_to_local_string(tmprootw, G.unicode_escape_all);
Info(slide, 1, ((char *)slide,
"checkdir: cannot create extraction directory: %s\n",
FnFilter1(tmproot)));
free(tmproot);
+ free(tmprootw);
G.rootlen = 0;
/* path didn't exist, tried to create, failed: */
/* file exists, or need 2+ subdir levels */
+ free(pathcomp);
return MPN_ERR_SKIP;
}
@@ -2446,13 +3722,17 @@
}
if (add_dot) /* had just "x:", make "x:." */
- tmproot[G.rootlen++] = '.';
- tmproot[G.rootlen++] = '/';
- tmproot[G.rootlen] = '\0';
- if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {
- free(tmproot);
+ tmprootw[G.rootlen++] = '.';
+ tmprootw[G.rootlen++] = '/';
+ tmprootw[G.rootlen] = '\0';
+ if ((G.rootpathw = (wchar_t *)realloc(tmprootw, (G.rootlen+1) * sizeof(wchar_t))) == NULL) {
+ free(tmprootw);
G.rootlen = 0;
return MPN_NOMEM;
}
- Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath)));
+ {
+ char *rootpath = wchar_to_local_string(G.rootpathw, G.unicode_escape_all);
+ Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath)));
+ free(rootpath);
+ }
}
return MPN_OK;
@@ -2467,5 +3747,5 @@
Trace((stderr, "freeing rootpath\n"));
if (G.rootlen > 0) {
- free(G.rootpath);
+ free(G.rootpathw);
G.rootlen = 0;
}
@@ -2475,6 +3755,7 @@
return MPN_INVALID; /* should never reach */
-} /* end function checkdir() */
+} /* end function checkdirw() */
+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
@@ -2809,4 +4090,99 @@
}
+
+
+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
+
+int zstat_win32w(__W32STAT_GLOBALS__ const wchar_t *pathw, z_stat *buf)
+{
+ if (!zstatw(pathw, buf))
+ {
+ char *path = wchar_to_local_string((wchar_t *)pathw, G.unicode_escape_all);
+ /* stat was successful, now redo the time-stamp fetches */
+#ifndef NO_W32TIMES_IZFIX
+ int fs_uses_loctime = FStampIsLocTimeW(__G__ pathw);
+#endif
+ HANDLE h;
+ FILETIME Modft, Accft, Creft;
+
+ TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime));
+ h = CreateFileW(pathw, GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h != INVALID_HANDLE_VALUE) {
+ BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
+ CloseHandle(h);
+
+ if (ftOK) {
+ FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft));
+ FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft));
+#ifndef NO_W32TIMES_IZFIX
+ if (!fs_uses_loctime) {
+ /* On a filesystem that stores UTC timestamps, we refill
+ * the time fields of the struct stat buffer by directly
+ * using the UTC values as returned by the Win32
+ * GetFileTime() API call.
+ */
+ NtfsFileTime2utime(&Modft, &(buf->st_mtime));
+ if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+ NtfsFileTime2utime(&Accft, &(buf->st_atime));
+ else
+ buf->st_atime = buf->st_mtime;
+ if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+ NtfsFileTime2utime(&Creft, &(buf->st_ctime));
+ else
+ buf->st_ctime = buf->st_mtime;
+ TTrace((stdout,"NTFS, recalculated modtime %08lx\n",
+ buf->st_mtime));
+ } else
+#endif /* NO_W32TIMES_IZFIX */
+ {
+ /* On VFAT and FAT-like filesystems, the FILETIME values
+ * are converted back to the stable local time before
+ * converting them to UTC unix time-stamps.
+ */
+ VFatFileTime2utime(&Modft, &(buf->st_mtime));
+ if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+ VFatFileTime2utime(&Accft, &(buf->st_atime));
+ else
+ buf->st_atime = buf->st_mtime;
+ if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+ VFatFileTime2utime(&Creft, &(buf->st_ctime));
+ else
+ buf->st_ctime = buf->st_mtime;
+ TTrace((stdout, "VFAT, recalculated modtime %08lx\n",
+ buf->st_mtime));
+ }
+ }
+ }
+ free(path);
+
+ return 0;
+ }
+#ifdef W32_STATROOT_FIX
+ else
+ {
+ DWORD flags;
+
+ flags = GetFileAttributesW(pathw);
+ if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
+ char *path = wchar_to_local_string((wchar_t *)pathw, G.unicode_escape_all);
+ Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
+ FnFilter1(path)));
+ free(path);
+ memset(buf, 0, sizeof(z_stat));
+ buf->st_atime = buf->st_ctime = buf->st_mtime =
+ dos_to_unix_time(DOSTIME_MINIMUM); /* 1-1-80 */
+ buf->st_mode = S_IFDIR | S_IREAD |
+ ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);
+ return 0;
+ } /* assumes: stat() won't fail on non-dirs without good reason */
+ }
+#endif /* W32_STATROOT_FIX */
+ return -1;
+}
+
+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */
+
#endif /* W32_STAT_BANDAID */
@@ -2939,6 +4315,5 @@
-#if 0
-#ifdef UNICODE_SUPPORT
+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)
wchar_t *utf8_to_wchar_string(utf8_string)
char *utf8_string; /* path to get utf-8 name for */
@@ -3030,22 +4405,40 @@
return qw;
}
-#endif /* UNICODE_SUPPORT */
-#endif /* 0 */
+int has_win32_wide()
+{
+ int is_win32_wide;
+ /* test if we have wide function support */
-/* --------------------------------------------------- */
-/* Large File Support
- *
- * Initial functions by E. Gordon and R. Nausedat
- * 9/10/2003
- * Lifted from Zip 3b, win32.c and place here by Myles Bennett
- * 7/6/2004
- *
- * These implement 64-bit file support for Windows. The
- * defines and headers are in win32/w32cfg.h.
- *
- * Moved to win32i64.c by Mike White to avoid conflicts in
- * same name functions in WiZ using UnZip and Zip libraries.
- * 9/25/2003
- */
+ /* first guess: On "real" WinNT, the WIN32 wide API >>is<< supported. */
+ is_win32_wide = IsWinNT();
+
+ if (!is_win32_wide)
+ {
+ /* On a non-WinNT environment (Win9x or Win32s), wide functions
( run in 1.778 second using v1.01-cache-2.11-cpan-d7f47b0818f )