X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gnu%2Futimens.c;h=116070cd260464a53a8a170d7887c1525caed88a;hb=4aa85f09e755fc827cd5ab6225f20c83cd42245d;hp=6582706e9b69cb9b67fde1bfb6b14734f388f22f;hpb=1a44d77d50f4fb37c0410eed04b82303624ea2ec;p=debian%2Ftar diff --git a/gnu/utimens.c b/gnu/utimens.c index 6582706e..116070cd 100644 --- a/gnu/utimens.c +++ b/gnu/utimens.c @@ -2,7 +2,7 @@ /* DO NOT EDIT! GENERATED AUTOMATICALLY! */ /* Set file access and modification times. - Copyright (C) 2003-2011 Free Software Foundation, Inc. + Copyright (C) 2003-2014 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 @@ -23,6 +23,7 @@ #include +#define _GL_UTIMENS_INLINE _GL_EXTERN_INLINE #include "utimens.h" #include @@ -91,10 +92,12 @@ validate_timespec (struct timespec timespec[2]) assert (timespec); if ((timespec[0].tv_nsec != UTIME_NOW && timespec[0].tv_nsec != UTIME_OMIT - && (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec)) + && ! (0 <= timespec[0].tv_nsec + && timespec[0].tv_nsec < TIMESPEC_RESOLUTION)) || (timespec[1].tv_nsec != UTIME_NOW && timespec[1].tv_nsec != UTIME_OMIT - && (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec))) + && ! (0 <= timespec[1].tv_nsec + && timespec[1].tv_nsec < TIMESPEC_RESOLUTION))) { errno = EINVAL; return -1; @@ -182,18 +185,13 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2]) if (adjustment_needed < 0) return -1; - /* Require that at least one of FD or FILE are valid. Works around + /* Require that at least one of FD or FILE are potentially valid, to avoid a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather than failing. */ - if (!file) + if (fd < 0 && !file) { - if (fd < 0) - { - errno = EBADF; - return -1; - } - if (dup2 (fd, fd) != fd) - return -1; + errno = EBADF; + return -1; } /* Some Linux-based NFS clients are buggy, and mishandle time stamps @@ -222,15 +220,19 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2]) if (0 <= utimensat_works_really) { int result; -# if __linux__ +# if __linux__ || __sun /* As recently as Linux kernel 2.6.32 (Dec 2009), several file systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, but work if both times are either explicitly specified or UTIME_NOW. Work around it with a preparatory [f]stat prior to calling futimens/utimensat; fortunately, there is not much timing impact due to the extra syscall even on file systems - where UTIME_OMIT would have worked. FIXME: Simplify this in - 2012, when file system bugs are no longer common. */ + where UTIME_OMIT would have worked. + + The same bug occurs in Solaris 11.1 (Apr 2013). + + FIXME: Simplify this for Linux in 2016 and for Solaris in + 2024, when file system bugs are no longer common. */ if (adjustment_needed == 2) { if (fd < 0 ? stat (file, &st) : fstat (fd, &st)) @@ -242,7 +244,7 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2]) /* Note that st is good, in case utimensat gives ENOSYS. */ adjustment_needed++; } -# endif /* __linux__ */ +# endif # if HAVE_UTIMENSAT if (fd < 0) { @@ -451,15 +453,19 @@ lutimens (char const *file, struct timespec const timespec[2]) if (0 <= lutimensat_works_really) { int result; -# if __linux__ +# if __linux__ || __sun /* As recently as Linux kernel 2.6.32 (Dec 2009), several file systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, but work if both times are either explicitly specified or UTIME_NOW. Work around it with a preparatory lstat prior to calling utimensat; fortunately, there is not much timing impact due to the extra syscall even on file systems where - UTIME_OMIT would have worked. FIXME: Simplify this in 2012, - when file system bugs are no longer common. */ + UTIME_OMIT would have worked. + + The same bug occurs in Solaris 11.1 (Apr 2013). + + FIXME: Simplify this for Linux in 2016 and for Solaris in + 2024, when file system bugs are no longer common. */ if (adjustment_needed == 2) { if (lstat (file, &st)) @@ -471,7 +477,7 @@ lutimens (char const *file, struct timespec const timespec[2]) /* Note that st is good, in case utimensat gives ENOSYS. */ adjustment_needed++; } -# endif /* __linux__ */ +# endif result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW); # ifdef __linux__ /* Work around a kernel bug: