diff options
author | Eric Blake <ebb9@byu.net> | 2009-12-17 07:32:00 -0700 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2009-12-19 16:58:45 -0700 |
commit | 9a669cf64253a2b2149d7f7cc5e0664c1bc7dda9 (patch) | |
tree | eb13f397b1f14e24aa856ca20dbf15ce47e91f7b /m4 | |
parent | 68f0f1af0f2cc75615d89234494dca043e99a73d (diff) | |
download | gnulib-9a669cf64253a2b2149d7f7cc5e0664c1bc7dda9.tar.gz |
futimens, utimensat: work around Linux bug
futimens is trivial - let fdutimens do the work. utimensat
is tougher: we don't want to call into local_utimensat,
because that can cause unnecessary chdir. So we have to
repeat the logic from utimens.c.
* m4/futimens.m4 (gl_FUNC_FUTIMENS): Detect ctime bug.
* m4/utimensat.m4 (gl_FUNC_UTIMENSAT): Likewise.
* lib/utimensat.c (rpl_utimensat): Work around it.
* lib/futimens.c (rpl_futimens): Adjust comment.
Diffstat (limited to 'm4')
-rw-r--r-- | m4/futimens.m4 | 33 | ||||
-rw-r--r-- | m4/utimensat.m4 | 28 |
2 files changed, 45 insertions, 16 deletions
diff --git a/m4/futimens.m4 b/m4/futimens.m4 index 0547e7ad54..ba5d6b666f 100644 --- a/m4/futimens.m4 +++ b/m4/futimens.m4 @@ -1,4 +1,4 @@ -# serial 1 +# serial 2 # See if we need to provide futimens replacement. dnl Copyright (C) 2009 Free Software Foundation, Inc. @@ -22,17 +22,32 @@ AC_DEFUN([gl_FUNC_FUTIMENS], [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include <fcntl.h> #include <sys/stat.h> +#include <unistd.h> +]], [[struct timespec ts[2] = { { 1, UTIME_OMIT }, { 1, UTIME_NOW } }; + int fd = creat ("conftest.file", 0600); + struct stat st; + if (fd < 0) return 1; + if (futimens (AT_FDCWD, NULL)) return 2; + if (futimens (fd, ts)) return 3; + sleep (1); + ts[0].tv_nsec = UTIME_NOW; + ts[1].tv_nsec = UTIME_OMIT; + if (futimens (fd, ts)) return 4; + if (fstat (fd, &st)) return 5; + if (st.st_ctime < st.st_atime) return 6; + ]])], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #ifdef __linux__ -/* The Linux kernel added futimens in 2.6.22, but it had bugs until 2.6.26. - Always replace futimens to support older kernels. */ +/* The Linux kernel added futimens in 2.6.22, but has bugs with UTIME_OMIT + in 2.6.32. Always replace futimens to support older kernels. */ choke me #endif -]], [[struct timespec ts[2] = { { 1, UTIME_OMIT }, { 1, UTIME_OMIT } }; - if (futimens (AT_FDCWD, NULL)) return 1; - return futimens (open (".", O_RDONLY), ts);]])], - [gl_cv_func_futimens_works=yes], - [gl_cv_func_futimens_works="needs runtime check"], - [gl_cv_func_futimens_works="guessing no"])]) + ]])], + [gl_cv_func_futimens_works=yes], + [gl_cv_func_futimens_works="needs runtime check"])], + [gl_cv_func_futimens_works=no], + [gl_cv_func_futimens_works="guessing no"]) + rm -f conftest.file]) if test "$gl_cv_func_futimens_works" != yes; then REPLACE_FUTIMENS=1 AC_LIBOBJ([futimens]) diff --git a/m4/utimensat.m4 b/m4/utimensat.m4 index 2a6033f2c0..21e1ea526d 100644 --- a/m4/utimensat.m4 +++ b/m4/utimensat.m4 @@ -1,4 +1,4 @@ -# serial 1 +# serial 2 # See if we need to provide utimensat replacement. dnl Copyright (C) 2009 Free Software Foundation, Inc. @@ -22,15 +22,29 @@ AC_DEFUN([gl_FUNC_UTIMENSAT], [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include <fcntl.h> #include <sys/stat.h> +#include <unistd.h> +]], [[struct timespec ts[2] = { { 1, UTIME_OMIT }, { 1, UTIME_NOW } }; + struct stat st; + const char *f = "conftest.file"; + if (close (creat (f, 0600))) return 1; + if (utimensat (AT_FDCWD, f, NULL, AT_SYMLINK_NOFOLLOW)) return 2; + if (utimensat (AT_FDCWD, f, ts, 0)) return 3; + sleep (1); + ts[0].tv_nsec = UTIME_NOW; + ts[1].tv_nsec = UTIME_OMIT; + if (utimensat (AT_FDCWD, f, ts, 0)) return 4; + if (stat (f, &st)) return 5; + if (st.st_ctime < st.st_atime) return 6;]])], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #ifdef __linux__ -/* The Linux kernel added utimensat in 2.6.22, but it had bugs until 2.6.26. - Always replace utimensat to support older kernels. */ +/* The Linux kernel added utimensat in 2.6.22, but has bugs with UTIME_OMIT + in 2.6.32. Always replace utimensat to support older kernels. */ choke me #endif -]], [[struct timespec ts[2] = { { 1, UTIME_OMIT }, { 1, UTIME_OMIT } }; - return utimensat (AT_FDCWD, ".", NULL, AT_SYMLINK_NOFOLLOW);]])], - [gl_cv_func_utimensat_works=yes], - [gl_cv_func_utimensat_works="needs runtime check"], + ]])], + [gl_cv_func_utimensat_works=yes], + [gl_cv_func_utimensat_works="needs runtime check"])], + [gl_cv_func_utimensat_works=no], [gl_cv_func_utimensat_works="guessing no"])]) if test "$gl_cv_func_utimensat_works" != yes; then REPLACE_UTIMENSAT=1 |