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(&ltm);

    /* 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 )