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