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