RTR3DECL(int) RTFileSetTimes(RTFILE hFile, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime) { if (!pAccessTime && !pModificationTime && !pBirthTime) return VINF_SUCCESS; /* NOP */ FILETIME CreationTimeFT; PFILETIME pCreationTimeFT = NULL; if (pBirthTime) pCreationTimeFT = RTTimeSpecGetNtFileTime(pBirthTime, &CreationTimeFT); FILETIME LastAccessTimeFT; PFILETIME pLastAccessTimeFT = NULL; if (pAccessTime) pLastAccessTimeFT = RTTimeSpecGetNtFileTime(pAccessTime, &LastAccessTimeFT); FILETIME LastWriteTimeFT; PFILETIME pLastWriteTimeFT = NULL; if (pModificationTime) pLastWriteTimeFT = RTTimeSpecGetNtFileTime(pModificationTime, &LastWriteTimeFT); int rc = VINF_SUCCESS; if (!SetFileTime((HANDLE)RTFileToNative(hFile), pCreationTimeFT, pLastAccessTimeFT, pLastWriteTimeFT)) { DWORD Err = GetLastError(); rc = RTErrConvertFromWin32(Err); Log(("RTFileSetTimes(%RTfile, %p, %p, %p, %p): SetFileTime failed with lasterr %d (%Rrc)\n", hFile, pAccessTime, pModificationTime, pChangeTime, pBirthTime, Err, rc)); } return rc; }
RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime) { FILETIME FileTime; SYSTEMTIME SysTime; if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTime, &FileTime), &SysTime)) { if (SetSystemTime(&SysTime)) return VINF_SUCCESS; } return RTErrConvertFromWin32(GetLastError()); }
RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec) { /* * FileTimeToLocalFileTime does not do the right thing, so we'll have * to convert to system time and SystemTimeToTzSpecificLocalTime instead. */ RTTIMESPEC LocalTime; SYSTEMTIME SystemTimeIn; FILETIME FileTime; if (FileTimeToSystemTime(RTTimeSpecGetNtFileTime(pTimeSpec, &FileTime), &SystemTimeIn)) { SYSTEMTIME SystemTimeOut; if (SystemTimeToTzSpecificLocalTime(NULL /* use current TZI */, &SystemTimeIn, &SystemTimeOut)) { if (SystemTimeToFileTime(&SystemTimeOut, &FileTime)) { RTTimeSpecSetNtFileTime(&LocalTime, &FileTime); pTime = RTTimeExplode(pTime, &LocalTime); if (pTime) pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL; return pTime; } } } /* * The fallback is to use the current offset. * (A better fallback would be to use the offset of the same time of the year.) */ LocalTime = *pTimeSpec; RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNano()); pTime = RTTimeExplode(pTime, &LocalTime); if (pTime) pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL; return pTime; }
RTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags) { /* * Validate input. */ AssertPtrReturn(pszPath, VERR_INVALID_POINTER); AssertReturn(*pszPath, VERR_INVALID_PARAMETER); AssertPtrNullReturn(pAccessTime, VERR_INVALID_POINTER); AssertPtrNullReturn(pModificationTime, VERR_INVALID_POINTER); AssertPtrNullReturn(pChangeTime, VERR_INVALID_POINTER); AssertPtrNullReturn(pBirthTime, VERR_INVALID_POINTER); AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); /* * Convert the path. */ PRTUTF16 pwszPath; int rc = RTStrToUtf16(pszPath, &pwszPath); if (RT_SUCCESS(rc)) { HANDLE hFile; if (fFlags & RTPATH_F_FOLLOW_LINK) hFile = CreateFileW(pwszPath, FILE_WRITE_ATTRIBUTES, /* dwDesiredAccess */ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, /* dwShareMode */ NULL, /* security attribs */ OPEN_EXISTING, /* dwCreationDisposition */ FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, NULL); else { /** @todo Symlink: Test RTPathSetTimesEx on Windows. (The code is disabled * because it's not tested yet.) */ #if 0 //def FILE_FLAG_OPEN_REPARSE_POINT hFile = CreateFileW(pwszPath, FILE_WRITE_ATTRIBUTES, /* dwDesiredAccess */ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, /* dwShareMode */ NULL, /* security attribs */ OPEN_EXISTING, /* dwCreationDisposition */ FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER) #endif hFile = CreateFileW(pwszPath, FILE_WRITE_ATTRIBUTES, /* dwDesiredAccess */ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, /* dwShareMode */ NULL, /* security attribs */ OPEN_EXISTING, /* dwCreationDisposition */ FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, NULL); } if (hFile != INVALID_HANDLE_VALUE) { /* * Check if it's a no-op. */ if (!pAccessTime && !pModificationTime && !pBirthTime) rc = VINF_SUCCESS; /* NOP */ else { /* * Convert the input and call the API. */ FILETIME CreationTimeFT; PFILETIME pCreationTimeFT = NULL; if (pBirthTime) pCreationTimeFT = RTTimeSpecGetNtFileTime(pBirthTime, &CreationTimeFT); FILETIME LastAccessTimeFT; PFILETIME pLastAccessTimeFT = NULL; if (pAccessTime) pLastAccessTimeFT = RTTimeSpecGetNtFileTime(pAccessTime, &LastAccessTimeFT); FILETIME LastWriteTimeFT; PFILETIME pLastWriteTimeFT = NULL; if (pModificationTime) pLastWriteTimeFT = RTTimeSpecGetNtFileTime(pModificationTime, &LastWriteTimeFT); if (SetFileTime(hFile, pCreationTimeFT, pLastAccessTimeFT, pLastWriteTimeFT)) rc = VINF_SUCCESS; else { DWORD Err = GetLastError(); rc = RTErrConvertFromWin32(Err); Log(("RTPathSetTimes('%s', %p, %p, %p, %p): SetFileTime failed with lasterr %d (%Rrc)\n", pszPath, pAccessTime, pModificationTime, pChangeTime, pBirthTime, Err, rc)); } } BOOL fRc = CloseHandle(hFile); Assert(fRc); NOREF(fRc); } else { DWORD Err = GetLastError(); rc = RTErrConvertFromWin32(Err); Log(("RTPathSetTimes('%s',,,,): failed with %Rrc and lasterr=%u\n", pszPath, rc, Err)); } RTUtf16Free(pwszPath); } LogFlow(("RTPathSetTimes(%p:{%s}, %p:{%RDtimespec}, %p:{%RDtimespec}, %p:{%RDtimespec}, %p:{%RDtimespec}): return %Rrc\n", pszPath, pszPath, pAccessTime, pAccessTime, pModificationTime, pModificationTime, pChangeTime, pChangeTime, pBirthTime, pBirthTime)); return rc; }