1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3 /* Set file access and modification times.
5 Copyright (C) 2003-2014 Free Software Foundation, Inc.
7 This program is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 /* Written by Paul Eggert. */
22 /* derived from a function in touch.c */
26 #define _GL_UTIMENS_INLINE _GL_EXTERN_INLINE
37 #include "stat-time.h"
44 /* Some systems (even some that do have <utime.h>) don't declare this
45 structure anywhere. */
46 #ifndef HAVE_STRUCT_UTIMBUF
54 /* Avoid recursion with rpl_futimens or rpl_utimensat. */
58 /* Solaris 9 mistakenly succeeds when given a non-directory with a
59 trailing slash. Force the use of rpl_stat for a fix. */
60 #ifndef REPLACE_FUNC_STAT_FILE
61 # define REPLACE_FUNC_STAT_FILE 0
64 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
65 /* Cache variables for whether the utimensat syscall works; used to
66 avoid calling the syscall if we know it will just fail with ENOSYS,
67 and to avoid unnecessary work in massaging timestamps if the
68 syscall will work. Multiple variables are needed, to distinguish
69 between the following scenarios on Linux:
70 utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
71 kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
72 kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
73 kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
74 utimensat completely works
75 For each cache variable: 0 = unknown, 1 = yes, -1 = no. */
76 static int utimensat_works_really;
77 static int lutimensat_works_really;
78 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
80 /* Validate the requested timestamps. Return 0 if the resulting
81 timespec can be used for utimensat (after possibly modifying it to
82 work around bugs in utimensat). Return a positive value if the
83 timespec needs further adjustment based on stat results: 1 if any
84 adjustment is needed for utimes, and 2 if any adjustment is needed
85 for Linux utimensat. Return -1, with errno set to EINVAL, if
86 timespec is out of range. */
88 validate_timespec (struct timespec timespec[2])
91 int utime_omit_count = 0;
93 if ((timespec[0].tv_nsec != UTIME_NOW
94 && timespec[0].tv_nsec != UTIME_OMIT
95 && ! (0 <= timespec[0].tv_nsec
96 && timespec[0].tv_nsec < TIMESPEC_RESOLUTION))
97 || (timespec[1].tv_nsec != UTIME_NOW
98 && timespec[1].tv_nsec != UTIME_OMIT
99 && ! (0 <= timespec[1].tv_nsec
100 && timespec[1].tv_nsec < TIMESPEC_RESOLUTION)))
105 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
106 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
107 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
108 fails to bump ctime. */
109 if (timespec[0].tv_nsec == UTIME_NOW
110 || timespec[0].tv_nsec == UTIME_OMIT)
112 timespec[0].tv_sec = 0;
114 if (timespec[0].tv_nsec == UTIME_OMIT)
117 if (timespec[1].tv_nsec == UTIME_NOW
118 || timespec[1].tv_nsec == UTIME_OMIT)
120 timespec[1].tv_sec = 0;
122 if (timespec[1].tv_nsec == UTIME_OMIT)
125 return result + (utime_omit_count == 1);
128 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
129 buffer STATBUF to obtain the current timestamps of the file. If
130 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
131 permissions issues). If both times are UTIME_OMIT, return true
132 (nothing further beyond the prior collection of STATBUF is
133 necessary); otherwise return false. */
135 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
137 struct timespec *timespec = *ts;
138 if (timespec[0].tv_nsec == UTIME_OMIT
139 && timespec[1].tv_nsec == UTIME_OMIT)
141 if (timespec[0].tv_nsec == UTIME_NOW
142 && timespec[1].tv_nsec == UTIME_NOW)
148 if (timespec[0].tv_nsec == UTIME_OMIT)
149 timespec[0] = get_stat_atime (statbuf);
150 else if (timespec[0].tv_nsec == UTIME_NOW)
151 gettime (×pec[0]);
153 if (timespec[1].tv_nsec == UTIME_OMIT)
154 timespec[1] = get_stat_mtime (statbuf);
155 else if (timespec[1].tv_nsec == UTIME_NOW)
156 gettime (×pec[1]);
161 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
162 TIMESPEC[0] and TIMESPEC[1], respectively.
163 FD must be either negative -- in which case it is ignored --
164 or a file descriptor that is open on FILE.
165 If FD is nonnegative, then FILE can be NULL, which means
166 use just futimes (or equivalent) instead of utimes (or equivalent),
167 and fail if on an old system without futimes (or equivalent).
168 If TIMESPEC is null, set the time stamps to the current time.
169 Return 0 on success, -1 (setting errno) on failure. */
172 fdutimens (int fd, char const *file, struct timespec const timespec[2])
174 struct timespec adjusted_timespec[2];
175 struct timespec *ts = timespec ? adjusted_timespec : NULL;
176 int adjustment_needed = 0;
181 adjusted_timespec[0] = timespec[0];
182 adjusted_timespec[1] = timespec[1];
183 adjustment_needed = validate_timespec (ts);
185 if (adjustment_needed < 0)
188 /* Require that at least one of FD or FILE are potentially valid, to avoid
189 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
197 /* Some Linux-based NFS clients are buggy, and mishandle time stamps
198 of files in NFS file systems in some cases. We have no
199 configure-time test for this, but please see
200 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
201 some of the problems with Linux 2.6.16. If this affects you,
202 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
203 help in some cases, albeit at a cost in performance. But you
204 really should upgrade your kernel to a fixed version, since the
205 problem affects many applications. */
207 #if HAVE_BUGGY_NFS_TIME_STAMPS
214 /* POSIX 2008 added two interfaces to set file timestamps with
215 nanosecond resolution; newer Linux implements both functions via
216 a single syscall. We provide a fallback for ENOSYS (for example,
217 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
218 running on Linux 2.6.18 kernel). */
219 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
220 if (0 <= utimensat_works_really)
223 # if __linux__ || __sun
224 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
225 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
226 but work if both times are either explicitly specified or
227 UTIME_NOW. Work around it with a preparatory [f]stat prior
228 to calling futimens/utimensat; fortunately, there is not much
229 timing impact due to the extra syscall even on file systems
230 where UTIME_OMIT would have worked.
232 The same bug occurs in Solaris 11.1 (Apr 2013).
234 FIXME: Simplify this for Linux in 2016 and for Solaris in
235 2024, when file system bugs are no longer common. */
236 if (adjustment_needed == 2)
238 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
240 if (ts[0].tv_nsec == UTIME_OMIT)
241 ts[0] = get_stat_atime (&st);
242 else if (ts[1].tv_nsec == UTIME_OMIT)
243 ts[1] = get_stat_mtime (&st);
244 /* Note that st is good, in case utimensat gives ENOSYS. */
251 result = utimensat (AT_FDCWD, file, ts, 0);
253 /* Work around a kernel bug:
254 http://bugzilla.redhat.com/442352
255 http://bugzilla.redhat.com/449910
256 It appears that utimensat can mistakenly return 280 rather
257 than -1 upon ENOSYS failure.
258 FIXME: remove in 2010 or whenever the offending kernels
259 are no longer in common use. */
262 # endif /* __linux__ */
263 if (result == 0 || errno != ENOSYS)
265 utimensat_works_really = 1;
269 # endif /* HAVE_UTIMENSAT */
273 result = futimens (fd, ts);
275 /* Work around the same bug as above. */
278 # endif /* __linux__ */
279 if (result == 0 || errno != ENOSYS)
281 utimensat_works_really = 1;
285 # endif /* HAVE_FUTIMENS */
287 utimensat_works_really = -1;
288 lutimensat_works_really = -1;
289 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
291 /* The platform lacks an interface to set file timestamps with
292 nanosecond resolution, so do the best we can, discarding any
293 fractional part of the timestamp. */
295 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
297 if (adjustment_needed != 3
298 && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
300 if (ts && update_timespec (&st, &ts))
305 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
306 struct timeval timeval[2];
310 timeval[0].tv_sec = ts[0].tv_sec;
311 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
312 timeval[1].tv_sec = ts[1].tv_sec;
313 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
322 return futimesat (AT_FDCWD, file, t);
327 /* If futimesat or futimes fails here, don't try to speed things
328 up by returning right away. glibc can incorrectly fail with
329 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
330 in high security mode doesn't allow ordinary users to read
331 /proc/self, so glibc incorrectly fails with errno == EACCES.
332 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
333 right away, but these cases are rare enough that they're not
334 worth optimizing, and who knows what other messed-up systems
335 are out there? So play it safe and fall back on the code
338 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
339 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
341 # define futimes(fd, t) futimesat (fd, NULL, t)
343 if (futimes (fd, t) == 0)
345 # if __linux__ && __GLIBC__
346 /* Work around a longstanding glibc bug, still present as
347 of 2010-12-27. On older Linux kernels that lack both
348 utimensat and utimes, glibc's futimes rounds instead of
349 truncating when falling back on utime. The same bug
350 occurs in futimesat with a null 2nd arg. */
353 bool abig = 500000 <= t[0].tv_usec;
354 bool mbig = 500000 <= t[1].tv_usec;
355 if ((abig | mbig) && fstat (fd, &st) == 0)
357 /* If these two subtractions overflow, they'll
358 track the overflows inside the buggy glibc. */
359 time_t adiff = st.st_atime - t[0].tv_sec;
360 time_t mdiff = st.st_mtime - t[1].tv_sec;
362 struct timeval *tt = NULL;
363 struct timeval truncated_timeval[2];
364 truncated_timeval[0] = t[0];
365 truncated_timeval[1] = t[1];
366 if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
368 tt = truncated_timeval;
371 if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
373 tt = truncated_timeval;
386 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
390 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
391 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
397 #if HAVE_WORKING_UTIMES
398 return utimes (file, t);
401 struct utimbuf utimbuf;
405 utimbuf.actime = ts[0].tv_sec;
406 utimbuf.modtime = ts[1].tv_sec;
412 return utime (file, ut);
414 #endif /* !HAVE_WORKING_UTIMES */
418 /* Set the access and modification time stamps of FILE to be
419 TIMESPEC[0] and TIMESPEC[1], respectively. */
421 utimens (char const *file, struct timespec const timespec[2])
423 return fdutimens (-1, file, timespec);
426 /* Set the access and modification time stamps of FILE to be
427 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
428 symlinks. Fail with ENOSYS if the platform does not support
429 changing symlink timestamps, but FILE was a symlink. */
431 lutimens (char const *file, struct timespec const timespec[2])
433 struct timespec adjusted_timespec[2];
434 struct timespec *ts = timespec ? adjusted_timespec : NULL;
435 int adjustment_needed = 0;
440 adjusted_timespec[0] = timespec[0];
441 adjusted_timespec[1] = timespec[1];
442 adjustment_needed = validate_timespec (ts);
444 if (adjustment_needed < 0)
447 /* The Linux kernel did not support symlink timestamps until
448 utimensat, in version 2.6.22, so we don't need to mimic
449 fdutimens' worry about buggy NFS clients. But we do have to
450 worry about bogus return values. */
453 if (0 <= lutimensat_works_really)
456 # if __linux__ || __sun
457 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
458 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
459 but work if both times are either explicitly specified or
460 UTIME_NOW. Work around it with a preparatory lstat prior to
461 calling utimensat; fortunately, there is not much timing
462 impact due to the extra syscall even on file systems where
463 UTIME_OMIT would have worked.
465 The same bug occurs in Solaris 11.1 (Apr 2013).
467 FIXME: Simplify this for Linux in 2016 and for Solaris in
468 2024, when file system bugs are no longer common. */
469 if (adjustment_needed == 2)
471 if (lstat (file, &st))
473 if (ts[0].tv_nsec == UTIME_OMIT)
474 ts[0] = get_stat_atime (&st);
475 else if (ts[1].tv_nsec == UTIME_OMIT)
476 ts[1] = get_stat_mtime (&st);
477 /* Note that st is good, in case utimensat gives ENOSYS. */
481 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
483 /* Work around a kernel bug:
484 http://bugzilla.redhat.com/442352
485 http://bugzilla.redhat.com/449910
486 It appears that utimensat can mistakenly return 280 rather
487 than -1 upon ENOSYS failure.
488 FIXME: remove in 2010 or whenever the offending kernels
489 are no longer in common use. */
493 if (result == 0 || errno != ENOSYS)
495 utimensat_works_really = 1;
496 lutimensat_works_really = 1;
500 lutimensat_works_really = -1;
501 #endif /* HAVE_UTIMENSAT */
503 /* The platform lacks an interface to set file timestamps with
504 nanosecond resolution, so do the best we can, discarding any
505 fractional part of the timestamp. */
507 if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
509 if (adjustment_needed != 3 && lstat (file, &st))
511 if (ts && update_timespec (&st, &ts))
515 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
516 no point trying lutimes if utimensat failed with ENOSYS. */
517 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
519 struct timeval timeval[2];
524 timeval[0].tv_sec = ts[0].tv_sec;
525 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
526 timeval[1].tv_sec = ts[1].tv_sec;
527 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
533 result = lutimes (file, t);
534 if (result == 0 || errno != ENOSYS)
537 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
539 /* Out of luck for symlinks, but we still handle regular files. */
540 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
542 if (!S_ISLNK (st.st_mode))
543 return fdutimens (-1, file, ts);