📄 win32.c
字号:
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);} /* end function VFatFileTime2utime() */#endif /* NT_TZBUG_WORKAROUND && W32_STAT_BANDAID */#if defined(NT_TZBUG_WORKAROUND) && !defined(NO_W32TIMES_IZFIX)local void utime2NtfsFileTime(time_t ut, FILETIME *pft){#ifndef NO_INT64 ULLNG64 NTtime; /* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX" * cannot overflow in 64-bit signed calculation, regardless whether "ut" * is signed or unsigned. */ NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) + ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); pft->dwLowDateTime = (DWORD)NTtime; pft->dwHighDateTime = (DWORD)(NTtime >> 32);#else /* NO_INT64 (64-bit integer arithmetics may not be supported) */ unsigned int b1, b2, carry = 0; unsigned long r0, r1, r2, r3; long r4; /* signed, to catch environments with signed time_t */ b1 = ut & 0xFFFF; b2 = (ut >> 16) & 0xFFFF; /* if ut is over 32 bits, too bad */ r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF); r2 = b1 * (NT_QUANTA_PER_UNIX >> 16); r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF); r4 = b2 * (NT_QUANTA_PER_UNIX >> 16); r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL; if (r0 < r1) carry++; r1 = r0; r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL; if (r0 < r1) carry++; pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO; if (pft->dwLowDateTime < r0) carry++; pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16) + UNIX_TIME_ZERO_HI + carry;#endif /* ?NO_INT64 */} /* end function utime2NtfsFileTime() */#endif /* NT_TZBUG_WORKAROUND && !NO_W32TIMES_IZFIX */#if 0 /* Currently, this is not used at all */long GetTheFileTime(const char *name, iztimes *z_ut){ HANDLE h; FILETIME Modft, Accft, Creft, lft; WORD dh, dl;#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(name) + 1); OemToAnsi(name, ansi_name); name = ansi_name;#endif h = CreateFile(name, 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);#ifdef USE_EF_UT_TIME if (ftOK && (z_ut != NULL)) { NtfsFileTime2utime(&Modft, &(z_ut->mtime)); if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) NtfsFileTime2utime(&Accft, &(z_ut->atime)); else z_ut->atime = z_ut->mtime; if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) NtfsFileTime2utime(&Creft, &(z_ut->ctime)); else z_ut->ctime = z_ut->mtime; }#endif FileTimeToLocalFileTime(&ft, &lft); FileTimeToDosDateTime(&lft, &dh, &dl); return(dh<<16) | dl; } else return 0L;}#endif /* never */void ChangeNameForFAT(char *name){ char *src, *dst, *next, *ptr, *dot, *start; static char invalid[] = ":;,=+\"[]<>| \t"; if ( isalpha((uch)name[0]) && (name[1] == ':') ) start = name + 2; else start = name; src = dst = start; if ( (*src == '/') || (*src == '\\') ) src++, dst++; while ( *src ) { for ( next = src; *next && (*next != '/') && (*next != '\\'); next++ ); for ( ptr = src, dot = NULL; ptr < next; ptr++ ) if ( *ptr == '.' ) { dot = ptr; /* remember last dot */ *ptr = '_'; } if ( dot == NULL ) for ( ptr = src; ptr < next; ptr++ ) if ( *ptr == '_' ) dot = ptr; /* remember last _ as if it were a dot */ if ( dot && (dot > src) && ((next - dot <= 4) || ((next - src > 8) && (dot - src > 3))) ) { if ( dot ) *dot = '.'; for ( ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++ ) *dst++ = *ptr; for ( ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++ ) *dst++ = *ptr; } else { if ( dot && (next - src == 1) ) *dot = '.'; /* special case: "." as a path component */ for ( ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++ ) *dst++ = *ptr; } *dst++ = *next; /* either '/' or 0 */ if ( *next ) { src = next + 1; if ( *src == 0 ) /* handle trailing '/' on dirs ! */ *dst = 0; } else break; } for ( src = start; *src != 0; ++src ) if ( (strchr(invalid, *src) != NULL) || (*src == ' ') ) *src = '_';}char *GetLongPathEA(const char *name){ return(NULL); /* volunteers ? */}int IsFileNameValid(x)const char *x;{ WIN32_FIND_DATA fd; HANDLE h;#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(x) + 1); OemToAnsi(x, ansi_name); x = (const char *)ansi_name;#endif if ((h = FindFirstFile(x, &fd)) == INVALID_HANDLE_VALUE) return FALSE; FindClose(h); return TRUE;}char *getVolumeLabel(drive, vtime, vmode, vutim) int drive; /* drive name: 'A' .. 'Z' or '\0' for current drive */ ulg *vtime; /* volume label creation time (DOS format) */ ulg *vmode; /* volume label file mode */ time_t *vutim;/* volume label creationtime (UNIX format) *//* If a volume label exists for the given drive, return its name and pretend to set its time and mode. The returned name is static data. */{ char rootpath[4]; static char vol[14]; DWORD fnlen, flags; *vmode = A_ARCHIVE | A_LABEL; /* this is what msdos returns */ *vtime = dostime(1980, 1, 1, 0, 0, 0); /* no true date info available */ *vutim = dos2unixtime(*vtime); strcpy(rootpath, "x:\\"); rootpath[0] = (char)drive; if (GetVolumeInformation(drive ? rootpath : NULL, vol, 13, NULL, &fnlen, &flags, NULL, 0))#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ return (AnsiToOem(vol, vol), vol);#else return vol;#endif else return NULL;}void stamp(f, d)char *f; /* name of file to change */ulg d; /* dos-style time to change it to *//* Set last updated and accessed time of file f to the DOS time d. */{#ifdef NT_TZBUG_WORKAROUND FILETIME Modft; /* File time type of Win32 API, `last modified' time */ HANDLE hFile; /* File handle defined in Win32 API */# ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(f) + 1); OemToAnsi(f, ansi_name);# define Ansi_Fname ansi_name# else# define Ansi_Fname f# endif /* open a handle to the file to prepare setting the mod-time stamp */ hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if ( hFile != INVALID_HANDLE_VALUE ) { /* convert time_t modtime into WIN32 native 64bit format */# ifndef NO_W32TIMES_IZFIX if (!FSusesLocalTime(f)) { time_t ux_modtime = dos2unixtime(d); utime2NtfsFileTime(ux_modtime, &Modft); } else# endif /* !NO_W32TIMES_IZFIX */ { FILETIME lft; DosDateTimeToFileTime((WORD)(d >> 16), (WORD)(d & 0xFFFFL), &lft); LocalFileTimeToFileTime(&lft, &Modft); } /* set Access and Modification times of the file to modtime */ SetFileTime(hFile, NULL, &Modft, &Modft); CloseHandle(hFile); }#else /* !NT_TZBUG_WORKAROUND */ struct utimbuf u; /* argument for utime() */ /* Convert DOS time to time_t format in u.actime and u.modtime */ u.actime = u.modtime = dos2unixtime(d); /* Set updated and accessed times of f */ utime(f, &u);#endif /* ?NT_TZBUG_WORKAROUND */}#endif /* !UTIL */int ZipIsWinNT(void) /* returns TRUE if real NT, FALSE if Win95 or Win32s */{ static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */ if (g_PlatformId == 0xFFFFFFFF) { /* note: GetVersionEx() doesn't exist on WinNT 3.1 */ if (GetVersion() < 0x80000000) g_PlatformId = TRUE; else g_PlatformId = FALSE; } return (int)g_PlatformId;}#ifndef UTIL#ifdef __WATCOMC__# include <io.h># define _get_osfhandle _os_handle/* gaah -- Watcom's docs claim that _get_osfhandle exists, but it doesn't. */#endif#ifdef HAVE_FSEEKABLE/* * return TRUE if file is seekable */int fseekable(fp)FILE *fp;{ return GetFileType((HANDLE)_get_osfhandle(fileno(fp))) == FILE_TYPE_DISK;}#endif /* HAVE_FSEEKABLE */#endif /* !UTIL */#if 0 /* seems to be never used; try it out... */char *StringLower(char *szArg){ char *szPtr;/* unsigned char *szPtr; */ for ( szPtr = szArg; *szPtr; szPtr++ ) *szPtr = lower[*szPtr]; return szArg;}#endif /* never */#ifdef W32_STAT_BANDAID/* All currently known variants of WIN32 operating systems (Windows 95/98, * WinNT 3.x, 4.0, 5.x) have a nasty bug in the OS kernel concerning * conversions between UTC and local time: In the time conversion functions * of the Win32 API, the timezone offset (including seasonal daylight saving * shift) between UTC and local time evaluation is erratically based on the * current system time. The correct evaluation must determine the offset * value as it {was/is/will be} for the actual time to be converted. * * Newer versions of MS C runtime lib's stat() returns utc time-stamps so * that localtime(timestamp) corresponds to the (potentially false) local * time shown by the OS' system programs (Explorer, command shell dir, etc.) * The RSXNT port follows the same strategy, but fails to recognize the * access-time attribute. * * For the NTFS file system (and other filesystems that store time-stamps * as UTC values), this results in st_mtime (, st_{c|a}time) fields which * are not stable but vary according to the seasonal change of "daylight * saving time in effect / not in effect". * * Other C runtime libs (CygWin, or the crtdll.dll supplied with Win9x/NT * return the unix-time equivalent of the UTC FILETIME values as got back * from the Win32 API call. This time, return values from NTFS are correct * whereas utimes from files on (V)FAT volumes vary according to the DST * switches. * * To achieve timestamp consistency of UTC (UT extra field) values in * Zip archives, the Info-ZIP programs require work-around code for * proper time handling in stat() (and other time handling routines). * * However, nowadays most other programs on Windows systems use the * time conversion strategy of Microsofts C runtime lib "msvcrt.dll". * To improve interoperability in environments where a "consistent" (but * false) "UTC<-->LocalTime" conversion is preferred over "stable" time
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -