Allow 'browse-url-emacs' to fetch URL in the selected window
[emacs.git] / lib / utimens.c
blobc0b0704eb29d29a50e53bb9b35f9ef41c218249f
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
8 later version.
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 */
22 #include <config.h>
24 #define _GL_UTIMENS_INLINE _GL_EXTERN_INLINE
25 #include "utimens.h"
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdbool.h>
30 #include <sys/stat.h>
31 #include <sys/time.h>
32 #include <unistd.h>
33 #include <utime.h>
35 #include "stat-time.h"
36 #include "timespec.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
46 # include <windows.h>
47 # if GNULIB_MSVC_NOTHROW
48 # include "msvc-nothrow.h"
49 # else
50 # include <io.h>
51 # endif
52 #endif
54 /* Avoid recursion with rpl_futimens or rpl_utimensat. */
55 #undef futimens
56 #undef 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
62 #endif
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. */
87 static int
88 validate_timespec (struct timespec timespec[2])
90 int result = 0;
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)))
101 errno = EINVAL;
102 return -1;
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;
112 result = 1;
113 if (timespec[0].tv_nsec == UTIME_OMIT)
114 utime_omit_count++;
116 if (timespec[1].tv_nsec == UTIME_NOW
117 || timespec[1].tv_nsec == UTIME_OMIT)
119 timespec[1].tv_sec = 0;
120 result = 1;
121 if (timespec[1].tv_nsec == UTIME_OMIT)
122 utime_omit_count++;
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. */
133 static bool
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)
139 return true;
140 if (timespec[0].tv_nsec == UTIME_NOW
141 && timespec[1].tv_nsec == UTIME_NOW)
143 *ts = NULL;
144 return false;
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 (&timespec[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 (&timespec[1]);
157 return false;
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;
176 struct stat st;
178 if (ts)
180 adjusted_timespec[0] = timespec[0];
181 adjusted_timespec[1] = timespec[1];
182 adjustment_needed = validate_timespec (ts);
184 if (adjustment_needed < 0)
185 return -1;
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
189 than failing. */
190 if (fd < 0 && !file)
192 errno = EBADF;
193 return -1;
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
207 if (fd < 0)
208 sync ();
209 else
210 fsync (fd);
211 #endif
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)
221 int result;
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))
238 return -1;
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. */
244 adjustment_needed++;
246 # endif
247 # if HAVE_UTIMENSAT
248 if (fd < 0)
250 result = utimensat (AT_FDCWD, file, ts, 0);
251 # ifdef __linux__
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. */
259 if (0 < result)
260 errno = ENOSYS;
261 # endif /* __linux__ */
262 if (result == 0 || errno != ENOSYS)
264 utimensat_works_really = 1;
265 return result;
268 # endif /* HAVE_UTIMENSAT */
269 # if HAVE_FUTIMENS
270 if (0 <= fd)
272 result = futimens (fd, ts);
273 # ifdef __linux__
274 /* Work around the same bug as above. */
275 if (0 < result)
276 errno = ENOSYS;
277 # endif /* __linux__ */
278 if (result == 0 || errno != ENOSYS)
280 utimensat_works_really = 1;
281 return result;
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> */
294 if (0 <= fd)
296 HANDLE handle;
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)
304 errno = EBADF;
305 return -1;
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 (&current_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;
327 else
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;
344 else
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))
353 return 0;
354 else
356 DWORD sft_error = GetLastError ();
357 #if 0
358 fprintf (stderr, "fdutimens SetFileTime error 0x%x\n", (unsigned int) sft_error);
359 #endif
360 switch (sft_error)
362 case ERROR_ACCESS_DENIED: /* fd was opened without O_RDWR */
363 errno = EACCES; /* not specified by POSIX */
364 break;
365 default:
366 errno = EINVAL;
367 break;
369 return -1;
372 #endif
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)))
382 return -1;
383 if (ts && update_timespec (&st, &ts))
384 return 0;
388 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
389 struct timeval timeval[2];
390 struct timeval *t;
391 if (ts)
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;
397 t = timeval;
399 else
400 t = NULL;
402 if (fd < 0)
404 # if HAVE_FUTIMESAT
405 return futimesat (AT_FDCWD, file, t);
406 # endif
408 else
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
419 below. */
421 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
422 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
423 # undef futimes
424 # define futimes(fd, t) futimesat (fd, NULL, t)
425 # endif
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. */
434 if (t)
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;
452 tt[0].tv_usec = 0;
454 if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
456 tt = truncated_timeval;
457 tt[1].tv_usec = 0;
459 if (tt)
460 futimes (fd, tt);
463 # endif
465 return 0;
467 # endif
469 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
471 if (!file)
473 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
474 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
475 errno = ENOSYS;
476 #endif
477 return -1;
480 #ifdef USE_SETFILETIME
481 return _gl_utimens_windows (file, ts);
482 #elif HAVE_WORKING_UTIMES
483 return utimes (file, t);
484 #else
486 struct utimbuf utimbuf;
487 struct utimbuf *ut;
488 if (ts)
490 utimbuf.actime = ts[0].tv_sec;
491 utimbuf.modtime = ts[1].tv_sec;
492 ut = &utimbuf;
494 else
495 ut = NULL;
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;
521 struct stat st;
523 if (ts)
525 adjusted_timespec[0] = timespec[0];
526 adjusted_timespec[1] = timespec[1];
527 adjustment_needed = validate_timespec (ts);
529 if (adjustment_needed < 0)
530 return -1;
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. */
537 #if HAVE_UTIMENSAT
538 if (0 <= lutimensat_works_really)
540 int result;
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))
557 return -1;
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. */
563 adjustment_needed++;
565 # endif
566 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
567 # ifdef __linux__
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. */
575 if (0 < result)
576 errno = ENOSYS;
577 # endif
578 if (result == 0 || errno != ENOSYS)
580 utimensat_works_really = 1;
581 lutimensat_works_really = 1;
582 return result;
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))
595 return -1;
596 if (ts && update_timespec (&st, &ts))
597 return 0;
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];
605 struct timeval *t;
606 int result;
607 if (ts)
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;
613 t = timeval;
615 else
616 t = NULL;
618 result = lutimes (file, t);
619 if (result == 0 || errno != ENOSYS)
620 return result;
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))
626 return -1;
627 if (!S_ISLNK (st.st_mode))
628 return fdutimens (-1, file, ts);
629 errno = ENOSYS;
630 return -1;