]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Add explicit time32 and time64 support
authorGuillem Jover <guillem@hadrons.org>
Fri, 9 Feb 2024 03:32:12 +0000 (04:32 +0100)
committerGuillem Jover <guillem@hadrons.org>
Tue, 27 Feb 2024 04:47:50 +0000 (05:47 +0100)
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.

configure.ac
include/Makefile.am
include/bsd/sys/cdefs.h
include/bsd/timeconv.h
m4/libbsd-large.m4 [new file with mode: 0644]
src/libbsd.map.in
src/timeconv.c
test/.gitignore
test/Makefile.am
test/timeconv32.c [new file with mode: 0644]
test/timeconv64.c [new file with mode: 0644]

index bedc615fa0b8cadb2dfbcc55005a047bb539e826..e516f9360d28be149dfae16099989a90ce88e704 100644 (file)
@@ -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
index 9a75b9750bfdbbbe1f0ee19e1a9db0ad1584f901..52b78be06cf0a26f375a3bd0f1d82a56ad195a2b 100644 (file)
@@ -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
index 126f4275c91342b65e24ade0fd533acac4735314..d2627c463920fbbad5be393fb6c807fb12823578 100644 (file)
 #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
 
index a426bd34ddddb875ac956e5b3e24fc7949e0c247..755c89cb669f561f2ecce3c1a748168bf8344389 100644 (file)
@@ -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 (file)
index 0000000..d279111
--- /dev/null
@@ -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])
+  ])
+])
index 9670d4cb50718fb1896421a79440acbdc6931546..d7047dcefa962467dfe8520827828b88141beb58 100644 (file)
@@ -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;
index 11f926e79dcb3b1261a45faaa5a14e36252436ff..0c122e48392ab232e109a8b990f0abc0de106cdf 100644 (file)
 
 #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
index a80f854eb3e7bbe57c84e658ee4305da5d3415e8..bfd55726960961b78393dd5362ca4f88cdcba115 100644 (file)
@@ -22,5 +22,7 @@ strl
 strmode
 strnstr
 strtonum
+timeconv32
+timeconv64
 vis
 vis-openbsd
index 1c64abb318edcff74633a57701ffbe31299f8f4b..13c3309c4bb4cae0fd9b0a1c71685c631807fea2 100644 (file)
@@ -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 (file)
index 0000000..549e612
--- /dev/null
@@ -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 (file)
index 0000000..d175ed2
--- /dev/null
@@ -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;
+}