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-2010 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 */
36 #include "stat-time.h"
43 /* Some systems (even some that do have <utime.h>) don't declare this
44 structure anywhere. */
45 #ifndef HAVE_STRUCT_UTIMBUF
53 /* Avoid recursion with rpl_futimens or rpl_utimensat. */
57 /* Solaris 9 mistakenly succeeds when given a non-directory with a
58 trailing slash. Force the use of rpl_stat for a fix. */
59 #ifndef REPLACE_FUNC_STAT_FILE
60 # define REPLACE_FUNC_STAT_FILE 0
63 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
64 /* Cache variables for whether the utimensat syscall works; used to
65 avoid calling the syscall if we know it will just fail with ENOSYS,
66 and to avoid unnecessary work in massaging timestamps if the
67 syscall will work. Multiple variables are needed, to distinguish
68 between the following scenarios on Linux:
69 utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
70 kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
71 kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
72 kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
73 utimensat completely works
74 For each cache variable: 0 = unknown, 1 = yes, -1 = no. */
75 static int utimensat_works_really;
76 static int lutimensat_works_really;
77 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
79 /* Validate the requested timestamps. Return 0 if the resulting
80 timespec can be used for utimensat (after possibly modifying it to
81 work around bugs in utimensat). Return a positive value if the
82 timespec needs further adjustment based on stat results: 1 if any
83 adjustment is needed for utimes, and 2 if any adjustment is needed
84 for Linux utimensat. Return -1, with errno set to EINVAL, if
85 timespec is out of range. */
87 validate_timespec (struct timespec timespec[2])
90 int utime_omit_count = 0;
92 if ((timespec[0].tv_nsec != UTIME_NOW
93 && timespec[0].tv_nsec != UTIME_OMIT
94 && (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec))
95 || (timespec[1].tv_nsec != UTIME_NOW
96 && timespec[1].tv_nsec != UTIME_OMIT
97 && (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec)))
102 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
103 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
104 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
105 fails to bump ctime. */
106 if (timespec[0].tv_nsec == UTIME_NOW
107 || timespec[0].tv_nsec == UTIME_OMIT)
109 timespec[0].tv_sec = 0;
111 if (timespec[0].tv_nsec == UTIME_OMIT)
114 if (timespec[1].tv_nsec == UTIME_NOW
115 || timespec[1].tv_nsec == UTIME_OMIT)
117 timespec[1].tv_sec = 0;
119 if (timespec[1].tv_nsec == UTIME_OMIT)
122 return result + (utime_omit_count == 1);
125 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
126 buffer STATBUF to obtain the current timestamps of the file. If
127 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
128 permissions issues). If both times are UTIME_OMIT, return true
129 (nothing further beyond the prior collection of STATBUF is
130 necessary); otherwise return false. */
132 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
134 struct timespec *timespec = *ts;
135 if (timespec[0].tv_nsec == UTIME_OMIT
136 && timespec[1].tv_nsec == UTIME_OMIT)
138 if (timespec[0].tv_nsec == UTIME_NOW
139 && timespec[1].tv_nsec == UTIME_NOW)
145 if (timespec[0].tv_nsec == UTIME_OMIT)
146 timespec[0] = get_stat_atime (statbuf);
147 else if (timespec[0].tv_nsec == UTIME_NOW)
148 gettime (×pec[0]);
150 if (timespec[1].tv_nsec == UTIME_OMIT)
151 timespec[1] = get_stat_mtime (statbuf);
152 else if (timespec[1].tv_nsec == UTIME_NOW)
153 gettime (×pec[1]);
158 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
159 TIMESPEC[0] and TIMESPEC[1], respectively.
160 FD must be either negative -- in which case it is ignored --
161 or a file descriptor that is open on FILE.
162 If FD is nonnegative, then FILE can be NULL, which means
163 use just futimes (or equivalent) instead of utimes (or equivalent),
164 and fail if on an old system without futimes (or equivalent).
165 If TIMESPEC is null, set the time stamps to the current time.
166 Return 0 on success, -1 (setting errno) on failure. */
169 fdutimens (char const *file, int fd, struct timespec const timespec[2])
171 struct timespec adjusted_timespec[2];
172 struct timespec *ts = timespec ? adjusted_timespec : NULL;
173 int adjustment_needed = 0;
178 adjusted_timespec[0] = timespec[0];
179 adjusted_timespec[1] = timespec[1];
180 adjustment_needed = validate_timespec (ts);
182 if (adjustment_needed < 0)
185 /* Require that at least one of FD or FILE are valid. Works around
186 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
195 if (dup2 (fd, fd) != fd)
199 /* Some Linux-based NFS clients are buggy, and mishandle time stamps
200 of files in NFS file systems in some cases. We have no
201 configure-time test for this, but please see
202 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
203 some of the problems with Linux 2.6.16. If this affects you,
204 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
205 help in some cases, albeit at a cost in performance. But you
206 really should upgrade your kernel to a fixed version, since the
207 problem affects many applications. */
209 #if HAVE_BUGGY_NFS_TIME_STAMPS
216 /* POSIX 2008 added two interfaces to set file timestamps with
217 nanosecond resolution; newer Linux implements both functions via
218 a single syscall. We provide a fallback for ENOSYS (for example,
219 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
220 running on Linux 2.6.18 kernel). */
221 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
222 if (0 <= utimensat_works_really)
226 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
227 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
228 but work if both times are either explicitly specified or
229 UTIME_NOW. Work around it with a preparatory [f]stat prior
230 to calling futimens/utimensat; fortunately, there is not much
231 timing impact due to the extra syscall even on file systems
232 where UTIME_OMIT would have worked. FIXME: Simplify this in
233 2012, 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. */
245 # endif /* __linux__ */
249 result = utimensat (AT_FDCWD, file, ts, 0);
251 /* Work around a kernel bug:
252 http://bugzilla.redhat.com/442352
253 http://bugzilla.redhat.com/449910
254 It appears that utimensat can mistakenly return 280 rather
255 than -1 upon ENOSYS failure.
256 FIXME: remove in 2010 or whenever the offending kernels
257 are no longer in common use. */
260 # endif /* __linux__ */
261 if (result == 0 || errno != ENOSYS)
263 utimensat_works_really = 1;
267 # endif /* HAVE_UTIMENSAT */
271 result = futimens (fd, ts);
273 /* Work around the same bug as above. */
276 # endif /* __linux__ */
277 if (result == 0 || errno != ENOSYS)
279 utimensat_works_really = 1;
283 # endif /* HAVE_FUTIMENS */
285 utimensat_works_really = -1;
286 lutimensat_works_really = -1;
287 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
289 /* The platform lacks an interface to set file timestamps with
290 nanosecond resolution, so do the best we can, discarding any
291 fractional part of the timestamp. */
293 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
295 if (adjustment_needed != 3
296 && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
298 if (ts && update_timespec (&st, &ts))
303 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
304 struct timeval timeval[2];
305 struct timeval const *t;
308 timeval[0].tv_sec = ts[0].tv_sec;
309 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
310 timeval[1].tv_sec = ts[1].tv_sec;
311 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
320 return futimesat (AT_FDCWD, file, t);
325 /* If futimesat or futimes fails here, don't try to speed things
326 up by returning right away. glibc can incorrectly fail with
327 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
328 in high security mode doesn't allow ordinary users to read
329 /proc/self, so glibc incorrectly fails with errno == EACCES.
330 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
331 right away, but these cases are rare enough that they're not
332 worth optimizing, and who knows what other messed-up systems
333 are out there? So play it safe and fall back on the code
335 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
336 if (futimesat (fd, NULL, t) == 0)
339 if (futimes (fd, t) == 0)
343 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
347 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
348 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
354 #if HAVE_WORKING_UTIMES
355 return utimes (file, t);
358 struct utimbuf utimbuf;
362 utimbuf.actime = ts[0].tv_sec;
363 utimbuf.modtime = ts[1].tv_sec;
369 return utime (file, ut);
371 #endif /* !HAVE_WORKING_UTIMES */
375 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
376 TIMESPEC[0] and TIMESPEC[1], respectively.
377 FD must be either negative -- in which case it is ignored --
378 or a file descriptor that is open on FILE.
379 If FD is nonnegative, then FILE can be NULL, which means
380 use just futimes (or equivalent) instead of utimes (or equivalent),
381 and fail if on an old system without futimes (or equivalent).
382 If TIMESPEC is null, set the time stamps to the current time.
383 Return 0 on success, -1 (setting errno) on failure. */
386 gl_futimens (int fd, char const *file, struct timespec const timespec[2])
388 return fdutimens (file, fd, timespec);
391 /* Set the access and modification time stamps of FILE to be
392 TIMESPEC[0] and TIMESPEC[1], respectively. */
394 utimens (char const *file, struct timespec const timespec[2])
396 return fdutimens (file, -1, timespec);
399 /* Set the access and modification time stamps of FILE to be
400 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
401 symlinks. Fail with ENOSYS if the platform does not support
402 changing symlink timestamps, but FILE was a symlink. */
404 lutimens (char const *file, struct timespec const timespec[2])
406 struct timespec adjusted_timespec[2];
407 struct timespec *ts = timespec ? adjusted_timespec : NULL;
408 int adjustment_needed = 0;
413 adjusted_timespec[0] = timespec[0];
414 adjusted_timespec[1] = timespec[1];
415 adjustment_needed = validate_timespec (ts);
417 if (adjustment_needed < 0)
420 /* The Linux kernel did not support symlink timestamps until
421 utimensat, in version 2.6.22, so we don't need to mimic
422 gl_futimens' worry about buggy NFS clients. But we do have to
423 worry about bogus return values. */
426 if (0 <= lutimensat_works_really)
430 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
431 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
432 but work if both times are either explicitly specified or
433 UTIME_NOW. Work around it with a preparatory lstat prior to
434 calling utimensat; fortunately, there is not much timing
435 impact due to the extra syscall even on file systems where
436 UTIME_OMIT would have worked. FIXME: Simplify this in 2012,
437 when file system bugs are no longer common. */
438 if (adjustment_needed == 2)
440 if (lstat (file, &st))
442 if (ts[0].tv_nsec == UTIME_OMIT)
443 ts[0] = get_stat_atime (&st);
444 else if (ts[1].tv_nsec == UTIME_OMIT)
445 ts[1] = get_stat_mtime (&st);
446 /* Note that st is good, in case utimensat gives ENOSYS. */
449 # endif /* __linux__ */
450 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
452 /* Work around a kernel bug:
453 http://bugzilla.redhat.com/442352
454 http://bugzilla.redhat.com/449910
455 It appears that utimensat can mistakenly return 280 rather
456 than -1 upon ENOSYS failure.
457 FIXME: remove in 2010 or whenever the offending kernels
458 are no longer in common use. */
462 if (result == 0 || errno != ENOSYS)
464 utimensat_works_really = 1;
465 lutimensat_works_really = 1;
469 lutimensat_works_really = -1;
470 #endif /* HAVE_UTIMENSAT */
472 /* The platform lacks an interface to set file timestamps with
473 nanosecond resolution, so do the best we can, discarding any
474 fractional part of the timestamp. */
476 if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
478 if (adjustment_needed != 3 && lstat (file, &st))
480 if (ts && update_timespec (&st, &ts))
484 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
485 no point trying lutimes if utimensat failed with ENOSYS. */
486 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
488 struct timeval timeval[2];
489 struct timeval const *t;
493 timeval[0].tv_sec = ts[0].tv_sec;
494 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
495 timeval[1].tv_sec = ts[1].tv_sec;
496 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
502 result = lutimes (file, t);
503 if (result == 0 || errno != ENOSYS)
506 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
508 /* Out of luck for symlinks, but we still handle regular files. */
509 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
511 if (!S_ISLNK (st.st_mode))
512 return fdutimens (file, -1, ts);