From: Thorsten Kukuk Date: Thu, 30 Nov 2023 16:28:53 +0100 Subject: libuuid: Add uuid_time64 for 64bit time_t on 32bit Signed-off-by: Thorsten Kukuk --- libuuid/src/libuuid.sym | 9 ++++++++ libuuid/src/uuid.h | 3 +++ libuuid/src/uuid_time.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/libuuid/src/libuuid.sym b/libuuid/src/libuuid.sym index 96372a8..0f67ede 100644 --- a/libuuid/src/libuuid.sym +++ b/libuuid/src/libuuid.sym @@ -52,6 +52,15 @@ global: uuid_parse_range; } UUID_2.31; +/* + * version(s) since util-linux.2.40 + */ +UUID_2.40 { +global: + uuid_time64; /* only on 32bit architectures with 64bit time_t */ +} UUID_2.36; + + /* * __uuid_* this is not part of the official API, this is diff --git a/libuuid/src/uuid.h b/libuuid/src/uuid.h index e791abf..2e3642c 100644 --- a/libuuid/src/uuid.h +++ b/libuuid/src/uuid.h @@ -109,6 +109,9 @@ extern void uuid_unparse_lower(const uuid_t uu, char *out); extern void uuid_unparse_upper(const uuid_t uu, char *out); /* uuid_time.c */ +#if defined(__USE_TIME_BITS64) && defined(__GLIBC__) +# define uuid_time uuid_time64 +#endif extern time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); extern int uuid_type(const uuid_t uu); extern int uuid_variant(const uuid_t uu); diff --git a/libuuid/src/uuid_time.c b/libuuid/src/uuid_time.c index 6f07d51..9b415b3 100644 --- a/libuuid/src/uuid_time.c +++ b/libuuid/src/uuid_time.c @@ -40,6 +40,7 @@ #define UUID MYUUID #endif +#include #include #ifdef HAVE_UNISTD_H #include @@ -53,7 +54,15 @@ #include "uuidP.h" -time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) +#undef uuid_time + +/* prototype to make compiler happy */ +time_t __uuid_time(const uuid_t uu, struct timeval *ret_tv); + + +/* this function could be 32bit time_t and 32bit timeval or 64bit, + depending on compiler flags and architecture. */ +time_t __uuid_time(const uuid_t uu, struct timeval *ret_tv) { struct timeval tv; struct uuid uuid; @@ -74,6 +83,54 @@ time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) return tv.tv_sec; } +#if defined(__USE_TIME_BITS64) && defined(__GLIBC__) +extern time_t uuid_time64(const uuid_t uu, struct timeval *ret_tv) __attribute__((weak, alias("__uuid_time"))); +#else +extern time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) __attribute__((weak, alias("__uuid_time"))); +#endif + +#if defined(__USE_TIME_BITS64) && defined(__GLIBC__) +struct timeval32 +{ + int32_t tv_sec; + int32_t tv_usec; +}; + +/* prototype to make compiler happy */ +int32_t __uuid_time32(const uuid_t uu, struct timeval32 *ret_tv); + +/* Check whether time fits in 32bit time_t. */ +static inline int +in_time32_t_range(time_t t) +{ + int32_t s; + + s = t; + + return s == t; +} + +int32_t __uuid_time32(const uuid_t uu, struct timeval32 *ret_tv) +{ + struct timeval tv; + time_t ret_time = __uuid_time(uu, &tv); + + if (! in_time32_t_range(ret_time)) { + ret_tv->tv_sec = -1; + ret_tv->tv_usec = -1; + errno = EOVERFLOW; + return -1; + } + + if (ret_tv) { + ret_tv->tv_sec = tv.tv_sec; + ret_tv->tv_usec = tv.tv_usec; + } + + return tv.tv_sec; +} +extern int32_t uuid_time(const uuid_t uu, struct timeval32 *ret_tv) __attribute__((weak, alias("__uuid_time32"))); +#endif int uuid_type(const uuid_t uu) {