diff -urNp coreutils-8.1-orig/lib/utimens.c coreutils-8.1/lib/utimens.c --- coreutils-8.1-orig/lib/utimens.c 2009-11-18 15:57:45.000000000 +0100 +++ coreutils-8.1/lib/utimens.c 2009-11-27 13:02:03.000000000 +0100 @@ -54,10 +54,12 @@ struct utimbuf #undef utimensat #if HAVE_UTIMENSAT || HAVE_FUTIMENS -/* Cache variable for whether syscall works; used to avoid calling the - syscall if we know it will just fail with ENOSYS. 0 = unknown, 1 = - yes, -1 = no. */ +/* Cache variables for whether the utimensat syscall works; used to + avoid calling the syscall if we know it will just fail with ENOSYS. + There are some Linux kernel versions where a flag of 0 passes, but + not AT_SYMLINK_NOFOLLOW. 0 = unknown, 1 = yes, -1 = no. */ static int utimensat_works_really; +static int lutimensat_works_really; #endif /* HAVE_UTIMENSAT || HAVE_UTIMENSAT */ /* Solaris 9 mistakenly succeeds when given a non-directory with a @@ -242,6 +244,7 @@ fdutimens (char const *file, int fd, str # endif /* HAVE_FUTIMENS */ } utimensat_works_really = -1; + lutimensat_works_really = -1; #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */ /* The platform lacks an interface to set file timestamps with @@ -381,7 +384,7 @@ lutimens (char const *file, struct times worry about bogus return values. */ #if HAVE_UTIMENSAT - if (0 <= utimensat_works_really) + if (0 <= lutimensat_works_really) { int result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW); # ifdef __linux__ @@ -397,11 +400,11 @@ lutimens (char const *file, struct times # endif if (result == 0 || errno != ENOSYS) { - utimensat_works_really = 1; + lutimensat_works_really = 1; return result; } } - utimensat_works_really = -1; + lutimensat_works_really = -1; #endif /* HAVE_UTIMENSAT */ /* The platform lacks an interface to set file timestamps with @@ -416,7 +419,9 @@ lutimens (char const *file, struct times return 0; } -#if HAVE_LUTIMES +/* On Linux, lutimes is a thin wrapper around utimensat, so there is + no point trying lutimes if utimensat failed with ENOSYS. */ +#if HAVE_LUTIMES && !HAVE_UTIMENSAT { struct timeval timeval[2]; struct timeval const *t; @@ -431,9 +436,11 @@ lutimens (char const *file, struct times else t = NULL; - return lutimes (file, t); + result = lutimes (file, t); + if (result == 0 || errno != ENOSYS) + return result; } -#endif /* HAVE_LUTIMES */ +#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */ /* Out of luck for symlinks, but we still handle regular files. */ if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))