Unverified Commit 446eaa94 authored by Marcel Raad's avatar Marcel Raad
Browse files

tool_operate: move filetime code to its own function

parent 81284374
Loading
Loading
Loading
Loading
+60 −49
Original line number Original line Diff line number Diff line
@@ -184,6 +184,64 @@ static curl_off_t VmsSpecialSize(const char *name,
}
}
#endif /* __VMS */
#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, &times)) {
      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,
static CURLcode operate_do(struct GlobalConfig *global,
                           struct OperationConfig *config)
                           struct OperationConfig *config)
{
{
@@ -1761,55 +1819,8 @@ static CURLcode operate_do(struct GlobalConfig *global,
          /* Ask libcurl if we got a remote file time */
          /* Ask libcurl if we got a remote file time */
          long filetime = -1;
          long filetime = -1;
          curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
          curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
          if(filetime >= 0) {
          if(filetime >= 0)
/* Windows utime() may attempt to adjust our unix gmt 'filetime' by a daylight
            setfiletime(filetime, outs.filename, config->global->errors);
   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, &times)) {
              fprintf(config->global->errors,
                      "Failed to set filetime %ld on outfile: errno %d\n",
                      filetime, errno);
            }
#endif
          }
        }
        }
#endif /* defined(HAVE_UTIME) || \
#endif /* defined(HAVE_UTIME) || \
          (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */
          (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */