1 /* Set file access and modification times.
3 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free
4 Software Foundation, Inc.
6 This program is free software: you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3 of the License, or any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 /* Written by Paul Eggert. */
21 /* derived from a function in touch.c */
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 and earlier fail to bump ctime if mtime is 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 static int utimensat_ctime_really;
78 /* Determine whether the kernel has a ctime bug. ST1 and ST2
79 correspond to stat data before and after a successful time change.
80 TIMES contains the timestamps that were used during the time change
81 (mtime will be UTIME_OMIT). Update the cache variable if there is
82 conclusive evidence of the kernel working or being buggy. Return
83 true if TIMES has been updated and another kernel call is needed,
84 whether or not the kernel is known to have the bug. */
86 detect_ctime_bug (struct stat *st1, struct stat *st2, struct timespec times[2])
89 if (st1->st_ctime != st2->st_ctime
90 || get_stat_ctime_ns (st1) != get_stat_ctime_ns (st2))
92 utimensat_ctime_really = 1;
95 /* The results are inconclusive if the ctime in st1 is within a file
96 system quantization window of now. For FAT, this is 2 seconds,
97 for systems with sub-second resolution, a typical resolution is
98 10 milliseconds; to be safe we declare an inconsistent result if
99 ctime is within a 20 millisecond window. Avoid an extra gettime
100 call if atime makes sense. It is unlikely that the original
101 ctime is later than now, but rather than deal with the overflow,
102 we treat that as consistent evidence of the bug. */
103 if (times[0].tv_nsec == UTIME_NOW)
104 now = get_stat_atime (st2);
107 if (now.tv_sec < st2->st_ctime
108 || 2 < now.tv_sec - st2->st_ctime
109 || (get_stat_ctime_ns (st2)
110 && now.tv_sec - st2->st_ctime < 2
111 && (20000000 < (1000000000 * (now.tv_sec - st2->st_ctime)
112 + now.tv_nsec - get_stat_ctime_ns (st2)))))
113 utimensat_ctime_really = -1;
114 times[1] = get_stat_mtime (st2);
117 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
119 /* Validate the requested timestamps. Return 0 if the resulting
120 timespec can be used for utimensat (after possibly modifying it to
121 work around bugs in utimensat). Return a positive value if the
122 timespec needs further adjustment based on stat results: 1 if any
123 adjustment is needed for utimes, and 2 if mtime was UTIME_OMIT and
124 an adjustment is needed for utimensat. Return -1, with errno set
125 to EINVAL, if timespec is out of range. */
127 validate_timespec (struct timespec timespec[2])
131 if ((timespec[0].tv_nsec != UTIME_NOW
132 && timespec[0].tv_nsec != UTIME_OMIT
133 && (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec))
134 || (timespec[1].tv_nsec != UTIME_NOW
135 && timespec[1].tv_nsec != UTIME_OMIT
136 && (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec)))
141 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
142 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
143 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
144 fails to bump ctime. */
145 if (timespec[0].tv_nsec == UTIME_NOW
146 || timespec[0].tv_nsec == UTIME_OMIT)
148 timespec[0].tv_sec = 0;
151 if (timespec[1].tv_nsec == UTIME_NOW)
153 timespec[1].tv_sec = 0;
156 else if (timespec[1].tv_nsec == UTIME_OMIT)
158 timespec[1].tv_sec = 0;
164 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
165 buffer STATBUF to obtain the current timestamps of the file. If
166 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
167 permissions issues). If both times are UTIME_OMIT, return true
168 (nothing further beyond the prior collection of STATBUF is
169 necessary); otherwise return false. */
171 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
173 struct timespec *timespec = *ts;
174 if (timespec[0].tv_nsec == UTIME_OMIT
175 && timespec[1].tv_nsec == UTIME_OMIT)
177 if (timespec[0].tv_nsec == UTIME_NOW
178 && timespec[1].tv_nsec == UTIME_NOW)
184 if (timespec[0].tv_nsec == UTIME_OMIT)
185 timespec[0] = get_stat_atime (statbuf);
186 else if (timespec[0].tv_nsec == UTIME_NOW)
187 gettime (×pec[0]);
189 if (timespec[1].tv_nsec == UTIME_OMIT)
190 timespec[1] = get_stat_mtime (statbuf);
191 else if (timespec[1].tv_nsec == UTIME_NOW)
192 gettime (×pec[1]);
197 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
198 TIMESPEC[0] and TIMESPEC[1], respectively.
199 FD must be either negative -- in which case it is ignored --
200 or a file descriptor that is open on FILE.
201 If FD is nonnegative, then FILE can be NULL, which means
202 use just futimes (or equivalent) instead of utimes (or equivalent),
203 and fail if on an old system without futimes (or equivalent).
204 If TIMESPEC is null, set the time stamps to the current time.
205 Return 0 on success, -1 (setting errno) on failure. */
208 fdutimens (char const *file, int fd, struct timespec const timespec[2])
210 struct timespec adjusted_timespec[2];
211 struct timespec *ts = timespec ? adjusted_timespec : NULL;
212 int adjustment_needed = 0;
216 adjusted_timespec[0] = timespec[0];
217 adjusted_timespec[1] = timespec[1];
218 adjustment_needed = validate_timespec (ts);
220 if (adjustment_needed < 0)
223 /* Require that at least one of FD or FILE are valid. Works around
224 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
233 if (dup2 (fd, fd) != fd)
237 /* Some Linux-based NFS clients are buggy, and mishandle time stamps
238 of files in NFS file systems in some cases. We have no
239 configure-time test for this, but please see
240 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
241 some of the problems with Linux 2.6.16. If this affects you,
242 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
243 help in some cases, albeit at a cost in performance. But you
244 really should upgrade your kernel to a fixed version, since the
245 problem affects many applications. */
247 #if HAVE_BUGGY_NFS_TIME_STAMPS
254 /* POSIX 2008 added two interfaces to set file timestamps with
255 nanosecond resolution; newer Linux implements both functions via
256 a single syscall. We provide a fallback for ENOSYS (for example,
257 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
258 running on Linux 2.6.18 kernel). */
259 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
260 if (0 <= utimensat_works_really)
265 /* Linux kernel 2.6.32 has a bug where it fails to bump ctime if
266 UTIME_OMIT was used for mtime. It costs time to do an extra
267 [f]stat up front, so we cache whether the function works. */
268 if (utimensat_ctime_really <= 0 && adjustment_needed == 2)
270 if (fd < 0 ? stat (file, &st1) : fstat (fd, &st1))
272 if (ts[0].tv_nsec == UTIME_OMIT)
274 if (utimensat_ctime_really < 0)
275 ts[1] = get_stat_mtime (&st1);
280 result = utimensat (AT_FDCWD, file, ts, 0);
282 /* Work around a kernel bug:
283 http://bugzilla.redhat.com/442352
284 http://bugzilla.redhat.com/449910
285 It appears that utimensat can mistakenly return 280 rather
286 than -1 upon ENOSYS failure.
287 FIXME: remove in 2010 or whenever the offending kernels
288 are no longer in common use. */
291 # endif /* __linux__ */
292 if (result == 0 || errno != ENOSYS)
294 utimensat_works_really = 1;
295 if (result == 0 && utimensat_ctime_really == 0
296 && adjustment_needed == 2)
298 /* Perform a followup stat to see if the kernel has
300 if (stat (file, &st2))
302 if (detect_ctime_bug (&st1, &st2, ts))
303 result = utimensat (AT_FDCWD, file, ts, 0);
308 # endif /* HAVE_UTIMENSAT */
311 result = futimens (fd, ts);
313 /* Work around the same bug as above. */
316 # endif /* __linux__ */
317 if (result == 0 || errno != ENOSYS)
319 utimensat_works_really = 1;
320 /* Work around the same bug as above. */
321 if (result == 0 && utimensat_ctime_really == 0
322 && adjustment_needed == 2)
324 if (fstat (fd, &st2))
326 if (detect_ctime_bug (&st1, &st2, ts))
327 result = futimens (fd, ts);
332 # endif /* HAVE_FUTIMENS */
334 utimensat_works_really = -1;
335 lutimensat_works_really = -1;
336 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
338 /* The platform lacks an interface to set file timestamps with
339 nanosecond resolution, so do the best we can, discarding any
340 fractional part of the timestamp. */
342 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
345 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
347 if (ts && update_timespec (&st, &ts))
352 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
353 struct timeval timeval[2];
354 struct timeval const *t;
357 timeval[0].tv_sec = ts[0].tv_sec;
358 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
359 timeval[1].tv_sec = ts[1].tv_sec;
360 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
369 return futimesat (AT_FDCWD, file, t);
374 /* If futimesat or futimes fails here, don't try to speed things
375 up by returning right away. glibc can incorrectly fail with
376 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
377 in high security mode doesn't allow ordinary users to read
378 /proc/self, so glibc incorrectly fails with errno == EACCES.
379 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
380 right away, but these cases are rare enough that they're not
381 worth optimizing, and who knows what other messed-up systems
382 are out there? So play it safe and fall back on the code
384 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
385 if (futimesat (fd, NULL, t) == 0)
388 if (futimes (fd, t) == 0)
392 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
396 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
397 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
403 #if HAVE_WORKING_UTIMES
404 return utimes (file, t);
407 struct utimbuf utimbuf;
411 utimbuf.actime = ts[0].tv_sec;
412 utimbuf.modtime = ts[1].tv_sec;
418 return utime (file, ut);
420 #endif /* !HAVE_WORKING_UTIMES */
424 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
425 TIMESPEC[0] and TIMESPEC[1], respectively.
426 FD must be either negative -- in which case it is ignored --
427 or a file descriptor that is open on FILE.
428 If FD is nonnegative, then FILE can be NULL, which means
429 use just futimes (or equivalent) instead of utimes (or equivalent),
430 and fail if on an old system without futimes (or equivalent).
431 If TIMESPEC is null, set the time stamps to the current time.
432 Return 0 on success, -1 (setting errno) on failure. */
435 gl_futimens (int fd, char const *file, struct timespec const timespec[2])
437 return fdutimens (file, fd, timespec);
440 /* Set the access and modification time stamps of FILE to be
441 TIMESPEC[0] and TIMESPEC[1], respectively. */
443 utimens (char const *file, struct timespec const timespec[2])
445 return fdutimens (file, -1, timespec);
448 /* Set the access and modification time stamps of FILE to be
449 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
450 symlinks. Fail with ENOSYS if the platform does not support
451 changing symlink timestamps, but FILE was a symlink. */
453 lutimens (char const *file, struct timespec const timespec[2])
455 struct timespec adjusted_timespec[2];
456 struct timespec *ts = timespec ? adjusted_timespec : NULL;
457 int adjustment_needed = 0;
462 adjusted_timespec[0] = timespec[0];
463 adjusted_timespec[1] = timespec[1];
464 adjustment_needed = validate_timespec (ts);
466 if (adjustment_needed < 0)
469 /* The Linux kernel did not support symlink timestamps until
470 utimensat, in version 2.6.22, so we don't need to mimic
471 gl_futimens' worry about buggy NFS clients. But we do have to
472 worry about bogus return values. */
475 if (0 <= lutimensat_works_really)
480 /* Linux kernel 2.6.32 has a bug where it fails to bump ctime if
481 UTIME_OMIT was used for mtime. It costs time to do an extra
482 lstat up front, so we cache whether the function works. */
483 if (utimensat_ctime_really <= 0 && adjustment_needed == 2)
485 if (lstat (file, &st1))
487 if (ts[0].tv_nsec == UTIME_OMIT)
489 if (utimensat_ctime_really < 0)
490 ts[1] = get_stat_mtime (&st1);
492 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
494 /* Work around a kernel bug:
495 http://bugzilla.redhat.com/442352
496 http://bugzilla.redhat.com/449910
497 It appears that utimensat can mistakenly return 280 rather
498 than -1 upon ENOSYS failure.
499 FIXME: remove in 2010 or whenever the offending kernels
500 are no longer in common use. */
504 if (result == 0 || errno != ENOSYS)
506 utimensat_works_really = 1;
507 lutimensat_works_really = 1;
508 if (result == 0 && utimensat_ctime_really == 0
509 && adjustment_needed == 2)
511 /* Perform a followup stat to see if the kernel has a
513 if (lstat (file, &st2))
515 if (detect_ctime_bug (&st1, &st2, ts))
516 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
521 lutimensat_works_really = -1;
522 #endif /* HAVE_UTIMENSAT */
524 /* The platform lacks an interface to set file timestamps with
525 nanosecond resolution, so do the best we can, discarding any
526 fractional part of the timestamp. */
528 if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
530 if (lstat (file, &st))
532 if (ts && update_timespec (&st, &ts))
536 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
537 no point trying lutimes if utimensat failed with ENOSYS. */
538 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
540 struct timeval timeval[2];
541 struct timeval const *t;
545 timeval[0].tv_sec = ts[0].tv_sec;
546 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
547 timeval[1].tv_sec = ts[1].tv_sec;
548 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
554 result = lutimes (file, t);
555 if (result == 0 || errno != ENOSYS)
558 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
560 /* Out of luck for symlinks, but we still handle regular files. */
561 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
563 if (!S_ISLNK (st.st_mode))
564 return fdutimens (file, -1, ts);