Imported Upstream version 1.5
[debian/gzip] / lib / utimens.c
1 /* Set file access and modification times.
2
3    Copyright (C) 2003-2012 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 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 */
76
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])
86 {
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)))
96     {
97       errno = EINVAL;
98       return -1;
99     }
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)
106     {
107       timespec[0].tv_sec = 0;
108       result = 1;
109       if (timespec[0].tv_nsec == UTIME_OMIT)
110         utime_omit_count++;
111     }
112   if (timespec[1].tv_nsec == UTIME_NOW
113       || timespec[1].tv_nsec == UTIME_OMIT)
114     {
115       timespec[1].tv_sec = 0;
116       result = 1;
117       if (timespec[1].tv_nsec == UTIME_OMIT)
118         utime_omit_count++;
119     }
120   return result + (utime_omit_count == 1);
121 }
122
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])
131 {
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)
138     {
139       *ts = NULL;
140       return false;
141     }
142
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]);
147
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]);
152
153   return false;
154 }
155
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.  */
165
166 int
167 fdutimens (int fd, char const *file, struct timespec const timespec[2])
168 {
169   struct timespec adjusted_timespec[2];
170   struct timespec *ts = timespec ? adjusted_timespec : NULL;
171   int adjustment_needed = 0;
172   struct stat st;
173
174   if (ts)
175     {
176       adjusted_timespec[0] = timespec[0];
177       adjusted_timespec[1] = timespec[1];
178       adjustment_needed = validate_timespec (ts);
179     }
180   if (adjustment_needed < 0)
181     return -1;
182
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)
187     {
188       errno = EBADF;
189       return -1;
190     }
191
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.  */
201
202 #if HAVE_BUGGY_NFS_TIME_STAMPS
203   if (fd < 0)
204     sync ();
205   else
206     fsync (fd);
207 #endif
208
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)
216     {
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)
228         {
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++;
237         }
238 # endif /* __linux__ */
239 # if HAVE_UTIMENSAT
240       if (fd < 0)
241         {
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)
255             {
256               utimensat_works_really = 1;
257               return result;
258             }
259         }
260 # endif /* HAVE_UTIMENSAT */
261 # if HAVE_FUTIMENS
262       if (0 <= fd)
263         {
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)
271             {
272               utimensat_works_really = 1;
273               return result;
274             }
275         }
276 # endif /* HAVE_FUTIMENS */
277     }
278   utimensat_works_really = -1;
279   lutimensat_works_really = -1;
280 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
281
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.  */
285
286   if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
287     {
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;
293     }
294
295   {
296 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
297     struct timeval timeval[2];
298     struct timeval *t;
299     if (ts)
300       {
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;
306       }
307     else
308       t = NULL;
309
310     if (fd < 0)
311       {
312 # if HAVE_FUTIMESAT
313         return futimesat (AT_FDCWD, file, t);
314 # endif
315       }
316     else
317       {
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.  */
328
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)
335           {
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)
343               {
344                 bool abig = 500000 <= t[0].tv_usec;
345                 bool mbig = 500000 <= t[1].tv_usec;
346                 if ((abig | mbig) && fstat (fd, &st) == 0)
347                   {
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;
352
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)
358                       {
359                         tt = truncated_timeval;
360                         tt[0].tv_usec = 0;
361                       }
362                     if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
363                       {
364                         tt = truncated_timeval;
365                         tt[1].tv_usec = 0;
366                       }
367                     if (tt)
368                       futimes (fd, tt);
369                   }
370               }
371 #  endif
372
373             return 0;
374           }
375 # endif
376       }
377 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
378
379     if (!file)
380       {
381 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG)          \
382         || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
383         errno = ENOSYS;
384 #endif
385         return -1;
386       }
387
388 #if HAVE_WORKING_UTIMES
389     return utimes (file, t);
390 #else
391     {
392       struct utimbuf utimbuf;
393       struct utimbuf *ut;
394       if (ts)
395         {
396           utimbuf.actime = ts[0].tv_sec;
397           utimbuf.modtime = ts[1].tv_sec;
398           ut = &utimbuf;
399         }
400       else
401         ut = NULL;
402
403       return utime (file, ut);
404     }
405 #endif /* !HAVE_WORKING_UTIMES */
406   }
407 }
408
409 /* Set the access and modification time stamps of FILE to be
410    TIMESPEC[0] and TIMESPEC[1], respectively.  */
411 int
412 utimens (char const *file, struct timespec const timespec[2])
413 {
414   return fdutimens (-1, file, timespec);
415 }
416
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.  */
421 int
422 lutimens (char const *file, struct timespec const timespec[2])
423 {
424   struct timespec adjusted_timespec[2];
425   struct timespec *ts = timespec ? adjusted_timespec : NULL;
426   int adjustment_needed = 0;
427   struct stat st;
428
429   if (ts)
430     {
431       adjusted_timespec[0] = timespec[0];
432       adjusted_timespec[1] = timespec[1];
433       adjustment_needed = validate_timespec (ts);
434     }
435   if (adjustment_needed < 0)
436     return -1;
437
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.  */
442
443 #if HAVE_UTIMENSAT
444   if (0 <= lutimensat_works_really)
445     {
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)
457         {
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++;
466         }
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)
481         {
482           utimensat_works_really = 1;
483           lutimensat_works_really = 1;
484           return result;
485         }
486     }
487   lutimensat_works_really = -1;
488 #endif /* HAVE_UTIMENSAT */
489
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.  */
493
494   if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
495     {
496       if (adjustment_needed != 3 && lstat (file, &st))
497         return -1;
498       if (ts && update_timespec (&st, &ts))
499         return 0;
500     }
501
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
505   {
506     struct timeval timeval[2];
507     struct timeval *t;
508     int result;
509     if (ts)
510       {
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;
516       }
517     else
518       t = NULL;
519
520     result = lutimes (file, t);
521     if (result == 0 || errno != ENOSYS)
522       return result;
523   }
524 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
525
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;
533 }