📄 win32.c
字号:
static int VFatFileTime2utime(const FILETIME *pft, time_t *ut){ FILETIME lft;#ifndef HAVE_MKTIME WORD wDOSDate, wDOSTime;#else SYSTEMTIME w32tm; struct tm ltm;#endif FileTimeToLocalFileTime(pft, &lft); 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. */ FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime); 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); /* 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; 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 UTCtime2Localtime() */ /* borrowed from Zip's mkgmtime() *//********************************/static time_t UTCtime2Localtime(time_t utctime){ time_t utc = utctime; struct tm *tm; unsigned years, months, days, hours, minutes, seconds;#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 tm = localtime(&utc); if (tm == (struct tm *)NULL) /* localtime() did not accept given utc time value; as an emergency exit, the unconverted utctime value is returned */ return utctime; years = tm->tm_year + 1900; /* year - 1900 -> year */ months = tm->tm_mon; /* 0..11 */ days = tm->tm_mday - 1; /* 1..31 -> 0..30 */ hours = tm->tm_hour; /* 0..23 */ minutes = tm->tm_min; /* 0..59 */ seconds = tm->tm_sec; /* 0..61 in ANSI C */ /* set `days' to the number of days into the year */ days += ydays[months] + (months > 1 && leap(years)); /* now set `days' to the number of days since 1 Jan 1970 */ days += 365 * (years - 1970) + nleap(years); return (time_t)(86400L * (ulg)days + 3600L * (ulg)hours + (ulg)(60 * minutes + seconds));} /* end function UTCtime2Localtime() *//********************************//* Function NTtzbugWorkaround() *//********************************/static void NTtzbugWorkaround(time_t ut, FILETIME *pft){ FILETIME C_RTL_locft, NTAPI_locft; time_t ux_loctime = UTCtime2Localtime(ut); /* This routine is only used when the target file system stores time- * stamps as local time in MSDOS format. Thus we make sure that the * resulting timestamp is within the range of MSDOS date-time values. */ if (ux_loctime < UTIME_1980_JAN_01_00_00) ux_loctime = UTIME_1980_JAN_01_00_00; utime2FileTime(ux_loctime, &C_RTL_locft); if (!FileTimeToLocalFileTime(pft, &NTAPI_locft)) return; else { long time_shift_l, time_shift_h; int carry = 0; time_shift_l = C_RTL_locft.dwLowDateTime - NTAPI_locft.dwLowDateTime; if (C_RTL_locft.dwLowDateTime < NTAPI_locft.dwLowDateTime) carry--; time_shift_h = C_RTL_locft.dwHighDateTime - NTAPI_locft.dwHighDateTime; pft->dwLowDateTime += time_shift_l; if (pft->dwLowDateTime < (ulg)time_shift_l) carry++; pft->dwHighDateTime += time_shift_h + carry; TTrace((stdout, "FileTime shift: %08lx:%08lx\n", time_shift_h+carry,time_shift_l)); }} /* end function NTtzbugWorkaround() */#endif /* ?NT_TZBUG_WORKAROUND *//****************************/ /* 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 NT_TZBUG_WORKAROUND time_t ux_modtime;#else /* !NT_TZBUG_WORKAROUND */ FILETIME locft; /* 64-bit value made up of two 32-bit [low & high] */ WORD wDOSDate; /* for converting from DOS date to Windows NT */ WORD wDOSTime;#endif /* ?NT_TZBUG_WORKAROUND */#ifdef USE_EF_UT_TIME unsigned eb_izux_flg; iztimes z_utime; /* struct for Unix-style actime & modtime, + creatime */#endif#if (defined(USE_EF_UT_TIME) && !defined(NT_TZBUG_WORKAROUND)) time_t utime_dosmin;# endif#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND)) int fs_uses_loctime = FStampIsLocTime(__G__ G.filename);#endif /* 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_BOUNDCHECK_1(z_utime.mtime) utime2FileTime(z_utime.mtime, pModFT); NT_TZBUG_PRECOMPENSATE(z_utime.mtime, pModFT) if (eb_izux_flg & EB_UT_FL_ATIME) { UTIME_BOUNDCHECK_N(z_utime.atime) utime2FileTime(z_utime.atime, pAccFT); NT_TZBUG_PRECOMPENSATE(z_utime.atime, pAccFT) } if (eb_izux_flg & EB_UT_FL_CTIME) { UTIME_BOUNDCHECK_N(z_utime.ctime) utime2FileTime(z_utime.ctime, pCreFT); NT_TZBUG_PRECOMPENSATE(z_utime.ctime, pCreFT) } return (int)eb_izux_flg; }#endif /* USE_EF_UT_TIME */#ifdef NT_TZBUG_WORKAROUND ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); utime2FileTime(ux_modtime, pModFT); NT_TZBUG_PRECOMPENSATE(ux_modtime, pModFT)#else /* !NT_TZBUG_WORKAROUND */ wDOSTime = (WORD)(G.lrec.last_mod_dos_datetime); wDOSDate = (WORD)(G.lrec.last_mod_dos_datetime >> 16); /* The DosDateTimeToFileTime() function converts a DOS date/time * into a 64-bit Windows NT file time */ if (!DosDateTimeToFileTime(wDOSDate, wDOSTime, &locft)) { Info(slide, 0, ((char *)slide, "DosDateTime failed: %d\n", (int)GetLastError())); return 0; } if (!LocalFileTimeToFileTime(&locft, pModFT)) { Info(slide, 0, ((char *)slide, "LocalFileTime failed: %d\n", (int)GetLastError())); *pModFT = locft; }#endif /* ?NT_TZBUG_WORKAROUND */ *pAccFT = *pModFT; return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);} /* end function getNTfiletime() *//****************************//* Function close_outfile() *//****************************/void close_outfile(__G) __GDEF{ FILETIME Modft; /* File time type defined in NT, `last modified' time */ FILETIME Accft; /* NT file time type, `last access' time */ FILETIME Creft; /* NT file time type, `file creation' time */ HANDLE hFile; /* File handle defined in NT */ int gotTime;#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name);# define Ansi_Fname ansi_name#else# define Ansi_Fname G.filename#endif /* Close the file and then re-open it using the Win32 * CreateFile call, so that the file can be created * with GENERIC_WRITE access, otherwise the SetFileTime * call will fail. */ fclose(G.outfile); /* don't set the time stamp and attributes on standard output */ if (uO.cflag) return; gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft); /* open a handle to the file before processing extra fields; we do this in case new security on file prevents us from updating time stamps */ hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /* sfield@microsoft.com: set attributes before time in case we decide to support other filetime members later. This also allows us to apply attributes before the security is changed, which may prevent this from succeeding otherwise. Also, since most files don't have any interesting attributes, only change them if something other than FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the file anyway, when it's created new. */ if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) { if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F)) Info(slide, 1, ((char *)slide, "\nwarning (%d): could not set file attributes\n", (int)GetLastError())); }#ifdef NTSD_EAS /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */ if (G.extra_field) { /* zipfile extra field may have extended attribs */ int err = EvalExtraFields(__G__ G.filename, G.extra_field, G.lrec.extra_field_length); if (err == IZ_EF_TRUNC) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), makeword(G.extra_field+2)-10, uO.qflag? "\n":"")); } }#endif /* NTSD_EAS */ if ( hFile == INVALID_HANDLE_VALUE ) Info(slide, 1, ((char *)slide, "\nCreateFile error %d when trying set file time\n", (int)GetLastError())); else { if (gotTime) { FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL; FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL; FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL; if (!SetFileTime(hFile, pCreft, pAccft, pModft)) Info(slide, 0, ((char *)slide, "\nSetFileTime failed: %d\n", (int)GetLastError())); } CloseHandle(hFile); } return;#undef Ansi_Fname} /* end function close_outfile() */#ifdef TIMESTAMP/*************************//* Function stamp_file() *//*************************/int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime){ FILETIME Modft; /* File time type defined in NT, `last modified' time */ HANDLE hFile; /* File handle defined in NT */ int errstat = 0; /* return status: 0 == "OK", -1 == "Failure" */#ifndef NT_TZBUG_WORKAROUND time_t utime_dosmin; /* internal variable for UTIME_BOUNDCHECK_1 */#endif int fs_uses_loctime = FStampIsLocTime(__G__ fname);#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(fname) + 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -