set(HAVE_LINUX_TCP_H 0)
endif()
set(HAVE_LOCALE_H 1)
+set(HAVE_LOCALTIME_R 1)
set(HAVE_LONGLONG 1)
if(APPLE)
set(HAVE_MACH_ABSOLUTE_TIME 1)
set(HAVE_IO_H 1)
set(HAVE_LINUX_TCP_H 0)
set(HAVE_LOCALE_H 1)
+set(HAVE_LOCALTIME_R 0)
set(HAVE_MEMRCHR 0)
set(HAVE_MSG_NOSIGNAL 0)
set(HAVE_NETDB_H 0)
check_function_exists("geteuid" HAVE_GETEUID)
check_function_exists("utime" HAVE_UTIME)
check_symbol_exists("gmtime_r" "stdlib.h;time.h" HAVE_GMTIME_R)
+check_symbol_exists("localtime_r" "stdlib.h;time.h" HAVE_LOCALTIME_R)
check_symbol_exists("gethostbyname_r" "netdb.h" HAVE_GETHOSTBYNAME_R)
check_symbol_exists("gethostname" "${CURL_INCLUDES}" HAVE_GETHOSTNAME) # winsock2.h unistd.h proto/bsdsocket.h
CURL_CHECK_FUNC_IOCTL
CURL_CHECK_FUNC_IOCTLSOCKET
CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL
+CURL_CHECK_FUNC_LOCALTIME_R
CURL_CHECK_FUNC_MEMRCHR
CURL_CHECK_FUNC_SIGACTION
CURL_CHECK_FUNC_SIGINTERRUPT
/* Define if you have the GNU gssapi libraries */
#undef HAVE_GSSGNU
+/* Define if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R
+
/* Define if you have the <netdb.h> header file. */
#define HAVE_NETDB_H
#define HAVE_LIBGEN_H 1
#define HAVE_LIBZ 1
#define HAVE_LOCALE_H 1
+#define HAVE_LOCALTIME_R 1
#define HAVE_LONGLONG 1
#define HAVE_NETDB_H 1
#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <locale.h> header file. */
#cmakedefine HAVE_LOCALE_H 1
+/* Define to 1 if you have a working localtime_r function. */
+#cmakedefine HAVE_LOCALTIME_R 1
+
/* Define to 1 if the compiler supports the 'long long' data type. */
#cmakedefine HAVE_LONGLONG 1
#define _CRT_NONSTDC_NO_DEPRECATE /* for close(), fileno(), unlink(), etc. */
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
-#define _CRT_SECURE_NO_WARNINGS /* for getenv(), strcpy(),
- in tests: localtime(), sscanf() */
+#define _CRT_SECURE_NO_WARNINGS /* for getenv(), strcpy(), tests: sscanf() */
#endif
#endif /* _MSC_VER */
])
+dnl CURL_CHECK_FUNC_LOCALTIME_R
+dnl -------------------------------------------------
+dnl Verify if localtime_r is available, prototyped, can
+dnl be compiled and seems to work. If all of these are
+dnl true, and usage has not been previously disallowed
+dnl with shell variable curl_disallow_localtime_r, then
+dnl HAVE_LOCALTIME_R will be defined.
+
+AC_DEFUN([CURL_CHECK_FUNC_LOCALTIME_R], [
+ AC_REQUIRE([CURL_INCLUDES_STDLIB])dnl
+ AC_REQUIRE([CURL_INCLUDES_TIME])dnl
+ #
+ tst_links_localtime_r="unknown"
+ tst_proto_localtime_r="unknown"
+ tst_compi_localtime_r="unknown"
+ tst_works_localtime_r="unknown"
+ tst_allow_localtime_r="unknown"
+ #
+ AC_MSG_CHECKING([if localtime_r can be linked])
+ AC_LINK_IFELSE([
+ AC_LANG_FUNC_LINK_TRY([localtime_r])
+ ],[
+ AC_MSG_RESULT([yes])
+ tst_links_localtime_r="yes"
+ ],[
+ AC_MSG_RESULT([no])
+ tst_links_localtime_r="no"
+ ])
+ #
+ if test "$tst_links_localtime_r" = "yes"; then
+ AC_MSG_CHECKING([if localtime_r is prototyped])
+ AC_EGREP_CPP([localtime_r],[
+ $curl_includes_time
+ ],[
+ AC_MSG_RESULT([yes])
+ tst_proto_localtime_r="yes"
+ ],[
+ AC_MSG_RESULT([no])
+ tst_proto_localtime_r="no"
+ ])
+ fi
+ #
+ if test "$tst_proto_localtime_r" = "yes"; then
+ AC_MSG_CHECKING([if localtime_r is compilable])
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+ $curl_includes_time
+ ]],[[
+ time_t clock = 1170352587;
+ struct tm result;
+ if(localtime_r(&clock, &result) != 0)
+ return 1;
+ (void)result;
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ tst_compi_localtime_r="yes"
+ ],[
+ AC_MSG_RESULT([no])
+ tst_compi_localtime_r="no"
+ ])
+ fi
+ #
+ dnl only do runtime verification when not cross-compiling
+ if test "$cross_compiling" != "yes" &&
+ test "$tst_compi_localtime_r" = "yes"; then
+ AC_MSG_CHECKING([if localtime_r seems to work])
+ CURL_RUN_IFELSE([
+ AC_LANG_PROGRAM([[
+ $curl_includes_stdlib
+ $curl_includes_time
+ ]],[[
+ time_t clock = 1170352587;
+ struct tm *tmp = 0;
+ struct tm result;
+ tmp = localtime_r(&clock, &result);
+ (void)result;
+ if(tmp)
+ return 0;
+ else
+ return 1;
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ tst_works_localtime_r="yes"
+ ],[
+ AC_MSG_RESULT([no])
+ tst_works_localtime_r="no"
+ ])
+ fi
+ #
+ if test "$tst_compi_localtime_r" = "yes" &&
+ test "$tst_works_localtime_r" != "no"; then
+ AC_MSG_CHECKING([if localtime_r usage allowed])
+ if test "x$curl_disallow_localtime_r" != "xyes"; then
+ AC_MSG_RESULT([yes])
+ tst_allow_localtime_r="yes"
+ else
+ AC_MSG_RESULT([no])
+ tst_allow_localtime_r="no"
+ fi
+ fi
+ #
+ AC_MSG_CHECKING([if localtime_r might be used])
+ if test "$tst_links_localtime_r" = "yes" &&
+ test "$tst_proto_localtime_r" = "yes" &&
+ test "$tst_compi_localtime_r" = "yes" &&
+ test "$tst_allow_localtime_r" = "yes" &&
+ test "$tst_works_localtime_r" != "no"; then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE_UNQUOTED(HAVE_LOCALTIME_R, 1,
+ [Define to 1 if you have a working localtime_r function.])
+ curl_cv_func_localtime_r="yes"
+ else
+ AC_MSG_RESULT([no])
+ curl_cv_func_localtime_r="no"
+ fi
+])
+
+
dnl CURL_CHECK_FUNC_INET_NTOP
dnl -------------------------------------------------
dnl Verify if inet_ntop is available, prototyped, can
</ItemDefinitionGroup>
<ItemGroup>
CURL_LIB_CURLX_C_FILES
+CURL_SRC_TOOLX_C_FILES
CURL_SRC_C_FILES
</ItemGroup>
<ItemGroup>
CURL_LIB_CURLX_H_FILES
+CURL_SRC_TOOLX_H_FILES
CURL_SRC_X_H_FILES
CURL_SRC_H_FILES
</ItemGroup>
for /f "delims=" %%c in ('dir /b ..\lib\vtls\*.c') do call :element lib\vtls "%%c" %3
) else if "!var!" == "CURL_LIB_VTLS_H_FILES" (
for /f "delims=" %%h in ('dir /b ..\lib\vtls\*.h') do call :element lib\vtls "%%h" %3
+ ) else if "!var!" == "CURL_SRC_TOOLX_C_FILES" (
+ for /f "delims=" %%c in ('dir /b ..\src\toolx\*.c') do call :element src\toolx "%%c" %3
+ ) else if "!var!" == "CURL_SRC_TOOLX_H_FILES" (
+ for /f "delims=" %%h in ('dir /b ..\src\toolx\*.h') do call :element src\toolx "%%h" %3
) else (
echo.!var!>> %3
)
../lib/curlx/warnless.h \
../lib/curlx/winapi.h
+TOOLX_CFILES = \
+ toolx/tool_time.c
+
+TOOLX_HFILES = \
+ toolx/tool_time.h
+
CURL_CFILES = \
config2setopts.c \
slist_wc.c \
tool_writeout.c \
tool_writeout_json.c \
tool_xattr.c \
- var.c
+ var.c \
+ $(TOOLX_CFILES)
CURL_HFILES = \
config2setopts.h \
tool_writeout.h \
tool_writeout_json.h \
tool_xattr.h \
- var.h
+ var.h \
+ $(TOOLX_HFILES)
CURL_RCFILES = curl.rc
#include "tool_msgs.h"
#include "tool_cb_dbg.h"
#include "tool_util.h"
+#include "toolx/tool_time.h"
static void dump(const char *timebuf, const char *idsbuf, const char *text,
FILE *stream, const unsigned char *ptr, size_t size,
/*
* Return the formatted HH:MM:SS for the tv_sec given.
- * NOT thread safe.
*/
static const char *hms_for_sec(time_t tv_sec)
{
static char hms_buf[12];
if(tv_sec != cached_tv_sec) {
- /* !checksrc! disable BANNEDFUNC 1 */
- struct tm *now = localtime(&tv_sec); /* not thread safe either */
+ struct tm now;
+ CURLcode result = toolx_localtime(tv_sec, &now);
+ if(result)
+ memset(&now, 0, sizeof(now));
curl_msnprintf(hms_buf, sizeof(hms_buf), "%02d:%02d:%02d",
- now->tm_hour, now->tm_min, now->tm_sec);
+ now.tm_hour, now.tm_min, now.tm_sec);
cached_tv_sec = tv_sec;
}
return hms_buf;
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_time.h"
+
+#if defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR <= 3)
+#include <sec_api/time_s.h> /* for _localtime32_s(), _localtime64_s() */
+#ifdef _USE_32BIT_TIME_T
+#define localtime_s _localtime32_s
+#else
+#define localtime_s _localtime64_s
+#endif
+#endif
+
+/*
+ * toolx_localtime() is a localtime() replacement for portability. Do not use
+ * the localtime_s(), localtime_r() or localtime() functions anywhere else but
+ * here.
+ */
+CURLcode toolx_localtime(time_t intime, struct tm *store)
+{
+#ifdef _WIN32
+ if(localtime_s(store, &intime)) /* thread-safe */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#elif defined(HAVE_LOCALTIME_R)
+ const struct tm *tm;
+ tm = localtime_r(&intime, store); /* thread-safe */
+ if(!tm)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#else
+ const struct tm *tm;
+ /* !checksrc! disable BANNEDFUNC 1 */
+ tm = localtime(&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;
+}
--- /dev/null
+#ifndef HEADER_TOOLX_TOOL_TIME_H
+#define HEADER_TOOLX_TOOL_TIME_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+CURLcode toolx_localtime(time_t intime, struct tm *store);
+
+#endif /* HEADER_TOOLX_TOOL_TIME_H */
#
###########################################################################
-# Get BUNDLE, FIRST_C, FIRST_H, UTILS_C, UTILS_H, CURLX_C, TESTS_C variables
+# Get BUNDLE, FIRST_C, FIRST_H, UTILS_C, UTILS_H, CURLX_C, TOOLX_C, TESTS_C variables
curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
add_custom_command(OUTPUT "${BUNDLE}.c"
COMMAND ${PERL_EXECUTABLE} "${PROJECT_SOURCE_DIR}/scripts/mk-unity.pl"
- --include ${UTILS_C} ${CURLX_C} --test ${TESTS_C} > "${BUNDLE}.c"
+ --include ${UTILS_C} ${CURLX_C} ${TOOLX_C} --test ${TESTS_C} > "${BUNDLE}.c"
DEPENDS
"${PROJECT_SOURCE_DIR}/scripts/mk-unity.pl" "${CMAKE_CURRENT_SOURCE_DIR}/Makefile.inc"
- ${FIRST_C} ${UTILS_C} ${CURLX_C} ${TESTS_C}
+ ${FIRST_C} ${UTILS_C} ${CURLX_C} ${TOOLX_C} ${TESTS_C}
VERBATIM)
add_executable(${BUNDLE} EXCLUDE_FROM_ALL "${BUNDLE}.c")
target_include_directories(${BUNDLE} PRIVATE
"${PROJECT_BINARY_DIR}/lib" # for "curl_config.h"
"${PROJECT_SOURCE_DIR}/lib" # for "curl_setup.h", curlx
+ "${PROJECT_SOURCE_DIR}/src" # for toolx
"${CMAKE_CURRENT_SOURCE_DIR}" # for the generated bundle source to find included test sources
)
target_compile_definitions(${BUNDLE} PRIVATE ${CURL_DEBUG_MACROS})
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "borrowed" files
+# $(top_srcdir)/src for toolx header files
# $(srcdir) for the generated bundle source to find included test sources
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_builddir)/lib \
-I$(top_srcdir)/lib \
+ -I$(top_srcdir)/src \
-I$(srcdir)
-# Get BUNDLE, FIRST_C, FIRST_H, UTILS_C, UTILS_H, CURLX_C, TESTS_C variables
+# Get BUNDLE, FIRST_C, FIRST_H, UTILS_C, UTILS_H, CURLX_C, TOOLX_C, TESTS_C variables
include Makefile.inc
EXTRA_DIST = CMakeLists.txt $(FIRST_C) $(FIRST_H) $(UTILS_C) $(UTILS_H) $(TESTS_C) \
# These are part of the libcurl static lib. Add them here when linking shared.
curlx_c_lib = $(CURLX_C)
endif
-$(BUNDLE).c: $(top_srcdir)/scripts/mk-unity.pl Makefile.inc $(FIRST_C) $(UTILS_C) $(curlx_c_lib) $(TESTS_C) lib1521.c
- @PERL@ $(top_srcdir)/scripts/mk-unity.pl --include $(UTILS_C) $(curlx_c_lib) --test $(TESTS_C) lib1521.c > $(BUNDLE).c
+$(BUNDLE).c: $(top_srcdir)/scripts/mk-unity.pl Makefile.inc $(FIRST_C) $(UTILS_C) $(curlx_c_lib) $(TOOLX_C) $(TESTS_C) lib1521.c
+ @PERL@ $(top_srcdir)/scripts/mk-unity.pl --include $(UTILS_C) $(curlx_c_lib) $(TOOLX_C) --test $(TESTS_C) lib1521.c > $(BUNDLE).c
noinst_PROGRAMS = $(BUNDLE)
LDADD = $(top_builddir)/lib/libcurl.la @LIBCURL_PC_LIBS_PRIVATE@
../../lib/curlx/warnless.c \
../../lib/curlx/winapi.c
+TOOLX_C = \
+ ../../src/toolx/tool_time.c
+
# All libtest programs
TESTS_C = \
cli_ftp_upload.c \
***************************************************************************/
#include "testtrace.h"
+#include <toolx/tool_time.h>
+
struct libtest_trace_cfg debug_config;
static time_t epoch_offset; /* for test time tracing */
timestr = &timebuf[0];
if(trace_cfg->tracetime) {
- struct tm *now;
+ CURLcode result;
+ struct tm now;
struct curltime tv;
time_t secs;
tv = curlx_now();
known_offset = 1;
}
secs = epoch_offset + tv.tv_sec;
- /* !checksrc! disable BANNEDFUNC 1 */
- now = localtime(&secs); /* not thread safe but we do not care */
+ result = toolx_localtime(secs, &now);
+ if(result)
+ memset(&now, 0, sizeof(now));
curl_msnprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
- now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
+ now.tm_hour, now.tm_min, now.tm_sec, (long)tv.tv_usec);
}
switch(type) {
#
###########################################################################
-# Get BUNDLE, FIRST_C, FIRST_H, UTILS_C, UTILS_H, CURLX_C, TESTS_C variables
+# Get BUNDLE, FIRST_C, FIRST_H, UTILS_C, UTILS_H, CURLX_C, TOOLX_C, TESTS_C variables
curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
add_custom_command(OUTPUT "${BUNDLE}.c"
COMMAND ${PERL_EXECUTABLE} "${PROJECT_SOURCE_DIR}/scripts/mk-unity.pl"
- --include ${UTILS_C} ${CURLX_C} --test ${TESTS_C} > "${BUNDLE}.c"
+ --include ${UTILS_C} ${CURLX_C} ${TOOLX_C} --test ${TESTS_C} > "${BUNDLE}.c"
DEPENDS
"${PROJECT_SOURCE_DIR}/scripts/mk-unity.pl" "${CMAKE_CURRENT_SOURCE_DIR}/Makefile.inc"
- ${FIRST_C} ${UTILS_C} ${CURLX_C} ${TESTS_C}
+ ${FIRST_C} ${UTILS_C} ${CURLX_C} ${TOOLX_C} ${TESTS_C}
VERBATIM)
add_executable(${BUNDLE} EXCLUDE_FROM_ALL "${BUNDLE}.c")
target_include_directories(${BUNDLE} PRIVATE
"${PROJECT_BINARY_DIR}/lib" # for "curl_config.h"
"${PROJECT_SOURCE_DIR}/lib" # for "curl_setup.h", curlx
+ "${PROJECT_SOURCE_DIR}/src" # for toolx
"${CMAKE_CURRENT_SOURCE_DIR}" # for the generated bundle source to find included test sources
)
set_target_properties(${BUNDLE} PROPERTIES OUTPUT_NAME "${BUNDLE}" PROJECT_LABEL "Test ${BUNDLE}" UNITY_BUILD OFF C_CLANG_TIDY "")
# $(top_srcdir)/include is for libcurl's external include files
# $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
# $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "borrowed" files
+# $(top_srcdir)/src for toolx header files
# $(srcdir) for the generated bundle source to find included test sources
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_builddir)/lib \
-I$(top_srcdir)/lib \
+ -I$(top_srcdir)/src \
-I$(srcdir)
-# Get BUNDLE, FIRST_C, FIRST_H, UTILS_C, UTILS_H, CURLX_C, TESTS_C variables
+# Get BUNDLE, FIRST_C, FIRST_H, UTILS_C, UTILS_H, CURLX_C, TOOLX_C, TESTS_C variables
include Makefile.inc
EXTRA_DIST = CMakeLists.txt .checksrc $(FIRST_C) $(FIRST_H) $(UTILS_C) $(UTILS_H) $(TESTS_C)
# Prevent LIBS from being used for all link targets
LIBS = $(BLANK_AT_MAKETIME)
-$(BUNDLE).c: $(top_srcdir)/scripts/mk-unity.pl Makefile.inc $(FIRST_C) $(UTILS_C) $(CURLX_C) $(TESTS_C)
- @PERL@ $(top_srcdir)/scripts/mk-unity.pl --include $(UTILS_C) $(CURLX_C) --test $(TESTS_C) > $(BUNDLE).c
+$(BUNDLE).c: $(top_srcdir)/scripts/mk-unity.pl Makefile.inc $(FIRST_C) $(UTILS_C) $(CURLX_C) $(TOOLX_C) $(TESTS_C)
+ @PERL@ $(top_srcdir)/scripts/mk-unity.pl --include $(UTILS_C) $(CURLX_C) $(TOOLX_C) --test $(TESTS_C) > $(BUNDLE).c
noinst_PROGRAMS = $(BUNDLE)
LDADD = @CURL_NETWORK_AND_TIME_LIBS@
../../lib/curlx/warnless.c \
../../lib/curlx/winapi.c
+TOOLX_C = \
+ ../../src/toolx/tool_time.c
+
# All test servers
TESTS_C = \
dnsd.c \
***************************************************************************/
#include "first.h"
+#include <toolx/tool_time.h>
+
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
char buffer[2048 + 1];
FILE *logfp;
struct curltime tv;
+ CURLcode result;
time_t sec;
- struct tm *now;
+ struct tm now;
char timebuf[50];
static time_t epoch_offset;
static int known_offset;
known_offset = 1;
}
sec = epoch_offset + tv.tv_sec;
- /* !checksrc! disable BANNEDFUNC 1 */
- now = localtime(&sec); /* not thread safe but we do not care */
+ result = toolx_localtime(sec, &now);
+ if(result)
+ memset(&now, 0, sizeof(now));
snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld",
- (int)now->tm_hour, (int)now->tm_min, (int)now->tm_sec,
- (long)tv.tv_usec);
+ now.tm_hour, now.tm_min, now.tm_sec, (long)tv.tv_usec);
va_start(ap, msg);
#ifdef __clang__