Paolo Bonzini <bonzini <at> gnu.org> writes: > > configure.ac: > > +AC_CHECK_FUNCS([usleep]) > > AC_CHECK_FUNCS_ONCE is better maybe?
Yep. Also, I was consistently seeing test-utimens failures on a Solaris 8 machine using NFS; I don't know if the bug was limited to Solaris 8, but suspect that other platforms using NFS might see it as well. But basically, utimens(,NULL) seemed to be choosing 'now' based on the server's notion of time, while using UTIME_NOW used gettime() to determine a timestamp from the client machine; but there is no guarantee that the client and server are in sync to the resolution given by file timestamps. I've got these three patches queued up in my local repository: >From 1dedaef9312e5d2353b0f32c4a748a98cced9636 Mon Sep 17 00:00:00 2001 From: Eric Blake <e...@byu.net> Date: Mon, 12 Oct 2009 10:36:33 -0600 Subject: [PATCH 1/3] sys_stat: guarantee struct timespec * lib/sys_stat.in.h (includes): Always include <time.h> * modules/sys_stat (Depends-on): Add time. * tests/test-sys_stat.c: Guarantee struct timespec, as well as mode_t permission values. * doc/posix-headers/sys_stat.texi (sys/stat.h): Document how to get at subsecond timestamps. Signed-off-by: Eric Blake <e...@byu.net> --- ChangeLog | 10 ++++++++++ doc/posix-headers/sys_stat.texi | 4 ++++ lib/sys_stat.in.h | 3 +++ modules/sys_stat | 1 + tests/test-sys_stat.c | 19 +++++++++++++++++++ 5 files changed, 37 insertions(+), 0 deletions(-) diff --git a/ChangeLog b/ChangeLog index b46babd..1768d74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-10-12 Eric Blake <e...@byu.net> + + sys_stat: guarantee struct timespec + * lib/sys_stat.in.h (includes): Always include <time.h> + * modules/sys_stat (Depends-on): Add time. + * tests/test-sys_stat.c: Guarantee struct timespec, as well as + mode_t permission values. + * doc/posix-headers/sys_stat.texi (sys/stat.h): Document how to + get at subsecond timestamps. + 2009-10-10 Eric Blake <e...@byu.net> futimens: new module diff --git a/doc/posix-headers/sys_stat.texi b/doc/posix-headers/sys_stat.texi index 33c8683..6cfbe3d 100644 --- a/doc/posix-headers/sys_stat.texi +++ b/doc/posix-headers/sys_stat.texi @@ -20,6 +20,10 @@ sys/stat.h @item The macros @code{UTIME_NOW} and @code{UTIME_OMIT} are missing on some platforms. +...@item +On some platforms, @code{struct stat} does not include @code{st_atim}, +...@code{st_mtim}, or @code{st_ctim} members. Use the gnulib module +...@samp{stat-time} for accessors to portably get at subsecond resolution. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index e543770..296cedd 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -38,6 +38,9 @@ /* Get nlink_t. */ #include <sys/types.h> +/* Get struct timespec. */ +#include <time.h> + /* The include_next requires a split double-inclusion guard. */ #...@include_next@ @NEXT_SYS_STAT_H@ diff --git a/modules/sys_stat b/modules/sys_stat index 5d8b0ef..708491f 100644 --- a/modules/sys_stat +++ b/modules/sys_stat @@ -9,6 +9,7 @@ m4/unistd_h.m4 Depends-on: include_next link-warning +time configure.ac: gl_HEADER_SYS_STAT_H diff --git a/tests/test-sys_stat.c b/tests/test-sys_stat.c index 25fe30d..a73f9b8 100644 --- a/tests/test-sys_stat.c +++ b/tests/test-sys_stat.c @@ -253,6 +253,23 @@ verify (!S_ISWHT (S_IFLNK)); verify (!S_ISWHT (S_IFSOCK)); #endif +/* POSIX 2008 requires traditional encoding of permission constants. */ +verify (S_IRWXU == 00700); +verify (S_IRUSR == 00400); +verify (S_IWUSR == 00200); +verify (S_IXUSR == 00100); +verify (S_IRWXG == 00070); +verify (S_IRGRP == 00040); +verify (S_IWGRP == 00020); +verify (S_IXGRP == 00010); +verify (S_IRWXO == 00007); +verify (S_IROTH == 00004); +verify (S_IWOTH == 00002); +verify (S_IXOTH == 00001); +verify (S_ISUID == 04000); +verify (S_ISGID == 02000); +verify (S_ISVTX == 01000); + #if ((0 <= UTIME_NOW && UTIME_NOW < 1000000000) \ || (0 <= UTIME_OMIT && UTIME_OMIT < 1000000000) \ || UTIME_NOW == UTIME_OMIT) @@ -262,6 +279,8 @@ invalid UTIME macros /* Check the existence of some types. */ nlink_t t1; +struct timespec t2; + int main () { -- 1.6.4.2 >From c14035f5a1f5f3372e92d432c9b42a8a9783cc69 Mon Sep 17 00:00:00 2001 From: Eric Blake <e...@byu.net> Date: Mon, 12 Oct 2009 10:37:48 -0600 Subject: [PATCH 2/3] stat-time-tests: minor optimization * modules/stat-time-tests (configure.ac): Use AC_CHECK_FUNCS_ONCE. Suggested by Paolo Bonzini. Signed-off-by: Eric Blake <e...@byu.net> --- ChangeLog | 4 ++++ modules/stat-time-tests | 2 +- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1768d74..2ba0f81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2009-10-12 Eric Blake <e...@byu.net> + stat-time-tests: minor optimization + * modules/stat-time-tests (configure.ac): Use AC_CHECK_FUNCS_ONCE. + Suggested by Paolo Bonzini. + sys_stat: guarantee struct timespec * lib/sys_stat.in.h (includes): Always include <time.h> * modules/sys_stat (Depends-on): Add time. diff --git a/modules/stat-time-tests b/modules/stat-time-tests index 3913ad2..05b2b62 100644 --- a/modules/stat-time-tests +++ b/modules/stat-time-tests @@ -6,7 +6,7 @@ time sleep configure.ac: -AC_CHECK_FUNCS([usleep]) +AC_CHECK_FUNCS_ONCE([usleep]) Makefile.am: TESTS += test-stat-time -- 1.6.4.2 >From a4f4362f709f3c2b19d8c005ea00224df2f1278d Mon Sep 17 00:00:00 2001 From: Eric Blake <e...@byu.net> Date: Mon, 12 Oct 2009 10:42:35 -0600 Subject: [PATCH 3/3] utimens-tests: port to NFS file systems Testing on Solaris 8 with NFS: creat() and utimens(,NULL) seem to set timestamps according to the current time on the server, while utimens(,{,UTIME_NOW}) sets timestamps according to the current time on the client. If two machines are not perfectly synchronized in time, then this makes time appear to move backwards. Avoid spurious test failures caused by a mtime comparison across machines, by instead doing 2 mtime comparisons, each known to be from timestamps tied to a single machine. * tests/test-utimens.h (test_utimens): Add a utimens call prior to grabbing stat buffer. Signed-off-by: Eric Blake <e...@byu.net> --- ChangeLog | 5 +++++ tests/test-utimens.h | 24 +++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2ba0f81..12e5c01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2009-10-12 Eric Blake <e...@byu.net> + utimens-tests: port to NFS file systems + * tests/test-utimens.h (test_utimens): Refactor utimecmp + comparisons to avoid spurious failures from timestamp drift + between NFS machines. + stat-time-tests: minor optimization * modules/stat-time-tests (configure.ac): Use AC_CHECK_FUNCS_ONCE. Suggested by Paolo Bonzini. diff --git a/tests/test-utimens.h b/tests/test-utimens.h index 04131d3..08d3ac0 100644 --- a/tests/test-utimens.h +++ b/tests/test-utimens.h @@ -56,10 +56,28 @@ test_utimens (int (*func) (char const *, struct timespec const *)) ASSERT (close (creat (BASE "file", 0600)) == 0); /* If utimens truncates to less resolution than the file system - supports, then time can appear to go backwards between now and - the follow-up utimens(file,NULL). Use UTIMECMP_TRUNCATE_SOURCE - to compensate, with st1 as the source. */ + supports, then time can appear to go backwards between now and a + follow-up utimens with UTIME_NOW or a NULL timespec. Use + UTIMECMP_TRUNCATE_SOURCE to compensate, with st1 as the + source. */ ASSERT (stat (BASE "file", &st1) == 0); + ASSERT (func (BASE "file", NULL) == 0); + ASSERT (stat (BASE "file", &st2) == 0); + ASSERT (0 <= utimecmp (BASE "file", &st2, &st1, UTIMECMP_TRUNCATE_SOURCE)); + { + /* On some NFS systems, the 'now' timestamp of creat or a NULL + timespec is determined by the server, but the 'now' timestamp + determined by gettime() (as is done when using UTIME_OMIT) is + determined by the client; since the two machines are not + necessarily on the same clock, this is another case where time + can appear to go backwards. The rest of this test cares about + client time, so manually use gettime() to set both times. */ + struct timespec ts[2]; + gettime (&ts[0]); + ts[1] = ts[0]; + ASSERT (func (BASE "file", ts) == 0); + ASSERT (stat (BASE "file", &st1) == 0); + } /* Invalid arguments. */ errno = 0; -- 1.6.4.2