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.
This commit is contained in:
Guillem Jover 2024-02-09 04:32:12 +01:00
parent 605614d642
commit 32d18dcf47
11 changed files with 371 additions and 21 deletions

View 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

View 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

View File

@ -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

View 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 */

51
m4/libbsd-large.m4 Normal file
View File

@ -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])
])
])

View 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;

View File

@ -32,17 +32,55 @@
#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((time_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
@ -50,68 +88,196 @@ _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_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.
*/
time_t
_time64_to_time(int64_t t64)
libbsd_time64_t
libbsd_time64_to_time_time64(int64_t t64);
libbsd_time64_t
libbsd_time64_to_time_time64(int64_t t64)
{
return((time_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
_time_to_time64(time_t 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
_time_to_long(time_t t)
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(_time_to_time64(t));
return(libbsd_time_to_time64_time64(t));
return((long)t);
}
time64_symbol(_time_to_long);
time_t
_long_to_time(long tlong)
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(_time32_to_time(tlong));
return((time_t)tlong);
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
_time_to_int(time_t t)
libbsd_time_to_int_time64(time_t t);
int
libbsd_time_to_int_time64(time_t t)
{
if (sizeof(int) == sizeof(int64_t))
return(_time_to_time64(t));
return(libbsd_time_to_time64_time64(t));
return((int)t);
}
time64_symbol(_time_to_int);
time_t
_int_to_time(int tint)
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(_time32_to_time(tint));
return((time_t)tint);
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
* 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_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.
*/
libbsd_time32_t
libbsd_time64_to_time_time32(int64_t t64);
libbsd_time32_t
libbsd_time64_to_time_time32(int64_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
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
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(libbsd_time_to_time64_time32(t));
return((long)t);
}
time32_symbol(_time_to_long);
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(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
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(libbsd_time_to_time64_time32(t));
return((int)t);
}
time32_symbol(_time_to_int);
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(libbsd_time32_to_time_time32(tint));
return((libbsd_time32_t)tint);
}
time32_symbol(_int_to_time);
#endif

2
test/.gitignore vendored
View File

@ -22,5 +22,7 @@ strl
strmode
strnstr
strtonum
timeconv32
timeconv64
vis
vis-openbsd

View 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)

43
test/timeconv32.c Normal file
View File

@ -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;
}

40
test/timeconv64.c Normal file
View File

@ -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;
}