annotate lib/utimens.c @ 12525:53f80a530574

futimens, utimensat: work around ntfs-3g bug With ntfs-3g, use of a single UTIME_OMIT failed to make any change to the remaining two timestamps. Furthermore, the previous fix for ctime happens to be specific to xfs, rather than global to the kernel. Therefore, to be valid, a cache would have to be per-device, which gets too expensive, especially considering that the cost of a preparatory stat pulls the file into kernel cache to speed up the resulting utimensat. So, blindly massage UTIME_OMIT on Linux, even on working filesystems like ext4. The bugs in xfs and ntfs-3g were reported to the kernel folks, and fixes written, but it will be several years before gnulib can assume that file systems in use have picked up the fixes. * lib/utimensat.c (rpl_utimensat): Drop attempts to cache whether a ctime bug is present, and expand workaround to cover ntfs-3g. * lib/utimens.c (fdutimens, lutimens): Likewise. (utimensat_ctime_really, detect_ctime_bug): Drop cache mechanism. (validate_timespec): Adjust return value. * m4/futimens.m4 (gl_FUNC_FUTIMENS): Update comment. * m4/utimensat.m4 (gl_FUNC_UTIMENSAT): Likewise. Reported by ctrn3e8 <ctrn3e8@gmail.com>. Signed-off-by: Eric Blake <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Wed, 30 Dec 2009 06:48:46 -0700
parents b5e42ef33b49
children 0774f328f2ff
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6734
3e5ad4566013 * utimens.c (futimens): glibc futimesat messes up if /proc
Paul Eggert <eggert@cs.ucla.edu>
parents: 6440
diff changeset
1 /* Set file access and modification times.
3e5ad4566013 * utimens.c (futimens): glibc futimesat messes up if /proc
Paul Eggert <eggert@cs.ucla.edu>
parents: 6440
diff changeset
2
12518
b5e42ef33b49 update nearly all FSF copyright year lists to include 2009
Jim Meyering <meyering@redhat.com>
parents: 12467
diff changeset
3 Copyright (C) 2003-2009 Free Software Foundation, Inc.
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
4
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8842
diff changeset
5 This program is free software: you can redistribute it and/or modify it
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
6 under the terms of the GNU General Public License as published by the
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8842
diff changeset
7 Free Software Foundation; either version 3 of the License, or any
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
8 later version.
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
9
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
10 This program is distributed in the hope that it will be useful,
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
13 GNU General Public License for more details.
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
14
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
15 You should have received a copy of the GNU General Public License
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 8842
diff changeset
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
17
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
18 /* Written by Paul Eggert. */
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
19
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
20 /* derived from a function in touch.c */
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
21
7302
8a1a9361108c * _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents: 6819
diff changeset
22 #include <config.h>
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
23
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
24 #include "utimens.h"
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
25
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
26 #include <assert.h>
5589
6ddb405e16b6 (futimens): Account for the fact that futimes
Paul Eggert <eggert@cs.ucla.edu>
parents: 5485
diff changeset
27 #include <errno.h>
6283
b377d8796118 * lib/utimens.c (futimens): Use futimesat if available.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5848
diff changeset
28 #include <fcntl.h>
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
29 #include <stdbool.h>
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
30 #include <sys/stat.h>
7897
b7a83a69ac23 * MODULES.html.sh (Support for systems lacking POSIX:2001): New
Paul Eggert <eggert@cs.ucla.edu>
parents: 7713
diff changeset
31 #include <sys/time.h>
6322
716071856296 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6297
diff changeset
32 #include <unistd.h>
5589
6ddb405e16b6 (futimens): Account for the fact that futimes
Paul Eggert <eggert@cs.ucla.edu>
parents: 5485
diff changeset
33
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
34 #include "stat-time.h"
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
35 #include "timespec.h"
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
36
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
37 #if HAVE_UTIME_H
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
38 # include <utime.h>
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
39 #endif
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
40
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
41 /* Some systems (even some that do have <utime.h>) don't declare this
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
42 structure anywhere. */
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
43 #ifndef HAVE_STRUCT_UTIMBUF
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
44 struct utimbuf
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
45 {
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
46 long actime;
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
47 long modtime;
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
48 };
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
49 #endif
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
50
12174
73f2681e0524 utimensat: new module
Eric Blake <ebb9@byu.net>
parents: 12173
diff changeset
51 /* Avoid recursion with rpl_futimens or rpl_utimensat. */
12162
fe82ecf4f214 futimens: new module
Eric Blake <ebb9@byu.net>
parents: 12161
diff changeset
52 #undef futimens
12174
73f2681e0524 utimensat: new module
Eric Blake <ebb9@byu.net>
parents: 12173
diff changeset
53 #undef utimensat
12162
fe82ecf4f214 futimens: new module
Eric Blake <ebb9@byu.net>
parents: 12161
diff changeset
54
12194
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
55 /* Solaris 9 mistakenly succeeds when given a non-directory with a
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
56 trailing slash. Force the use of rpl_stat for a fix. */
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
57 #ifndef REPLACE_FUNC_STAT_FILE
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
58 # define REPLACE_FUNC_STAT_FILE 0
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
59 #endif
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
60
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
61 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
62 /* Cache variables for whether the utimensat syscall works; used to
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
63 avoid calling the syscall if we know it will just fail with ENOSYS,
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
64 and to avoid unnecessary work in massaging timestamps if the
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
65 syscall will work. Multiple variables are needed, to distinguish
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
66 between the following scenarios on Linux:
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
67 utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
68 kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
69 kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
70 kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
71 utimensat completely works
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
72 For each cache variable: 0 = unknown, 1 = yes, -1 = no. */
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
73 static int utimensat_works_really;
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
74 static int lutimensat_works_really;
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
75 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
76
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
77 /* Validate the requested timestamps. Return 0 if the resulting
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
78 timespec can be used for utimensat (after possibly modifying it to
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
79 work around bugs in utimensat). Return a positive value if the
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
80 timespec needs further adjustment based on stat results: 1 if any
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
81 adjustment is needed for utimes, and 2 if any adjustment is needed
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
82 for Linux utimensat. Return -1, with errno set to EINVAL, if
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
83 timespec is out of range. */
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
84 static int
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
85 validate_timespec (struct timespec timespec[2])
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
86 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
87 int result = 0;
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
88 int utime_omit_count = 0;
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
89 assert (timespec);
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
90 if ((timespec[0].tv_nsec != UTIME_NOW
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
91 && timespec[0].tv_nsec != UTIME_OMIT
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
92 && (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec))
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
93 || (timespec[1].tv_nsec != UTIME_NOW
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
94 && timespec[1].tv_nsec != UTIME_OMIT
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
95 && (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec)))
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
96 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
97 errno = EINVAL;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
98 return -1;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
99 }
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
100 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
101 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
102 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
103 fails to bump ctime. */
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
104 if (timespec[0].tv_nsec == UTIME_NOW
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
105 || timespec[0].tv_nsec == UTIME_OMIT)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
106 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
107 timespec[0].tv_sec = 0;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
108 result = 1;
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
109 if (timespec[0].tv_nsec == UTIME_OMIT)
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
110 utime_omit_count++;
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
111 }
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
112 if (timespec[1].tv_nsec == UTIME_NOW
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
113 || timespec[1].tv_nsec == UTIME_OMIT)
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
114 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
115 timespec[1].tv_sec = 0;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
116 result = 1;
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
117 if (timespec[1].tv_nsec == UTIME_OMIT)
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
118 utime_omit_count++;
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
119 }
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
120 return result + (utime_omit_count == 1);
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
121 }
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
122
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
123 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
124 buffer STATBUF to obtain the current timestamps of the file. If
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
125 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
126 permissions issues). If both times are UTIME_OMIT, return true
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
127 (nothing further beyond the prior collection of STATBUF is
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
128 necessary); otherwise return false. */
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
129 static bool
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
130 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
131 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
132 struct timespec *timespec = *ts;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
133 if (timespec[0].tv_nsec == UTIME_OMIT
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
134 && timespec[1].tv_nsec == UTIME_OMIT)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
135 return true;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
136 if (timespec[0].tv_nsec == UTIME_NOW
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
137 && timespec[1].tv_nsec == UTIME_NOW)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
138 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
139 *ts = NULL;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
140 return false;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
141 }
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
142
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
143 if (timespec[0].tv_nsec == UTIME_OMIT)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
144 timespec[0] = get_stat_atime (statbuf);
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
145 else if (timespec[0].tv_nsec == UTIME_NOW)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
146 gettime (&timespec[0]);
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
147
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
148 if (timespec[1].tv_nsec == UTIME_OMIT)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
149 timespec[1] = get_stat_mtime (statbuf);
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
150 else if (timespec[1].tv_nsec == UTIME_NOW)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
151 gettime (&timespec[1]);
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
152
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
153 return false;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
154 }
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
155
5485
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
156 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
157 TIMESPEC[0] and TIMESPEC[1], respectively.
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
158 FD must be either negative -- in which case it is ignored --
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
159 or a file descriptor that is open on FILE.
6297
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
160 If FD is nonnegative, then FILE can be NULL, which means
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
161 use just futimes (or equivalent) instead of utimes (or equivalent),
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
162 and fail if on an old system without futimes (or equivalent).
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
163 If TIMESPEC is null, set the time stamps to the current time.
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
164 Return 0 on success, -1 (setting errno) on failure. */
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
165
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
166 int
12161
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
167 fdutimens (char const *file, int fd, struct timespec const timespec[2])
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
168 {
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
169 struct timespec adjusted_timespec[2];
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
170 struct timespec *ts = timespec ? adjusted_timespec : NULL;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
171 int adjustment_needed = 0;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
172
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
173 if (ts)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
174 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
175 adjusted_timespec[0] = timespec[0];
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
176 adjusted_timespec[1] = timespec[1];
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
177 adjustment_needed = validate_timespec (ts);
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
178 }
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
179 if (adjustment_needed < 0)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
180 return -1;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
181
12157
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
182 /* Require that at least one of FD or FILE are valid. Works around
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
183 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
184 than failing. */
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
185 if (!file)
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
186 {
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
187 if (fd < 0)
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
188 {
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
189 errno = EBADF;
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
190 return -1;
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
191 }
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
192 if (dup2 (fd, fd) != fd)
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
193 return -1;
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
194 }
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
195
7712
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
196 /* Some Linux-based NFS clients are buggy, and mishandle time stamps
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
197 of files in NFS file systems in some cases. We have no
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
198 configure-time test for this, but please see
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
199 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
200 some of the problems with Linux 2.6.16. If this affects you,
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
201 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
202 help in some cases, albeit at a cost in performance. But you
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
203 really should upgrade your kernel to a fixed version, since the
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
204 problem affects many applications. */
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
205
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
206 #if HAVE_BUGGY_NFS_TIME_STAMPS
7713
064005e1c3c3 Prefer fd < 0 to ! (0 <= fd).
Paul Eggert <eggert@cs.ucla.edu>
parents: 7712
diff changeset
207 if (fd < 0)
064005e1c3c3 Prefer fd < 0 to ! (0 <= fd).
Paul Eggert <eggert@cs.ucla.edu>
parents: 7712
diff changeset
208 sync ();
064005e1c3c3 Prefer fd < 0 to ! (0 <= fd).
Paul Eggert <eggert@cs.ucla.edu>
parents: 7712
diff changeset
209 else
7712
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
210 fsync (fd);
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
211 #endif
aead3397193a * lib/utimens.c (futimens) [HAVE_BUGGY_NFS_TIME_STAMPS]: Add a
Paul Eggert <eggert@cs.ucla.edu>
parents: 7302
diff changeset
212
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
213 /* POSIX 2008 added two interfaces to set file timestamps with
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
214 nanosecond resolution; newer Linux implements both functions via
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
215 a single syscall. We provide a fallback for ENOSYS (for example,
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
216 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
217 running on Linux 2.6.18 kernel). */
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
218 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
219 if (0 <= utimensat_works_really)
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
220 {
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
221 int result;
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
222 # if __linux__
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
223 struct stat st;
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
224 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
225 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
226 but work if both times are either explicitly specified or
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
227 UTIME_NOW. Work around it with a preparatory [f]stat prior
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
228 to calling futimens/utimensat; fortunately, there is not much
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
229 timing impact due to the extra syscall even on file systems
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
230 where UTIME_OMIT would have worked. FIXME: Simplify this in
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
231 2012, when file system bugs are no longer common. */
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
232 if (adjustment_needed == 2)
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
233 {
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
234 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
235 return -1;
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
236 if (ts[0].tv_nsec == UTIME_OMIT)
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
237 ts[0] = get_stat_atime (&st);
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
238 else if (ts[1].tv_nsec == UTIME_OMIT)
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
239 ts[1] = get_stat_mtime (&st);
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
240 }
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
241 # endif /* __linux__ */
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
242 # if HAVE_UTIMENSAT
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
243 if (fd < 0)
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
244 {
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
245 result = utimensat (AT_FDCWD, file, ts, 0);
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
246 # ifdef __linux__
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
247 /* Work around a kernel bug:
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
248 http://bugzilla.redhat.com/442352
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
249 http://bugzilla.redhat.com/449910
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
250 It appears that utimensat can mistakenly return 280 rather
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
251 than -1 upon ENOSYS failure.
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
252 FIXME: remove in 2010 or whenever the offending kernels
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
253 are no longer in common use. */
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
254 if (0 < result)
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
255 errno = ENOSYS;
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
256 # endif /* __linux__ */
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
257 if (result == 0 || errno != ENOSYS)
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
258 {
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
259 utimensat_works_really = 1;
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
260 return result;
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
261 }
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
262 }
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
263 # endif /* HAVE_UTIMENSAT */
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
264 # if HAVE_FUTIMENS
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
265 {
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
266 result = futimens (fd, ts);
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
267 # ifdef __linux__
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
268 /* Work around the same bug as above. */
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
269 if (0 < result)
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
270 errno = ENOSYS;
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
271 # endif /* __linux__ */
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
272 if (result == 0 || errno != ENOSYS)
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
273 {
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
274 utimensat_works_really = 1;
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
275 return result;
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
276 }
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
277 }
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
278 # endif /* HAVE_FUTIMENS */
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
279 }
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
280 utimensat_works_really = -1;
12353
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
281 lutimensat_works_really = -1;
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
282 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
283
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
284 /* The platform lacks an interface to set file timestamps with
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
285 nanosecond resolution, so do the best we can, discarding any
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
286 fractional part of the timestamp. */
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
287
12194
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
288 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
289 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
290 struct stat st;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
291 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
292 return -1;
12194
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
293 if (ts && update_timespec (&st, &ts))
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
294 return 0;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
295 }
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
296
6297
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
297 {
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
298 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
299 struct timeval timeval[2];
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
300 struct timeval const *t;
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
301 if (ts)
6297
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
302 {
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
303 timeval[0].tv_sec = ts[0].tv_sec;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
304 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
305 timeval[1].tv_sec = ts[1].tv_sec;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
306 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
307 t = timeval;
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
308 }
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
309 else
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
310 t = NULL;
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
311
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
312 if (fd < 0)
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
313 {
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
314 # if HAVE_FUTIMESAT
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
315 return futimesat (AT_FDCWD, file, t);
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
316 # endif
6297
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
317 }
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
318 else
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
319 {
12317
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
320 /* If futimesat or futimes fails here, don't try to speed things
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
321 up by returning right away. glibc can incorrectly fail with
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
322 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
323 in high security mode doesn't allow ordinary users to read
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
324 /proc/self, so glibc incorrectly fails with errno == EACCES.
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
325 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
326 right away, but these cases are rare enough that they're not
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
327 worth optimizing, and who knows what other messed-up systems
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
328 are out there? So play it safe and fall back on the code
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
329 below. */
12317
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
330 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
331 if (futimesat (fd, NULL, t) == 0)
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
332 return 0;
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
333 # elif HAVE_FUTIMES
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
334 if (futimes (fd, t) == 0)
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
335 return 0;
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
336 # endif
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
337 }
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
338 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
339
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
340 if (!file)
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
341 {
12317
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
342 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
407921985bc0 utimens: fix regression on Solaris
Eric Blake <ebb9@byu.net>
parents: 12256
diff changeset
343 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
344 errno = ENOSYS;
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
345 #endif
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
346 return -1;
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
347 }
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
348
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
349 #if HAVE_WORKING_UTIMES
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
350 return utimes (file, t);
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
351 #else
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
352 {
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
353 struct utimbuf utimbuf;
12157
7fb8a2ac5948 utimens: validate futimens usage
Eric Blake <ebb9@byu.net>
parents: 12134
diff changeset
354 struct utimbuf *ut;
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
355 if (ts)
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
356 {
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
357 utimbuf.actime = ts[0].tv_sec;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
358 utimbuf.modtime = ts[1].tv_sec;
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
359 ut = &utimbuf;
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
360 }
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
361 else
12133
799664c0f270 openat, utimens: whitespace cleanup
Eric Blake <ebb9@byu.net>
parents: 11941
diff changeset
362 ut = NULL;
10133
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
363
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
364 return utime (file, ut);
bbccff5988c3 Prefer new POSIX 200x interfaces over futimesat.
Eric Blake <ebb9@byu.net>
parents: 9613
diff changeset
365 }
10154
148190ed341d Provide futimens/utimensat fallbacks for older kernels.
Eric Blake <ebb9@byu.net>
parents: 10133
diff changeset
366 #endif /* !HAVE_WORKING_UTIMES */
6297
10379892281e * utimens.c (ENOSYS): Define if not already defined.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6283
diff changeset
367 }
5147
3249aec7f48c Import from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents:
diff changeset
368 }
5485
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
369
12161
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
370 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
371 TIMESPEC[0] and TIMESPEC[1], respectively.
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
372 FD must be either negative -- in which case it is ignored --
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
373 or a file descriptor that is open on FILE.
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
374 If FD is nonnegative, then FILE can be NULL, which means
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
375 use just futimes (or equivalent) instead of utimes (or equivalent),
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
376 and fail if on an old system without futimes (or equivalent).
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
377 If TIMESPEC is null, set the time stamps to the current time.
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
378 Return 0 on success, -1 (setting errno) on failure. */
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
379
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
380 int
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
381 gl_futimens (int fd, char const *file, struct timespec const timespec[2])
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
382 {
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
383 return fdutimens (file, fd, timespec);
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
384 }
c4a167621772 utimens: introduce fdutimens
Eric Blake <ebb9@byu.net>
parents: 12160
diff changeset
385
5485
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
386 /* Set the access and modification time stamps of FILE to be
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
387 TIMESPEC[0] and TIMESPEC[1], respectively. */
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
388 int
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
389 utimens (char const *file, struct timespec const timespec[2])
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
390 {
12173
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
391 return fdutimens (file, -1, timespec);
5485
863556283cee (__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5147
diff changeset
392 }
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
393
12173
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
394 /* Set the access and modification time stamps of FILE to be
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
395 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
396 symlinks. Fail with ENOSYS if the platform does not support
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
397 changing symlink timestamps, but FILE was a symlink. */
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
398 int
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
399 lutimens (char const *file, struct timespec const timespec[2])
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
400 {
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
401 struct timespec adjusted_timespec[2];
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
402 struct timespec *ts = timespec ? adjusted_timespec : NULL;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
403 int adjustment_needed = 0;
12173
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
404 struct stat st;
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
405
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
406 if (ts)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
407 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
408 adjusted_timespec[0] = timespec[0];
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
409 adjusted_timespec[1] = timespec[1];
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
410 adjustment_needed = validate_timespec (ts);
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
411 }
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
412 if (adjustment_needed < 0)
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
413 return -1;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
414
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
415 /* The Linux kernel did not support symlink timestamps until
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
416 utimensat, in version 2.6.22, so we don't need to mimic
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
417 gl_futimens' worry about buggy NFS clients. But we do have to
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
418 worry about bogus return values. */
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
419
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
420 #if HAVE_UTIMENSAT
12353
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
421 if (0 <= lutimensat_works_really)
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
422 {
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
423 int result;
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
424 # if __linux__
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
425 struct stat st;
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
426 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
427 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
428 but work if both times are either explicitly specified or
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
429 UTIME_NOW. Work around it with a preparatory lstat prior to
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
430 calling utimensat; fortunately, there is not much timing
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
431 impact due to the extra syscall even on file systems where
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
432 UTIME_OMIT would have worked. FIXME: Simplify this in 2012,
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
433 when file system bugs are no longer common. */
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
434 if (adjustment_needed == 2)
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
435 {
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
436 if (lstat (file, &st))
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
437 return -1;
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
438 if (ts[0].tv_nsec == UTIME_OMIT)
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
439 ts[0] = get_stat_atime (&st);
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
440 else if (ts[1].tv_nsec == UTIME_OMIT)
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
441 ts[1] = get_stat_mtime (&st);
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
442 }
12525
53f80a530574 futimens, utimensat: work around ntfs-3g bug
Eric Blake <ebb9@byu.net>
parents: 12518
diff changeset
443 # endif /* __linux__ */
12467
912bdb1c31fb utimens: work around Linux ctime bug
Eric Blake <ebb9@byu.net>
parents: 12447
diff changeset
444 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
445 # ifdef __linux__
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
446 /* Work around a kernel bug:
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
447 http://bugzilla.redhat.com/442352
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
448 http://bugzilla.redhat.com/449910
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
449 It appears that utimensat can mistakenly return 280 rather
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
450 than -1 upon ENOSYS failure.
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
451 FIXME: remove in 2010 or whenever the offending kernels
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
452 are no longer in common use. */
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
453 if (0 < result)
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
454 errno = ENOSYS;
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
455 # endif
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
456 if (result == 0 || errno != ENOSYS)
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
457 {
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
458 utimensat_works_really = 1;
12353
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
459 lutimensat_works_really = 1;
12172
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
460 return result;
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
461 }
52ebfd595434 utimens: cache whether utimensat syscall works
Eric Blake <ebb9@byu.net>
parents: 12162
diff changeset
462 }
12353
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
463 lutimensat_works_really = -1;
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
464 #endif /* HAVE_UTIMENSAT */
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
465
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
466 /* The platform lacks an interface to set file timestamps with
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
467 nanosecond resolution, so do the best we can, discarding any
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
468 fractional part of the timestamp. */
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
469
12194
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
470 if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
471 {
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
472 if (lstat (file, &st))
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
473 return -1;
12194
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
474 if (ts && update_timespec (&st, &ts))
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
475 return 0;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
476 }
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
477
12353
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
478 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
479 no point trying lutimes if utimensat failed with ENOSYS. */
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
480 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
481 {
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
482 struct timeval timeval[2];
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
483 struct timeval const *t;
12447
b79168ca6a08 utimens: one more try at avoiding compiler warning
Eric Blake <ebb9@byu.net>
parents: 12377
diff changeset
484 int result;
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
485 if (ts)
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
486 {
12160
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
487 timeval[0].tv_sec = ts[0].tv_sec;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
488 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
489 timeval[1].tv_sec = ts[1].tv_sec;
d0732ed2dd55 utimens: add UTIME_NOW and UTIME_OMIT support
Eric Blake <ebb9@byu.net>
parents: 12158
diff changeset
490 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
491 t = timeval;
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
492 }
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
493 else
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
494 t = NULL;
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
495
12353
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
496 result = lutimes (file, t);
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
497 if (result == 0 || errno != ENOSYS)
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
498 return result;
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
499 }
12353
fd066c132b7d utimens: work around older Linux failure with symlinks
Eric Blake <ebb9@byu.net>
parents: 12317
diff changeset
500 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
501
12173
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
502 /* Out of luck for symlinks, but we still handle regular files. */
12194
16c7c4fa9754 utimensat: work around Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents: 12174
diff changeset
503 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
12173
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
504 return -1;
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
505 if (!S_ISLNK (st.st_mode))
efdb2ab5743f utimens: let lutimens work on non-symlinks
Eric Blake <ebb9@byu.net>
parents: 12172
diff changeset
506 return fdutimens (file, -1, ts);
12158
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
507 errno = ENOSYS;
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
508 return -1;
899dd13e9f8b utimens: add lutimens interface
Eric Blake <ebb9@byu.net>
parents: 12157
diff changeset
509 }