1 // 2 // utime.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // The utime and futime families of functions, which set the modification time 7 // for a file. 8 // 9 #include <corecrt_internal_lowio.h> 10 #include <corecrt_internal_time.h> 11 12 13 14 // Sets the modification time for a file, where 'file_name' is the name of the 15 // file. Returns zero on success; returns -1 and sets errno on failure. 16 template <typename TimeType, typename Character, typename TimeBufferType> 17 static int __cdecl common_utime( 18 Character const* const file_name, 19 TimeBufferType* const times 20 ) throw() 21 { 22 typedef __crt_time_traits<TimeType, Character> time_traits; 23 24 _VALIDATE_RETURN(file_name != nullptr, EINVAL, -1) 25 26 // Open the file, since the underlying system call needs a handle. Note 27 // that the _utime definition says you must have write permission for the 28 // file to change its time, so we open the file for write only. Also, we 29 // must force it to open in binary mode so that we don't remove ^Z's from 30 // binary files. 31 int fh; 32 if (time_traits::tsopen_s(&fh, file_name, _O_RDWR | _O_BINARY, _SH_DENYNO, 0) != 0) 33 return -1; 34 35 int const result = time_traits::futime(fh, times); 36 37 errno_t stored_errno = 0; 38 if (result == -1) 39 stored_errno = errno; 40 41 _close(fh); 42 43 if (result == -1) 44 errno = stored_errno; 45 46 return result; 47 } 48 49 extern "C" int __cdecl _utime32(char const* const file_name, __utimbuf32* const times) 50 { 51 return common_utime<__time32_t>(file_name, times); 52 } 53 54 extern "C" int __cdecl _wutime32(wchar_t const* const file_name, __utimbuf32* const times) 55 { 56 return common_utime<__time32_t>(file_name, times); 57 } 58 59 extern "C" int __cdecl _utime64(char const* const file_name, __utimbuf64* const times) 60 { 61 return common_utime<__time64_t>(file_name, times); 62 } 63 64 extern "C" int __cdecl _wutime64(wchar_t const* const file_name, __utimbuf64* const times) 65 { 66 return common_utime<__time64_t>(file_name, times); 67 } 68 69 70 71 // Sets the modification time for an open file, where the 'fh' is the lowio file 72 // handle of the open file. Returns zero on success; returns -1 and sets errno 73 // on failure. 74 template <typename TimeType, typename TimeBufferType> 75 static int __cdecl common_futime(int const fh, TimeBufferType* times) throw() 76 { 77 typedef __crt_time_time_t_traits<TimeType> time_traits; 78 79 _CHECK_FH_RETURN(fh, EBADF, -1); 80 81 _VALIDATE_RETURN(fh >= 0 && static_cast<unsigned>(fh) < static_cast<unsigned>(_nhandle), EBADF, -1); 82 _VALIDATE_RETURN(_osfile(fh) & FOPEN, EBADF, -1); 83 84 TimeBufferType default_times; 85 86 if (times == nullptr) 87 { 88 time_traits::time(&default_times.modtime); 89 default_times.actime = default_times.modtime; 90 times = &default_times; 91 } 92 93 tm tm_value; 94 if (time_traits::localtime_s(&tm_value, ×->modtime) != 0) 95 { 96 errno = EINVAL; 97 return -1; 98 } 99 100 SYSTEMTIME local_time; 101 local_time.wYear = static_cast<WORD>(tm_value.tm_year + 1900); 102 local_time.wMonth = static_cast<WORD>(tm_value.tm_mon + 1); 103 local_time.wDay = static_cast<WORD>(tm_value.tm_mday); 104 local_time.wHour = static_cast<WORD>(tm_value.tm_hour); 105 local_time.wMinute = static_cast<WORD>(tm_value.tm_min); 106 local_time.wSecond = static_cast<WORD>(tm_value.tm_sec); 107 local_time.wMilliseconds = 0; 108 109 SYSTEMTIME system_time; 110 FILETIME last_write_time; 111 if (!TzSpecificLocalTimeToSystemTime(nullptr, &local_time, &system_time) || 112 !SystemTimeToFileTime(&system_time, &last_write_time)) 113 { 114 errno = EINVAL; 115 return -1; 116 } 117 118 if (time_traits::localtime_s(&tm_value, ×->actime) != 0) 119 { 120 errno = EINVAL; 121 return -1; 122 } 123 124 local_time.wYear = static_cast<WORD>(tm_value.tm_year + 1900); 125 local_time.wMonth = static_cast<WORD>(tm_value.tm_mon + 1); 126 local_time.wDay = static_cast<WORD>(tm_value.tm_mday); 127 local_time.wHour = static_cast<WORD>(tm_value.tm_hour); 128 local_time.wMinute = static_cast<WORD>(tm_value.tm_min); 129 local_time.wSecond = static_cast<WORD>(tm_value.tm_sec); 130 local_time.wMilliseconds = 0; 131 132 FILETIME last_access_time; 133 if (!TzSpecificLocalTimeToSystemTime(nullptr, &local_time, &system_time) || 134 !SystemTimeToFileTime(&system_time, &last_access_time)) 135 { 136 errno = EINVAL; 137 return -1; 138 } 139 140 if (!SetFileTime(reinterpret_cast<HANDLE>(_get_osfhandle(fh)), nullptr, &last_access_time, &last_write_time)) 141 { 142 errno = EINVAL; 143 return -1; 144 } 145 146 return 0; 147 } 148 149 extern "C" int __cdecl _futime32(int const fh, __utimbuf32* const times) 150 { 151 return common_futime<__time32_t>(fh, times); 152 } 153 154 extern "C" int __cdecl _futime64(int const fh, __utimbuf64* const times) 155 { 156 return common_futime<__time64_t>(fh, times); 157 } 158