Mercurial > hg > octave-shane > gnulib-hg
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 |
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 | 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 | 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 | 8 later version. |
9 | |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
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 | 17 |
18 /* Written by Paul Eggert. */ | |
19 | |
20 /* derived from a function in touch.c */ | |
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 | 23 |
24 #include "utimens.h" | |
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 | 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 | 37 #if HAVE_UTIME_H |
38 # include <utime.h> | |
39 #endif | |
40 | |
41 /* Some systems (even some that do have <utime.h>) don't declare this | |
42 structure anywhere. */ | |
43 #ifndef HAVE_STRUCT_UTIMBUF | |
44 struct utimbuf | |
45 { | |
46 long actime; | |
47 long modtime; | |
48 }; | |
49 #endif | |
50 | |
12174 | 51 /* Avoid recursion with rpl_futimens or rpl_utimensat. */ |
12162 | 52 #undef futimens |
12174 | 53 #undef utimensat |
12162 | 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 (×pec[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 (×pec[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 | 165 |
166 int | |
12161 | 167 fdutimens (char const *file, int fd, struct timespec const timespec[2]) |
5147 | 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 | 285 nanosecond resolution, so do the best we can, discarding any |
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 | 368 } |
5485
863556283cee
(__attribute__, ATTRIBUTE_UNUSED): New macros.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5147
diff
changeset
|
369 |
12161 | 370 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be |
371 TIMESPEC[0] and TIMESPEC[1], respectively. | |
372 FD must be either negative -- in which case it is ignored -- | |
373 or a file descriptor that is open on FILE. | |
374 If FD is nonnegative, then FILE can be NULL, which means | |
375 use just futimes (or equivalent) instead of utimes (or equivalent), | |
376 and fail if on an old system without futimes (or equivalent). | |
377 If TIMESPEC is null, set the time stamps to the current time. | |
378 Return 0 on success, -1 (setting errno) on failure. */ | |
379 | |
380 int | |
381 gl_futimens (int fd, char const *file, struct timespec const timespec[2]) | |
382 { | |
383 return fdutimens (file, fd, timespec); | |
384 } | |
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 } |