From 6536b952f68e49259420ee1924a238b5aa3feff3 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 15 Aug 2017 16:47:22 -0700 Subject: [PATCH 2/2] =?UTF-8?q?futimens:=20don=E2=80=99t=20assume=20struct?= =?UTF-8?q?=20timespec=20layout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * m4/futimens.m4 (gl_FUNC_FUTIMENS): * m4/utimensat.m4 (gl_FUNC_UTIMENSAT): * tests/test-fdutimensat.c (main): * tests/test-futimens.h (test_futimens): * tests/test-lutimens.h (test_lutimens): * tests/test-utimens.h (test_utimens): * tests/test-utimensat.c (main): Don’t assume that struct timespec is a two-member structure in tv_sec, tv_nsec order. Although this is true on all platforms we know about, POSIX does not guarantee it. --- ChangeLog | 12 ++++++++++++ m4/futimens.m4 | 6 +++++- m4/utimensat.m4 | 12 ++++++++++-- tests/test-fdutimensat.c | 5 ++++- tests/test-futimens.h | 24 ++++++++++++++++++++---- tests/test-lutimens.h | 39 ++++++++++++++++++++++++++++++++------- tests/test-utimens.h | 34 ++++++++++++++++++++++++++++------ tests/test-utimensat.c | 6 +++++- 8 files changed, 116 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3d87c90..bc0c169 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2017-08-15 Paul Eggert + futimens: don’t assume struct timespec layout + * m4/futimens.m4 (gl_FUNC_FUTIMENS): + * m4/utimensat.m4 (gl_FUNC_UTIMENSAT): + * tests/test-fdutimensat.c (main): + * tests/test-futimens.h (test_futimens): + * tests/test-lutimens.h (test_lutimens): + * tests/test-utimens.h (test_utimens): + * tests/test-utimensat.c (main): + Don’t assume that struct timespec is a two-member structure in + tv_sec, tv_nsec order. Although this is true on all platforms we + know about, POSIX does not guarantee it. + rename: document+test NetBSD rename Test failure reported by Bruno Haible in: http://lists.gnu.org/archive/html/bug-gnulib/2017-08/msg00104.html diff --git a/m4/futimens.m4 b/m4/futimens.m4 index 12bed98..d68bff3 100644 --- a/m4/futimens.m4 +++ b/m4/futimens.m4 @@ -23,10 +23,14 @@ AC_DEFUN([gl_FUNC_FUTIMENS], #include #include #include -]], [[struct timespec ts[2] = { { 1, UTIME_OMIT }, { 1, UTIME_NOW } }; +]], [[struct timespec ts[2]; int fd = creat ("conftest.file", 0600); struct stat st; if (fd < 0) return 1; + ts[0].tv_sec = 1; + ts[0].tv_nsec = UTIME_OMIT; + ts[1].tv_sec = 1; + ts[1].tv_nsec = UTIME_NOW; errno = 0; if (futimens (AT_FDCWD, NULL) == 0) return 2; if (errno != EBADF) return 3; diff --git a/m4/utimensat.m4 b/m4/utimensat.m4 index b4666c0..78da3cc 100644 --- a/m4/utimensat.m4 +++ b/m4/utimensat.m4 @@ -34,14 +34,22 @@ AC_DEFUN([gl_FUNC_UTIMENSAT], } /* Test whether UTIME_NOW and UTIME_OMIT work. */ { - struct timespec ts[2] = { { 1, UTIME_OMIT }, { 1, UTIME_NOW } }; + struct timespec ts[2]; + ts[0].tv_sec = 1; + ts[0].tv_nsec = UTIME_OMIT; + ts[1].tv_sec = 1; + ts[1].tv_nsec = UTIME_NOW; if (utimensat (AT_FDCWD, f, ts, 0)) result |= 4; } sleep (1); { - struct timespec ts[2] = { { 1, UTIME_NOW }, { 1, UTIME_OMIT } }; struct stat st; + struct timespec ts[2]; + ts[0].tv_sec = 1; + ts[0].tv_nsec = UTIME_NOW; + ts[1].tv_sec = 1; + ts[1].tv_nsec = UTIME_OMIT; if (utimensat (AT_FDCWD, f, ts, 0)) result |= 8; if (stat (f, &st)) diff --git a/tests/test-fdutimensat.c b/tests/test-fdutimensat.c index fa35bc4..b42cba3 100644 --- a/tests/test-fdutimensat.c +++ b/tests/test-fdutimensat.c @@ -125,8 +125,11 @@ main (void) ASSERT (fdutimensat (AT_FDCWD, fd, ".", NULL, 0) == -1); ASSERT (errno == ENOTDIR); { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } }; + struct timespec ts[2]; struct stat st; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1] = ts[0]; ASSERT (fdutimensat (fd, dfd, BASE "dir/file", ts, 0) == 0); ASSERT (stat ("file", &st) == 0); ASSERT (st.st_atime == Y2K); diff --git a/tests/test-futimens.h b/tests/test-futimens.h index 40bcb9e..727be3b 100644 --- a/tests/test-futimens.h +++ b/tests/test-futimens.h @@ -97,13 +97,21 @@ test_futimens (int (*func) (int, struct timespec const *), ASSERT (errno == EBADF); } { - struct timespec ts[2] = { { Y2K, UTIME_BOGUS_POS }, { Y2K, 0 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = UTIME_BOGUS_POS; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = 0; errno = 0; ASSERT (func (fd, ts) == -1); ASSERT (errno == EINVAL); } { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, UTIME_BOGUS_NEG } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = UTIME_BOGUS_NEG; errno = 0; ASSERT (func (fd, ts) == -1); ASSERT (errno == EINVAL); @@ -115,7 +123,11 @@ test_futimens (int (*func) (int, struct timespec const *), /* Set both times. */ { - struct timespec ts[2] = { { Y2K, BILLION / 2 - 1 }, { Y2K, BILLION - 1 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = BILLION / 2 - 1; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = BILLION - 1; ASSERT (func (fd, ts) == 0); ASSERT (fstat (fd, &st2) == 0); ASSERT (st2.st_atime == Y2K); @@ -131,7 +143,11 @@ test_futimens (int (*func) (int, struct timespec const *), /* Play with UTIME_OMIT, UTIME_NOW. */ { struct stat st3; - struct timespec ts[2] = { { BILLION, UTIME_OMIT }, { 0, UTIME_NOW } }; + struct timespec ts[2]; + ts[0].tv_sec = BILLION; + ts[0].tv_nsec = UTIME_OMIT; + ts[1].tv_sec = 0; + ts[1].tv_nsec = UTIME_NOW; nap (); ASSERT (func (fd, ts) == 0); ASSERT (fstat (fd, &st3) == 0); diff --git a/tests/test-lutimens.h b/tests/test-lutimens.h index b590855..e18f249 100644 --- a/tests/test-lutimens.h +++ b/tests/test-lutimens.h @@ -44,7 +44,10 @@ test_lutimens (int (*func) (char const *, struct timespec const *), bool print) ASSERT (st1.st_atime != Y2K); ASSERT (st1.st_mtime != Y2K); { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1] = ts[0]; errno = 0; ASSERT (func (BASE "file/", ts) == -1); ASSERT (errno == ENOTDIR); @@ -53,7 +56,10 @@ test_lutimens (int (*func) (char const *, struct timespec const *), bool print) ASSERT (st1.st_mtime == st2.st_mtime); } { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1] = ts[0]; nap (); ASSERT (func (BASE "file", ts) == 0); } @@ -106,13 +112,21 @@ test_lutimens (int (*func) (char const *, struct timespec const *), bool print) /* Invalid arguments. */ { - struct timespec ts[2] = { { Y2K, UTIME_BOGUS_POS }, { Y2K, 0 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = UTIME_BOGUS_POS; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = 0; errno = 0; ASSERT (func (BASE "link", ts) == -1); ASSERT (errno == EINVAL); } { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, UTIME_BOGUS_NEG } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = UTIME_BOGUS_NEG; errno = 0; ASSERT (func (BASE "link", ts) == -1); ASSERT (errno == EINVAL); @@ -127,7 +141,11 @@ test_lutimens (int (*func) (char const *, struct timespec const *), bool print) /* Set both times. */ { - struct timespec ts[2] = { { Y2K, BILLION / 2 - 1 }, { Y2K, BILLION - 1 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = BILLION / 2 - 1; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = BILLION - 1; nap (); ASSERT (func (BASE "link", ts) == 0); ASSERT (lstat (BASE "link", &st2) == 0); @@ -147,7 +165,11 @@ test_lutimens (int (*func) (char const *, struct timespec const *), bool print) /* Play with UTIME_OMIT, UTIME_NOW. */ { struct stat st3; - struct timespec ts[2] = { { BILLION, UTIME_OMIT }, { 0, UTIME_NOW } }; + struct timespec ts[2]; + ts[0].tv_sec = BILLION; + ts[0].tv_nsec = UTIME_OMIT; + ts[1].tv_sec = 0; + ts[1].tv_nsec = UTIME_NOW; nap (); ASSERT (func (BASE "link", ts) == 0); ASSERT (lstat (BASE "link", &st3) == 0); @@ -181,7 +203,10 @@ test_lutimens (int (*func) (char const *, struct timespec const *), bool print) ASSERT (symlink (BASE "dir", BASE "link") == 0); ASSERT (mkdir (BASE "dir", 0700) == 0); { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1] = ts[0]; ASSERT (func (BASE "link/", ts) == 0); } /* On cygwin 1.5, stat() changes atime of directories, so only check diff --git a/tests/test-utimens.h b/tests/test-utimens.h index 8af2efe..ff53875 100644 --- a/tests/test-utimens.h +++ b/tests/test-utimens.h @@ -66,19 +66,30 @@ test_utimens (int (*func) (char const *, struct timespec const *), bool print) ASSERT (func ("", NULL) == -1); ASSERT (errno == ENOENT); { - struct timespec ts[2] = { { Y2K, UTIME_BOGUS_POS }, { Y2K, 0 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = UTIME_BOGUS_POS; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = 0; errno = 0; ASSERT (func (BASE "file", ts) == -1); ASSERT (errno == EINVAL); } { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, UTIME_BOGUS_NEG } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = UTIME_BOGUS_NEG; errno = 0; ASSERT (func (BASE "file", ts) == -1); ASSERT (errno == EINVAL); } { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1] = ts[0]; errno = 0; ASSERT (func (BASE "file/", ts) == -1); ASSERT (errno == ENOTDIR || errno == EINVAL); @@ -90,7 +101,11 @@ test_utimens (int (*func) (char const *, struct timespec const *), bool print) /* Set both times. */ { - struct timespec ts[2] = { { Y2K, BILLION / 2 - 1 }, { Y2K, BILLION - 1 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = BILLION / 2 - 1; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = BILLION - 1; ASSERT (func (BASE "file", ts) == 0); ASSERT (stat (BASE "file", &st2) == 0); ASSERT (st2.st_atime == Y2K); @@ -106,7 +121,11 @@ test_utimens (int (*func) (char const *, struct timespec const *), bool print) /* Play with UTIME_OMIT, UTIME_NOW. */ { struct stat st3; - struct timespec ts[2] = { { BILLION, UTIME_OMIT }, { 0, UTIME_NOW } }; + struct timespec ts[2]; + ts[0].tv_sec = BILLION; + ts[0].tv_nsec = UTIME_OMIT; + ts[1].tv_sec = 0; + ts[1].tv_nsec = UTIME_NOW; nap (); ASSERT (func (BASE "file", ts) == 0); ASSERT (stat (BASE "file", &st3) == 0); @@ -145,7 +164,10 @@ test_utimens (int (*func) (char const *, struct timespec const *), bool print) ASSERT (func (BASE "link/", NULL) == -1); ASSERT (errno == ENOTDIR); { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } }; + struct timespec ts[2]; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1] = ts[0]; ASSERT (func (BASE "link", ts) == 0); ASSERT (lstat (BASE "link", &st2) == 0); /* Can't compare atimes, since lstat() changes symlink atime on cygwin. */ diff --git a/tests/test-utimensat.c b/tests/test-utimensat.c index de5ae5a..e5a3685 100644 --- a/tests/test-utimensat.c +++ b/tests/test-utimensat.c @@ -101,8 +101,12 @@ main (void) ASSERT (utimensat (fd, ".", NULL, 0) == -1); ASSERT (errno == ENOTDIR); { - struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } }; + struct timespec ts[2]; struct stat st; + ts[0].tv_sec = Y2K; + ts[0].tv_nsec = 0; + ts[1].tv_sec = Y2K; + ts[1].tv_nsec = 0; ASSERT (utimensat (dfd, BASE "dir/file", ts, AT_SYMLINK_NOFOLLOW) == 0); ASSERT (stat ("file", &st) == 0); ASSERT (st.st_atime == Y2K); -- 2.7.4