Support gnulib-style timestamps in checkpoint logs

* gnulib.modules: Add nstrftime-limited, time_rz.  Sort.
* src/checkpoint.c: Include <strftime.h>.
(format_checkpoint_string): Use nstrftime instead of strftime.
Also fix an obscure bug on platforms that lack tm_gmtoff+tm_zone by
calling tzalloc on those platforms; if it fails, fall back on gmtime.
Also, use fwrite instead of fprintf, since we typically know the
length already and this gives us a more-accurate byte count
in case there are partial writes.
This commit is contained in:
Paul Eggert
2025-11-23 09:44:03 -08:00
parent 85d99f18af
commit 2bbc58bf0b
2 changed files with 37 additions and 15 deletions

View File

@@ -37,8 +37,8 @@ dup2
errno-h
error
exclude
extern-inline
exitfail
extern-inline
faccessat
fchmodat
fchownat
@@ -52,6 +52,7 @@ fnmatch-gnu
free-posix
fseeko
fstatat
full-read
full-write
futimens
gendocs
@@ -81,6 +82,7 @@ mkdirat
mkdtemp
mkfifoat
modechange
nstrftime-limited
obstack
openat
openat2
@@ -94,7 +96,6 @@ reallocarray
renameat
root-uid
rpmatch
full-read
safe-read
same-inode
savedir
@@ -105,22 +106,23 @@ std-gnu23
stdcountof-h
stddef-h
stdint-h
stpcpy
stdopen
stpcpy
strdup-posix
strerror
stringeq
strnlen
symlinkat
sys_stat-h
time_rz
timespec
timespec-sub
unlinkat
unlinkdir
unlocked-io
utimensat
version-etc-fsf
verror
version-etc-fsf
xalignalloc
xalloc
xalloc-die

View File

@@ -22,6 +22,7 @@
#include <wordsplit.h>
#include <flexmember.h>
#include <strftime.h>
#include <sys/ioctl.h>
#include <termios.h>
@@ -306,22 +307,41 @@ format_checkpoint_string (FILE *fp, intmax_t len,
{
struct timespec ts = current_timespec ();
struct tm *tm = localtime (&ts.tv_sec);
char const *tmstr = NULL;
#if HAVE_STRUCT_TM_TM_GMTOFF && HAVE_STRUCT_TM_TM_ZONE
/* struct tm has POSIX.1-2024 tm_gmtoff and tm_zone,
so nstrftime ignores tz and any tz value will do. */
timezone_t tz = 0;
#else
static timezone_t tz;
if (tm && !tz)
{
tz = tzalloc (getenv ("TZ"));
if (!tz)
tm = NULL;
}
#endif
/* Keep BUF relatively small, as any text timestamp
not fitting into BUF is likely a DoS attack. */
char buf[max (SYSINT_BUFSIZE, 256)];
if (tm)
char buf[max (TIMESPEC_STRSIZE_BOUND, 256)];
ptrdiff_t buflen =
(tm
? nstrftime (buf, sizeof buf, arg ? arg : "%c",
tm, tz, ts.tv_nsec)
: -1);
char const *tmstr;
idx_t tmstrlen;
if (buflen < 0)
{
buf[0] = '\0';
char const *fmt = arg ? arg : "%c";
if (strftime (buf, sizeof buf, fmt, tm) != 0 || !buf[0])
tmstr = buf;
tmstr = code_timespec (ts, buf);
tmstrlen = strlen (tmstr);
}
if (!tmstr)
tmstr = timetostr (ts.tv_sec, buf);
len = add_printf (len, fprintf (fp, "%s", tmstr));
else
{
tmstr = buf;
tmstrlen = buflen;
}
len = add_printf (len, fwrite (tmstr, 1, tmstrlen, stdout));
}
break;