quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

tool_filetime.c (5698B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 #include "tool_filetime.h"
     25 #include "tool_cfgable.h"
     26 #include "tool_msgs.h"
     27 
     28 #ifdef HAVE_UTIME_H
     29 #  include <utime.h>
     30 #elif defined(HAVE_SYS_UTIME_H)
     31 #  include <sys/utime.h>
     32 #endif
     33 
     34 /* Returns 0 on success, non-zero on file problems */
     35 int getfiletime(const char *filename, struct GlobalConfig *global,
     36                 curl_off_t *stamp)
     37 {
     38   int rc = 1;
     39 
     40 /* Windows stat() may attempt to adjust the Unix GMT file time by a daylight
     41    saving time offset and since it is GMT that is bad behavior. When we have
     42    access to a 64-bit type we can bypass stat and get the times directly. */
     43 #if defined(_WIN32) && !defined(CURL_WINDOWS_UWP)
     44   HANDLE hfile;
     45   TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar(filename);
     46 
     47   hfile = CreateFile(tchar_filename, FILE_READ_ATTRIBUTES,
     48                      (FILE_SHARE_READ | FILE_SHARE_WRITE |
     49                       FILE_SHARE_DELETE),
     50                      NULL, OPEN_EXISTING, 0, NULL);
     51   curlx_unicodefree(tchar_filename);
     52   if(hfile != INVALID_HANDLE_VALUE) {
     53     FILETIME ft;
     54     if(GetFileTime(hfile, NULL, NULL, &ft)) {
     55       curl_off_t converted = (curl_off_t)ft.dwLowDateTime
     56         | ((curl_off_t)ft.dwHighDateTime) << 32;
     57 
     58       if(converted < 116444736000000000)
     59         warnf(global, "Failed to get filetime: underflow");
     60       else {
     61         *stamp = (converted - 116444736000000000) / 10000000;
     62         rc = 0;
     63       }
     64     }
     65     else {
     66       warnf(global, "Failed to get filetime: "
     67             "GetFileTime failed: GetLastError %u",
     68             (unsigned int)GetLastError());
     69     }
     70     CloseHandle(hfile);
     71   }
     72   else if(GetLastError() != ERROR_FILE_NOT_FOUND) {
     73     warnf(global, "Failed to get filetime: "
     74           "CreateFile failed: GetLastError %u",
     75           (unsigned int)GetLastError());
     76   }
     77 #else
     78   struct_stat statbuf;
     79   if(-1 != stat(filename, &statbuf)) {
     80     *stamp = (curl_off_t)statbuf.st_mtime;
     81     rc = 0;
     82   }
     83   else
     84     warnf(global, "Failed to get filetime: %s", strerror(errno));
     85 #endif
     86   return rc;
     87 }
     88 
     89 #if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || defined(_WIN32)
     90 void setfiletime(curl_off_t filetime, const char *filename,
     91                  struct GlobalConfig *global)
     92 {
     93   if(filetime >= 0) {
     94 /* Windows utime() may attempt to adjust the Unix GMT file time by a daylight
     95    saving time offset and since it is GMT that is bad behavior. When we have
     96    access to a 64-bit type we can bypass utime and set the times directly. */
     97 #if defined(_WIN32) && !defined(CURL_WINDOWS_UWP)
     98     HANDLE hfile;
     99     TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar(filename);
    100 
    101     /* 910670515199 is the maximum Unix filetime that can be used as a
    102        Windows FILETIME without overflow: 30827-12-31T23:59:59. */
    103     if(filetime > 910670515199) {
    104       warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
    105             " on outfile: overflow", filetime);
    106       curlx_unicodefree(tchar_filename);
    107       return;
    108     }
    109 
    110     hfile = CreateFile(tchar_filename, FILE_WRITE_ATTRIBUTES,
    111                        (FILE_SHARE_READ | FILE_SHARE_WRITE |
    112                         FILE_SHARE_DELETE),
    113                        NULL, OPEN_EXISTING, 0, NULL);
    114     curlx_unicodefree(tchar_filename);
    115     if(hfile != INVALID_HANDLE_VALUE) {
    116       curl_off_t converted = ((curl_off_t)filetime * 10000000) +
    117         116444736000000000;
    118       FILETIME ft;
    119       ft.dwLowDateTime = (DWORD)(converted & 0xFFFFFFFF);
    120       ft.dwHighDateTime = (DWORD)(converted >> 32);
    121       if(!SetFileTime(hfile, NULL, &ft, &ft)) {
    122         warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
    123               " on outfile: SetFileTime failed: GetLastError %u",
    124               filetime, (unsigned int)GetLastError());
    125       }
    126       CloseHandle(hfile);
    127     }
    128     else {
    129       warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
    130             " on outfile: CreateFile failed: GetLastError %u",
    131             filetime, (unsigned int)GetLastError());
    132     }
    133 
    134 #elif defined(HAVE_UTIMES)
    135     struct timeval times[2];
    136     times[0].tv_sec = times[1].tv_sec = (time_t)filetime;
    137     times[0].tv_usec = times[1].tv_usec = 0;
    138     if(utimes(filename, times)) {
    139       warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
    140             " on '%s': %s", filetime, filename, strerror(errno));
    141     }
    142 
    143 #elif defined(HAVE_UTIME)
    144     struct utimbuf times;
    145     times.actime = (time_t)filetime;
    146     times.modtime = (time_t)filetime;
    147     if(utime(filename, &times)) {
    148       warnf(global, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T
    149             " on '%s': %s", filetime, filename, strerror(errno));
    150     }
    151 #endif
    152   }
    153 }
    154 #endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) ||        \
    155           defined(_WIN32) */