📄 win32.c
字号:
* 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_zipwin32(const char *path, struct stat *buf){ if (!stat(path, buf)) {#if (!defined(UTIL) && defined(NT_TZBUG_WORKAROUND)) /* stat was successful, now redo the time-stamp fetches */#ifndef NO_W32TIMES_IZFIX int fs_uses_loctime = FSusesLocalTime(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); OemToAnsi(path, ansi_path);# define Ansi_Path ansi_path#else# define Ansi_Path path#endif Trace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime)); h = CreateFile(Ansi_Path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h != INVALID_HANDLE_VALUE) { BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft); CloseHandle(h); if (ftOK) {#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; Tracev((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; Tracev((stdout, "VFAT, recalculated modtime %08lx\n", buf->st_mtime)); } } }# undef Ansi_Path#endif /* !UTIL && NT_TZBUG_WORKAROUND */ 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); OemToAnsi(path, ansi_path);# define Ansi_Path ansi_path#else# define Ansi_Path path#endif flags = GetFileAttributes(Ansi_Path); if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) { Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n", path)); memset(buf, 0, sizeof(struct stat)); buf->st_atime = buf->st_ctime = buf->st_mtime = dos2unixtime(DOSTIME_MINIMUM); /* !!! you MUST NOT add a cast to the type of "st_mode" here; * !!! different compilers do not agree on the "st_mode" size! * !!! (And, some compiler may not declare the "mode_t" type * !!! identifier, so you cannot use it, either.) */ 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; /* read current timezone settings from registry if TZ envvar missing */ res = GetTimeZoneInformation(&tzinfo); if (res != TIME_ZONE_ID_INVALID) { struct rule startrule, stoprule; conv_to_rule(&(tzinfo.StandardDate), &stoprule); conv_to_rule(&(tzinfo.DaylightDate), &startrule); sp->timecnt = 0; sp->ttis[0].tt_abbrind = 0; if ((sp->charcnt = WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1, sp->chars, sizeof(sp->chars), NULL, NULL)) == 0) sp->chars[sp->charcnt++] = '\0'; sp->ttis[1].tt_abbrind = sp->charcnt; sp->charcnt += WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1, sp->chars + sp->charcnt, sizeof(sp->chars) - sp->charcnt, NULL, NULL); if ((sp->charcnt - sp->ttis[1].tt_abbrind) == 0) sp->chars[sp->charcnt++] = '\0'; sp->ttis[0].tt_gmtoff = - (tzinfo.Bias + tzinfo.StandardBias) * MINSPERHOUR; sp->ttis[1].tt_gmtoff = - (tzinfo.Bias + tzinfo.DaylightBias) * MINSPERHOUR; sp->ttis[0].tt_isdst = 0; sp->ttis[1].tt_isdst = 1; sp->typecnt = (startrule.r_mon == 0 && stoprule.r_mon == 0) ? 1 : 2; if (sp->typecnt > 1) (*fill_tzstate_from_rules)(sp, &startrule, &stoprule); return TRUE; } return FALSE;}#endif /* W32_USE_IZ_TIMEZONE */#ifndef WINDLL/* This replacement getch() function was originally created for Watcom C * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32 * ports apply this replacement rather that their supplied getch() (or * alike) function. There are problems with unabsorbed LF characters left * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed. * (Under Win95, ENTER returns two(!!) characters: CR-LF.) This problem * does not appear when run on a WinNT console prompt! *//* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. *//* Note that if PASSWD_FROM_STDIN is defined, the file containing *//* the password must have a carriage return after the word, not a *//* Unix-style newline (linefeed only). This discards linefeeds. */int getch_win32(void){ HANDLE stin; DWORD rc; unsigned char buf[2]; int ret = -1; DWORD odemode = ~(DWORD)0;# ifdef PASSWD_FROM_STDIN stin = GetStdHandle(STD_INPUT_HANDLE);# else stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (stin == INVALID_HANDLE_VALUE) return -1;# endif if (GetConsoleMode(stin, &odemode)) SetConsoleMode(stin, ENABLE_PROCESSED_INPUT); /* raw except ^C noticed */ if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) ret = buf[0]; /* when the user hits return we get CR LF. We discard the LF, not the CR, * because when we call this for the first time after a previous input * such as the one for "replace foo? [y]es, ..." the LF may still be in * the input stream before whatever the user types at our prompt. */ if (ret == '\n') if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) ret = buf[0]; if (odemode != ~(DWORD)0) SetConsoleMode(stin, odemode);# ifndef PASSWD_FROM_STDIN CloseHandle(stin);# endif return ret;}/******************************//* Function version_local() *//******************************/void version_local(){ static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s.\n\n";#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__)) char buf[80];#if (defined(_MSC_VER) && (_MSC_VER > 900)) char buf2[80];#endif#endif/* Define the compiler name and version strings */#if defined(_MSC_VER) /* MSC == MSVC++, including the SDK compiler */ sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100);# define COMPILER_NAME1 buf# if (_MSC_VER == 800)# define COMPILER_NAME2 "(Visual C++ v1.1)"# elif (_MSC_VER == 850)# define COMPILER_NAME2 "(Windows NT v3.5 SDK)"# elif (_MSC_VER == 900)# define COMPILER_NAME2 "(Visual C++ v2.x)"# elif (_MSC_VER > 900) sprintf(buf2, "(Visual C++ v%d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10);# define COMPILER_NAME2 buf2# else# define COMPILER_NAME2 "(bad version)"# endif#elif defined(__WATCOMC__)# if (__WATCOMC__ % 10 > 0)/* We do this silly test because __WATCOMC__ gives two digits for the *//* minor version, but Watcom packaging prefers to show only one digit. */ sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100, __WATCOMC__ % 100);# else sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100, (__WATCOMC__ % 100) / 10);# endif /* __WATCOMC__ % 10 > 0 */# define COMPILER_NAME1 buf# define COMPILER_NAME2 ""#elif defined(__TURBOC__)# ifdef __BORLANDC__# define COMPILER_NAME1 "Borland C++"# if (__BORLANDC__ == 0x0452) /* __BCPLUSPLUS__ = 0x0320 */# define COMPILER_NAME2 " 4.0 or 4.02"# elif (__BORLANDC__ == 0x0460) /* __BCPLUSPLUS__ = 0x0340 */# define COMPILER_NAME2 " 4.5"# elif (__BORLANDC__ == 0x0500) /* __TURBOC__ = 0x0500 */# define COMPILER_NAME2 " 5.0"# elif (__BORLANDC__ == 0x0520) /* __TURBOC__ = 0x0520 */# define COMPILER_NAME2 " 5.2 (C++ Builder 1.0)"# elif (__BORLANDC__ == 0x0530) /* __BCPLUSPLUS__ = 0x0530 */# define COMPILER_NAME2 " 5.3 (C++ Builder 3.0)"# elif (__BORLANDC__ == 0x0540) /* __BCPLUSPLUS__ = 0x0540 */# define COMPILER_NAME2 " 5.4 (C++ Builder 4.0)"# elif (__BORLANDC__ == 0x0550) /* __BCPLUSPLUS__ = 0x0550 */# define COMPILER_NAME2 " 5.5 (C++ Builder 5.0)"# elif (__BORLANDC__ == 0x0551) /* __BCPLUSPLUS__ = 0x0551 */# define COMPILER_NAME2 " 5.5.1 (C++ Builder 5.0.1)"# elif (__BORLANDC__ == 0x0560) /* __BCPLUSPLUS__ = 0x0560 */# define COMPILER_NAME2 " 5.6 (C++ Builder 6)"# else# define COMPILER_NAME2 " later than 5.6"# endif# else /* !__BORLANDC__ */# define COMPILER_NAME1 "Turbo C"# if (__TURBOC__ >= 0x0400) /* Kevin: 3.0 -> 0x0401 */# define COMPILER_NAME2 "++ 3.0 or later"# elif (__TURBOC__ == 0x0295) /* [661] vfy'd by Kevin */# define COMPILER_NAME2 "++ 1.0"# endif# endif /* __BORLANDC__ */#elif defined(__GNUC__)# ifdef __RSXNT__# if (defined(__DJGPP__) && !defined(__EMX__)) sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ", __DJGPP__, __DJGPP_MINOR__);# define COMPILER_NAME1 buf# elif defined(__DJGPP__) sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ", __DJGPP__, __DJGPP_MINOR__);# define COMPILER_NAME1 buf# elif (defined(__GO32__) && !defined(__EMX__))# define COMPILER_NAME1 "rsxnt(djgpp v1.x) / gcc "# elif defined(__GO32__)# define COMPILER_NAME1 "rsxnt(emx + djgpp v1.x) / gcc "# elif defined(__EMX__)# define COMPILER_NAME1 "rsxnt(emx)+gcc "# else# define COMPILER_NAME1 "rsxnt(unknown) / gcc "# endif# elif defined(__CYGWIN__)# define COMPILER_NAME1 "Cygnus win32 / gcc "# elif defined(__MINGW32__)# define COMPILER_NAME1 "mingw32 / gcc "# else# define COMPILER_NAME1 "gcc "# endif# define COMPILER_NAME2 __VERSION__#elif defined(__LCC__)# define COMPILER_NAME1 "LCC-Win32"# define COMPILER_NAME2 ""#else# define COMPILER_NAME1 "unknown compiler (SDK?)"# define COMPILER_NAME2 ""#endif/* Define the compile date string */#ifdef __DATE__# define COMPILE_DATE " on " __DATE__#else# define COMPILE_DATE ""#endif printf(CompiledWith, COMPILER_NAME1, COMPILER_NAME2, "\nWindows 9x / Windows NT/2000/XP/etc.", " (32-bit)", COMPILE_DATE); return;} /* end function version_local() */#endif /* !WINDLL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -