X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Futimens.c;h=71bc510d86bb57db59203877a55fdd25d45ab694;hb=8badccbd46d6cbd0f1fa2014e01ce8a7cae2b272;hp=b60ec879a3a158c6820c42789bb43582e85ad926;hpb=52bcc4fca9336df9167ed2f5d0aeaeaf874302c2;p=gnulib.git diff --git a/lib/utimens.c b/lib/utimens.c index b60ec879a..71bc510d8 100644 --- a/lib/utimens.c +++ b/lib/utimens.c @@ -1,4 +1,7 @@ -/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +/* Set file access and modification times. + + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software + Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -18,14 +21,14 @@ /* derived from a function in touch.c */ -#ifdef HAVE_CONFIG_H -# include -#endif +#include #include "utimens.h" #include #include +#include +#include #if HAVE_UTIME_H # include @@ -51,8 +54,10 @@ struct utimbuf # endif #endif -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ -# define __attribute__(x) +#ifndef __attribute__ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# define __attribute__(x) +# endif #endif #ifndef ATTRIBUTE_UNUSED @@ -73,6 +78,23 @@ int futimens (int fd ATTRIBUTE_UNUSED, char const *file, struct timespec const timespec[2]) { + /* Some Linux-based NFS clients are buggy, and mishandle time stamps + of files in NFS file systems in some cases. We have no + configure-time test for this, but please see + for references to + some of the problems with Linux 2.6.16. If this affects you, + compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to + help in some cases, albeit at a cost in performance. But you + really should upgrade your kernel to a fixed version, since the + problem affects many applications. */ + +#if HAVE_BUGGY_NFS_TIME_STAMPS + if (fd < 0) + sync (); + else + fsync (fd); +#endif + /* There's currently no interface to set file timestamps with nanosecond resolution, so do the best we can, discarding any fractional part of the timestamp. */ @@ -90,40 +112,57 @@ futimens (int fd ATTRIBUTE_UNUSED, else t = NULL; + + if (fd < 0) + { # if HAVE_FUTIMESAT - return fd < 0 ? futimesat (AT_FDCWD, file, t) : futimesat (fd, NULL, t); -# elif HAVE_FUTIMES - if (0 <= fd) + return futimesat (AT_FDCWD, file, t); +# endif + } + else { + /* 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 + right away, but these cases are rare enough that they're not + 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_FUTIMESAT + if (futimesat (fd, NULL, t) == 0) + return 0; +# elif HAVE_FUTIMES if (futimes (fd, t) == 0) return 0; - - /* On GNU/Linux without the futimes syscall and without /proc - mounted, glibc futimes fails with errno == ENOENT. Fall back - on utimes if we get a weird error number like that. */ - switch (errno) - { - case EACCES: - case EIO: - case EPERM: - case EROFS: - return -1; - } - } # endif + } #endif -#if ! HAVE_FUTIMES_AT - if (!file) { +#if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES)) errno = ENOSYS; +#endif + + /* Prefer EBADF to ENOSYS if both error numbers apply. */ + if (errno == ENOSYS) + { + int fd2 = dup (fd); + int dup_errno = errno; + if (0 <= fd2) + close (fd2); + errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS); + } + return -1; } -# if HAVE_WORKING_UTIMES +#if HAVE_WORKING_UTIMES return utimes (file, t); -# else +#else { struct utimbuf utimbuf; struct utimbuf const *ut; @@ -138,8 +177,6 @@ futimens (int fd ATTRIBUTE_UNUSED, return utime (file, ut); } -# endif - #endif }