📄 win32.c
字号:
/* Copyright (c) 1990-2006 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2005-Feb-10 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html*//* * WIN32 specific functions for ZIP. * * The WIN32 version of ZIP heavily relies on the MSDOS and OS2 versions, * since we have to do similar things to switch between NTFS, HPFS and FAT. */#include "../zip.h"#include <stdlib.h>#include <stdio.h>#include <limits.h>#include <time.h>#include <ctype.h>#include <windows.h>#ifdef __RSXNT__# include <alloca.h># include "../win32/rsxntwin.h"#endif#include "../win32/win32zip.h"#define A_RONLY 0x01#define A_HIDDEN 0x02#define A_SYSTEM 0x04#define A_LABEL 0x08#define A_DIR 0x10#define A_ARCHIVE 0x20#define EAID 0x0009#if (defined(__MINGW32__) && !defined(USE_MINGW_GLOBBING)) int _CRT_glob = 0; /* suppress command line globbing by C RTL */#endif#ifndef UTILextern int noisy;#ifndef NO_W32TIMES_IZFIX#if defined(NT_TZBUG_WORKAROUND)local int FSusesLocalTime(const char *path);#endif#if defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND)local int NtfsFileTime2utime(const FILETIME *pft, time_t *ut);#endif#if defined(NT_TZBUG_WORKAROUND) && !defined(NO_W32TIMES_IZFIX)local void utime2NtfsFileTime(time_t ut, FILETIME *pft);#endif#endif /* !NO_W32TIMES_IZFIX */#if defined(NT_TZBUG_WORKAROUND) && defined(W32_STAT_BANDAID)local int VFatFileTime2utime(const FILETIME *pft, time_t *ut);#endif/* FAT / HPFS detection */int IsFileSystemOldFAT(const char *dir){ static char lastDrive = '\0'; /* cached drive of last GetVolumeInformation call */ static int lastDriveOldFAT = 0; /* cached OldFAT value of last GetVolumeInformation call */ char root[4]; DWORD vfnsize; DWORD vfsflags; /* * We separate FAT and HPFS+other file systems here. * I consider other systems to be similar to HPFS/NTFS, i.e. * support for long file names and being case sensitive to some extent. */ strncpy(root, dir, 3); if ( isalpha((uch)root[0]) && (root[1] == ':') ) { root[0] = to_up(dir[0]); root[2] = '\\'; root[3] = 0; } else { root[0] = '\\'; root[1] = 0; } if (lastDrive == root[0]) { return lastDriveOldFAT; } if ( !GetVolumeInformation(root, NULL, 0, NULL, &vfnsize, &vfsflags, NULL, 0)) { fprintf(mesg, "zip diagnostic: GetVolumeInformation failed\n"); return(FALSE); } lastDrive = root[0]; lastDriveOldFAT = vfnsize <= 12; return lastDriveOldFAT;}/* access mode bits and time stamp */int GetFileMode(const char *name){DWORD dwAttr;#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(name) + 1); OemToAnsi(name, ansi_name); name = (const char *)ansi_name;#endif dwAttr = GetFileAttributes(name); if ( dwAttr == 0xFFFFFFFF ) { fprintf(mesg, "zip diagnostic: GetFileAttributes failed\n"); return(0x20); /* the most likely, though why the error? security? */ } return( (dwAttr&FILE_ATTRIBUTE_READONLY ? A_RONLY :0) | (dwAttr&FILE_ATTRIBUTE_HIDDEN ? A_HIDDEN :0) | (dwAttr&FILE_ATTRIBUTE_SYSTEM ? A_SYSTEM :0) | (dwAttr&FILE_ATTRIBUTE_DIRECTORY ? A_DIR :0) | (dwAttr&FILE_ATTRIBUTE_ARCHIVE ? A_ARCHIVE :0));}#if defined(NT_TZBUG_WORKAROUND) && !defined(NO_W32TIMES_IZFIX)local int FSusesLocalTime(const char *path){ char *tmp0; char rootPathName[4]; char tmp1[MAX_PATH], tmp2[MAX_PATH]; DWORD volSerNo, maxCompLen, fileSysFlags;#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_path = (char *)alloca(strlen(path) + 1); OemToAnsi(path, ansi_path); path = (const char *)ansi_path;#endif if (isalpha((uch)path[0]) && (path[1] == ':')) tmp0 = (char *)path; else { GetFullPathName(path, MAX_PATH, tmp1, &tmp0); tmp0 = &tmp1[0]; } strncpy(rootPathName, tmp0, 3); /* Build the root path name, */ rootPathName[3] = '\0'; /* e.g. "A:/" */ GetVolumeInformation((LPCTSTR)rootPathName, (LPTSTR)tmp1, (DWORD)MAX_PATH, &volSerNo, &maxCompLen, &fileSysFlags, (LPTSTR)tmp2, (DWORD)MAX_PATH); /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in * local time! */ return !strncmp(strupr(tmp2), "FAT", 3) || !strncmp(tmp2, "VFAT", 4) || !strncmp(tmp2, "HPFS", 4);} /* end function FSusesLocalTime() */#endif /* NT_TZBUG_WORKAROUND && !NO_W32TIMES_IZFIX */#if defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND)#if (defined(__GNUC__) || defined(ULONG_LONG_MAX)) typedef long long LLONG64; typedef unsigned long long ULLNG64;#elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64;#elif (defined(_MSC_VER) && (_MSC_VER >= 1100)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64;#elif (defined(__IBMC__) && (__IBMC__ >= 350)) typedef __int64 LLONG64; typedef unsigned __int64 ULLNG64;#else# define NO_INT64#endif/* scale factor and offset for conversion time_t -> FILETIME */# define NT_QUANTA_PER_UNIX 10000000L# define FTQUANTA_PER_UT_L (NT_QUANTA_PER_UNIX & 0xFFFF)# define FTQUANTA_PER_UT_H (NT_QUANTA_PER_UNIX >> 16)# 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#ifndef NO_W32TIMES_IZFIXlocal int NtfsFileTime2utime(const FILETIME *pft, time_t *ut){#ifndef NO_INT64 ULLNG64 NTtime; NTtime = ((ULLNG64)pft->dwLowDateTime + ((ULLNG64)pft->dwHighDateTime << 32)); /* 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; } } 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 /* NO_INT64 (64-bit integer arithmetics may not be supported) */ /* 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) /* daycount at the end of month[m-1] */ static ZCONST ush ydays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; time_t days; SYSTEMTIME w32tm; /* 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; } } 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 /* ?NO_INT64 */} /* end function NtfsFileTime2utime() */#endif /* !NO_W32TIMES_IZFIX */#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND */#if defined(NT_TZBUG_WORKAROUND) && defined(W32_STAT_BANDAID)local int VFatFileTime2utime(const FILETIME *pft, time_t *ut){ FILETIME lft; SYSTEMTIME w32tm; struct tm ltm; if (!FileTimeToLocalFileTime(pft, &lft)) { /* if pft cannot be converted to local time, return current time */ return time(NULL); } FileTimeToSystemTime(&lft, &w32tm); /* 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; } } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -