1/* Set file access and modification times.
2
3   Copyright (C) 2003-2014 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 <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
45struct 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 used with xfs or ntfs-3g fail to honor UTIME_OMIT
72   utimensat completely works
73   For each cache variable: 0 = unknown, 1 = yes, -1 = no.  */
74static int utimensat_works_really;
75static int lutimensat_works_really;
76#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
77
78/* Validate the requested timestamps.  Return 0 if the resulting
79   timespec can be used for utimensat (after possibly modifying it to
80   work around bugs in utimensat).  Return a positive value if the
81   timespec needs further adjustment based on stat results: 1 if any
82   adjustment is needed for utimes, and 2 if any adjustment is needed
83   for Linux utimensat.  Return -1, with errno set to EINVAL, if
84   timespec is out of range.  */
85static int
86validate_timespec (struct timespec timespec[2])
87{
88  int result = 0;
89  int utime_omit_count = 0;
90  assert (timespec);
91  if ((timespec[0].tv_nsec != UTIME_NOW
92       && timespec[0].tv_nsec != UTIME_OMIT
93       && ! (0 <= timespec[0].tv_nsec
94             && timespec[0].tv_nsec < TIMESPEC_RESOLUTION))
95      || (timespec[1].tv_nsec != UTIME_NOW
96          && timespec[1].tv_nsec != UTIME_OMIT
97          && ! (0 <= timespec[1].tv_nsec
98                && timespec[1].tv_nsec < TIMESPEC_RESOLUTION)))
99    {
100      errno = EINVAL;
101      return -1;
102    }
103  /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
104     EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
105     Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
106     fails to bump ctime.  */
107  if (timespec[0].tv_nsec == UTIME_NOW
108      || timespec[0].tv_nsec == UTIME_OMIT)
109    {
110      timespec[0].tv_sec = 0;
111      result = 1;
112      if (timespec[0].tv_nsec == UTIME_OMIT)
113        utime_omit_count++;
114    }
115  if (timespec[1].tv_nsec == UTIME_NOW
116      || timespec[1].tv_nsec == UTIME_OMIT)
117    {
118      timespec[1].tv_sec = 0;
119      result = 1;
120      if (timespec[1].tv_nsec == UTIME_OMIT)
121        utime_omit_count++;
122    }
123  return result + (utime_omit_count == 1);
124}
125
126/* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
127   buffer STATBUF to obtain the current timestamps of the file.  If
128   both times are UTIME_NOW, set *TS to NULL (as this can avoid some
129   permissions issues).  If both times are UTIME_OMIT, return true
130   (nothing further beyond the prior collection of STATBUF is
131   necessary); otherwise return false.  */
132static bool
133update_timespec (struct stat const *statbuf, struct timespec *ts[2])
134{
135  struct timespec *timespec = *ts;
136  if (timespec[0].tv_nsec == UTIME_OMIT
137      && timespec[1].tv_nsec == UTIME_OMIT)
138    return true;
139  if (timespec[0].tv_nsec == UTIME_NOW
140      && timespec[1].tv_nsec == UTIME_NOW)
141    {
142      *ts = NULL;
143      return false;
144    }
145
146  if (timespec[0].tv_nsec == UTIME_OMIT)
147    timespec[0] = get_stat_atime (statbuf);
148  else if (timespec[0].tv_nsec == UTIME_NOW)
149    gettime (&timespec[0]);
150
151  if (timespec[1].tv_nsec == UTIME_OMIT)
152    timespec[1] = get_stat_mtime (statbuf);
153  else if (timespec[1].tv_nsec == UTIME_NOW)
154    gettime (&timespec[1]);
155
156  return false;
157}
158
159/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
160   TIMESPEC[0] and TIMESPEC[1], respectively.
161   FD must be either negative -- in which case it is ignored --
162   or a file descriptor that is open on FILE.
163   If FD is nonnegative, then FILE can be NULL, which means
164   use just futimes (or equivalent) instead of utimes (or equivalent),
165   and fail if on an old system without futimes (or equivalent).
166   If TIMESPEC is null, set the time stamps to the current time.
167   Return 0 on success, -1 (setting errno) on failure.  */
168
169int
170fdutimens (int fd, char const *file, struct timespec const timespec[2])
171{
172  struct timespec adjusted_timespec[2];
173  struct timespec *ts = timespec ? adjusted_timespec : NULL;
174  int adjustment_needed = 0;
175  struct stat st;
176
177  if (ts)
178    {
179      adjusted_timespec[0] = timespec[0];
180      adjusted_timespec[1] = timespec[1];
181      adjustment_needed = validate_timespec (ts);
182    }
183  if (adjustment_needed < 0)
184    return -1;
185
186  /* Require that at least one of FD or FILE are potentially valid, to avoid
187     a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
188     than failing.  */
189  if (fd < 0 && !file)
190    {
191      errno = EBADF;
192      return -1;
193    }
194
195  /* Some Linux-based NFS clients are buggy, and mishandle time stamps
196     of files in NFS file systems in some cases.  We have no
197     configure-time test for this, but please see
198     <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
199     some of the problems with Linux 2.6.16.  If this affects you,
200     compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
201     help in some cases, albeit at a cost in performance.  But you
202     really should upgrade your kernel to a fixed version, since the
203     problem affects many applications.  */
204
205#if HAVE_BUGGY_NFS_TIME_STAMPS
206  if (fd < 0)
207    sync ();
208  else
209    fsync (fd);
210#endif
211
212  /* POSIX 2008 added two interfaces to set file timestamps with
213     nanosecond resolution; newer Linux implements both functions via
214     a single syscall.  We provide a fallback for ENOSYS (for example,
215     compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
216     running on Linux 2.6.18 kernel).  */
217#if HAVE_UTIMENSAT || HAVE_FUTIMENS
218  if (0 <= utimensat_works_really)
219    {
220      int result;
221# if __linux__ || __sun
222      /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
223         systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
224         but work if both times are either explicitly specified or
225         UTIME_NOW.  Work around it with a preparatory [f]stat prior
226         to calling futimens/utimensat; fortunately, there is not much
227         timing impact due to the extra syscall even on file systems
228         where UTIME_OMIT would have worked.
229
230         The same bug occurs in Solaris 11.1 (Apr 2013).
231
232         FIXME: Simplify this for Linux in 2016 and for Solaris in
233         2024, 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
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.  */
418int
419utimens (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.  */
428int
429lutimens (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__ || __sun
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.
462
463         The same bug occurs in Solaris 11.1 (Apr 2013).
464
465         FIXME: Simplify this for Linux in 2016 and for Solaris in
466         2024, when file system bugs are no longer common.  */
467      if (adjustment_needed == 2)
468        {
469          if (lstat (file, &st))
470            return -1;
471          if (ts[0].tv_nsec == UTIME_OMIT)
472            ts[0] = get_stat_atime (&st);
473          else if (ts[1].tv_nsec == UTIME_OMIT)
474            ts[1] = get_stat_mtime (&st);
475          /* Note that st is good, in case utimensat gives ENOSYS.  */
476          adjustment_needed++;
477        }
478# endif
479      result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
480# ifdef __linux__
481      /* Work around a kernel bug:
482         http://bugzilla.redhat.com/442352
483         http://bugzilla.redhat.com/449910
484         It appears that utimensat can mistakenly return 280 rather
485         than -1 upon ENOSYS failure.
486         FIXME: remove in 2010 or whenever the offending kernels
487         are no longer in common use.  */
488      if (0 < result)
489        errno = ENOSYS;
490# endif
491      if (result == 0 || errno != ENOSYS)
492        {
493          utimensat_works_really = 1;
494          lutimensat_works_really = 1;
495          return result;
496        }
497    }
498  lutimensat_works_really = -1;
499#endif /* HAVE_UTIMENSAT */
500
501  /* The platform lacks an interface to set file timestamps with
502     nanosecond resolution, so do the best we can, discarding any
503     fractional part of the timestamp.  */
504
505  if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
506    {
507      if (adjustment_needed != 3 && lstat (file, &st))
508        return -1;
509      if (ts && update_timespec (&st, &ts))
510        return 0;
511    }
512
513  /* On Linux, lutimes is a thin wrapper around utimensat, so there is
514     no point trying lutimes if utimensat failed with ENOSYS.  */
515#if HAVE_LUTIMES && !HAVE_UTIMENSAT
516  {
517    struct timeval timeval[2];
518    struct timeval *t;
519    int result;
520    if (ts)
521      {
522        timeval[0].tv_sec = ts[0].tv_sec;
523        timeval[0].tv_usec = ts[0].tv_nsec / 1000;
524        timeval[1].tv_sec = ts[1].tv_sec;
525        timeval[1].tv_usec = ts[1].tv_nsec / 1000;
526        t = timeval;
527      }
528    else
529      t = NULL;
530
531    result = lutimes (file, t);
532    if (result == 0 || errno != ENOSYS)
533      return result;
534  }
535#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
536
537  /* Out of luck for symlinks, but we still handle regular files.  */
538  if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
539    return -1;
540  if (!S_ISLNK (st.st_mode))
541    return fdutimens (-1, file, ts);
542  errno = ENOSYS;
543  return -1;
544}
545