diff options
author | Mattias Andrée <maandree@kth.se> | 2024-01-09 22:04:24 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2024-01-09 22:04:24 +0100 |
commit | ae850b1ac755f471beac4dbfef4654fe3fbaaae9 (patch) | |
tree | 319e7f7f1b99cd1ee75e100f0a29b0f7c827ccea /libpatch_create_timestamp_now.c | |
download | libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.gz libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.bz2 libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.xz |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'libpatch_create_timestamp_now.c')
-rw-r--r-- | libpatch_create_timestamp_now.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/libpatch_create_timestamp_now.c b/libpatch_create_timestamp_now.c new file mode 100644 index 0000000..b0bef09 --- /dev/null +++ b/libpatch_create_timestamp_now.c @@ -0,0 +1,73 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifdef __linux__ +# include <sys/timex.h> +#endif + + +size_t +libpatch_create_timestamp_now(char *buf, size_t bufsize, signed frac, int zone, enum libpatch_style style) +{ + struct timespec ts; +#ifdef __linux__ + struct timex timex; + struct tm tm; + int r; +#endif + + if (frac < 0) { + if (clock_gettime(CLOCK_REALTIME, &ts)) { + frac = 9; + } else { + frac = 0; + while (ts.tv_nsec < 1000000000L) { + ts.tv_nsec *= 10; + frac += 1; + } + } + } + +#ifdef __linux__ + memset(&timex, 0, sizeof(timex)); + if (frac > 6) + timex.status = ADJ_NANO; + r = adjtimex(&timex); + if (r == -1) { + if (errno == ENOSYS) + goto fallback; + return 0; + } + + if (timex.time.tv_sec % (24 * 60 * 60) == 0) { + if (r == TIME_INS) { + timex.time.tv_sec -= 1; + if (!localtime_r(&timex.time.tv_sec, &tm)) + return 0; + tm.tm_sec += 1; + } else if (r == TIME_DEL) { + timex.time.tv_sec += 1; + if (!localtime_r(&timex.time.tv_sec, &tm)) + return 0; + } else { + if (!localtime_r(&timex.time.tv_sec, &tm)) + return 0; + } + } else if (r == TIME_OOP) { + if (!localtime_r(&timex.time.tv_sec, &tm)) + return 0; + tm.tm_sec += 1; + } else { + if (!localtime_r(&timex.time.tv_sec, &tm)) + return 0; + } + + return libpatch_create_timestamp(buf, bufsize, &tm, (uintmax_t)timex.time.tv_usec, + frac > 6 ? 9U : 6U, (unsigned)frac, zone, style); + +fallback: +#endif + + if (clock_gettime(CLOCK_REALTIME, &ts)) + return 0; + return libpatch_create_timestamp_ts(buf, bufsize, &ts, (unsigned)frac, zone, style); +} |