⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32.c

📁 给出了 zip 压缩算法的完整实现过程。
💻 C
📖 第 1 页 / 共 3 页
字号:
 * 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 + -