From d25b0503795f1fbf557632ce870298f52f2a78c1 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Mon, 5 Feb 2018 21:57:39 +0100 Subject: time-cond: fix reading the file modification time on Windows On Windows, stat() may adjust the unix file time by a daylight saving time offset. Avoid this by calling GetFileTime() instead. Fixes #2164 Closes #2204 --- src/tool_operate.c | 95 ++++-------------------------------------------------- 1 file changed, 6 insertions(+), 89 deletions(-) (limited to 'src/tool_operate.c') diff --git a/src/tool_operate.c b/src/tool_operate.c index 5401955af..f326a0d0c 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -25,12 +25,6 @@ # include #endif -#ifdef HAVE_UTIME_H -# include -#elif defined(HAVE_SYS_UTIME_H) -# include -#endif - #ifdef HAVE_LOCALE_H # include #endif @@ -56,6 +50,7 @@ #include "tool_dirhie.h" #include "tool_doswin.h" #include "tool_easysrc.h" +#include "tool_filetime.h" #include "tool_getparam.h" #include "tool_helpers.h" #include "tool_homedir.h" @@ -174,79 +169,6 @@ static curl_off_t VmsSpecialSize(const char *name, } #endif /* __VMS */ -#if defined(HAVE_UTIME) || \ - (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) -static void setfiletime(long filetime, const char *filename, - FILE *error_stream) -{ - if(filetime >= 0) { -/* Windows utime() may attempt to adjust our unix gmt 'filetime' by a daylight - saving time offset and since it's GMT that is bad behavior. When we have - access to a 64-bit type we can bypass utime and set the times directly. */ -#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8) - HANDLE hfile; - -#if (SIZEOF_LONG >= 8) - /* 910670515199 is the maximum unix filetime that can be used as a - Windows FILETIME without overflow: 30827-12-31T23:59:59. */ - if(filetime > CURL_OFF_T_C(910670515199)) { - fprintf(error_stream, - "Failed to set filetime %ld on outfile: overflow\n", - filetime); - return; - } -#endif /* SIZEOF_LONG >= 8 */ - - hfile = CreateFileA(filename, FILE_WRITE_ATTRIBUTES, - (FILE_SHARE_READ | FILE_SHARE_WRITE | - FILE_SHARE_DELETE), - NULL, OPEN_EXISTING, 0, NULL); - if(hfile != INVALID_HANDLE_VALUE) { - curl_off_t converted = ((curl_off_t)filetime * 10000000) + - CURL_OFF_T_C(116444736000000000); - FILETIME ft; - ft.dwLowDateTime = (DWORD)(converted & 0xFFFFFFFF); - ft.dwHighDateTime = (DWORD)(converted >> 32); - if(!SetFileTime(hfile, NULL, &ft, &ft)) { - fprintf(error_stream, - "Failed to set filetime %ld on outfile: " - "SetFileTime failed: GetLastError %u\n", - filetime, GetLastError()); - } - CloseHandle(hfile); - } - else { - fprintf(error_stream, - "Failed to set filetime %ld on outfile: " - "CreateFile failed: GetLastError %u\n", - filetime, GetLastError()); - } - -#elif defined(HAVE_UTIMES) - struct timeval times[2]; - times[0].tv_sec = times[1].tv_sec = filetime; - times[0].tv_usec = times[1].tv_usec = 0; - if(utimes(filename, times)) { - fprintf(error_stream, - "Failed to set filetime %ld on outfile: errno %d\n", - filetime, errno); - } - -#elif defined(HAVE_UTIME) - struct utimbuf times; - times.actime = (time_t)filetime; - times.modtime = (time_t)filetime; - if(utime(filename, ×)) { - fprintf(error_stream, - "Failed to set filetime %ld on outfile: errno %d\n", - filetime, errno); - } -#endif - } -} -#endif /* defined(HAVE_UTIME) || \ - (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */ - #define BUFFER_SIZE (100*1024) static CURLcode operate_do(struct GlobalConfig *global, @@ -710,7 +632,7 @@ static CURLcode operate_do(struct GlobalConfig *global, * to be considered with one appended if implied CC */ #ifdef __VMS - /* Calculate the real upload site for VMS */ + /* Calculate the real upload size for VMS */ infd = -1; if(stat(uploadfile, &fileinfo) == 0) { fileinfo.st_size = VmsSpecialSize(uploadfile, &fileinfo); @@ -1232,7 +1154,7 @@ static CURLcode operate_do(struct GlobalConfig *global, #endif my_setopt_enum(curl, CURLOPT_TIMECONDITION, (long)config->timecond); - my_setopt(curl, CURLOPT_TIMEVALUE, (long)config->condtime); + my_setopt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime); my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest); customrequest_helper(config, config->httpreq, config->customrequest); my_setopt(curl, CURLOPT_STDERR, global->errors); @@ -1841,18 +1763,13 @@ static CURLcode operate_do(struct GlobalConfig *global, } #endif -#if defined(HAVE_UTIME) || \ - (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) /* File time can only be set _after_ the file has been closed */ if(!result && config->remote_time && outs.s_isreg && outs.filename) { /* Ask libcurl if we got a remote file time */ - long filetime = -1; - curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); - if(filetime >= 0) - setfiletime(filetime, outs.filename, config->global->errors); + curl_off_t filetime = -1; + curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime); + setfiletime(filetime, outs.filename, config->global->errors); } -#endif /* defined(HAVE_UTIME) || \ - (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */ #ifdef USE_METALINK if(!metalink && config->use_metalink && result == CURLE_OK) { -- cgit v1.2.3