Add separator.pbm tool-bar image
[emacs.git] / lib / utimens.c
blob7386dcf210de32fa122d082cf55264409a1da0d3
1 /* Set file access and modification times.
3 Copyright (C) 2003-2015 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 <http://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>
34 #include "stat-time.h"
35 #include "timespec.h"
37 #if HAVE_UTIME_H
38 # include <utime.h>
39 #endif
41 /* Some systems (even some that do have <utime.h>) don't declare this
42 structure anywhere. */
43 #ifndef HAVE_STRUCT_UTIMBUF
44 struct utimbuf
46 long actime;
47 long modtime;
49 #endif
51 /* Avoid recursion with rpl_futimens or rpl_utimensat. */
52 #undef futimens
53 #undef utimensat
55 /* Solaris 9 mistakenly succeeds when given a non-directory with a
56 trailing slash. Force the use of rpl_stat for a fix. */
57 #ifndef REPLACE_FUNC_STAT_FILE
58 # define REPLACE_FUNC_STAT_FILE 0
59 #endif
61 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
62 /* Cache variables for whether the utimensat syscall works; used to
63 avoid calling the syscall if we know it will just fail with ENOSYS,
64 and to avoid unnecessary work in massaging timestamps if the
65 syscall will work. Multiple variables are needed, to distinguish
66 between the following scenarios on Linux:
67 utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
68 kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
69 kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
70 kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
71 utimensat completely works
72 For each cache variable: 0 = unknown, 1 = yes, -1 = no. */
73 static int utimensat_works_really;
74 static int lutimensat_works_really;
75 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
77 /* Validate the requested timestamps. Return 0 if the resulting
78 timespec can be used for utimensat (after possibly modifying it to
79 work around bugs in utimensat). Return a positive value if the
80 timespec needs further adjustment based on stat results: 1 if any
81 adjustment is needed for utimes, and 2 if any adjustment is needed
82 for Linux utimensat. Return -1, with errno set to EINVAL, if
83 timespec is out of range. */
84 static int
85 validate_timespec (struct timespec timespec[2])
87 int result = 0;
88 int utime_omit_count = 0;
89 if ((timespec[0].tv_nsec != UTIME_NOW
90 && timespec[0].tv_nsec != UTIME_OMIT
91 && ! (0 <= timespec[0].tv_nsec
92 && timespec[0].tv_nsec < TIMESPEC_RESOLUTION))
93 || (timespec[1].tv_nsec != UTIME_NOW
94 && timespec[1].tv_nsec != UTIME_OMIT
95 && ! (0 <= timespec[1].tv_nsec
96 && timespec[1].tv_nsec < TIMESPEC_RESOLUTION)))
98 errno = EINVAL;
99 return -1;
101 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
102 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
103 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
104 fails to bump ctime. */
105 if (timespec[0].tv_nsec == UTIME_NOW
106 || timespec[0].tv_nsec == UTIME_OMIT)
108 timespec[0].tv_sec = 0;
109 result = 1;
110 if (timespec[0].tv_nsec == UTIME_OMIT)
111 utime_omit_count++;
113 if (timespec[1].tv_nsec == UTIME_NOW
114 || timespec[1].tv_nsec == UTIME_OMIT)
116 timespec[1].tv_sec = 0;
117 result = 1;
118 if (timespec[1].tv_nsec == UTIME_OMIT)
119 utime_omit_count++;
121 return result + (utime_omit_count == 1);
124 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
125 buffer STATBUF to obtain the current timestamps of the file. If
126 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
127 permissions issues). If both times are UTIME_OMIT, return true
128 (nothing further beyond the prior collection of STATBUF is
129 necessary); otherwise return false. */
130 static bool
131 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
133 struct timespec *timespec = *ts;
134 if (timespec[0].tv_nsec == UTIME_OMIT
135 && timespec[1].tv_nsec == UTIME_OMIT)
136 return true;
137 if (timespec[0].tv_nsec == UTIME_NOW
138 && timespec[1].tv_nsec == UTIME_NOW)
140 *ts = NULL;
141 return false;
144 if (timespec[0].tv_nsec == UTIME_OMIT)
145 timespec[0] = get_stat_atime (statbuf);
146 else if (timespec[0].tv_nsec == UTIME_NOW)
147 gettime (&timespec[0]);
149 if (timespec[1].tv_nsec == UTIME_OMIT)
150 timespec[1] = get_stat_mtime (statbuf);
151 else if (timespec[1].tv_nsec == UTIME_NOW)
152 gettime (&timespec[1]);
154 return false;
157 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
158 TIMESPEC[0] and TIMESPEC[1], respectively.
159 FD must be either negative -- in which case it is ignored --
160 or a file descriptor that is open on FILE.
161 If FD is nonnegative, then FILE can be NULL, which means
162 use just futimes (or equivalent) instead of utimes (or equivalent),
163 and fail if on an old system without futimes (or equivalent).
164 If TIMESPEC is null, set the time stamps to the current time.
165 Return 0 on success, -1 (setting errno) on failure. */
168 fdutimens (int fd, char const *file, struct timespec const timespec[2])
170 struct timespec adjusted_timespec[2];
171 struct timespec *ts = timespec ? adjusted_timespec : NULL;
172 int adjustment_needed = 0;
173 struct stat st;
175 if (ts)
177 adjusted_timespec[0] = timespec[0];
178 adjusted_timespec[1] = timespec[1];
179 adjustment_needed = validate_timespec (ts);
181 if (adjustment_needed < 0)
182 return -1;
184 /* Require that at least one of FD or FILE are potentially valid, to avoid
185 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
186 than failing. */
187 if (fd < 0 && !file)
189 errno = EBADF;
190 return -1;
193 /* Some Linux-based NFS clients are buggy, and mishandle time stamps
194 of files in NFS file systems in some cases. We have no
195 configure-time test for this, but please see
196 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
197 some of the problems with Linux 2.6.16. If this affects you,
198 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
199 help in some cases, albeit at a cost in performance. But you
200 really should upgrade your kernel to a fixed version, since the
201 problem affects many applications. */
203 #if HAVE_BUGGY_NFS_TIME_STAMPS
204 if (fd < 0)
205 sync ();
206 else
207 fsync (fd);
208 #endif
210 /* POSIX 2008 added two interfaces to set file timestamps with
211 nanosecond resolution; newer Linux implements both functions via
212 a single syscall. We provide a fallback for ENOSYS (for example,
213 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
214 running on Linux 2.6.18 kernel). */
215 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
216 if (0 <= utimensat_works_really)
218 int result;
219 # if __linux__ || __sun
220 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
221 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
222 but work if both times are either explicitly specified or
223 UTIME_NOW. Work around it with a preparatory [f]stat prior
224 to calling futimens/utimensat; fortunately, there is not much
225 timing impact due to the extra syscall even on file systems
226 where UTIME_OMIT would have worked.
228 The same bug occurs in Solaris 11.1 (Apr 2013).
230 FIXME: Simplify this for Linux in 2016 and for Solaris in
231 2024, when file system bugs are no longer common. */
232 if (adjustment_needed == 2)
234 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
235 return -1;
236 if (ts[0].tv_nsec == UTIME_OMIT)
237 ts[0] = get_stat_atime (&st);
238 else if (ts[1].tv_nsec == UTIME_OMIT)
239 ts[1] = get_stat_mtime (&st);
240 /* Note that st is good, in case utimensat gives ENOSYS. */
241 adjustment_needed++;
243 # endif
244 # if HAVE_UTIMENSAT
245 if (fd < 0)
247 result = utimensat (AT_FDCWD, file, ts, 0);
248 # ifdef __linux__
249 /* Work around a kernel bug:
250 http://bugzilla.redhat.com/442352
251 http://bugzilla.redhat.com/449910
252 It appears that utimensat can mistakenly return 280 rather
253 than -1 upon ENOSYS failure.
254 FIXME: remove in 2010 or whenever the offending kernels
255 are no longer in common use. */
256 if (0 < result)
257 errno = ENOSYS;
258 # endif /* __linux__ */
259 if (result == 0 || errno != ENOSYS)
261 utimensat_works_really = 1;
262 return result;
265 # endif /* HAVE_UTIMENSAT */
266 # if HAVE_FUTIMENS
267 if (0 <= fd)
269 result = futimens (fd, ts);
270 # ifdef __linux__
271 /* Work around the same bug as above. */
272 if (0 < result)
273 errno = ENOSYS;
274 # endif /* __linux__ */
275 if (result == 0 || errno != ENOSYS)
277 utimensat_works_really = 1;
278 return result;
281 # endif /* HAVE_FUTIMENS */
283 utimensat_works_really = -1;
284 lutimensat_works_really = -1;
285 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
287 /* The platform lacks an interface to set file timestamps with
288 nanosecond resolution, so do the best we can, discarding any
289 fractional part of the timestamp. */
291 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
293 if (adjustment_needed != 3
294 && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
295 return -1;
296 if (ts && update_timespec (&st, &ts))
297 return 0;
301 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
302 struct timeval timeval[2];
303 struct timeval *t;
304 if (ts)
306 timeval[0].tv_sec = ts[0].tv_sec;
307 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
308 timeval[1].tv_sec = ts[1].tv_sec;
309 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
310 t = timeval;
312 else
313 t = NULL;
315 if (fd < 0)
317 # if HAVE_FUTIMESAT
318 return futimesat (AT_FDCWD, file, t);
319 # endif
321 else
323 /* If futimesat or futimes fails here, don't try to speed things
324 up by returning right away. glibc can incorrectly fail with
325 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
326 in high security mode doesn't allow ordinary users to read
327 /proc/self, so glibc incorrectly fails with errno == EACCES.
328 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
329 right away, but these cases are rare enough that they're not
330 worth optimizing, and who knows what other messed-up systems
331 are out there? So play it safe and fall back on the code
332 below. */
334 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
335 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
336 # undef futimes
337 # define futimes(fd, t) futimesat (fd, NULL, t)
338 # endif
339 if (futimes (fd, t) == 0)
341 # if __linux__ && __GLIBC__
342 /* Work around a longstanding glibc bug, still present as
343 of 2010-12-27. On older Linux kernels that lack both
344 utimensat and utimes, glibc's futimes rounds instead of
345 truncating when falling back on utime. The same bug
346 occurs in futimesat with a null 2nd arg. */
347 if (t)
349 bool abig = 500000 <= t[0].tv_usec;
350 bool mbig = 500000 <= t[1].tv_usec;
351 if ((abig | mbig) && fstat (fd, &st) == 0)
353 /* If these two subtractions overflow, they'll
354 track the overflows inside the buggy glibc. */
355 time_t adiff = st.st_atime - t[0].tv_sec;
356 time_t mdiff = st.st_mtime - t[1].tv_sec;
358 struct timeval *tt = NULL;
359 struct timeval truncated_timeval[2];
360 truncated_timeval[0] = t[0];
361 truncated_timeval[1] = t[1];
362 if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
364 tt = truncated_timeval;
365 tt[0].tv_usec = 0;
367 if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
369 tt = truncated_timeval;
370 tt[1].tv_usec = 0;
372 if (tt)
373 futimes (fd, tt);
376 # endif
378 return 0;
380 # endif
382 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
384 if (!file)
386 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
387 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
388 errno = ENOSYS;
389 #endif
390 return -1;
393 #if HAVE_WORKING_UTIMES
394 return utimes (file, t);
395 #else
397 struct utimbuf utimbuf;
398 struct utimbuf *ut;
399 if (ts)
401 utimbuf.actime = ts[0].tv_sec;
402 utimbuf.modtime = ts[1].tv_sec;
403 ut = &utimbuf;
405 else
406 ut = NULL;
408 return utime (file, ut);
410 #endif /* !HAVE_WORKING_UTIMES */
414 /* Set the access and modification time stamps of FILE to be
415 TIMESPEC[0] and TIMESPEC[1], respectively. */
417 utimens (char const *file, struct timespec const timespec[2])
419 return fdutimens (-1, file, timespec);
422 /* Set the access and modification time stamps of FILE to be
423 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
424 symlinks. Fail with ENOSYS if the platform does not support
425 changing symlink timestamps, but FILE was a symlink. */
427 lutimens (char const *file, struct timespec const timespec[2])
429 struct timespec adjusted_timespec[2];
430 struct timespec *ts = timespec ? adjusted_timespec : NULL;
431 int adjustment_needed = 0;
432 struct stat st;
434 if (ts)
436 adjusted_timespec[0] = timespec[0];
437 adjusted_timespec[1] = timespec[1];
438 adjustment_needed = validate_timespec (ts);
440 if (adjustment_needed < 0)
441 return -1;
443 /* The Linux kernel did not support symlink timestamps until
444 utimensat, in version 2.6.22, so we don't need to mimic
445 fdutimens' worry about buggy NFS clients. But we do have to
446 worry about bogus return values. */
448 #if HAVE_UTIMENSAT
449 if (0 <= lutimensat_works_really)
451 int result;
452 # if __linux__ || __sun
453 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
454 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
455 but work if both times are either explicitly specified or
456 UTIME_NOW. Work around it with a preparatory lstat prior to
457 calling utimensat; fortunately, there is not much timing
458 impact due to the extra syscall even on file systems where
459 UTIME_OMIT would have worked.
461 The same bug occurs in Solaris 11.1 (Apr 2013).
463 FIXME: Simplify this for Linux in 2016 and for Solaris in
464 2024, when file system bugs are no longer common. */
465 if (adjustment_needed == 2)
467 if (lstat (file, &st))
468 return -1;
469 if (ts[0].tv_nsec == UTIME_OMIT)
470 ts[0] = get_stat_atime (&st);
471 else if (ts[1].tv_nsec == UTIME_OMIT)
472 ts[1] = get_stat_mtime (&st);
473 /* Note that st is good, in case utimensat gives ENOSYS. */
474 adjustment_needed++;
476 # endif
477 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
478 # ifdef __linux__
479 /* Work around a kernel bug:
480 http://bugzilla.redhat.com/442352
481 http://bugzilla.redhat.com/449910
482 It appears that utimensat can mistakenly return 280 rather
483 than -1 upon ENOSYS failure.
484 FIXME: remove in 2010 or whenever the offending kernels
485 are no longer in common use. */
486 if (0 < result)
487 errno = ENOSYS;
488 # endif
489 if (result == 0 || errno != ENOSYS)
491 utimensat_works_really = 1;
492 lutimensat_works_really = 1;
493 return result;
496 lutimensat_works_really = -1;
497 #endif /* HAVE_UTIMENSAT */
499 /* The platform lacks an interface to set file timestamps with
500 nanosecond resolution, so do the best we can, discarding any
501 fractional part of the timestamp. */
503 if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
505 if (adjustment_needed != 3 && lstat (file, &st))
506 return -1;
507 if (ts && update_timespec (&st, &ts))
508 return 0;
511 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
512 no point trying lutimes if utimensat failed with ENOSYS. */
513 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
515 struct timeval timeval[2];
516 struct timeval *t;
517 int result;
518 if (ts)
520 timeval[0].tv_sec = ts[0].tv_sec;
521 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
522 timeval[1].tv_sec = ts[1].tv_sec;
523 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
524 t = timeval;
526 else
527 t = NULL;
529 result = lutimes (file, t);
530 if (result == 0 || errno != ENOSYS)
531 return result;
533 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
535 /* Out of luck for symlinks, but we still handle regular files. */
536 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
537 return -1;
538 if (!S_ISLNK (st.st_mode))
539 return fdutimens (-1, file, ts);
540 errno = ENOSYS;
541 return -1;