summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillem Jover <guillem@hadrons.org>2024-02-09 04:32:12 +0100
committerGuillem Jover <guillem@hadrons.org>2024-02-27 05:47:50 +0100
commit32d18dcf47a8ac9f0e21b787bc154f8ca72dbdd8 (patch)
treef24f71d47d25fd298f88cd57bdb78021951d9b0b
parent605614d6423083863c7c71bf53786bfec77bbf6a (diff)
Add explicit time32 and time64 support
Handle the three potential system scenarios: - system time_t is time64 - system time_t is time32 and supports time64 - system time_t is time32 and does not support time64 Add the explicit time32 and time64 functions when necessary and map them accordingly for each of these cases.
-rw-r--r--configure.ac1
-rw-r--r--include/Makefile.am11
-rw-r--r--include/bsd/sys/cdefs.h4
-rw-r--r--include/bsd/timeconv.h13
-rw-r--r--m4/libbsd-large.m451
-rw-r--r--src/libbsd.map.in11
-rw-r--r--src/timeconv.c208
-rw-r--r--test/.gitignore2
-rw-r--r--test/Makefile.am8
-rw-r--r--test/timeconv32.c43
-rw-r--r--test/timeconv64.c40
11 files changed, 371 insertions, 21 deletions
diff --git a/configure.ac b/configure.ac
index bedc615..e516f93 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,6 +29,7 @@ user_CFLAGS=${CFLAGS-unset}
# Checks for operating system services and capabilities.
AC_USE_SYSTEM_EXTENSIONS
AC_SYS_LARGEFILE
+LIBBSD_SYS_TIME64
AM_PROG_AR
LT_INIT
diff --git a/include/Makefile.am b/include/Makefile.am
index 9a75b97..52b78be 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -75,3 +75,14 @@ nobase_include_HEADERS += \
bsd/vis.h \
# EOL
endif
+
+do_header_subst = $(AM_V_GEN) $(SED) \
+ -e 's:^//\(.define LIBBSD_SYS_TIME_BITS\).*:\1 $(LIBBSD_SYS_TIME_BITS):' \
+ -e 's:^//\(.define LIBBSD_SYS_HAS_TIME64\).*:\1 $(LIBBSD_SYS_HAS_TIME64):' \
+ # EOL
+
+install-data-hook:
+ $(do_header_subst) <$(DESTDIR)$(includedir)/bsd/sys/cdefs.h \
+ >$(DESTDIR)$(includedir)/bsd/sys/cdefs.h.new
+ mv $(DESTDIR)$(includedir)/bsd/sys/cdefs.h.new \
+ $(DESTDIR)$(includedir)/bsd/sys/cdefs.h
diff --git a/include/bsd/sys/cdefs.h b/include/bsd/sys/cdefs.h
index 126f427..d2627c4 100644
--- a/include/bsd/sys/cdefs.h
+++ b/include/bsd/sys/cdefs.h
@@ -86,6 +86,10 @@
#define _SYS_CDEFS_H
#endif
+/* Define the ABI for the current system. */
+//#define LIBBSD_SYS_TIME_BITS 0
+//#define LIBBSD_SYS_HAS_TIME64 0
+
#define LIBBSD_CONCAT(x, y) x ## y
#define LIBBSD_STRING(x) #x
diff --git a/include/bsd/timeconv.h b/include/bsd/timeconv.h
index a426bd3..755c89c 100644
--- a/include/bsd/timeconv.h
+++ b/include/bsd/timeconv.h
@@ -58,4 +58,17 @@ time_t _long_to_time(long tlong);
int _time_to_int(time_t t);
time_t _int_to_time(int tint);
+#if LIBBSD_SYS_TIME_BITS == 32 && LIBBSD_SYS_HAS_TIME64
+#if defined _TIME_BITS && _TIME_BITS == 64
+time_t LIBBSD_REDIRECT(_time32_to_time, (int32_t t32), _time32_to_time_time64);
+int32_t LIBBSD_REDIRECT(_time_to_time32, (time_t t), _time_to_time32_time64);
+time_t LIBBSD_REDIRECT(_time64_to_time, (int64_t t64), _time64_to_time_time64);
+int64_t LIBBSD_REDIRECT(_time_to_time64, (time_t t), _time_to_time64_time64);
+long LIBBSD_REDIRECT(_time_to_long, (time_t t), _time_to_long_time64);
+time_t LIBBSD_REDIRECT(_long_to_time, (long tlong), _long_to_time_time64);
+int LIBBSD_REDIRECT(_time_to_int, (time_t t), _time_to_int_time64);
+time_t LIBBSD_REDIRECT(_int_to_time, (int tint), _int_to_time_time64);
+#endif
+#endif
+
#endif /* LIBBSD_TIMECONV_H */
diff --git a/m4/libbsd-large.m4 b/m4/libbsd-large.m4
new file mode 100644
index 0000000..d279111
--- /dev/null
+++ b/m4/libbsd-large.m4
@@ -0,0 +1,51 @@
+# Copyright © 2024 Guillem Jover <guillem@hadrons.org>
+
+# LIBBSD_SYS_TIME64
+# -----------------
+# Check for availability of time64 support.
+AC_DEFUN([LIBBSD_SYS_TIME64], [
+ # Check the default time_t size.
+ AC_CHECK_SIZEOF([time_t], [], [[
+#undef _TIME_BITS
+#include <time.h>
+]])
+ AS_IF([test $ac_cv_sizeof_time_t = 8], [
+ libbsd_sys_time_bits=64
+ ], [
+ libbsd_sys_time_bits=32
+ ])
+ AC_DEFINE_UNQUOTED([LIBBSD_SYS_TIME_BITS], [$libbsd_sys_time_bits],
+ [The number of bits for the default system time_t ABI])
+ AC_SUBST([LIBBSD_SYS_TIME_BITS], [$libbsd_sys_time_bits])
+ AS_UNSET([ac_cv_sizeof_time_t])
+ AM_CONDITIONAL([LIBBSD_SYS_IS_TIME32], [test "$libbsd_sys_time_bits" -eq 32])
+
+ # Check the whether the system supports 64-bit time_t.
+ AC_CHECK_SIZEOF([time_t], [], [[
+#define _FILE_OFFSET_BITS 64
+#define _TIME_BITS 64
+#include <time.h>
+]])
+ AS_IF([test $ac_cv_sizeof_time_t = 8], [
+ libbsd_sys_has_time64=1
+ ], [
+ libbsd_sys_has_time64=0
+ ])
+ AC_DEFINE_UNQUOTED([LIBBSD_SYS_HAS_TIME64], [$libbsd_sys_has_time64],
+ [Enable if the system supports 64-bit time_t])
+ AC_SUBST([LIBBSD_SYS_HAS_TIME64], [$libbsd_sys_has_time64])
+ AM_CONDITIONAL([LIBBSD_SYS_HAS_TIME64], [test "$libbsd_sys_has_time64" -eq 1])
+ AS_IF([test "$libbsd_sys_time_bits" = 32 && \
+ test "$libbsd_sys_has_time64" -eq 1], [
+ abi_time64=yes
+ ], [
+ abi_time64=no
+ ])
+ LIBBSD_SELECT_ABI([time64], [explicit time64 time_t support])
+
+ AS_IF([test $ac_cv_sys_file_offset_bits = 64 && \
+ test $libbsd_sys_time_bits = 32 && \
+ test $ac_cv_sizeof_time_t = 8], [
+ AC_DEFINE([_TIME_BITS], [64], [Enable 64-bit time_t support])
+ ])
+])
diff --git a/src/libbsd.map.in b/src/libbsd.map.in
index 9670d4c..d7047dc 100644
--- a/src/libbsd.map.in
+++ b/src/libbsd.map.in
@@ -305,4 +305,15 @@ LIBBSD_0.12.0 {
vasprintf;
asprintf;
#endif
+
+#if LIBBSD_ABI_TIMECONV && LIBBSD_ABI_TIME64
+ _time32_to_time_time64;
+ _time_to_time32_time64;
+ _time64_to_time_time64;
+ _time_to_time64_time64;
+ _time_to_long_time64;
+ _long_to_time_time64;
+ _time_to_int_time64;
+ _int_to_time_time64;
+#endif
} LIBBSD_0.11.0;
diff --git a/src/timeconv.c b/src/timeconv.c
index 11f926e..0c122e4 100644
--- a/src/timeconv.c
+++ b/src/timeconv.c
@@ -32,17 +32,161 @@
#include <sys/cdefs.h>
#include <sys/types.h>
-#include <timeconv.h>
+
+#include "local-link.h"
+
+#if LIBBSD_SYS_TIME_BITS == 64
+/*
+ * - enable time64 functions
+ * - symver libbsd<func>_time64 -> <func> 0.7
+ */
+#define time32_symbol(name)
+#define time64_symbol(name) \
+ libbsd_strong_alias(libbsd ## name ## _time64, name)
+#elif LIBBSD_SYS_TIME_BITS == 32 && LIBBSD_SYS_HAS_TIME64
+/*
+ * - enable time32 functions
+ * - enable time64 functions
+ * - symver libbsd<func>_time32 -> <func> 0.7
+ * - map libbsd<func>_time64 <func>_time64 0.12
+ */
+#define time32_symbol(name) \
+ libbsd_strong_alias(libbsd ## name ## _time32, name)
+#define time64_symbol(name) \
+ libbsd_strong_alias(libbsd ## name ## _time64, name ## _time64)
+#elif LIBBSD_SYS_TIME_BITS == 32 && !LIBBSD_SYS_HAS_TIME64
+/*
+ * - enable time32 functions
+ * - symver libbsd<func>_time32 -> <func>
+ */
+#define time32_symbol(name) \
+ libbsd_strong_alias(libbsd ## name ## _time32, name)
+#define time64_symbol(name)
+#else
+#error "Unknown time_t support"
+#endif
+
+#if LIBBSD_SYS_HAS_TIME64
+typedef int64_t libbsd_time64_t;
/*
* Convert a 32 bit representation of time_t into time_t. XXX needs to
* implement the 50-year rule to handle post-2038 conversions.
*/
-time_t
-_time32_to_time(int32_t t32)
+libbsd_time64_t
+libbsd_time32_to_time_time64(int32_t t32);
+libbsd_time64_t
+libbsd_time32_to_time_time64(int32_t t32)
+{
+ return((libbsd_time64_t)t32);
+}
+time64_symbol(_time32_to_time);
+
+/*
+ * Convert time_t to a 32 bit representation. If time_t is 64 bits we can
+ * simply chop it down. The resulting 32 bit representation can be
+ * converted back to a temporally local 64 bit time_t using time32_to_time.
+ */
+int32_t
+libbsd_time_to_time32_time64(libbsd_time64_t t);
+int32_t
+libbsd_time_to_time32_time64(libbsd_time64_t t)
+{
+ return((int32_t)t);
+}
+time64_symbol(_time_to_time32);
+
+/*
+ * Convert a 64 bit representation of time_t into time_t. If time_t is
+ * represented as 32 bits we can simply chop it and not support times
+ * past 2038.
+ */
+libbsd_time64_t
+libbsd_time64_to_time_time64(int64_t t64);
+libbsd_time64_t
+libbsd_time64_to_time_time64(int64_t t64)
+{
+ return((libbsd_time64_t)t64);
+}
+time64_symbol(_time64_to_time);
+
+/*
+ * Convert time_t to a 64 bit representation. If time_t is represented
+ * as 32 bits we simply sign-extend and do not support times past 2038.
+ */
+int64_t
+libbsd_time_to_time64_time64(libbsd_time64_t t);
+int64_t
+libbsd_time_to_time64_time64(libbsd_time64_t t)
+{
+ return((int64_t)t);
+}
+time64_symbol(_time_to_time64);
+
+/*
+ * Convert to/from 'long'. Depending on the sizeof(long) this may or
+ * may not require using the 50-year rule.
+ */
+long
+libbsd_time_to_long_time64(libbsd_time64_t t);
+long
+libbsd_time_to_long_time64(libbsd_time64_t t)
+{
+ if (sizeof(long) == sizeof(int64_t))
+ return(libbsd_time_to_time64_time64(t));
+ return((long)t);
+}
+time64_symbol(_time_to_long);
+
+libbsd_time64_t
+libbsd_long_to_time_time64(long tlong);
+libbsd_time64_t
+libbsd_long_to_time_time64(long tlong)
+{
+ if (sizeof(long) == sizeof(int32_t))
+ return(libbsd_time32_to_time_time64(tlong));
+ return((libbsd_time64_t)tlong);
+}
+time64_symbol(_long_to_time);
+
+/*
+ * Convert to/from 'int'. Depending on the sizeof(int) this may or
+ * may not require using the 50-year rule.
+ */
+int
+libbsd_time_to_int_time64(time_t t);
+int
+libbsd_time_to_int_time64(time_t t)
{
- return((time_t)t32);
+ if (sizeof(int) == sizeof(int64_t))
+ return(libbsd_time_to_time64_time64(t));
+ return((int)t);
}
+time64_symbol(_time_to_int);
+
+libbsd_time64_t
+libbsd_int_to_time_time64(int tint);
+libbsd_time64_t
+libbsd_int_to_time_time64(int tint)
+{
+ if (sizeof(int) == sizeof(int32_t))
+ return(libbsd_time32_to_time_time64(tint));
+ return((libbsd_time64_t)tint);
+}
+time64_symbol(_int_to_time);
+#endif
+
+#if LIBBSD_SYS_TIME_BITS == 32
+typedef int32_t libbsd_time32_t;
+
+libbsd_time32_t
+libbsd_time32_to_time_time32(int32_t t32);
+libbsd_time32_t
+libbsd_time32_to_time_time32(int32_t t32)
+{
+ return((libbsd_time32_t)t32);
+}
+time32_symbol(_time32_to_time);
/*
* Convert time_t to a 32 bit representation. If time_t is 64 bits we can
@@ -50,68 +194,90 @@ _time32_to_time(int32_t t32)
* converted back to a temporally local 64 bit time_t using time32_to_time.
*/
int32_t
-_time_to_time32(time_t t)
+libbsd_time_to_time32_time32(libbsd_time32_t t);
+int32_t
+libbsd_time_to_time32_time32(libbsd_time32_t t)
{
return((int32_t)t);
}
+time32_symbol(_time_to_time32);
/*
* Convert a 64 bit representation of time_t into time_t. If time_t is
* represented as 32 bits we can simply chop it and not support times
* past 2038.
*/
-time_t
-_time64_to_time(int64_t t64)
+libbsd_time32_t
+libbsd_time64_to_time_time32(int64_t t64);
+libbsd_time32_t
+libbsd_time64_to_time_time32(int64_t t64)
{
- return((time_t)t64);
+ return((libbsd_time32_t)t64);
}
+time32_symbol(_time64_to_time);
/*
* Convert time_t to a 64 bit representation. If time_t is represented
* as 32 bits we simply sign-extend and do not support times past 2038.
*/
int64_t
-_time_to_time64(time_t t)
+libbsd_time_to_time64_time32(libbsd_time32_t t);
+int64_t
+libbsd_time_to_time64_time32(libbsd_time32_t t)
{
return((int64_t)t);
}
+time32_symbol(_time_to_time64);
/*
* Convert to/from 'long'. Depending on the sizeof(long) this may or
* may not require using the 50-year rule.
*/
long
-_time_to_long(time_t t)
+libbsd_time_to_long_time32(libbsd_time32_t t);
+long
+libbsd_time_to_long_time32(libbsd_time32_t t)
{
if (sizeof(long) == sizeof(int64_t))
- return(_time_to_time64(t));
+ return(libbsd_time_to_time64_time32(t));
return((long)t);
}
+time32_symbol(_time_to_long);
-time_t
-_long_to_time(long tlong)
+libbsd_time32_t
+libbsd_long_to_time_time32(long tlong);
+libbsd_time32_t
+libbsd_long_to_time_time32(long tlong)
{
if (sizeof(long) == sizeof(int32_t))
- return(_time32_to_time(tlong));
- return((time_t)tlong);
+ return(libbsd_time32_to_time_time32(tlong));
+ return((libbsd_time32_t)tlong);
}
+time32_symbol(_long_to_time);
/*
* Convert to/from 'int'. Depending on the sizeof(int) this may or
* may not require using the 50-year rule.
*/
int
-_time_to_int(time_t t)
+libbsd_time_to_int_time32(libbsd_time32_t t);
+int
+libbsd_time_to_int_time32(libbsd_time32_t t)
{
if (sizeof(int) == sizeof(int64_t))
- return(_time_to_time64(t));
+ return(libbsd_time_to_time64_time32(t));
return((int)t);
}
+time32_symbol(_time_to_int);
-time_t
-_int_to_time(int tint)
+libbsd_time32_t
+libbsd_int_to_time_time32(int tint);
+libbsd_time32_t
+libbsd_int_to_time_time32(int tint)
{
if (sizeof(int) == sizeof(int32_t))
- return(_time32_to_time(tint));
- return((time_t)tint);
+ return(libbsd_time32_to_time_time32(tint));
+ return((libbsd_time32_t)tint);
}
+time32_symbol(_int_to_time);
+#endif
diff --git a/test/.gitignore b/test/.gitignore
index a80f854..bfd5572 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -22,5 +22,7 @@ strl
strmode
strnstr
strtonum
+timeconv32
+timeconv64
vis
vis-openbsd
diff --git a/test/Makefile.am b/test/Makefile.am
index 1c64abb..13c3309 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -182,4 +182,12 @@ check_PROGRAMS += \
# EOL
endif
+if LIBBSD_SYS_IS_TIME32
+check_PROGRAMS += timeconv32
+endif
+
+if LIBBSD_SYS_HAS_TIME64
+check_PROGRAMS += timeconv64
+endif
+
TESTS = $(check_SCRIPTS) $(check_PROGRAMS)
diff --git a/test/timeconv32.c b/test/timeconv32.c
new file mode 100644
index 0000000..549e612
--- /dev/null
+++ b/test/timeconv32.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2024 Guillem Jover <guillem@hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#undef _TIME_BITS
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <timeconv.h>
+
+int
+main(int argc, char **argv)
+{
+ time_t t;
+
+ t = _time64_to_time(INT64_MAX);
+ assert(t < INT64_MAX);
+
+ return 0;
+}
diff --git a/test/timeconv64.c b/test/timeconv64.c
new file mode 100644
index 0000000..d175ed2
--- /dev/null
+++ b/test/timeconv64.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2024 Guillem Jover <guillem@hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <timeconv.h>
+
+int
+main(int argc, char **argv)
+{
+ time_t t;
+
+ t = _time64_to_time(INT64_MAX);
+ assert(t == INT64_MAX);
+
+ return 0;
+}