From: Eric Blake Date: Wed, 18 Nov 2009 13:59:44 +0000 (-0700) Subject: utimens: fix regression on Solaris X-Git-Tag: stable/20091120~9 X-Git-Url: https://erislabs.net/gitweb/?a=commitdiff_plain;h=72abcbb073b9ea67920501360a3935c95cc2cdad;p=gnulib.git utimens: fix regression on Solaris Revert commit 26c5fd742f. Solaris lacks futimens and futimes, so futimesat is the only way to change fd timestamps. But since FreeBSD futimesat can't change fd timestamps, we need a configure check to avoid the crash there. * m4/utimens.m4 (gl_UTIMENS): Check for BSD bug. * lib/utimens.c (fdutimens): Revert 2009-11-08 change; Solaris 10 can only change fd timestamps via futimesat. Instead, use an additional witness macro to avoid BSD bug. Reported by Jim Meyering. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index 2975adc8b..46dd66001 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-11-18 Eric Blake + + utimens: fix regression on Solaris + * m4/utimens.m4 (gl_UTIMENS): Check for BSD bug. + * lib/utimens.c (fdutimens): Revert 2009-11-08 change; Solaris 10 + can only change fd timestamps via futimesat. Instead, use an + additional witness macro to avoid BSD bug. + Reported by Jim Meyering. + 2009-11-17 Simon Josefsson * gnulib-tool: Support LGPLv3+ licenses in module files. Tiny diff --git a/lib/utimens.c b/lib/utimens.c index bd482d7d0..eb63487c4 100644 --- a/lib/utimens.c +++ b/lib/utimens.c @@ -280,9 +280,9 @@ fdutimens (char const *file, int fd, struct timespec const timespec[2]) } else { - /* If futimesat (above) or futimes fails here, don't try to speed - things up by returning right away. glibc can incorrectly fail - with errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0 + /* If futimesat or futimes fails here, don't try to speed things + up by returning right away. glibc can incorrectly fail with + errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0 in high security mode doesn't allow ordinary users to read /proc/self, so glibc incorrectly fails with errno == EACCES. If errno == EIO, EPERM, or EROFS, it's probably safe to fail @@ -290,7 +290,10 @@ fdutimens (char const *file, int fd, struct timespec const timespec[2]) worth optimizing, and who knows what other messed-up systems are out there? So play it safe and fall back on the code below. */ -# if HAVE_FUTIMES +# if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG + if (futimesat (fd, NULL, t) == 0) + return 0; +# elif HAVE_FUTIMES if (futimes (fd, t) == 0) return 0; # endif @@ -299,7 +302,8 @@ fdutimens (char const *file, int fd, struct timespec const timespec[2]) if (!file) { -#if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES)) +#if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \ + || (HAVE_WORKING_UTIMES && HAVE_FUTIMES)) errno = ENOSYS; #endif return -1; diff --git a/m4/utimens.m4 b/m4/utimens.m4 index 381d087d2..35ef9490a 100644 --- a/m4/utimens.m4 +++ b/m4/utimens.m4 @@ -4,7 +4,7 @@ dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. -dnl serial 3 +dnl serial 4 AC_DEFUN([gl_UTIMENS], [ @@ -15,4 +15,28 @@ AC_DEFUN([gl_UTIMENS], AC_REQUIRE([gl_CHECK_TYPE_STRUCT_TIMESPEC]) AC_REQUIRE([gl_CHECK_TYPE_STRUCT_UTIMBUF]) AC_CHECK_FUNCS_ONCE([futimes futimesat futimens utimensat lutimes]) + + if test $ac_cv_func_futimens = no && test $ac_cv_func_futimesat = yes; then + dnl FreeBSD 8.0-rc2 mishandles futimesat(fd,NULL,time). It is not + dnl standardized, but Solaris implemented it first and uses it as + dnl its only means to set fd time. + AC_CACHE_CHECK([whether futimesat handles NULL file], + [gl_cv_func_futimesat_works], + [touch conftest.file + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +]], [[ int fd = open ("conftest.file", O_RDWR); + if (fd < 0) return 1; + if (futimesat (fd, NULL, NULL)) return 2; + ]])], + [gl_cv_func_futimesat_works=yes], + [gl_cv_func_futimesat_works=no], + [gl_cv_func_futimesat_works="guessing no"]) + rm -f conftest.file]) + if test "$gl_cv_func_futimesat_works" != yes; then + AC_DEFINE([FUTIMESAT_NULL_BUG], [1], + [Define to 1 if futimesat mishandles a NULL file name.]) + fi + fi ])