1 /* Assist in file system timestamp tests.
2 Copyright (C) 2009-2016 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Eric Blake <ebb9@byu.net>, 2009. */
25 /* File descriptor used for the witness file. */
26 static int nap_fd = -1;
28 /* Return A - B, in ns.
29 Return 0 if the true result would be negative.
30 Return INT_MAX if the true result would be greater than INT_MAX. */
32 diff_timespec (struct timespec a, struct timespec b)
39 if (! (bs < as || (bs == as && bns < ans)))
41 if (as - bs <= INT_MAX / 1000000000)
43 int sdiff = (as - bs) * 1000000000;
44 int usdiff = ans - bns;
45 if (usdiff < INT_MAX - sdiff)
46 return sdiff + usdiff;
52 get_stat (int fd, struct stat *st, int do_write)
55 ASSERT (write (fd, "\n", 1) == 1);
56 ASSERT (fstat (fd, st) == 0);
59 /* Given a file whose descriptor is FD, see whether delaying by DELAY
60 nanoseconds causes a change in a file's ctime and mtime.
61 OLD_ST is the file's status, recently gotten. */
63 nap_works (int fd, int delay, struct stat old_st)
66 struct timespec delay_spec;
67 delay_spec.tv_sec = delay / 1000000000;
68 delay_spec.tv_nsec = delay % 1000000000;
69 ASSERT (nanosleep (&delay_spec, 0) == 0);
70 get_stat (fd, &st, 1);
72 if ( diff_timespec (get_stat_ctime (&st), get_stat_ctime (&old_st))
73 && diff_timespec (get_stat_mtime (&st), get_stat_mtime (&old_st)))
79 #define TEMPFILE BASE "nap.tmp"
82 clear_temp_file (void)
86 ASSERT (close (nap_fd) != -1);
87 ASSERT (unlink (TEMPFILE) != -1);
91 /* Sleep long enough to notice a timestamp difference on the file
92 system in the current directory. Use an adaptive approach, trying
93 to find the smallest delay which works on the current file system
94 to make the timestamp difference appear. Assert a maximum delay of
95 ~2 seconds, more precisely sum(2^n) from 0 to 30 = 2^31 - 1 = 2.1s.
96 Assumes that BASE is defined, and requires that the test module
97 depends on nanosleep. */
102 static int delay = 1;
106 atexit (clear_temp_file);
107 ASSERT ((nap_fd = creat (TEMPFILE, 0600)) != -1);
108 get_stat (nap_fd, &old_st, 0);
112 ASSERT (0 <= nap_fd);
113 get_stat (nap_fd, &old_st, 1);
117 delay = delay / 2; /* Try half of the previous delay. */
120 for ( ; delay <= 2147483647; delay = delay * 2)
121 if (nap_works (nap_fd, delay, old_st))
124 /* Bummer: even the highest nap delay didn't work. */
128 #endif /* GLTEST_NAP_H */