Archive-Unzip-Burst
view release on metacpan or search on metacpan
unzip-6.0/win32/win32.c view on Meta::CPAN
#ifdef __RSXNT__
/* RSXNT environment lacks a translation function from C file pointer
to Win32-API file handle. So, simply do nothing. */
return 0;
#else /* !__RSXNT__ */
/* not yet verified, if that really creates an unfragmented file
rommel@ars.de
*/
HANDLE os_fh;
#ifdef Z_UINT8_DEFINED
LARGE_INTEGER fsbuf;
#endif
/* Win9x supports FAT file system, only; presetting file size does
not help to prevent fragmentation. */
if (!IsWinNT()) return 0;
/* Win32-API calls require access to the Win32 file handle.
The interface function used to retrieve the Win32 handle for
a file opened by the C rtl is non-standard and may not be
available for every Win32 compiler environment.
(see also win32/win32.c of the Zip distribution)
*/
os_fh = (HANDLE)_get_osfhandle(fileno(file));
/* move file pointer behind the last byte of the expected file size */
#ifdef Z_UINT8_DEFINED
fsbuf.QuadPart = filesize;
if ((SetFilePointer(os_fh, fsbuf.LowPart, &fsbuf.HighPart, FILE_BEGIN)
== 0xFFFFFFFF) && GetLastError() != NO_ERROR)
#else
if (SetFilePointer(os_fh, (ulg)filesize, 0, FILE_BEGIN) == 0xFFFFFFFF)
#endif
return -1;
/* extend/truncate file to the current position */
if (SetEndOfFile(os_fh) == 0)
return -1;
/* move file position pointer back to the start of the file! */
return (SetFilePointer(os_fh, 0, 0, FILE_BEGIN) == 0xFFFFFFFF) ? -1 : 0;
#endif /* ?__RSXNT__ */
} /* end function SetFileSize() */
/****************************/
/* Function close_outfile() */
/****************************/
void close_outfile(__G)
__GDEF
{
FILETIME Modft; /* File time type defined in NT, `last modified' time */
FILETIME Accft; /* NT file time type, `last access' time */
FILETIME Creft; /* NT file time type, `file creation' time */
HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */
int gotTime;
#ifdef NTSD_EAS
uch *ebSDptr;
unsigned ebSDlen;
#endif
#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
INTERN_TO_ISO(G.filename, ansi_name);
# define Ansi_Fname ansi_name
#else
# define Ansi_Fname G.filename
#endif
#ifndef __RSXNT__
if (IsWinNT()) {
/* Truncate the file to the current position.
* This is needed to remove excess allocation in case the
* extraction has failed or stopped prematurely. */
SetEndOfFile((HANDLE)_get_osfhandle(fileno(G.outfile)));
}
#endif
/* Close the file and then re-open it using the Win32
* CreateFile call, so that the file can be created
* with GENERIC_WRITE access, otherwise the SetFileTime
* call will fail. */
fclose(G.outfile);
/* don't set the time stamp and attributes on standard output */
if (uO.cflag)
return;
/* skip restoring time stamps on user's request */
if (uO.D_flag <= 1) {
gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);
/* open a handle to the file before processing extra fields;
we do this in case new security on file prevents us from updating
time stamps */
hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
} else {
gotTime = 0;
}
/* sfield@microsoft.com: set attributes before time in case we decide to
support other filetime members later. This also allows us to apply
attributes before the security is changed, which may prevent this
from succeeding otherwise. Also, since most files don't have
any interesting attributes, only change them if something other than
FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well
as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the
file anyway, when it's created new. */
if ((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {
if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))
Info(slide, 1, ((char *)slide,
"\nwarning (%d): could not set file attributes\n",
(int)GetLastError()));
}
#ifdef NTSD_EAS
/* set NTFS SD extra fields */
if (G.extra_field && /* zipfile extra field may have extended attribs */
FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,
&ebSDptr, &ebSDlen))
unzip-6.0/win32/win32.c view on Meta::CPAN
#ifdef NTSD_EAS
/* set extended attributes from extra fields */
if (G.extra_field && /* zipfile e.f. may have extended attribs */
FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,
&ebSDptr, &ebSDlen)) {
/* ebSDlen contains the payload size of the e.f. block, but
we store it including the e.b. header. */
ebSDlen += EB_HEADSIZE;
} else {
/* no NTSD e.f. block -> no space needed to allocate */
ebSDlen = 0;
}
#endif /* NTSD_EAS */
d_entry = (NTdirattr *)malloc(sizeof(NTdirattr)
#ifdef NTSD_EAS
+ ebSDlen
#endif
+ strlen(G.filename));
*pd = (direntry *)d_entry;
if (d_entry == (NTdirattr *)NULL) {
return PK_MEM;
}
#ifdef NTSD_EAS
if (ebSDlen > 0)
memcpy(d_entry->buf, ebSDptr, ebSDlen);
d_entry->SDlen = ebSDlen;
d_entry->fn = d_entry->buf + ebSDlen;
#else
d_entry->fn = d_entry->buf;
#endif
strcpy(d_entry->fn, G.filename);
d_entry->perms = G.pInfo->file_attr;
d_entry->gotTime = (uO.D_flag <= 0
? getNTfiletime(__G__ &(d_entry->Modft),
&(d_entry->Accft), &(d_entry->Creft))
: 0);
return PK_OK;
} /* end function defer_dir_attribs() */
int set_direc_attribs(__G__ d)
__GDEF
direntry *d;
{
int errval;
HANDLE hFile = INVALID_HANDLE_VALUE; /* File handle defined in NT */
#ifdef __RSXNT__
char *ansi_name;
#endif
/* Win9x does not support setting directory time stamps. */
if (!IsWinNT())
return PK_OK;
errval = PK_OK;
#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
ansi_name = (char *)alloca(strlen(d->fn) + 1);
INTERN_TO_ISO(d->fn, ansi_name);
# define Ansi_Dirname ansi_name
#else
# define Ansi_Dirname d->fn
#endif
/* 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 = CreateFileA(Ansi_Dirname, FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
}
#ifdef NTSD_EAS
if (NtAtt(d)->SDlen > 0) {
int err;
if (QCOND2) {
Info(slide, 1, ((char *)slide, " set attrib: %-22s ",
FnFilter1(d->fn)));
}
/* set NTFS SD extra fields */
err = SetSD(__G__ Ansi_Dirname, NtAtt(d)->perms,
NtAtt(d)->buf, NtAtt(d)->SDlen - EB_HEADSIZE);
if (err == IZ_EF_TRUNC) {
if (!QCOND2)
Info(slide, 1, ((char *)slide, "%-22s ",
FnFilter1(d->fn)));
Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
NtAtt(d)->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) {
Info(slide, 1, ((char *)slide,
"warning: CreateFile() error %d (set file times for %s)\n",
(int)GetLastError(), FnFilter1(d->fn)));
if (!errval)
errval = PK_WARN;
} else {
if (NtAtt(d)->gotTime) {
FILETIME *pModft = (NtAtt(d)->gotTime & EB_UT_FL_MTIME)
? &(NtAtt(d)->Modft) : NULL;
FILETIME *pAccft = (NtAtt(d)->gotTime & EB_UT_FL_ATIME)
? &(NtAtt(d)->Accft) : NULL;
FILETIME *pCreft = (NtAtt(d)->gotTime & EB_UT_FL_CTIME)
? &(NtAtt(d)->Creft) : NULL;
if (!SetFileTime(hFile, pCreft, pAccft, pModft)) {
Info(slide, 0, ((char *)slide,
"warning: SetFileTime() for %s error %d\n",
FnFilter1(d->fn), (int)GetLastError()));
if (!errval)
errval = PK_WARN;
}
}
CloseHandle(hFile);
}
}
return errval;
} /* end function set_direc_attribs() */
#endif /* SET_DIR_ATTRIB */
#ifdef TIMESTAMP
/*************************/
/* Function stamp_file() */
/*************************/
int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime)
{
FILETIME Modft; /* File time type defined in NT, `last modified' time */
HANDLE hFile; /* File handle defined in NT */
int errstat = 0; /* return status: 0 == "OK", -1 == "Failure" */
int fs_uses_loctime = FStampIsLocTime(__G__ fname);
#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
char *ansi_name = (char *)alloca(strlen(fname) + 1);
INTERN_TO_ISO(fname, ansi_name);
# define Ansi_Fname ansi_name
#else
# define Ansi_Fname fname
#endif
/* open a handle to the file to prepare setting the mod-time stamp */
hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if ( hFile == INVALID_HANDLE_VALUE ) {
errstat = -1;
} else {
/* convert time_t modtime into WIN32 native 64bit format */
UTIME_2_IZFILETIME(modtime, &Modft)
/* set Access and Modification times of the file to modtime */
if (!SetFileTime(hFile, NULL, &Modft, &Modft)) {
errstat = -1;
}
CloseHandle(hFile);
}
return errstat;
#undef Ansi_Fname
} /* end function stamp_file() */
#endif /* TIMESTAMP */
/***********************/
/* Function isfloppy() */ /* more precisely, is it removable? */
/***********************/
static int isfloppy(int nDrive) /* 1 == A:, 2 == B:, etc. */
{
char rootPathName[4];
rootPathName[0] = (char)('A' + nDrive - 1); /* build the root path */
rootPathName[1] = ':'; /* name, e.g. "A:/" */
rootPathName[2] = '/';
rootPathName[3] = '\0';
return (GetDriveTypeA(rootPathName) == DRIVE_REMOVABLE);
} /* end function isfloppy() */
/*****************************/
/* Function NTQueryVolInfo() */
/*****************************/
/*
* Note: 8.3 limits on filenames apply only to old-style FAT filesystems.
* More recent versions of Windows (Windows NT 3.5 / Windows 4.0)
* can support long filenames (LFN) on FAT filesystems. Check the
* filesystem maximum component length field to detect LFN support.
*/
static int NTQueryVolInfo(__GPRO__ const char *name)
{
/* static char lastRootPath[4] = ""; */
/* static int lastVolOldFAT; */
/* static int lastVolLocTim; */
char *tmp0;
char tmp1[MAX_PATH], tmp2[MAX_PATH];
DWORD volSerNo, maxCompLen, fileSysFlags;
#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
char *ansi_name = (char *)alloca(strlen(name) + 1);
INTERN_TO_ISO(name, ansi_name);
name = ansi_name;
#endif
if ((!strncmp(name, "//", 2) || !strncmp(name, "\\\\", 2)) &&
(name[2] != '\0' && name[2] != '/' && name[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 (isalpha((uch)name[0]) && (name[1] == ':'))
tmp0 = (char *)name;
else
{
if (!GetFullPathNameA(name, MAX_PATH, tmp1, &tmp0))
return FALSE;
tmp0 = &tmp1[0];
}
if (strncmp(G.lastRootPath, tmp0, 2) != 0) {
/* For speed, we skip repeated queries for the same device */
strncpy(G.lastRootPath, tmp0, 2); /* Build the root path name, */
G.lastRootPath[2] = '/'; /* e.g. "A:/" */
G.lastRootPath[3] = '\0';
if (!GetVolumeInformationA((LPCSTR)G.lastRootPath,
(LPSTR)tmp1, (DWORD)MAX_PATH,
&volSerNo, &maxCompLen, &fileSysFlags,
(LPSTR)tmp2, (DWORD)MAX_PATH)) {
G.lastRootPath[0] = '\0';
return FALSE;
}
/* LFNs are available if the component length is > 12 */
G.lastVolOldFAT = (maxCompLen <= 12);
/* G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3); old version */
/* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in
* local time!
*/
G.lastVolLocTim = !strncmp(strupr(tmp2), "VFAT", 4) ||
!strncmp(tmp2, "HPFS", 4) ||
!strncmp(tmp2, "FAT", 3);
}
return TRUE;
} /* end function NTQueryVolInfo() */
/*****************************/
/* Function IsVolumeOldFAT() */
/*****************************/
unzip-6.0/win32/win32.c view on Meta::CPAN
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;
case ';': /* start of VMS version? */
lastsemi = pp; /* remove VMS version later... */
*pp++ = ';'; /* but keep semicolon for now */
break;
#ifdef ACORN_FTYPE_NFS
case ',': /* NFS filetype extension */
lastcomma = pp;
*pp++ = ','; /* keep for now; may need to remove */
break; /* later, if requested */
#endif
case ' ': /* keep spaces unless specifically */
/* NT cannot create filenames with spaces on FAT volumes */
if (uO.sflag || IsVolumeOldFAT(__G__ G.filename))
*pp++ = '_';
else
*pp++ = ' ';
break;
default:
/* allow European characters in filenames: */
if (isprint(workch) || workch >= 127)
#ifdef _MBCS
{
memcpy(pp, cp, CLEN(cp));
INCSTR(pp);
}
#else
*pp++ = (char)workch;
#endif
} /* 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 (lastchar(G.filename, G.fnlen) == '/') {
#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
INTERN_TO_ISO(G.filename, ansi_name);
# define Ansi_Fname ansi_name
#else
# define Ansi_Fname G.filename
#endif
checkdir(__G__ G.filename, GETPATH);
if (G.created_dir) {
if (QCOND2) {
Info(slide, 0, ((char *)slide, " creating: %-22s\n",
FnFilter1(G.filename)));
}
/* set file attributes:
The default for newly created directories is "DIR attribute
flags set", so there is no need to change attributes unless
one of the DOS style attribute flags is set. The readonly
attribute need not be masked, since it does not prevent
modifications in the new directory. */
if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {
if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))
Info(slide, 1, ((char *)slide,
"\nwarning (%d): could not set file attributes for %s\n",
(int)GetLastError(), FnFilter1(G.filename)));
}
/* set dir time (note trailing '/') */
return (error & ~MPN_MASK) | MPN_CREATED_DIR;
} else if (IS_OVERWRT_ALL) {
/* overwrite attributes of existing directory on user's request */
/* set file attributes: */
if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {
if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))
Info(slide, 1, ((char *)slide,
"\nwarning (%d): could not set file attributes for %s\n",
(int)GetLastError(), FnFilter1(G.filename)));
}
}
/* 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; /* semi-colon was kept: expect #'s after */
while (isdigit((uch)(*pp)))
++pp;
if (*pp == '\0') /* only digits between ';' and end: nuke */
*lastsemi = '\0';
}
#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 */
maskDOSdevice(__G__ pathcomp);
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);
if (G.pInfo->vollabel) { /* set the volume label now */
char drive[4];
#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
INTERN_TO_ISO(G.filename, ansi_name);
# define Ansi_Fname ansi_name
#else
# define Ansi_Fname G.filename
#endif
/* Build a drive string, e.g. "b:" */
drive[0] = (char)('a' + G.nLabelDrive - 1);
strcpy(drive + 1, ":\\");
if (QCOND2)
Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive,
FnFilter1(G.filename)));
if (!SetVolumeLabelA(drive, Ansi_Fname)) {
Info(slide, 1, ((char *)slide,
"mapname: error setting volume label\n"));
return (error & ~MPN_MASK) | MPN_ERR_SKIP;
}
/* success: skip the "extraction" quietly */
return (error & ~MPN_MASK) | MPN_INF_SKIP;
#undef Ansi_Fname
}
Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n",
FnFilter1(G.filename), error));
return error;
} /* end function mapname() */
/****************************/
/* Function maskDOSdevice() */
/****************************/
static void maskDOSdevice(__G__ pathcomp)
__GDEF
char *pathcomp;
{
/*---------------------------------------------------------------------------
Put an underscore in front of the file name if the file name is a
DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to
extract such a file would fail at best and wedge us at worst.
---------------------------------------------------------------------------*/
#if !defined(S_IFCHR) && defined(_S_IFCHR)
# define S_IFCHR _S_IFCHR
#endif
#if !defined(S_ISCHR)
# if defined(_S_ISCHR)
# define S_ISCHR(m) _S_ISCHR(m)
# elif defined(S_IFCHR)
# define S_ISCHR(m) ((m) & S_IFCHR)
# endif
#endif
#ifdef DEBUG
if (zstat(pathcomp, &G.statbuf) == 0) {
Trace((stderr,
"maskDOSdevice() stat(\"%s\", buf) st_mode result: %X, %o\n",
unzip-6.0/win32/win32.c view on Meta::CPAN
}
#endif /* MORE */
#ifdef W32_STAT_BANDAID
/* All currently known variants of WIN32 operating systems (Windows 95/98,
* WinNT 3.x, 4.0, 5.x) have a nasty bug in the OS kernel concerning
* conversions between UTC and local time: In the time conversion functions
* of the Win32 API, the timezone offset (including seasonal daylight saving
* shift) between UTC and local time evaluation is erratically based on the
* current system time. The correct evaluation must determine the offset
* value as it {was/is/will be} for the actual time to be converted.
*
* Newer versions of MS C runtime lib's stat() returns utc time-stamps so
* that localtime(timestamp) corresponds to the (potentially false) local
* time shown by the OS' system programs (Explorer, command shell dir, etc.)
* The RSXNT port follows the same strategy, but fails to recognize the
* access-time attribute.
*
* For the NTFS file system (and other filesystems that store time-stamps
* as UTC values), this results in st_mtime (, st_{c|a}time) fields which
* are not stable but vary according to the seasonal change of "daylight
* saving time in effect / not in effect".
*
* Other C runtime libs (CygWin), or the crtdll.dll supplied with Win9x/NT
* return the unix-time equivalent of the UTC FILETIME values as got back
* from the Win32 API call. This time, return values from NTFS are correct
* whereas utimes from files on (V)FAT volumes vary according to the DST
* switches.
*
* To achieve timestamp consistency of UTC (UT extra field) values in
* Zip archives, the Info-ZIP programs require work-around code for
* proper time handling in stat() (and other time handling routines).
*
* However, nowadays most other programs on Windows systems use the
* time conversion strategy of Microsofts C runtime lib "msvcrt.dll".
* To improve interoperability in environments where a "consistent" (but
* false) "UTC<-->LocalTime" conversion is preferred over "stable" time
* stamps, the Info-ZIP specific time conversion handling can be
* deactivated by defining the preprocessor flag NO_W32TIMES_IZFIX.
*/
/* stat() functions under Windows95 tend to fail for root directories. *
* Watcom and Borland, at least, are affected by this bug. Watcom made *
* a partial fix for 11.0 but still missed some cases. This substitute *
* detects the case and fills in reasonable values. Otherwise we get *
* effects like failure to extract to a root dir because it's not found. */
int zstat_win32(__W32STAT_GLOBALS__ const char *path, z_stat *buf)
{
if (!zstat(path, buf))
{
/* stat was successful, now redo the time-stamp fetches */
#ifndef NO_W32TIMES_IZFIX
int fs_uses_loctime = FStampIsLocTime(__G__ path);
#endif
HANDLE h;
FILETIME Modft, Accft, Creft;
#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
char *ansi_path = (char *)alloca(strlen(path) + 1);
INTERN_TO_ISO(path, ansi_path);
# define Ansi_Path ansi_path
#else
# define Ansi_Path path
#endif
TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime));
h = CreateFileA(Ansi_Path, 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));
}
}
}
# undef Ansi_Path
return 0;
}
#ifdef W32_STATROOT_FIX
else
{
DWORD flags;
#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
char *ansi_path = (char *)alloca(strlen(path) + 1);
INTERN_TO_ISO(path, ansi_path);
# define Ansi_Path ansi_path
#else
# define Ansi_Path path
#endif
flags = GetFileAttributesA(Ansi_Path);
if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
FnFilter1(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 */
# undef Ansi_Path
}
#endif /* W32_STATROOT_FIX */
return -1;
}
#endif /* W32_STAT_BANDAID */
#ifdef W32_USE_IZ_TIMEZONE
#include "timezone.h"
#define SECSPERMIN 60
#define MINSPERHOUR 60
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule);
static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule)
{
if (lpw32tm->wYear != 0) {
ptrule->r_type = JULIAN_DAY;
ptrule->r_day = ydays[lpw32tm->wMonth - 1] + lpw32tm->wDay;
} else {
ptrule->r_type = MONTH_NTH_DAY_OF_WEEK;
ptrule->r_mon = lpw32tm->wMonth;
ptrule->r_day = lpw32tm->wDayOfWeek;
ptrule->r_week = lpw32tm->wDay;
}
ptrule->r_time = (long)lpw32tm->wHour * SECSPERHOUR +
(long)(lpw32tm->wMinute * SECSPERMIN) +
(long)lpw32tm->wSecond;
}
int GetPlatformLocalTimezone(register struct state * ZCONST sp,
void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,
ZCONST struct rule * ZCONST start,
ZCONST struct rule * ZCONST end))
{
TIME_ZONE_INFORMATION tzinfo;
DWORD res;
( run in 1.490 second using v1.01-cache-2.11-cpan-d01c6094234 )