1 /* Set file access and modification times.
3 Copyright (C) 2003-2018 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 <https://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"
38 /* On native Windows, use SetFileTime; but avoid this when compiling
39 GNU Emacs, which arranges for this in some other way and which
40 defines WIN32_LEAN_AND_MEAN itself. */
42 #if ((defined _WIN32 || defined __WIN32__) \
43 && ! defined __CYGWIN__ && ! defined EMACS_CONFIGURATION)
44 # define USE_SETFILETIME
45 # define WIN32_LEAN_AND_MEAN
47 # if GNULIB_MSVC_NOTHROW
48 # include "msvc-nothrow.h"
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;
92 if ((timespec
[0].tv_nsec
!= UTIME_NOW
93 && timespec
[0].tv_nsec
!= UTIME_OMIT
94 && ! (0 <= timespec
[0].tv_nsec
95 && timespec
[0].tv_nsec
< TIMESPEC_RESOLUTION
))
96 || (timespec
[1].tv_nsec
!= UTIME_NOW
97 && timespec
[1].tv_nsec
!= UTIME_OMIT
98 && ! (0 <= timespec
[1].tv_nsec
99 && timespec
[1].tv_nsec
< TIMESPEC_RESOLUTION
)))
104 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
105 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
106 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
107 fails to bump ctime. */
108 if (timespec
[0].tv_nsec
== UTIME_NOW
109 || timespec
[0].tv_nsec
== UTIME_OMIT
)
111 timespec
[0].tv_sec
= 0;
113 if (timespec
[0].tv_nsec
== UTIME_OMIT
)
116 if (timespec
[1].tv_nsec
== UTIME_NOW
117 || timespec
[1].tv_nsec
== UTIME_OMIT
)
119 timespec
[1].tv_sec
= 0;
121 if (timespec
[1].tv_nsec
== UTIME_OMIT
)
124 return result
+ (utime_omit_count
== 1);
127 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
128 buffer STATBUF to obtain the current timestamps of the file. If
129 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
130 permissions issues). If both times are UTIME_OMIT, return true
131 (nothing further beyond the prior collection of STATBUF is
132 necessary); otherwise return false. */
134 update_timespec (struct stat
const *statbuf
, struct timespec
*ts
[2])
136 struct timespec
*timespec
= *ts
;
137 if (timespec
[0].tv_nsec
== UTIME_OMIT
138 && timespec
[1].tv_nsec
== UTIME_OMIT
)
140 if (timespec
[0].tv_nsec
== UTIME_NOW
141 && timespec
[1].tv_nsec
== UTIME_NOW
)
147 if (timespec
[0].tv_nsec
== UTIME_OMIT
)
148 timespec
[0] = get_stat_atime (statbuf
);
149 else if (timespec
[0].tv_nsec
== UTIME_NOW
)
150 gettime (×pec
[0]);
152 if (timespec
[1].tv_nsec
== UTIME_OMIT
)
153 timespec
[1] = get_stat_mtime (statbuf
);
154 else if (timespec
[1].tv_nsec
== UTIME_NOW
)
155 gettime (×pec
[1]);
160 /* Set the access and modification timestamps of FD (a.k.a. FILE) to be
161 TIMESPEC[0] and TIMESPEC[1], respectively.
162 FD must be either negative -- in which case it is ignored --
163 or a file descriptor that is open on FILE.
164 If FD is nonnegative, then FILE can be NULL, which means
165 use just futimes (or equivalent) instead of utimes (or equivalent),
166 and fail if on an old system without futimes (or equivalent).
167 If TIMESPEC is null, set the timestamps to the current time.
168 Return 0 on success, -1 (setting errno) on failure. */
171 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
173 struct timespec adjusted_timespec
[2];
174 struct timespec
*ts
= timespec
? adjusted_timespec
: NULL
;
175 int adjustment_needed
= 0;
180 adjusted_timespec
[0] = timespec
[0];
181 adjusted_timespec
[1] = timespec
[1];
182 adjustment_needed
= validate_timespec (ts
);
184 if (adjustment_needed
< 0)
187 /* Require that at least one of FD or FILE are potentially valid, to avoid
188 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
196 /* Some Linux-based NFS clients are buggy, and mishandle timestamps
197 of files in NFS file systems in some cases. We have no
198 configure-time test for this, but please see
199 <https://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
200 some of the problems with Linux 2.6.16. If this affects you,
201 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
202 help in some cases, albeit at a cost in performance. But you
203 really should upgrade your kernel to a fixed version, since the
204 problem affects many applications. */
206 #if HAVE_BUGGY_NFS_TIME_STAMPS
213 /* POSIX 2008 added two interfaces to set file timestamps with
214 nanosecond resolution; newer Linux implements both functions via
215 a single syscall. We provide a fallback for ENOSYS (for example,
216 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
217 running on Linux 2.6.18 kernel). */
218 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
219 if (0 <= utimensat_works_really
)
222 # if __linux__ || __sun
223 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
224 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
225 but work if both times are either explicitly specified or
226 UTIME_NOW. Work around it with a preparatory [f]stat prior
227 to calling futimens/utimensat; fortunately, there is not much
228 timing impact due to the extra syscall even on file systems
229 where UTIME_OMIT would have worked.
231 The same bug occurs in Solaris 11.1 (Apr 2013).
233 FIXME: Simplify this for Linux in 2016 and for Solaris in
234 2024, when file system bugs are no longer common. */
235 if (adjustment_needed
== 2)
237 if (fd
< 0 ? stat (file
, &st
) : fstat (fd
, &st
))
239 if (ts
[0].tv_nsec
== UTIME_OMIT
)
240 ts
[0] = get_stat_atime (&st
);
241 else if (ts
[1].tv_nsec
== UTIME_OMIT
)
242 ts
[1] = get_stat_mtime (&st
);
243 /* Note that st is good, in case utimensat gives ENOSYS. */
250 result
= utimensat (AT_FDCWD
, file
, ts
, 0);
252 /* Work around a kernel bug:
253 https://bugzilla.redhat.com/show_bug.cgi?id=442352
254 https://bugzilla.redhat.com/show_bug.cgi?id=449910
255 It appears that utimensat can mistakenly return 280 rather
256 than -1 upon ENOSYS failure.
257 FIXME: remove in 2010 or whenever the offending kernels
258 are no longer in common use. */
261 # endif /* __linux__ */
262 if (result
== 0 || errno
!= ENOSYS
)
264 utimensat_works_really
= 1;
268 # endif /* HAVE_UTIMENSAT */
272 result
= futimens (fd
, ts
);
274 /* Work around the same bug as above. */
277 # endif /* __linux__ */
278 if (result
== 0 || errno
!= ENOSYS
)
280 utimensat_works_really
= 1;
284 # endif /* HAVE_FUTIMENS */
286 utimensat_works_really
= -1;
287 lutimensat_works_really
= -1;
288 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
290 #ifdef USE_SETFILETIME
291 /* On native Windows, use SetFileTime(). See
292 <https://msdn.microsoft.com/en-us/library/ms724933.aspx>
293 <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */
297 FILETIME current_time
;
298 FILETIME last_access_time
;
299 FILETIME last_write_time
;
301 handle
= (HANDLE
) _get_osfhandle (fd
);
302 if (handle
== INVALID_HANDLE_VALUE
)
308 if (ts
== NULL
|| ts
[0].tv_nsec
== UTIME_NOW
|| ts
[1].tv_nsec
== UTIME_NOW
)
310 /* GetSystemTimeAsFileTime
311 <https://msdn.microsoft.com/en-us/library/ms724397.aspx>.
312 It would be overkill to use
313 GetSystemTimePreciseAsFileTime
314 <https://msdn.microsoft.com/en-us/library/hh706895.aspx>. */
315 GetSystemTimeAsFileTime (¤t_time
);
318 if (ts
== NULL
|| ts
[0].tv_nsec
== UTIME_NOW
)
320 last_access_time
= current_time
;
322 else if (ts
[0].tv_nsec
== UTIME_OMIT
)
324 last_access_time
.dwLowDateTime
= 0;
325 last_access_time
.dwHighDateTime
= 0;
329 ULONGLONG time_since_16010101
=
330 (ULONGLONG
) ts
[0].tv_sec
* 10000000 + ts
[0].tv_nsec
/ 100 + 116444736000000000LL;
331 last_access_time
.dwLowDateTime
= (DWORD
) time_since_16010101
;
332 last_access_time
.dwHighDateTime
= time_since_16010101
>> 32;
335 if (ts
== NULL
|| ts
[1].tv_nsec
== UTIME_NOW
)
337 last_write_time
= current_time
;
339 else if (ts
[1].tv_nsec
== UTIME_OMIT
)
341 last_write_time
.dwLowDateTime
= 0;
342 last_write_time
.dwHighDateTime
= 0;
346 ULONGLONG time_since_16010101
=
347 (ULONGLONG
) ts
[1].tv_sec
* 10000000 + ts
[1].tv_nsec
/ 100 + 116444736000000000LL;
348 last_write_time
.dwLowDateTime
= (DWORD
) time_since_16010101
;
349 last_write_time
.dwHighDateTime
= time_since_16010101
>> 32;
352 if (SetFileTime (handle
, NULL
, &last_access_time
, &last_write_time
))
356 DWORD sft_error
= GetLastError ();
358 fprintf (stderr
, "fdutimens SetFileTime error 0x%x\n", (unsigned int) sft_error
);
362 case ERROR_ACCESS_DENIED
: /* fd was opened without O_RDWR */
363 errno
= EACCES
; /* not specified by POSIX */
374 /* The platform lacks an interface to set file timestamps with
375 nanosecond resolution, so do the best we can, discarding any
376 fractional part of the timestamp. */
378 if (adjustment_needed
|| (REPLACE_FUNC_STAT_FILE
&& fd
< 0))
380 if (adjustment_needed
!= 3
381 && (fd
< 0 ? stat (file
, &st
) : fstat (fd
, &st
)))
383 if (ts
&& update_timespec (&st
, &ts
))
388 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
389 struct timeval timeval
[2];
393 timeval
[0].tv_sec
= ts
[0].tv_sec
;
394 timeval
[0].tv_usec
= ts
[0].tv_nsec
/ 1000;
395 timeval
[1].tv_sec
= ts
[1].tv_sec
;
396 timeval
[1].tv_usec
= ts
[1].tv_nsec
/ 1000;
405 return futimesat (AT_FDCWD
, file
, t
);
410 /* If futimesat or futimes fails here, don't try to speed things
411 up by returning right away. glibc can incorrectly fail with
412 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
413 in high security mode doesn't allow ordinary users to read
414 /proc/self, so glibc incorrectly fails with errno == EACCES.
415 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
416 right away, but these cases are rare enough that they're not
417 worth optimizing, and who knows what other messed-up systems
418 are out there? So play it safe and fall back on the code
421 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
422 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
424 # define futimes(fd, t) futimesat (fd, NULL, t)
426 if (futimes (fd
, t
) == 0)
428 # if __linux__ && __GLIBC__
429 /* Work around a longstanding glibc bug, still present as
430 of 2010-12-27. On older Linux kernels that lack both
431 utimensat and utimes, glibc's futimes rounds instead of
432 truncating when falling back on utime. The same bug
433 occurs in futimesat with a null 2nd arg. */
436 bool abig
= 500000 <= t
[0].tv_usec
;
437 bool mbig
= 500000 <= t
[1].tv_usec
;
438 if ((abig
| mbig
) && fstat (fd
, &st
) == 0)
440 /* If these two subtractions overflow, they'll
441 track the overflows inside the buggy glibc. */
442 time_t adiff
= st
.st_atime
- t
[0].tv_sec
;
443 time_t mdiff
= st
.st_mtime
- t
[1].tv_sec
;
445 struct timeval
*tt
= NULL
;
446 struct timeval truncated_timeval
[2];
447 truncated_timeval
[0] = t
[0];
448 truncated_timeval
[1] = t
[1];
449 if (abig
&& adiff
== 1 && get_stat_atime_ns (&st
) == 0)
451 tt
= truncated_timeval
;
454 if (mbig
&& mdiff
== 1 && get_stat_mtime_ns (&st
) == 0)
456 tt
= truncated_timeval
;
469 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
473 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
474 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
480 #ifdef USE_SETFILETIME
481 return _gl_utimens_windows (file
, ts
);
482 #elif HAVE_WORKING_UTIMES
483 return utimes (file
, t
);
486 struct utimbuf utimbuf
;
490 utimbuf
.actime
= ts
[0].tv_sec
;
491 utimbuf
.modtime
= ts
[1].tv_sec
;
497 return utime (file
, ut
);
499 #endif /* !HAVE_WORKING_UTIMES */
503 /* Set the access and modification timestamps of FILE to be
504 TIMESPEC[0] and TIMESPEC[1], respectively. */
506 utimens (char const *file
, struct timespec
const timespec
[2])
508 return fdutimens (-1, file
, timespec
);
511 /* Set the access and modification timestamps of FILE to be
512 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
513 symlinks. Fail with ENOSYS if the platform does not support
514 changing symlink timestamps, but FILE was a symlink. */
516 lutimens (char const *file
, struct timespec
const timespec
[2])
518 struct timespec adjusted_timespec
[2];
519 struct timespec
*ts
= timespec
? adjusted_timespec
: NULL
;
520 int adjustment_needed
= 0;
525 adjusted_timespec
[0] = timespec
[0];
526 adjusted_timespec
[1] = timespec
[1];
527 adjustment_needed
= validate_timespec (ts
);
529 if (adjustment_needed
< 0)
532 /* The Linux kernel did not support symlink timestamps until
533 utimensat, in version 2.6.22, so we don't need to mimic
534 fdutimens' worry about buggy NFS clients. But we do have to
535 worry about bogus return values. */
538 if (0 <= lutimensat_works_really
)
541 # if __linux__ || __sun
542 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
543 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
544 but work if both times are either explicitly specified or
545 UTIME_NOW. Work around it with a preparatory lstat prior to
546 calling utimensat; fortunately, there is not much timing
547 impact due to the extra syscall even on file systems where
548 UTIME_OMIT would have worked.
550 The same bug occurs in Solaris 11.1 (Apr 2013).
552 FIXME: Simplify this for Linux in 2016 and for Solaris in
553 2024, when file system bugs are no longer common. */
554 if (adjustment_needed
== 2)
556 if (lstat (file
, &st
))
558 if (ts
[0].tv_nsec
== UTIME_OMIT
)
559 ts
[0] = get_stat_atime (&st
);
560 else if (ts
[1].tv_nsec
== UTIME_OMIT
)
561 ts
[1] = get_stat_mtime (&st
);
562 /* Note that st is good, in case utimensat gives ENOSYS. */
566 result
= utimensat (AT_FDCWD
, file
, ts
, AT_SYMLINK_NOFOLLOW
);
568 /* Work around a kernel bug:
569 https://bugzilla.redhat.com/show_bug.cgi?id=442352
570 https://bugzilla.redhat.com/show_bug.cgi?id=449910
571 It appears that utimensat can mistakenly return 280 rather
572 than -1 upon ENOSYS failure.
573 FIXME: remove in 2010 or whenever the offending kernels
574 are no longer in common use. */
578 if (result
== 0 || errno
!= ENOSYS
)
580 utimensat_works_really
= 1;
581 lutimensat_works_really
= 1;
585 lutimensat_works_really
= -1;
586 #endif /* HAVE_UTIMENSAT */
588 /* The platform lacks an interface to set file timestamps with
589 nanosecond resolution, so do the best we can, discarding any
590 fractional part of the timestamp. */
592 if (adjustment_needed
|| REPLACE_FUNC_STAT_FILE
)
594 if (adjustment_needed
!= 3 && lstat (file
, &st
))
596 if (ts
&& update_timespec (&st
, &ts
))
600 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
601 no point trying lutimes if utimensat failed with ENOSYS. */
602 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
604 struct timeval timeval
[2];
609 timeval
[0].tv_sec
= ts
[0].tv_sec
;
610 timeval
[0].tv_usec
= ts
[0].tv_nsec
/ 1000;
611 timeval
[1].tv_sec
= ts
[1].tv_sec
;
612 timeval
[1].tv_usec
= ts
[1].tv_nsec
/ 1000;
618 result
= lutimes (file
, t
);
619 if (result
== 0 || errno
!= ENOSYS
)
622 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
624 /* Out of luck for symlinks, but we still handle regular files. */
625 if (!(adjustment_needed
|| REPLACE_FUNC_STAT_FILE
) && lstat (file
, &st
))
627 if (!S_ISLNK (st
.st_mode
))
628 return fdutimens (-1, file
, ts
);