Move `Curl_gmtime()` to curlx and rename to `curlx_gmtime()`. Then call
the internal wrapper also from the curl tool, to avoid using the banned
`gmtime()` directly, and using better, thread-safe alternatives when
available.
Windows `gmtime_s()` requires mingw-w64 v4+ or MSVC. Use local
workaround to also support mingw-w64 v3. `gmtime_s()` also makes
defining `_CRT_SECURE_NO_WARNINGS` unnecessary.
Also:
- lib: drop unused `parsedate.h` includes.
- drop redundant cast from `gmtime_r()` result.
- autotools: reverse condition in the proto detection to avoid
misleading readers. (the condition plays no role in detection.)
- note Windows XP's default `msvcrt.dll` doesn't offer secure CRT APIs.
XP likely needs a newer version of this DLL, or may not run.
Refs:
https://learn.microsoft.com/cpp/c-runtime-library/reference/gmtime-gmtime32-gmtime64
https://learn.microsoft.com/cpp/c-runtime-library/reference/gmtime-s-gmtime32-s-gmtime64-s
https://pubs.opengroup.org/onlinepubs/
9799919799/functions/gmtime.html
https://linux.die.net/man/3/gmtime_r
Ref: #19957 (for `localtime_r()`)
Follow-up to
54d9f060b4b0a8fb5fa006813e4db1ca5c1a07e8
Closes #19955
#include "strdup.h"
#include "curlx/inet_pton.h"
#include "curlx/strparse.h"
+#include "curlx/timeval.h"
#include "connect.h"
#define MAX_ALTSVC_LINE 4095
const char *dst6_post = "";
const char *src6_pre = "";
const char *src6_post = "";
- CURLcode result = Curl_gmtime(as->expires, &stamp);
+ CURLcode result = curlx_gmtime(as->expires, &stamp);
if(result)
return result;
#ifdef USE_IPV6
#define _CRT_NONSTDC_NO_DEPRECATE /* for close(), fileno(), unlink(), etc. */
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
-#define _CRT_SECURE_NO_WARNINGS /* for getenv(), gmtime(), strcpy(),
+#define _CRT_SECURE_NO_WARNINGS /* for getenv(), strcpy(),
in tests: localtime(), sscanf() */
#endif
#endif /* _MSC_VER */
return TIMEDIFF_T_MIN;
return diff * 1000000 + newer.tv_usec - older.tv_usec;
}
+
+#if defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR <= 3)
+#include <sec_api/time_s.h> /* for _gmtime32_s(), _gmtime64_s() */
+#ifdef _USE_32BIT_TIME_T
+#define gmtime_s _gmtime32_s
+#else
+#define gmtime_s _gmtime64_s
+#endif
+#endif
+
+/*
+ * curlx_gmtime() is a gmtime() replacement for portability. Do not use
+ * the gmtime_s(), gmtime_r() or gmtime() functions anywhere else but here.
+ */
+CURLcode curlx_gmtime(time_t intime, struct tm *store)
+{
+#ifdef _WIN32
+ if(gmtime_s(store, &intime)) /* thread-safe */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#elif defined(HAVE_GMTIME_R)
+ const struct tm *tm;
+ tm = gmtime_r(&intime, store); /* thread-safe */
+ if(!tm)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#else
+ const struct tm *tm;
+ /* !checksrc! disable BANNEDFUNC 1 */
+ tm = gmtime(&intime); /* not thread-safe */
+ if(tm)
+ *store = *tm; /* copy the pointed struct to the local copy */
+ else
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#endif
+
+ return CURLE_OK;
+}
*/
timediff_t curlx_timediff_us(struct curltime newer, struct curltime older);
+CURLcode curlx_gmtime(time_t intime, struct tm *store);
+
#endif /* HEADER_CURL_TIMEVAL_H */
#include "url.h"
#include "parsedate.h" /* for the week day and month names */
#include "curlx/fopen.h"
+#include "curlx/timeval.h"
#include "curlx/warnless.h"
#include "curl_range.h"
}
filetime = (time_t)statbuf.st_mtime;
- result = Curl_gmtime(filetime, &buffer);
+ result = curlx_gmtime(filetime, &buffer);
if(result)
return result;
#include "strdup.h"
#include "curlx/strerr.h"
#include "curlx/strparse.h"
+#include "curlx/timeval.h"
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
struct tm buffer;
const struct tm *tm = &buffer;
- result = Curl_gmtime(filetime, &buffer);
+ result = curlx_gmtime(filetime, &buffer);
if(result)
return result;
#include "curl_share.h"
#include "strdup.h"
#include "curlx/strparse.h"
+#include "curlx/timeval.h"
#define MAX_HSTS_LINE 4095
#define MAX_HSTS_HOSTLEN 2048
e.includeSubDomains = sts->includeSubDomains;
if(sts->expires != TIME_T_MAX) {
- result = Curl_gmtime((time_t)sts->expires, &stamp);
+ result = curlx_gmtime((time_t)sts->expires, &stamp);
if(result)
return result;
{
struct tm stamp;
if(sts->expires != TIME_T_MAX) {
- CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp);
+ CURLcode result = curlx_gmtime((time_t)sts->expires, &stamp);
if(result)
return result;
curl_mfprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
#include "bufref.h"
#include "curl_ctype.h"
#include "curlx/strparse.h"
+#include "curlx/timeval.h"
/*
* Forward declarations.
/* no condition was asked for */
return CURLE_OK;
- result = Curl_gmtime(data->set.timevalue, &keeptime);
+ result = curlx_gmtime(data->set.timevalue, &keeptime);
if(result) {
failf(data, "Invalid TIMEVALUE");
return result;
#include "http_aws_sigv4.h"
#include "curl_sha256.h"
#include "transfer.h"
-#include "parsedate.h"
#include "sendf.h"
#include "escape.h"
#include "curlx/strparse.h"
+#include "curlx/timeval.h"
#include <time.h>
#else
clock = time(NULL);
#endif
- result = Curl_gmtime(clock, &tm);
+ result = curlx_gmtime(clock, &tm);
if(result) {
goto fail;
}
int rc = parsedate(p, tp);
return (rc == PARSEDATE_FAIL);
}
-
-/*
- * Curl_gmtime() is a gmtime() replacement for portability. Do not use the
- * gmtime_r() or gmtime() functions anywhere else but here.
- *
- */
-
-CURLcode Curl_gmtime(time_t intime, struct tm *store)
-{
- const struct tm *tm;
-#ifdef HAVE_GMTIME_R
- /* thread-safe version */
- tm = (struct tm *)gmtime_r(&intime, store);
-#else
- /* !checksrc! disable BANNEDFUNC 1 */
- tm = gmtime(&intime);
- if(tm)
- *store = *tm; /* copy the pointed struct to the local copy */
-#endif
-
- if(!tm)
- return CURLE_BAD_FUNCTION_ARGUMENT;
- return CURLE_OK;
-}
extern const char * const Curl_wkday[7];
extern const char * const Curl_month[12];
-CURLcode Curl_gmtime(time_t intime, struct tm *store);
-
/* Curl_getdate_capped() differs from curl_getdate() in that this returns
TIME_T_MAX in case the parsed time value was too big, instead of an
error. */
#include "../select.h"
#include "../strdup.h"
#include "../curlx/fopen.h"
+#include "../curlx/timeval.h"
#include "../curlx/warnless.h"
#include "x509asn1.h"
#include "../multiif.h"
struct tm buffer;
const struct tm *tm = &buffer;
char str[96];
- CURLcode result = Curl_gmtime(stamp, &buffer);
+ CURLcode result = curlx_gmtime(stamp, &buffer);
if(result)
return;
#include "vtls_int.h"
#include "vtls_scache.h"
#include "x509asn1.h"
-#include "../parsedate.h"
#include "../connect.h" /* for the connect timeout */
#include "../select.h"
#include "../multiif.h"
#include "vtls_int.h"
#include "vtls_scache.h"
#include "keylog.h"
-#include "../parsedate.h"
#include "../connect.h" /* for the connect timeout */
#include "../progress.h"
#include "../select.h"
]],[[
time_t tm = 1170352587;
struct tm result;
- if(gmtime_r(&tm, &result) != 0)
+ if(gmtime_r(&tm, &result) == 0)
return 1;
(void)result;
]])
ptr += 6;
end = strchr(ptr, '}');
if(end) {
- struct tm *utc;
struct dynbuf format;
char output[256]; /* max output time length */
#ifdef HAVE_GETTIMEOFDAY
result = curlx_dyn_addn(&format, &ptr[i], 1);
}
if(!result) {
- /* !checksrc! disable BANNEDFUNC 1 */
- utc = gmtime(&secs);
- if(curlx_dyn_len(&format) && utc &&
- strftime(output, sizeof(output), curlx_dyn_ptr(&format), utc))
+ struct tm utc;
+ result = curlx_gmtime(secs, &utc);
+ if(curlx_dyn_len(&format) && !result &&
+ strftime(output, sizeof(output), curlx_dyn_ptr(&format), &utc))
fputs(output, stream);
curlx_dyn_free(&format);
}