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