Apply GNU coding style to objc-mode as well as c-mode
[emacs.git] / lib / utimens.c
blobc126b9551a6dd4f681a44c3b5f2727a1116dca4e
1 /* Set file access and modification times.
3 Copyright (C) 2003-2012 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 #include "utimens.h"
26 #include <assert.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 assert (timespec);
90 if ((timespec[0].tv_nsec != UTIME_NOW
91 && timespec[0].tv_nsec != UTIME_OMIT
92 && (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec))
93 || (timespec[1].tv_nsec != UTIME_NOW
94 && timespec[1].tv_nsec != UTIME_OMIT
95 && (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec)))
97 errno = EINVAL;
98 return -1;
100 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
101 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
102 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
103 fails to bump ctime. */
104 if (timespec[0].tv_nsec == UTIME_NOW
105 || timespec[0].tv_nsec == UTIME_OMIT)
107 timespec[0].tv_sec = 0;
108 result = 1;
109 if (timespec[0].tv_nsec == UTIME_OMIT)
110 utime_omit_count++;
112 if (timespec[1].tv_nsec == UTIME_NOW
113 || timespec[1].tv_nsec == UTIME_OMIT)
115 timespec[1].tv_sec = 0;
116 result = 1;
117 if (timespec[1].tv_nsec == UTIME_OMIT)
118 utime_omit_count++;
120 return result + (utime_omit_count == 1);
123 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
124 buffer STATBUF to obtain the current timestamps of the file. If
125 both times are UTIME_NOW, set *TS to NULL (as this can avoid some
126 permissions issues). If both times are UTIME_OMIT, return true
127 (nothing further beyond the prior collection of STATBUF is
128 necessary); otherwise return false. */
129 static bool
130 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
132 struct timespec *timespec = *ts;
133 if (timespec[0].tv_nsec == UTIME_OMIT
134 && timespec[1].tv_nsec == UTIME_OMIT)
135 return true;
136 if (timespec[0].tv_nsec == UTIME_NOW
137 && timespec[1].tv_nsec == UTIME_NOW)
139 *ts = NULL;
140 return false;
143 if (timespec[0].tv_nsec == UTIME_OMIT)
144 timespec[0] = get_stat_atime (statbuf);
145 else if (timespec[0].tv_nsec == UTIME_NOW)
146 gettime (&timespec[0]);
148 if (timespec[1].tv_nsec == UTIME_OMIT)
149 timespec[1] = get_stat_mtime (statbuf);
150 else if (timespec[1].tv_nsec == UTIME_NOW)
151 gettime (&timespec[1]);
153 return false;
156 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
157 TIMESPEC[0] and TIMESPEC[1], respectively.
158 FD must be either negative -- in which case it is ignored --
159 or a file descriptor that is open on FILE.
160 If FD is nonnegative, then FILE can be NULL, which means
161 use just futimes (or equivalent) instead of utimes (or equivalent),
162 and fail if on an old system without futimes (or equivalent).
163 If TIMESPEC is null, set the time stamps to the current time.
164 Return 0 on success, -1 (setting errno) on failure. */
167 fdutimens (int fd, char const *file, struct timespec const timespec[2])
169 struct timespec adjusted_timespec[2];
170 struct timespec *ts = timespec ? adjusted_timespec : NULL;
171 int adjustment_needed = 0;
172 struct stat st;
174 if (ts)
176 adjusted_timespec[0] = timespec[0];
177 adjusted_timespec[1] = timespec[1];
178 adjustment_needed = validate_timespec (ts);
180 if (adjustment_needed < 0)
181 return -1;
183 /* Require that at least one of FD or FILE are potentially valid, to avoid
184 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
185 than failing. */
186 if (fd < 0 && !file)
188 errno = EBADF;
189 return -1;
192 /* Some Linux-based NFS clients are buggy, and mishandle time stamps
193 of files in NFS file systems in some cases. We have no
194 configure-time test for this, but please see
195 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
196 some of the problems with Linux 2.6.16. If this affects you,
197 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
198 help in some cases, albeit at a cost in performance. But you
199 really should upgrade your kernel to a fixed version, since the
200 problem affects many applications. */
202 #if HAVE_BUGGY_NFS_TIME_STAMPS
203 if (fd < 0)
204 sync ();
205 else
206 fsync (fd);
207 #endif
209 /* POSIX 2008 added two interfaces to set file timestamps with
210 nanosecond resolution; newer Linux implements both functions via
211 a single syscall. We provide a fallback for ENOSYS (for example,
212 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
213 running on Linux 2.6.18 kernel). */
214 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
215 if (0 <= utimensat_works_really)
217 int result;
218 # if __linux__
219 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
220 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
221 but work if both times are either explicitly specified or
222 UTIME_NOW. Work around it with a preparatory [f]stat prior
223 to calling futimens/utimensat; fortunately, there is not much
224 timing impact due to the extra syscall even on file systems
225 where UTIME_OMIT would have worked. FIXME: Simplify this in
226 2012, when file system bugs are no longer common. */
227 if (adjustment_needed == 2)
229 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
230 return -1;
231 if (ts[0].tv_nsec == UTIME_OMIT)
232 ts[0] = get_stat_atime (&st);
233 else if (ts[1].tv_nsec == UTIME_OMIT)
234 ts[1] = get_stat_mtime (&st);
235 /* Note that st is good, in case utimensat gives ENOSYS. */
236 adjustment_needed++;
238 # endif /* __linux__ */
239 # if HAVE_UTIMENSAT
240 if (fd < 0)
242 result = utimensat (AT_FDCWD, file, ts, 0);
243 # ifdef __linux__
244 /* Work around a kernel bug:
245 http://bugzilla.redhat.com/442352
246 http://bugzilla.redhat.com/449910
247 It appears that utimensat can mistakenly return 280 rather
248 than -1 upon ENOSYS failure.
249 FIXME: remove in 2010 or whenever the offending kernels
250 are no longer in common use. */
251 if (0 < result)
252 errno = ENOSYS;
253 # endif /* __linux__ */
254 if (result == 0 || errno != ENOSYS)
256 utimensat_works_really = 1;
257 return result;
260 # endif /* HAVE_UTIMENSAT */
261 # if HAVE_FUTIMENS
262 if (0 <= fd)
264 result = futimens (fd, ts);
265 # ifdef __linux__
266 /* Work around the same bug as above. */
267 if (0 < result)
268 errno = ENOSYS;
269 # endif /* __linux__ */
270 if (result == 0 || errno != ENOSYS)
272 utimensat_works_really = 1;
273 return result;
276 # endif /* HAVE_FUTIMENS */
278 utimensat_works_really = -1;
279 lutimensat_works_really = -1;
280 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
282 /* The platform lacks an interface to set file timestamps with
283 nanosecond resolution, so do the best we can, discarding any
284 fractional part of the timestamp. */
286 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
288 if (adjustment_needed != 3
289 && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
290 return -1;
291 if (ts && update_timespec (&st, &ts))
292 return 0;
296 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
297 struct timeval timeval[2];
298 struct timeval *t;
299 if (ts)
301 timeval[0].tv_sec = ts[0].tv_sec;
302 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
303 timeval[1].tv_sec = ts[1].tv_sec;
304 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
305 t = timeval;
307 else
308 t = NULL;
310 if (fd < 0)
312 # if HAVE_FUTIMESAT
313 return futimesat (AT_FDCWD, file, t);
314 # endif
316 else
318 /* If futimesat or futimes fails here, don't try to speed things
319 up by returning right away. glibc can incorrectly fail with
320 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
321 in high security mode doesn't allow ordinary users to read
322 /proc/self, so glibc incorrectly fails with errno == EACCES.
323 If errno == EIO, EPERM, or EROFS, it's probably safe to fail
324 right away, but these cases are rare enough that they're not
325 worth optimizing, and who knows what other messed-up systems
326 are out there? So play it safe and fall back on the code
327 below. */
329 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
330 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
331 # undef futimes
332 # define futimes(fd, t) futimesat (fd, NULL, t)
333 # endif
334 if (futimes (fd, t) == 0)
336 # if __linux__ && __GLIBC__
337 /* Work around a longstanding glibc bug, still present as
338 of 2010-12-27. On older Linux kernels that lack both
339 utimensat and utimes, glibc's futimes rounds instead of
340 truncating when falling back on utime. The same bug
341 occurs in futimesat with a null 2nd arg. */
342 if (t)
344 bool abig = 500000 <= t[0].tv_usec;
345 bool mbig = 500000 <= t[1].tv_usec;
346 if ((abig | mbig) && fstat (fd, &st) == 0)
348 /* If these two subtractions overflow, they'll
349 track the overflows inside the buggy glibc. */
350 time_t adiff = st.st_atime - t[0].tv_sec;
351 time_t mdiff = st.st_mtime - t[1].tv_sec;
353 struct timeval *tt = NULL;
354 struct timeval truncated_timeval[2];
355 truncated_timeval[0] = t[0];
356 truncated_timeval[1] = t[1];
357 if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
359 tt = truncated_timeval;
360 tt[0].tv_usec = 0;
362 if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
364 tt = truncated_timeval;
365 tt[1].tv_usec = 0;
367 if (tt)
368 futimes (fd, tt);
371 # endif
373 return 0;
375 # endif
377 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
379 if (!file)
381 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
382 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
383 errno = ENOSYS;
384 #endif
385 return -1;
388 #if HAVE_WORKING_UTIMES
389 return utimes (file, t);
390 #else
392 struct utimbuf utimbuf;
393 struct utimbuf *ut;
394 if (ts)
396 utimbuf.actime = ts[0].tv_sec;
397 utimbuf.modtime = ts[1].tv_sec;
398 ut = &utimbuf;
400 else
401 ut = NULL;
403 return utime (file, ut);
405 #endif /* !HAVE_WORKING_UTIMES */
409 /* Set the access and modification time stamps of FILE to be
410 TIMESPEC[0] and TIMESPEC[1], respectively. */
412 utimens (char const *file, struct timespec const timespec[2])
414 return fdutimens (-1, file, timespec);
417 /* Set the access and modification time stamps of FILE to be
418 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
419 symlinks. Fail with ENOSYS if the platform does not support
420 changing symlink timestamps, but FILE was a symlink. */
422 lutimens (char const *file, struct timespec const timespec[2])
424 struct timespec adjusted_timespec[2];
425 struct timespec *ts = timespec ? adjusted_timespec : NULL;
426 int adjustment_needed = 0;
427 struct stat st;
429 if (ts)
431 adjusted_timespec[0] = timespec[0];
432 adjusted_timespec[1] = timespec[1];
433 adjustment_needed = validate_timespec (ts);
435 if (adjustment_needed < 0)
436 return -1;
438 /* The Linux kernel did not support symlink timestamps until
439 utimensat, in version 2.6.22, so we don't need to mimic
440 fdutimens' worry about buggy NFS clients. But we do have to
441 worry about bogus return values. */
443 #if HAVE_UTIMENSAT
444 if (0 <= lutimensat_works_really)
446 int result;
447 # if __linux__
448 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
449 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
450 but work if both times are either explicitly specified or
451 UTIME_NOW. Work around it with a preparatory lstat prior to
452 calling utimensat; fortunately, there is not much timing
453 impact due to the extra syscall even on file systems where
454 UTIME_OMIT would have worked. FIXME: Simplify this in 2012,
455 when file system bugs are no longer common. */
456 if (adjustment_needed == 2)
458 if (lstat (file, &st))
459 return -1;
460 if (ts[0].tv_nsec == UTIME_OMIT)
461 ts[0] = get_stat_atime (&st);
462 else if (ts[1].tv_nsec == UTIME_OMIT)
463 ts[1] = get_stat_mtime (&st);
464 /* Note that st is good, in case utimensat gives ENOSYS. */
465 adjustment_needed++;
467 # endif /* __linux__ */
468 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
469 # ifdef __linux__
470 /* Work around a kernel bug:
471 http://bugzilla.redhat.com/442352
472 http://bugzilla.redhat.com/449910
473 It appears that utimensat can mistakenly return 280 rather
474 than -1 upon ENOSYS failure.
475 FIXME: remove in 2010 or whenever the offending kernels
476 are no longer in common use. */
477 if (0 < result)
478 errno = ENOSYS;
479 # endif
480 if (result == 0 || errno != ENOSYS)
482 utimensat_works_really = 1;
483 lutimensat_works_really = 1;
484 return result;
487 lutimensat_works_really = -1;
488 #endif /* HAVE_UTIMENSAT */
490 /* The platform lacks an interface to set file timestamps with
491 nanosecond resolution, so do the best we can, discarding any
492 fractional part of the timestamp. */
494 if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
496 if (adjustment_needed != 3 && lstat (file, &st))
497 return -1;
498 if (ts && update_timespec (&st, &ts))
499 return 0;
502 /* On Linux, lutimes is a thin wrapper around utimensat, so there is
503 no point trying lutimes if utimensat failed with ENOSYS. */
504 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
506 struct timeval timeval[2];
507 struct timeval *t;
508 int result;
509 if (ts)
511 timeval[0].tv_sec = ts[0].tv_sec;
512 timeval[0].tv_usec = ts[0].tv_nsec / 1000;
513 timeval[1].tv_sec = ts[1].tv_sec;
514 timeval[1].tv_usec = ts[1].tv_nsec / 1000;
515 t = timeval;
517 else
518 t = NULL;
520 result = lutimes (file, t);
521 if (result == 0 || errno != ENOSYS)
522 return result;
524 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
526 /* Out of luck for symlinks, but we still handle regular files. */
527 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
528 return -1;
529 if (!S_ISLNK (st.st_mode))
530 return fdutimens (-1, file, ts);
531 errno = ENOSYS;
532 return -1;