Archive-Unzip-Burst
view release on metacpan or search on metacpan
unzip-6.0/win32/win32.c view on Meta::CPAN
#ifndef SFX
/**************************/
/* Function test_NTSD() */ /* returns PK_WARN when NTSD data is invalid */
/**************************/
#ifdef __BORLANDC__
/* Turn off warning about not using all parameters for this function only */
#pragma argsused
#endif
int test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize)
__GDEF
uch *eb;
unsigned eb_size;
uch *eb_ucptr;
ulg eb_ucsize;
{
return (ValidateSecurity(eb_ucptr) ? PK_OK : PK_WARN);
} /* end function test_NTSD() */
#endif /* !SFX */
#endif /* NTSD_EAS */
/**********************/
/* Function IsWinNT() */
/**********************/
int IsWinNT(void) /* returns TRUE if real NT, FALSE if Win9x or Win32s */
{
static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */
if (g_PlatformId == 0xFFFFFFFF) {
/* note: GetVersionEx() doesn't exist on WinNT 3.1 */
if (GetVersion() < 0x80000000)
g_PlatformId = TRUE;
else
g_PlatformId = FALSE;
}
return (int)g_PlatformId;
}
/* DEBUG_TIME insertion: */
#ifdef DEBUG_TIME
static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft);
static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft)
{
SYSTEMTIME w32tm;
int rval;
rval = FileTimeToSystemTime(pft, &w32tm);
if (!rval) {
fprintf(hdo, "%s\n %08lX,%08lX (%s) -> Conversion failed !!!\n",
TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),
(isloc ? "local" : "UTC"));
} else {
fprintf(hdo, "%s\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\n",
TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),
w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour,
w32tm.wMinute, w32tm.wSecond, (isloc ? "local" : "UTC"));
}
return rval;
}
#define FTTrace(x) show_NTFileTime x
#else
#define FTTrace(x)
#endif /* DEBUG_TIME */
/* end of DEBUG_TIME insertion */
#ifndef IZ_USE_INT64
# if (defined(__GNUC__) || defined(ULONG_LONG_MAX))
typedef long long LLONG64;
typedef unsigned long long ULLNG64;
# define IZ_USE_INT64
# elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))
typedef __int64 LLONG64;
typedef unsigned __int64 ULLNG64;
# define IZ_USE_INT64
# elif (defined(_MSC_VER) && (_MSC_VER >= 1100))
typedef __int64 LLONG64;
typedef unsigned __int64 ULLNG64;
# define IZ_USE_INT64
# elif (defined(__IBMC__) && (__IBMC__ >= 350))
typedef __int64 LLONG64;
typedef unsigned __int64 ULLNG64;
# define IZ_USE_INT64
# elif defined(HAVE_INT64)
typedef __int64 LLONG64;
typedef unsigned __int64 ULLNG64;
# define IZ_USE_INT64
# endif
#endif
/* scale factor and offset for conversion time_t -> FILETIME */
#define NT_QUANTA_PER_UNIX 10000000L
#define UNIX_TIME_ZERO_HI 0x019DB1DEUL
#define UNIX_TIME_ZERO_LO 0xD53E8000UL
/* special FILETIME values for bound-checks */
#define UNIX_TIME_UMAX_HI 0x0236485EUL
#define UNIX_TIME_UMAX_LO 0xD4A5E980UL
#define UNIX_TIME_SMIN_HI 0x0151669EUL
#define UNIX_TIME_SMIN_LO 0xD53E8000UL
#define UNIX_TIME_SMAX_HI 0x01E9FD1EUL
#define UNIX_TIME_SMAX_LO 0xD4A5E980UL
#define DOSTIME_MIN_FT_HI 0x01A8E79FUL
#define DOSTIME_MIN_FT_LO 0xE1D58000UL
/* time_t equivalent of DOSTIME_MINIMUM */
#define UTIME_1980_JAN_01_00_00 315532800L
#ifndef NO_W32TIMES_IZFIX
/*********************************/
/* Function utime2NtfsFileTime() */ /* convert Unix time_t format into the */
/*********************************/ /* form used by SetFileTime() in NT/9x */
static void utime2NtfsFileTime(time_t ut, FILETIME *pft)
{
#ifdef IZ_USE_INT64
ULLNG64 NTtime;
/* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX"
* cannot overflow in 64-bit signed calculation, regardless whether "ut"
* is signed or unsigned. */
NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) +
((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
pft->dwLowDateTime = (DWORD)NTtime;
pft->dwHighDateTime = (DWORD)(NTtime >> 32);
#else /* !IZ_USE_INT64 (64-bit integer arithmetics may not be supported) */
unsigned int b1, b2, carry = 0;
unsigned long r0, r1, r2, r3;
long r4; /* signed, to catch environments with signed time_t */
b1 = ut & 0xFFFF;
b2 = (ut >> 16) & 0xFFFF; /* if ut is over 32 bits, too bad */
r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF);
r2 = b1 * (NT_QUANTA_PER_UNIX >> 16);
r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF);
r4 = b2 * (NT_QUANTA_PER_UNIX >> 16);
r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL;
if (r0 < r1)
carry++;
r1 = r0;
r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL;
if (r0 < r1)
carry++;
pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO;
if (pft->dwLowDateTime < r0)
carry++;
pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16)
+ UNIX_TIME_ZERO_HI + carry;
#endif /* ?IZ_USE_INT64 */
} /* end function utime2NtfsFileTime() */
#endif /* !NO_W32TIMES_IZFIX */
/*********************************/
/* Function utime2VFatFileTime() */ /* convert Unix time_t format into the */
/*********************************/ /* form used by SetFileTime() in NT/9x */
static void utime2VFatFileTime(time_t ut, FILETIME *pft, int clipDosMin)
{
time_t utc = ut;
struct tm *ltm;
SYSTEMTIME w32tm;
FILETIME lft;
/* The milliseconds field gets always initialized to 0. */
w32tm.wMilliseconds = 0;
#ifdef __BORLANDC__ /* Borland C++ 5.x crashes when trying to reference tm */
if (utc < UTIME_1980_JAN_01_00_00)
utc = UTIME_1980_JAN_01_00_00;
#endif
ltm = localtime(&utc);
if (ltm == (struct tm *)NULL)
/* localtime() did not accept given utc time value; try to use
the UTC value */
ltm = gmtime(&utc);
if (ltm == (struct tm *)NULL) {
if (ut <= (UTIME_1980_JAN_01_00_00 + 86400)) {
/* use DOSTIME_MINIMUM date instead of "early" failure dates */
w32tm.wYear = 1980;
w32tm.wMonth = 1;
w32tm.wDay = 1;
w32tm.wHour = 0;
w32tm.wMinute = 0;
w32tm.wSecond = 0;
} else {
/* as a last resort, use the current system time */
GetLocalTime(&w32tm);
}
} else if (clipDosMin && (ltm->tm_year < 80)) {
w32tm.wYear = 1980;
w32tm.wMonth = 1;
w32tm.wDay = 1;
w32tm.wHour = 0;
w32tm.wMinute = 0;
w32tm.wSecond = 0;
} else {
w32tm.wYear = ltm->tm_year + 1900; /* year + 1900 -> year */
w32tm.wMonth = ltm->tm_mon + 1; /* 0..11 -> 1..12 */
w32tm.wDay = ltm->tm_mday; /* 1..31 */
w32tm.wHour = ltm->tm_hour; /* 0..23 */
w32tm.wMinute = ltm->tm_min; /* 0..59 */
w32tm.wSecond = ltm->tm_sec; /* 0..61 in ANSI C */
}
SystemTimeToFileTime(&w32tm, &lft);
LocalFileTimeToFileTime(&lft, pft);
} /* end function utime2VFatFileTime() */
/* nonzero if `y' is a leap year, else zero */
#define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)
/* number of leap years from 1970 to `y' (not including `y' itself) */
#define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400)
extern ZCONST ush ydays[]; /* defined in fileio.c */
#if (defined(W32_STAT_BANDAID) && !defined(NO_W32TIMES_IZFIX))
/*********************************/
/* Function NtfsFileTime2utime() */
/*********************************/
static int NtfsFileTime2utime(const FILETIME *pft, time_t *ut)
{
#ifdef IZ_USE_INT64
ULLNG64 NTtime;
NTtime = ((ULLNG64)pft->dwLowDateTime +
((ULLNG64)pft->dwHighDateTime << 32));
#ifndef TIME_T_TYPE_DOUBLE
/* underflow and overflow handling */
#ifdef CHECK_UTIME_SIGNED_UNSIGNED
if ((time_t)0x80000000L < (time_t)0L)
{
if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO +
((ULLNG64)UNIX_TIME_SMIN_HI << 32))) {
*ut = (time_t)LONG_MIN;
return FALSE;
}
if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO +
((ULLNG64)UNIX_TIME_SMAX_HI << 32))) {
*ut = (time_t)LONG_MAX;
return FALSE;
}
}
else
#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
{
if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO +
((ULLNG64)UNIX_TIME_ZERO_HI << 32))) {
*ut = (time_t)0;
return FALSE;
}
if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO +
((ULLNG64)UNIX_TIME_UMAX_HI << 32))) {
*ut = (time_t)ULONG_MAX;
return FALSE;
}
}
#endif /* !TIME_T_TYPE_DOUBLE */
NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO +
((ULLNG64)UNIX_TIME_ZERO_HI << 32));
*ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX);
return TRUE;
#else /* !IZ_USE_INT64 (64-bit integer arithmetics may not be supported) */
time_t days;
SYSTEMTIME w32tm;
#ifndef TIME_T_TYPE_DOUBLE
/* underflow and overflow handling */
#ifdef CHECK_UTIME_SIGNED_UNSIGNED
if ((time_t)0x80000000L < (time_t)0L)
{
if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
(pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
*ut = (time_t)LONG_MIN;
return FALSE;
if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
(pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
*ut = (time_t)LONG_MAX;
return FALSE;
}
}
else
#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
{
if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
(pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
*ut = (time_t)0;
return FALSE;
}
if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
(pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
*ut = (time_t)ULONG_MAX;
return FALSE;
}
}
#endif /* !TIME_T_TYPE_DOUBLE */
FileTimeToSystemTime(pft, &w32tm);
/* set `days' to the number of days into the year */
days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] +
(w32tm.wMonth > 2 && leap (w32tm.wYear));
/* now set `days' to the number of days since 1 Jan 1970 */
days += 365 * (time_t)(w32tm.wYear - 1970) +
(time_t)(nleap(w32tm.wYear));
*ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour +
(time_t)(60 * w32tm.wMinute + w32tm.wSecond));
return TRUE;
#endif /* ?IZ_USE_INT64 */
} /* end function NtfsFileTime2utime() */
#endif /* W32_STAT_BANDAID && !NO_W32TIMES_IZFIX */
#ifdef W32_STAT_BANDAID
/*********************************/
/* Function VFatFileTime2utime() */
/*********************************/
static int VFatFileTime2utime(const FILETIME *pft, time_t *ut)
{
FILETIME lft;
#ifndef HAVE_MKTIME
WORD wDOSDate, wDOSTime;
#else
SYSTEMTIME w32tm;
struct tm ltm;
#endif
if (!FileTimeToLocalFileTime(pft, &lft)) {
/* if pft cannot be converted to local time, set ut to current time */
time(ut);
return FALSE;
}
FTTrace((stdout, "VFatFT2utime, feed for mktime()", 1, &lft));
#ifndef HAVE_MKTIME
/* This version of the FILETIME-to-UNIXTIME conversion function
* uses DOS-DATE-TIME format as intermediate stage. For modification
* and access times, this is no problem. But, the extra fine resolution
* of the VFAT-stored creation time gets lost.
*/
if (!FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime)) {
static const FILETIME dosmin_ft =
{DOSTIME_MIN_FT_LO, DOSTIME_MIN_FT_HI};
if (CompareFileTime(&lft, &dosmin_ft) <= 0) {
/* underflow -> set to minimum DOS time */
wDOSDate = (WORD)((DWORD)DOSTIME_MINIMUM >> 16);
wDOSTime = (WORD)DOSTIME_MINIMUM;
} else {
/* overflow -> set to maximum DOS time */
wDOSDate = (WORD)0xFF9F; /* 2107-12-31 */
wDOSTime = (WORD)0xBF7D; /* 23:59:58 */
}
}
TTrace((stdout,"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\n",
(unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f),
(unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f),
(unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e)));
*ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime);
/* a cheap error check: dos_to_unix_time() only returns an odd time
* when clipping at maximum time_t value. DOS_DATE_TIME values have
* a resolution of 2 seconds and are therefore even numbers.
*/
return (((*ut)&1) == (time_t)0);
#else /* HAVE_MKTIME */
FileTimeToSystemTime(&lft, &w32tm);
#ifndef TIME_T_TYPE_DOUBLE
/* underflow and overflow handling */
/* TODO: The range checks are not accurate, the actual limits may
* be off by one daylight-saving-time shift (typically 1 hour),
* depending on the current state of "is_dst".
*/
#ifdef CHECK_UTIME_SIGNED_UNSIGNED
if ((time_t)0x80000000L < (time_t)0L)
{
if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
(pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
*ut = (time_t)LONG_MIN;
return FALSE;
if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
(pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
*ut = (time_t)LONG_MAX;
return FALSE;
}
}
else
#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
{
if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
(pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
*ut = (time_t)0;
return FALSE;
}
if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
(pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
*ut = (time_t)ULONG_MAX;
return FALSE;
}
}
#endif /* !TIME_T_TYPE_DOUBLE */
ltm.tm_year = w32tm.wYear - 1900;
ltm.tm_mon = w32tm.wMonth - 1;
ltm.tm_mday = w32tm.wDay;
ltm.tm_hour = w32tm.wHour;
ltm.tm_min = w32tm.wMinute;
ltm.tm_sec = w32tm.wSecond;
ltm.tm_isdst = -1; /* let mktime determine if DST is in effect */
*ut = mktime(<m);
/* a cheap error check: mktime returns "(time_t)-1L" on conversion errors.
* Normally, we would have to apply a consistency check because "-1"
* could also be a valid time. But, it is quite unlikely to read back odd
* time numbers from file systems that store time stamps in DOS format.
* (The only known exception is creation time on VFAT partitions.)
*/
return (*ut != (time_t)-1L);
#endif /* ?HAVE_MKTIME */
} /* end function VFatFileTime2utime() */
#endif /* W32_STAT_BANDAID */
/******************************/
/* Function FStampIsLocTime() */
/******************************/
static int FStampIsLocTime(__GPRO__ const char *path)
{
return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE);
}
#ifndef NO_W32TIMES_IZFIX
# define UTIME_2_IZFILETIME(ut, pft) \
if (fs_uses_loctime) {utime2VFatFileTime(ut, pft, TRUE);} \
else {utime2NtfsFileTime(ut, pft);}
#else
# define UTIME_2_IZFILETIME(ut, pft) \
utime2VFatFileTime(ut, pft, fs_uses_loctime);
#endif
/****************************/ /* Get the file time in a format that */
/* Function getNTfiletime() */ /* can be used by SetFileTime() in NT */
/****************************/
static int getNTfiletime(__G__ pModFT, pAccFT, pCreFT)
__GDEF
FILETIME *pModFT;
FILETIME *pAccFT;
FILETIME *pCreFT;
{
#ifdef USE_EF_UT_TIME
unsigned eb_izux_flg;
iztimes z_utime; /* struct for Unix-style actime & modtime, + creatime */
#endif
int fs_uses_loctime = FStampIsLocTime(__G__ G.filename);
/* Copy and/or convert time and date variables, if necessary;
* return a flag indicating which time stamps are available. */
#ifdef USE_EF_UT_TIME
if (G.extra_field &&
#ifdef IZ_CHECK_TZ
G.tz_is_valid &&
#endif
((eb_izux_flg = ef_scan_for_izux(G.extra_field,
G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
&z_utime, NULL)) & EB_UT_FL_MTIME))
{
TTrace((stderr, "getNTfiletime: Unix e.f. modif. time = %lu\n",
z_utime.mtime));
UTIME_2_IZFILETIME(z_utime.mtime, pModFT)
if (eb_izux_flg & EB_UT_FL_ATIME) {
UTIME_2_IZFILETIME(z_utime.atime, pAccFT)
}
if (eb_izux_flg & EB_UT_FL_CTIME) {
UTIME_2_IZFILETIME(z_utime.ctime, pCreFT)
}
return (int)eb_izux_flg;
}
#endif /* USE_EF_UT_TIME */
#ifndef NO_W32TIMES_IZFIX
if (!fs_uses_loctime) {
time_t ux_modtime;
ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
utime2NtfsFileTime(ux_modtime, pModFT);
} else
#endif /* NO_W32TIMES_IZFIX */
{
FILETIME lft;
DosDateTimeToFileTime((WORD)(G.lrec.last_mod_dos_datetime >> 16),
(WORD)(G.lrec.last_mod_dos_datetime & 0xFFFFL),
&lft);
LocalFileTimeToFileTime(&lft, pModFT);
}
*pAccFT = *pModFT;
return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
} /* end function getNTfiletime() */
/**************************/
/* Function SetFileSize() */
/**************************/
int SetFileSize(FILE *file, zusz_t filesize)
{
#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() */
unzip-6.0/win32/win32.c view on Meta::CPAN
* 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;
( run in 1.187 second using v1.01-cache-2.11-cpan-5735350b133 )