Fix tests/ckmtime.c arithmetic

* tests/ckmtime.c (main): Don’t assume time_t is signed.
Avoid integer overflows (quite possible if time_t is 32 bit).
Do calculations precisely, without any rounding errors.
This commit is contained in:
Paul Eggert
2024-07-30 08:35:59 -07:00
parent 7557fdd4df
commit dcc90722ac

View File

@@ -1,6 +1,6 @@
/* Check if filesystem timestamps are consistent with the system time.
Copyright (C) 2016-2024 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any later
@@ -25,42 +25,35 @@
#include <stat-time.h>
#include <timespec.h>
#define TEMPLATE "ckmtime.XXXXXX"
#define BILLION 1000000000
/* Some filesystems can slightly offset the timestamps of newly created files.
To compensate for it, tar testsuite waits at least 1 second before creating
next level of incremental backups.
However, NFS mounts can offset the timestamps by bigger amounts.
However, NFS mounts can offset the timestamps by bigger amounts.
This program returns with success (0) if a newly created file is assigned
mtime matching the system time to the nearest second.
*/
int
main (int argc, char **argv)
{
int fd;
char name[sizeof(TEMPLATE)];
struct stat st;
struct timespec ts, td;
double diff;
gettime (&ts);
strcpy (name, TEMPLATE);
umask (077);
fd = mkstemp (name);
assert (fd != -1);
unlink (name);
assert (fstat (fd, &st) == 0);
close (fd);
struct timespec s = current_timespec ();
td = timespec_sub (get_stat_mtime (&st), ts);
diff = td.tv_sec * BILLION + td.tv_nsec;
if (diff < 0)
diff = - diff;
if (diff / BILLION >= 1)
umask (077);
char name[] = "ckmtime.XXXXXX";
int fd = mkstemp (name);
assert (0 <= fd);
unlink (name);
struct stat st;
int r = fstat (fd, &st);
assert (0 <= r);
r = close (fd);
assert (0 <= r);
struct timespec
t = get_stat_mtime (&st),
d = timespec_cmp (s, t) < 0 ? timespec_sub (t, s) : timespec_sub (s, t);
if (timespec_cmp (make_timespec (1, 0), d) < 0)
{
fprintf (stderr, "file timestamp unreliable\n");
return 1;