1 /* Set file access and modification times.
3 Copyright (C) 2003-2014 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3 of the License, or any
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Written by Paul Eggert. */
20 /* derived from a function in touch.c */
24 #define _GL_UTIMENS_INLINE _GL_EXTERN_INLINE
35 #include "stat-time.h"
42 /* Some systems (even some that do have <utime.h>) don't declare this
43 structure anywhere. */
44 #ifndef HAVE_STRUCT_UTIMBUF
52 /* Avoid recursion with rpl_futimens or rpl_utimensat. */
56 /* Solaris 9 mistakenly succeeds when given a non-directory with a
57 trailing slash. Force the use of rpl_stat for a fix. */
58 #ifndef REPLACE_FUNC_STAT_FILE
59 # define REPLACE_FUNC_STAT_FILE 0
62 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
63 /* Cache variables for whether the utimensat syscall works; used to
64 avoid calling the syscall if we know it will just fail with ENOSYS,
65 and to avoid unnecessary work in massaging timestamps if the
66 syscall will work. Multiple variables are needed, to distinguish
67 between the following scenarios on Linux:
68 utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
69 kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
70 kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
71 kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
72 utimensat completely works
73 For each cache variable: 0 = unknown, 1 = yes, -1 = no. */
74 static int utimensat_works_really;
75 static int lutimensat_works_really;
76 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
78 /* Validate the requested timestamps. Return 0 if the resulting
79 timespec can be used for utimensat (after possibly modifying it to
80 work around bugs in utimensat). Return a positive value if the
81 timespec needs further adjustment based on stat results: 1 if any
82 adjustment is needed for utimes, and 2 if any adjustment is needed
83 for Linux utimensat. Return -1, with errno set to EINVAL, if
84 timespec is out of range. */
86 validate_timespec (struct timespec timespec[2])
89 int utime_omit_count = 0;
91 if ((timespec[0].tv_nsec != UTIME_NOW
92 && timespec[0].tv_nsec != UTIME_OMIT
93 && ! (0 <= timespec[0].tv_nsec
94 && timespec[0].tv_nsec < TIMESPEC_RESOLUTION))
95 || (timespec[1].tv_nsec != UTIME_NOW
96 && timespec[1].tv_nsec != UTIME_OMIT
97 && ! (0 <= timespec[1].tv_nsec
98 && timespec[1].tv_nsec < TIMESPEC_RESOLUTION)))
103 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
104 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
105 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
106 fails to bump ctime. */
107 if (timespec[0].tv_nsec == UTIME_NOW
108 || timespec[0].tv_nsec == UTIME_OMIT)
110 timespec[0].tv_sec = 0;
112 if (timespec[0].tv_nsec == UTIME_OMIT)
115 if (timespec[1].tv_nsec == UTIME_NOW
116 || timespec[1].tv_nsec == UTIME_OMIT)
118 timespec[1].tv_sec = 0;
120 if (timespec[1].tv_nsec == UTIME_OMIT)
123 return result + (utime_omit_count == 1);
126 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
127 buffer STATBUF to obtain the current timestamps of the file. If
128 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
129 permissions issues). If both times are UTIME_OMIT, return true
130 (nothing further beyond the prior collection of STATBUF is
131 necessary); otherwise return false. */
133 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
135 struct timespec *timespec = *ts;
136 if (timespec[0].tv_nsec == UTIME_OMIT
137 && timespec[1].tv_nsec == UTIME_OMIT)
139 if (timespec[0].tv_nsec == UTIME_NOW
140 && timespec[1].tv_nsec == UTIME_NOW)
146 if (timespec[0].tv_nsec == UTIME_OMIT)
147 timespec[0] = get_stat_atime (statbuf);
148 else if (timespec[0].tv_nsec == UTIME_NOW)
149 gettime (×pec[0]);
151 if (timespec[1].tv_nsec == UTIME_OMIT)
152 timespec[1] = get_stat_mtime (statbuf);
153 else if (timespec[1].tv_nsec == UTIME_NOW)
154 gettime (×pec[1]);
159 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
160 TIMESPEC[0] and TIMESPEC[1], respectively.
161 FD must be either negative -- in which case it is ignored --
162 or a file descriptor that is open on FILE.
163 If FD is nonnegative, then FILE can be NULL, which means
164 use just futimes (or equivalent) instead of utimes (or equivalent),
165 and fail if on an old system without futimes (or equivalent).
166 If TIMESPEC is null, set the time stamps to the current time.
167 Return 0 on success, -1 (setting errno) on failure. */
170 fdutimens (int fd, char const *file, struct timespec const timespec[2])
172 struct timespec adjusted_timespec[2];
173 struct timespec *ts = timespec ? adjusted_timespec : NULL;
174 int adjustment_needed = 0;
179 adjusted_timespec[0] = timespec[0];
180 adjusted_timespec[1] = timespec[1];
181 adjustment_needed = validate_timespec (ts);
183 if (adjustment_needed < 0)
186 /* Require that at least one of FD or FILE are potentially valid, to avoid
187 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
195 /* Some Linux-based NFS clients are buggy, and mishandle time stamps
196 of files in NFS file systems in some cases. We have no
197 configure-time test for this, but please see
198 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
199 some of the problems with Linux 2.6.16. If this affects you,
200 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
201 help in some cases, albeit at a cost in performance. But you
202 really should upgrade your kernel to a fixed version, since the
203 problem affects many applications. */
205 #if HAVE_BUGGY_NFS_TIME_STAMPS
212 /* POSIX 2008 added two interfaces to set file timestamps with
213 nanosecond resolution; newer Linux implements both functions via
214 a single syscall. We provide a fallback for ENOSYS (for example,
215 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
216 running on Linux 2.6.18 kernel). */
217 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
218 if (0 <= utimensat_works_really)
221 # if __linux__ || __sun
222 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
223 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
224 but work if both times are either explicitly specified or
225 UTIME_NOW. Work around it with a preparatory [f]stat prior
226 to calling futimens/utimensat; fortunately, there is not much
227 timing impact due to the extra syscall even on file systems
228 where UTIME_OMIT would have worked.
230 The same bug occurs in Solaris 11.1 (Apr 2013).
232 FIXME: Simplify this for Linux in 2016 and for Solaris in
233 2024, when file system bugs are no longer common. */
234 if (adjustment_needed == 2)
236 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
238 if (ts[0].tv_nsec == UTIME_OMIT)
239 ts[0] = get_stat_atime (&st);
240 else if (ts[1].tv_nsec == UTIME_OMIT)
241 ts[1] = get_stat_mtime (&st);
242 /* Note that st is good, in case utimensat gives ENOSYS. */
247 /* Work around lack of UTIME_NOW/UTIME_OMIT support:
248 <https://bugs.debian.org/762677>. */
249 if (adjustment_needed > 0)
251 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
253 update_timespec (&st, &ts);
254 /* Note that st is good, in case futimens gives ENOSYS. */
255 adjustment_needed = 3;
261 result = utimensat (AT_FDCWD, file, ts, 0);
263 /* Work around a kernel bug:
264 http://bugzilla.redhat.com/442352
265 http://bugzilla.redhat.com/449910
266 It appears that utimensat can mistakenly return 280 rather
267 than -1 upon ENOSYS failure.
268 FIXME: remove in 2010 or whenever the offending kernels
269 are no longer in common use. */
272 # endif /* __linux__ */
273 if (result == 0 || errno != ENOSYS)
275 utimensat_works_really = 1;
279 # endif /* HAVE_UTIMENSAT */
283 result = futimens (fd, ts);
285 /* Work around the same bug as above. */
288 # endif /* __linux__ */
289 if (result == 0 || errno != ENOSYS)
291 utimensat_works_really = 1;
295 # endif /* HAVE_FUTIMENS */
297 utimensat_works_really = -1;
298 lutimensat_works_really = -1;
299 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
301 /* The platform lacks an interface to set file timestamps with
302 nanosecond resolution, so do the best we can, discarding any
303 fractional part of the timestamp. */
305 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
307 if (adjustment_needed != 3
308 && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
310 if (ts && update_timespec (&st, &ts))
315 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
316 struct timeval timeval[2];
320 timeval[0].tv_sec = ts[0].tv_sec;
321 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
322 timeval[1].tv_sec = ts[1].tv_sec;
323 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
332 return futimesat (AT_FDCWD, file, t);
337 /* If futimesat or futimes fails here, don't try to speed things
338 up by returning right away. glibc can incorrectly fail with
339 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
340 in high security mode doesn't allow ordinary users to read
341 /proc/self, so glibc incorrectly fails with errno == EACCES.
342 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
343 right away, but these cases are rare enough that they're not
344 worth optimizing, and who knows what other messed-up systems
345 are out there? So play it safe and fall back on the code
348 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
349 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
351 # define futimes(fd, t) futimesat (fd, NULL, t)
353 if (futimes (fd, t) == 0)
355 # if __linux__ && __GLIBC__
356 /* Work around a longstanding glibc bug, still present as
357 of 2010-12-27. On older Linux kernels that lack both
358 utimensat and utimes, glibc's futimes rounds instead of
359 truncating when falling back on utime. The same bug
360 occurs in futimesat with a null 2nd arg. */
363 bool abig = 500000 <= t[0].tv_usec;
364 bool mbig = 500000 <= t[1].tv_usec;
365 if ((abig | mbig) && fstat (fd, &st) == 0)
367 /* If these two subtractions overflow, they'll
368 track the overflows inside the buggy glibc. */
369 time_t adiff = st.st_atime - t[0].tv_sec;
370 time_t mdiff = st.st_mtime - t[1].tv_sec;
372 struct timeval *tt = NULL;
373 struct timeval truncated_timeval[2];
374 truncated_timeval[0] = t[0];
375 truncated_timeval[1] = t[1];
376 if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
378 tt = truncated_timeval;
381 if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
383 tt = truncated_timeval;
396 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
400 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
401 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
407 #if HAVE_WORKING_UTIMES
408 return utimes (file, t);
411 struct utimbuf utimbuf;
415 utimbuf.actime = ts[0].tv_sec;
416 utimbuf.modtime = ts[1].tv_sec;
422 return utime (file, ut);
424 #endif /* !HAVE_WORKING_UTIMES */
428 /* Set the access and modification time stamps of FILE to be
429 TIMESPEC[0] and TIMESPEC[1], respectively. */
431 utimens (char const *file, struct timespec const timespec[2])
433 return fdutimens (-1, file, timespec);
436 /* Set the access and modification time stamps of FILE to be
437 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
438 symlinks. Fail with ENOSYS if the platform does not support
439 changing symlink timestamps, but FILE was a symlink. */
441 lutimens (char const *file, struct timespec const timespec[2])
443 struct timespec adjusted_timespec[2];
444 struct timespec *ts = timespec ? adjusted_timespec : NULL;
445 int adjustment_needed = 0;
450 adjusted_timespec[0] = timespec[0];
451 adjusted_timespec[1] = timespec[1];
452 adjustment_needed = validate_timespec (ts);
454 if (adjustment_needed < 0)
457 /* The Linux kernel did not support symlink timestamps until
458 utimensat, in version 2.6.22, so we don't need to mimic
459 fdutimens' worry about buggy NFS clients. But we do have to
460 worry about bogus return values. */
463 if (0 <= lutimensat_works_really)
466 # if __linux__ || __sun
467 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
468 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
469 but work if both times are either explicitly specified or
470 UTIME_NOW. Work around it with a preparatory lstat prior to
471 calling utimensat; fortunately, there is not much timing
472 impact due to the extra syscall even on file systems where
473 UTIME_OMIT would have worked.
475 The same bug occurs in Solaris 11.1 (Apr 2013).
477 FIXME: Simplify this for Linux in 2016 and for Solaris in
478 2024, when file system bugs are no longer common. */
479 if (adjustment_needed == 2)
481 if (lstat (file, &st))
483 if (ts[0].tv_nsec == UTIME_OMIT)
484 ts[0] = get_stat_atime (&st);
485 else if (ts[1].tv_nsec == UTIME_OMIT)
486 ts[1] = get_stat_mtime (&st);
487 /* Note that st is good, in case utimensat gives ENOSYS. */
491 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
493 /* Work around a kernel bug:
494 http://bugzilla.redhat.com/442352
495 http://bugzilla.redhat.com/449910
496 It appears that utimensat can mistakenly return 280 rather
497 than -1 upon ENOSYS failure.
498 FIXME: remove in 2010 or whenever the offending kernels
499 are no longer in common use. */
503 if (result == 0 || errno != ENOSYS)
505 utimensat_works_really = 1;
506 lutimensat_works_really = 1;
510 lutimensat_works_really = -1;
511 #endif /* HAVE_UTIMENSAT */
513 /* The platform lacks an interface to set file timestamps with
514 nanosecond resolution, so do the best we can, discarding any
515 fractional part of the timestamp. */
517 if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
519 if (adjustment_needed != 3 && lstat (file, &st))
521 if (ts && update_timespec (&st, &ts))
525 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
526 no point trying lutimes if utimensat failed with ENOSYS. */
527 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
529 struct timeval timeval[2];
534 timeval[0].tv_sec = ts[0].tv_sec;
535 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
536 timeval[1].tv_sec = ts[1].tv_sec;
537 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
543 result = lutimes (file, t);
544 if (result == 0 || errno != ENOSYS)
547 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
549 /* Out of luck for symlinks, but we still handle regular files. */
550 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
552 if (!S_ISLNK (st.st_mode))
553 return fdutimens (-1, file, ts);