?? win32.c
字號:
#endif /* ?IZ_USE_INT64 */} /* end function FileTime2utime() */#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 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);#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(<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; int 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 * (time_t)days + (time_t)(3600L * hours + (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 SetFileSize() *//**************************/int SetFileSize(FILE *file, ulg 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; /* 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 */ if (SetFilePointer(os_fh, filesize, 0, FILE_BEGIN) == 0xFFFFFFFF) 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() *//****************************//* 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 {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -