From 446eaa941d29dd728a81847b5ca2424b0f254cf5 Mon Sep 17 00:00:00 2001 From: Marcel Raad Date: Sat, 1 Apr 2017 11:22:53 +0200 Subject: tool_operate: move filetime code to its own function Ref: https://github.com/curl/curl/pull/1378 --- src/tool_operate.c | 109 +++++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/src/tool_operate.c b/src/tool_operate.c index 572c8d0cc..bb698ffec 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -184,6 +184,64 @@ static curl_off_t VmsSpecialSize(const char *name, } #endif /* __VMS */ +#if defined(HAVE_UTIME) || \ + (defined(WIN32) && (CURL_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) && (CURL_SIZEOF_CURL_OFF_T >= 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)) { + HANDLE 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()); + } + } + else { + fprintf(error_stream, + "Failed to set filetime %ld on outfile: overflow\n", + filetime); + } +#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) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */ + static CURLcode operate_do(struct GlobalConfig *global, struct OperationConfig *config) { @@ -1761,55 +1819,8 @@ static CURLcode operate_do(struct GlobalConfig *global, /* Ask libcurl if we got a remote file time */ long filetime = -1; curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); - 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) && (CURL_SIZEOF_CURL_OFF_T >= 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)) { - HANDLE hfile = CreateFileA(outs.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(config->global->errors, - "Failed to set filetime %ld on outfile: " - "SetFileTime failed: GetLastError %u\n", - filetime, GetLastError()); - } - CloseHandle(hfile); - } - else { - fprintf(config->global->errors, - "Failed to set filetime %ld on outfile: " - "CreateFile failed: GetLastError %u\n", - filetime, GetLastError()); - } - } - else { - fprintf(config->global->errors, - "Failed to set filetime %ld on outfile: overflow\n", - filetime); - } -#elif defined(HAVE_UTIME) - struct utimbuf times; - times.actime = (time_t)filetime; - times.modtime = (time_t)filetime; - if(utime(outs.filename, ×)) { - fprintf(config->global->errors, - "Failed to set filetime %ld on outfile: errno %d\n", - filetime, errno); - } -#endif - } + if(filetime >= 0) + setfiletime(filetime, outs.filename, config->global->errors); } #endif /* defined(HAVE_UTIME) || \ (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */ -- cgit v1.2.1