maint: update copyright
[gnulib.git] / lib / utimens.c
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
45 struct 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.  */
74 static int utimensat_works_really;
75 static 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.  */
85 static int
86 validate_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.  */
132 static bool
133 update_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
169 int
170 fdutimens (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.  */
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__ || __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 }