utimens: work around Linux ctime bug
[gnulib.git] / lib / utimens.c
1 /* Set file access and modification times.
2
3    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free
4    Software Foundation, Inc.
5
6    This program is free software: you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 3 of the License, or any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 /* Written by Paul Eggert.  */
20
21 /* derived from a function in touch.c */
22
23 #include <config.h>
24
25 #include "utimens.h"
26
27 #include <assert.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdbool.h>
31 #include <sys/stat.h>
32 #include <sys/time.h>
33 #include <unistd.h>
34
35 #include "stat-time.h"
36 #include "timespec.h"
37
38 #if HAVE_UTIME_H
39 # include <utime.h>
40 #endif
41
42 /* Some systems (even some that do have <utime.h>) don't declare this
43    structure anywhere.  */
44 #ifndef HAVE_STRUCT_UTIMBUF
45 struct utimbuf
46 {
47   long actime;
48   long modtime;
49 };
50 #endif
51
52 /* Avoid recursion with rpl_futimens or rpl_utimensat.  */
53 #undef futimens
54 #undef utimensat
55
56 /* Solaris 9 mistakenly succeeds when given a non-directory with a
57    trailing slash.  Force the use of rpl_stat for a fix.  */
58 #ifndef REPLACE_FUNC_STAT_FILE
59 # define REPLACE_FUNC_STAT_FILE 0
60 #endif
61
62 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
63 /* Cache variables for whether the utimensat syscall works; used to
64    avoid calling the syscall if we know it will just fail with ENOSYS,
65    and to avoid unnecessary work in massaging timestamps if the
66    syscall will work.  Multiple variables are needed, to distinguish
67    between the following scenarios on Linux:
68    utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
69    kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
70    kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
71    kernel 2.6.32 and earlier fail to bump ctime if mtime is UTIME_OMIT
72    utimensat completely works
73    For each cache variable: 0 = unknown, 1 = yes, -1 = no.  */
74 static int utimensat_works_really;
75 static int lutimensat_works_really;
76 static int utimensat_ctime_really;
77
78 /* Determine whether the kernel has a ctime bug.  ST1 and ST2
79    correspond to stat data before and after a successful time change.
80    TIMES contains the timestamps that were used during the time change
81    (mtime will be UTIME_OMIT).  Update the cache variable if there is
82    conclusive evidence of the kernel working or being buggy.  Return
83    true if TIMES has been updated and another kernel call is needed,
84    whether or not the kernel is known to have the bug.  */
85 static bool
86 detect_ctime_bug (struct stat *st1, struct stat *st2, struct timespec times[2])
87 {
88   struct timespec now;
89   if (st1->st_ctime != st2->st_ctime
90       || get_stat_ctime_ns (st1) != get_stat_ctime_ns (st2))
91     {
92       utimensat_ctime_really = 1;
93       return false;
94     }
95   /* The results are inconclusive if the ctime in st1 is within a file
96      system quantization window of now.  For FAT, this is 2 seconds,
97      for systems with sub-second resolution, a typical resolution is
98      10 milliseconds; to be safe we declare an inconsistent result if
99      ctime is within a 20 millisecond window.  Avoid an extra gettime
100      call if atime makes sense.  It is unlikely that the original
101      ctime is later than now, but rather than deal with the overflow,
102      we treat that as consistent evidence of the bug.  */
103   if (times[0].tv_nsec == UTIME_NOW)
104     now = get_stat_atime (st2);
105   else
106     gettime (&now);
107   if (now.tv_sec < st2->st_ctime
108       || 2 < now.tv_sec - st2->st_ctime
109       || (get_stat_ctime_ns (st2)
110           && now.tv_sec - st2->st_ctime < 2
111           && (20000000 < (1000000000 * (now.tv_sec - st2->st_ctime)
112                           + now.tv_nsec - get_stat_ctime_ns (st2)))))
113     utimensat_ctime_really = -1;
114   times[1] = get_stat_mtime (st2);
115   return true;
116 }
117 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
118
119 /* Validate the requested timestamps.  Return 0 if the resulting
120    timespec can be used for utimensat (after possibly modifying it to
121    work around bugs in utimensat).  Return a positive value if the
122    timespec needs further adjustment based on stat results: 1 if any
123    adjustment is needed for utimes, and 2 if mtime was UTIME_OMIT and
124    an adjustment is needed for utimensat.  Return -1, with errno set
125    to EINVAL, if timespec is out of range.  */
126 static int
127 validate_timespec (struct timespec timespec[2])
128 {
129   int result = 0;
130   assert (timespec);
131   if ((timespec[0].tv_nsec != UTIME_NOW
132        && timespec[0].tv_nsec != UTIME_OMIT
133        && (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec))
134       || (timespec[1].tv_nsec != UTIME_NOW
135           && timespec[1].tv_nsec != UTIME_OMIT
136           && (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec)))
137     {
138       errno = EINVAL;
139       return -1;
140     }
141   /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
142      EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
143      Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
144      fails to bump ctime.  */
145   if (timespec[0].tv_nsec == UTIME_NOW
146       || timespec[0].tv_nsec == UTIME_OMIT)
147     {
148       timespec[0].tv_sec = 0;
149       result = 1;
150     }
151   if (timespec[1].tv_nsec == UTIME_NOW)
152     {
153       timespec[1].tv_sec = 0;
154       result = 1;
155     }
156   else if (timespec[1].tv_nsec == UTIME_OMIT)
157     {
158       timespec[1].tv_sec = 0;
159       result = 2;
160     }
161   return result;
162 }
163
164 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
165    buffer STATBUF to obtain the current timestamps of the file.  If
166    both times are UTIME_NOW, set *TS to NULL (as this can avoid some
167    permissions issues).  If both times are UTIME_OMIT, return true
168    (nothing further beyond the prior collection of STATBUF is
169    necessary); otherwise return false.  */
170 static bool
171 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
172 {
173   struct timespec *timespec = *ts;
174   if (timespec[0].tv_nsec == UTIME_OMIT
175       && timespec[1].tv_nsec == UTIME_OMIT)
176     return true;
177   if (timespec[0].tv_nsec == UTIME_NOW
178       && timespec[1].tv_nsec == UTIME_NOW)
179     {
180       *ts = NULL;
181       return false;
182     }
183
184   if (timespec[0].tv_nsec == UTIME_OMIT)
185     timespec[0] = get_stat_atime (statbuf);
186   else if (timespec[0].tv_nsec == UTIME_NOW)
187     gettime (&timespec[0]);
188
189   if (timespec[1].tv_nsec == UTIME_OMIT)
190     timespec[1] = get_stat_mtime (statbuf);
191   else if (timespec[1].tv_nsec == UTIME_NOW)
192     gettime (&timespec[1]);
193
194   return false;
195 }
196
197 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
198    TIMESPEC[0] and TIMESPEC[1], respectively.
199    FD must be either negative -- in which case it is ignored --
200    or a file descriptor that is open on FILE.
201    If FD is nonnegative, then FILE can be NULL, which means
202    use just futimes (or equivalent) instead of utimes (or equivalent),
203    and fail if on an old system without futimes (or equivalent).
204    If TIMESPEC is null, set the time stamps to the current time.
205    Return 0 on success, -1 (setting errno) on failure.  */
206
207 int
208 fdutimens (char const *file, int fd, struct timespec const timespec[2])
209 {
210   struct timespec adjusted_timespec[2];
211   struct timespec *ts = timespec ? adjusted_timespec : NULL;
212   int adjustment_needed = 0;
213
214   if (ts)
215     {
216       adjusted_timespec[0] = timespec[0];
217       adjusted_timespec[1] = timespec[1];
218       adjustment_needed = validate_timespec (ts);
219     }
220   if (adjustment_needed < 0)
221     return -1;
222
223   /* Require that at least one of FD or FILE are valid.  Works around
224      a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
225      than failing.  */
226   if (!file)
227     {
228       if (fd < 0)
229         {
230           errno = EBADF;
231           return -1;
232         }
233       if (dup2 (fd, fd) != fd)
234         return -1;
235     }
236
237   /* Some Linux-based NFS clients are buggy, and mishandle time stamps
238      of files in NFS file systems in some cases.  We have no
239      configure-time test for this, but please see
240      <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
241      some of the problems with Linux 2.6.16.  If this affects you,
242      compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
243      help in some cases, albeit at a cost in performance.  But you
244      really should upgrade your kernel to a fixed version, since the
245      problem affects many applications.  */
246
247 #if HAVE_BUGGY_NFS_TIME_STAMPS
248   if (fd < 0)
249     sync ();
250   else
251     fsync (fd);
252 #endif
253
254   /* POSIX 2008 added two interfaces to set file timestamps with
255      nanosecond resolution; newer Linux implements both functions via
256      a single syscall.  We provide a fallback for ENOSYS (for example,
257      compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
258      running on Linux 2.6.18 kernel).  */
259 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
260   if (0 <= utimensat_works_really)
261     {
262       int result;
263       struct stat st1;
264       struct stat st2;
265       /* Linux kernel 2.6.32 has a bug where it fails to bump ctime if
266          UTIME_OMIT was used for mtime.  It costs time to do an extra
267          [f]stat up front, so we cache whether the function works.  */
268       if (utimensat_ctime_really <= 0 && adjustment_needed == 2)
269         {
270           if (fd < 0 ? stat (file, &st1) : fstat (fd, &st1))
271             return -1;
272           if (ts[0].tv_nsec == UTIME_OMIT)
273             return 0;
274           if (utimensat_ctime_really < 0)
275             ts[1] = get_stat_mtime (&st1);
276         }
277 # if HAVE_UTIMENSAT
278       if (fd < 0)
279         {
280           result = utimensat (AT_FDCWD, file, ts, 0);
281 #  ifdef __linux__
282           /* Work around a kernel bug:
283              http://bugzilla.redhat.com/442352
284              http://bugzilla.redhat.com/449910
285              It appears that utimensat can mistakenly return 280 rather
286              than -1 upon ENOSYS failure.
287              FIXME: remove in 2010 or whenever the offending kernels
288              are no longer in common use.  */
289           if (0 < result)
290             errno = ENOSYS;
291 #  endif /* __linux__ */
292           if (result == 0 || errno != ENOSYS)
293             {
294               utimensat_works_really = 1;
295               if (result == 0 && utimensat_ctime_really == 0
296                   && adjustment_needed == 2)
297                 {
298                   /* Perform a followup stat to see if the kernel has
299                      a ctime bug.  */
300                   if (stat (file, &st2))
301                     return -1;
302                   if (detect_ctime_bug (&st1, &st2, ts))
303                     result = utimensat (AT_FDCWD, file, ts, 0);
304                 }
305               return result;
306             }
307         }
308 # endif /* HAVE_UTIMENSAT */
309 # if HAVE_FUTIMENS
310       {
311         result = futimens (fd, ts);
312 #  ifdef __linux__
313         /* Work around the same bug as above.  */
314         if (0 < result)
315           errno = ENOSYS;
316 #  endif /* __linux__ */
317         if (result == 0 || errno != ENOSYS)
318           {
319             utimensat_works_really = 1;
320             /* Work around the same bug as above.  */
321             if (result == 0 && utimensat_ctime_really == 0
322                 && adjustment_needed == 2)
323               {
324                 if (fstat (fd, &st2))
325                   return -1;
326                 if (detect_ctime_bug (&st1, &st2, ts))
327                   result = futimens (fd, ts);
328               }
329             return result;
330           }
331       }
332 # endif /* HAVE_FUTIMENS */
333     }
334   utimensat_works_really = -1;
335   lutimensat_works_really = -1;
336 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
337
338   /* The platform lacks an interface to set file timestamps with
339      nanosecond resolution, so do the best we can, discarding any
340      fractional part of the timestamp.  */
341
342   if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
343     {
344       struct stat st;
345       if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
346         return -1;
347       if (ts && update_timespec (&st, &ts))
348         return 0;
349     }
350
351   {
352 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
353     struct timeval timeval[2];
354     struct timeval const *t;
355     if (ts)
356       {
357         timeval[0].tv_sec = ts[0].tv_sec;
358         timeval[0].tv_usec = ts[0].tv_nsec / 1000;
359         timeval[1].tv_sec = ts[1].tv_sec;
360         timeval[1].tv_usec = ts[1].tv_nsec / 1000;
361         t = timeval;
362       }
363     else
364       t = NULL;
365
366     if (fd < 0)
367       {
368 # if HAVE_FUTIMESAT
369         return futimesat (AT_FDCWD, file, t);
370 # endif
371       }
372     else
373       {
374         /* If futimesat or futimes fails here, don't try to speed things
375            up by returning right away.  glibc can incorrectly fail with
376            errno == ENOENT if /proc isn't mounted.  Also, Mandrake 10.0
377            in high security mode doesn't allow ordinary users to read
378            /proc/self, so glibc incorrectly fails with errno == EACCES.
379            If errno == EIO, EPERM, or EROFS, it's probably safe to fail
380            right away, but these cases are rare enough that they're not
381            worth optimizing, and who knows what other messed-up systems
382            are out there?  So play it safe and fall back on the code
383            below.  */
384 # if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
385         if (futimesat (fd, NULL, t) == 0)
386           return 0;
387 # elif HAVE_FUTIMES
388         if (futimes (fd, t) == 0)
389           return 0;
390 # endif
391       }
392 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
393
394     if (!file)
395       {
396 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG)          \
397         || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
398         errno = ENOSYS;
399 #endif
400         return -1;
401       }
402
403 #if HAVE_WORKING_UTIMES
404     return utimes (file, t);
405 #else
406     {
407       struct utimbuf utimbuf;
408       struct utimbuf *ut;
409       if (ts)
410         {
411           utimbuf.actime = ts[0].tv_sec;
412           utimbuf.modtime = ts[1].tv_sec;
413           ut = &utimbuf;
414         }
415       else
416         ut = NULL;
417
418       return utime (file, ut);
419     }
420 #endif /* !HAVE_WORKING_UTIMES */
421   }
422 }
423
424 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
425    TIMESPEC[0] and TIMESPEC[1], respectively.
426    FD must be either negative -- in which case it is ignored --
427    or a file descriptor that is open on FILE.
428    If FD is nonnegative, then FILE can be NULL, which means
429    use just futimes (or equivalent) instead of utimes (or equivalent),
430    and fail if on an old system without futimes (or equivalent).
431    If TIMESPEC is null, set the time stamps to the current time.
432    Return 0 on success, -1 (setting errno) on failure.  */
433
434 int
435 gl_futimens (int fd, char const *file, struct timespec const timespec[2])
436 {
437   return fdutimens (file, fd, timespec);
438 }
439
440 /* Set the access and modification time stamps of FILE to be
441    TIMESPEC[0] and TIMESPEC[1], respectively.  */
442 int
443 utimens (char const *file, struct timespec const timespec[2])
444 {
445   return fdutimens (file, -1, timespec);
446 }
447
448 /* Set the access and modification time stamps of FILE to be
449    TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
450    symlinks.  Fail with ENOSYS if the platform does not support
451    changing symlink timestamps, but FILE was a symlink.  */
452 int
453 lutimens (char const *file, struct timespec const timespec[2])
454 {
455   struct timespec adjusted_timespec[2];
456   struct timespec *ts = timespec ? adjusted_timespec : NULL;
457   int adjustment_needed = 0;
458   struct stat st;
459
460   if (ts)
461     {
462       adjusted_timespec[0] = timespec[0];
463       adjusted_timespec[1] = timespec[1];
464       adjustment_needed = validate_timespec (ts);
465     }
466   if (adjustment_needed < 0)
467     return -1;
468
469   /* The Linux kernel did not support symlink timestamps until
470      utimensat, in version 2.6.22, so we don't need to mimic
471      gl_futimens' worry about buggy NFS clients.  But we do have to
472      worry about bogus return values.  */
473
474 #if HAVE_UTIMENSAT
475   if (0 <= lutimensat_works_really)
476     {
477       int result;
478       struct stat st1;
479       struct stat st2;
480       /* Linux kernel 2.6.32 has a bug where it fails to bump ctime if
481          UTIME_OMIT was used for mtime.  It costs time to do an extra
482          lstat up front, so we cache whether the function works.  */
483       if (utimensat_ctime_really <= 0 && adjustment_needed == 2)
484         {
485           if (lstat (file, &st1))
486             return -1;
487           if (ts[0].tv_nsec == UTIME_OMIT)
488             return 0;
489           if (utimensat_ctime_really < 0)
490             ts[1] = get_stat_mtime (&st1);
491         }
492       result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
493 # ifdef __linux__
494       /* Work around a kernel bug:
495          http://bugzilla.redhat.com/442352
496          http://bugzilla.redhat.com/449910
497          It appears that utimensat can mistakenly return 280 rather
498          than -1 upon ENOSYS failure.
499          FIXME: remove in 2010 or whenever the offending kernels
500          are no longer in common use.  */
501       if (0 < result)
502         errno = ENOSYS;
503 # endif
504       if (result == 0 || errno != ENOSYS)
505         {
506           utimensat_works_really = 1;
507           lutimensat_works_really = 1;
508           if (result == 0 && utimensat_ctime_really == 0
509               && adjustment_needed == 2)
510             {
511               /* Perform a followup stat to see if the kernel has a
512                  ctime bug.  */
513               if (lstat (file, &st2))
514                 return -1;
515               if (detect_ctime_bug (&st1, &st2, ts))
516                 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
517             }
518           return result;
519         }
520     }
521   lutimensat_works_really = -1;
522 #endif /* HAVE_UTIMENSAT */
523
524   /* The platform lacks an interface to set file timestamps with
525      nanosecond resolution, so do the best we can, discarding any
526      fractional part of the timestamp.  */
527
528   if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
529     {
530       if (lstat (file, &st))
531         return -1;
532       if (ts && update_timespec (&st, &ts))
533         return 0;
534     }
535
536   /* On Linux, lutimes is a thin wrapper around utimensat, so there is
537      no point trying lutimes if utimensat failed with ENOSYS.  */
538 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
539   {
540     struct timeval timeval[2];
541     struct timeval const *t;
542     int result;
543     if (ts)
544       {
545         timeval[0].tv_sec = ts[0].tv_sec;
546         timeval[0].tv_usec = ts[0].tv_nsec / 1000;
547         timeval[1].tv_sec = ts[1].tv_sec;
548         timeval[1].tv_usec = ts[1].tv_nsec / 1000;
549         t = timeval;
550       }
551     else
552       t = NULL;
553
554     result = lutimes (file, t);
555     if (result == 0 || errno != ENOSYS)
556       return result;
557   }
558 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
559
560   /* Out of luck for symlinks, but we still handle regular files.  */
561   if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
562     return -1;
563   if (!S_ISLNK (st.st_mode))
564     return fdutimens (file, -1, ts);
565   errno = ENOSYS;
566   return -1;
567 }