87123605ba2460605a5d7755106aa3fc1849c759
[gnulib.git] / lib / utimens.c
1 /* Set file access and modification times.
2
3    Copyright (C) 2003-2013 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        && (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec))
94       || (timespec[1].tv_nsec != UTIME_NOW
95           && timespec[1].tv_nsec != UTIME_OMIT
96           && (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec)))
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__
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.  FIXME: Simplify this in
227          2012, when file system bugs are no longer common.  */
228       if (adjustment_needed == 2)
229         {
230           if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
231             return -1;
232           if (ts[0].tv_nsec == UTIME_OMIT)
233             ts[0] = get_stat_atime (&st);
234           else if (ts[1].tv_nsec == UTIME_OMIT)
235             ts[1] = get_stat_mtime (&st);
236           /* Note that st is good, in case utimensat gives ENOSYS.  */
237           adjustment_needed++;
238         }
239 # endif /* __linux__ */
240 # if HAVE_UTIMENSAT
241       if (fd < 0)
242         {
243           result = utimensat (AT_FDCWD, file, ts, 0);
244 #  ifdef __linux__
245           /* Work around a kernel bug:
246              http://bugzilla.redhat.com/442352
247              http://bugzilla.redhat.com/449910
248              It appears that utimensat can mistakenly return 280 rather
249              than -1 upon ENOSYS failure.
250              FIXME: remove in 2010 or whenever the offending kernels
251              are no longer in common use.  */
252           if (0 < result)
253             errno = ENOSYS;
254 #  endif /* __linux__ */
255           if (result == 0 || errno != ENOSYS)
256             {
257               utimensat_works_really = 1;
258               return result;
259             }
260         }
261 # endif /* HAVE_UTIMENSAT */
262 # if HAVE_FUTIMENS
263       if (0 <= fd)
264         {
265           result = futimens (fd, ts);
266 #  ifdef __linux__
267           /* Work around the same bug as above.  */
268           if (0 < result)
269             errno = ENOSYS;
270 #  endif /* __linux__ */
271           if (result == 0 || errno != ENOSYS)
272             {
273               utimensat_works_really = 1;
274               return result;
275             }
276         }
277 # endif /* HAVE_FUTIMENS */
278     }
279   utimensat_works_really = -1;
280   lutimensat_works_really = -1;
281 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
282
283   /* The platform lacks an interface to set file timestamps with
284      nanosecond resolution, so do the best we can, discarding any
285      fractional part of the timestamp.  */
286
287   if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
288     {
289       if (adjustment_needed != 3
290           && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
291         return -1;
292       if (ts && update_timespec (&st, &ts))
293         return 0;
294     }
295
296   {
297 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
298     struct timeval timeval[2];
299     struct timeval *t;
300     if (ts)
301       {
302         timeval[0].tv_sec = ts[0].tv_sec;
303         timeval[0].tv_usec = ts[0].tv_nsec / 1000;
304         timeval[1].tv_sec = ts[1].tv_sec;
305         timeval[1].tv_usec = ts[1].tv_nsec / 1000;
306         t = timeval;
307       }
308     else
309       t = NULL;
310
311     if (fd < 0)
312       {
313 # if HAVE_FUTIMESAT
314         return futimesat (AT_FDCWD, file, t);
315 # endif
316       }
317     else
318       {
319         /* If futimesat or futimes fails here, don't try to speed things
320            up by returning right away.  glibc can incorrectly fail with
321            errno == ENOENT if /proc isn't mounted.  Also, Mandrake 10.0
322            in high security mode doesn't allow ordinary users to read
323            /proc/self, so glibc incorrectly fails with errno == EACCES.
324            If errno == EIO, EPERM, or EROFS, it's probably safe to fail
325            right away, but these cases are rare enough that they're not
326            worth optimizing, and who knows what other messed-up systems
327            are out there?  So play it safe and fall back on the code
328            below.  */
329
330 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
331 #  if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
332 #   undef futimes
333 #   define futimes(fd, t) futimesat (fd, NULL, t)
334 #  endif
335         if (futimes (fd, t) == 0)
336           {
337 #  if __linux__ && __GLIBC__
338             /* Work around a longstanding glibc bug, still present as
339                of 2010-12-27.  On older Linux kernels that lack both
340                utimensat and utimes, glibc's futimes rounds instead of
341                truncating when falling back on utime.  The same bug
342                occurs in futimesat with a null 2nd arg.  */
343             if (t)
344               {
345                 bool abig = 500000 <= t[0].tv_usec;
346                 bool mbig = 500000 <= t[1].tv_usec;
347                 if ((abig | mbig) && fstat (fd, &st) == 0)
348                   {
349                     /* If these two subtractions overflow, they'll
350                        track the overflows inside the buggy glibc.  */
351                     time_t adiff = st.st_atime - t[0].tv_sec;
352                     time_t mdiff = st.st_mtime - t[1].tv_sec;
353
354                     struct timeval *tt = NULL;
355                     struct timeval truncated_timeval[2];
356                     truncated_timeval[0] = t[0];
357                     truncated_timeval[1] = t[1];
358                     if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
359                       {
360                         tt = truncated_timeval;
361                         tt[0].tv_usec = 0;
362                       }
363                     if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
364                       {
365                         tt = truncated_timeval;
366                         tt[1].tv_usec = 0;
367                       }
368                     if (tt)
369                       futimes (fd, tt);
370                   }
371               }
372 #  endif
373
374             return 0;
375           }
376 # endif
377       }
378 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
379
380     if (!file)
381       {
382 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG)          \
383         || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
384         errno = ENOSYS;
385 #endif
386         return -1;
387       }
388
389 #if HAVE_WORKING_UTIMES
390     return utimes (file, t);
391 #else
392     {
393       struct utimbuf utimbuf;
394       struct utimbuf *ut;
395       if (ts)
396         {
397           utimbuf.actime = ts[0].tv_sec;
398           utimbuf.modtime = ts[1].tv_sec;
399           ut = &utimbuf;
400         }
401       else
402         ut = NULL;
403
404       return utime (file, ut);
405     }
406 #endif /* !HAVE_WORKING_UTIMES */
407   }
408 }
409
410 /* Set the access and modification time stamps of FILE to be
411    TIMESPEC[0] and TIMESPEC[1], respectively.  */
412 int
413 utimens (char const *file, struct timespec const timespec[2])
414 {
415   return fdutimens (-1, file, timespec);
416 }
417
418 /* Set the access and modification time stamps of FILE to be
419    TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
420    symlinks.  Fail with ENOSYS if the platform does not support
421    changing symlink timestamps, but FILE was a symlink.  */
422 int
423 lutimens (char const *file, struct timespec const timespec[2])
424 {
425   struct timespec adjusted_timespec[2];
426   struct timespec *ts = timespec ? adjusted_timespec : NULL;
427   int adjustment_needed = 0;
428   struct stat st;
429
430   if (ts)
431     {
432       adjusted_timespec[0] = timespec[0];
433       adjusted_timespec[1] = timespec[1];
434       adjustment_needed = validate_timespec (ts);
435     }
436   if (adjustment_needed < 0)
437     return -1;
438
439   /* The Linux kernel did not support symlink timestamps until
440      utimensat, in version 2.6.22, so we don't need to mimic
441      fdutimens' worry about buggy NFS clients.  But we do have to
442      worry about bogus return values.  */
443
444 #if HAVE_UTIMENSAT
445   if (0 <= lutimensat_works_really)
446     {
447       int result;
448 # if __linux__
449       /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
450          systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
451          but work if both times are either explicitly specified or
452          UTIME_NOW.  Work around it with a preparatory lstat prior to
453          calling utimensat; fortunately, there is not much timing
454          impact due to the extra syscall even on file systems where
455          UTIME_OMIT would have worked.  FIXME: Simplify this in 2012,
456          when file system bugs are no longer common.  */
457       if (adjustment_needed == 2)
458         {
459           if (lstat (file, &st))
460             return -1;
461           if (ts[0].tv_nsec == UTIME_OMIT)
462             ts[0] = get_stat_atime (&st);
463           else if (ts[1].tv_nsec == UTIME_OMIT)
464             ts[1] = get_stat_mtime (&st);
465           /* Note that st is good, in case utimensat gives ENOSYS.  */
466           adjustment_needed++;
467         }
468 # endif /* __linux__ */
469       result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
470 # ifdef __linux__
471       /* Work around a kernel bug:
472          http://bugzilla.redhat.com/442352
473          http://bugzilla.redhat.com/449910
474          It appears that utimensat can mistakenly return 280 rather
475          than -1 upon ENOSYS failure.
476          FIXME: remove in 2010 or whenever the offending kernels
477          are no longer in common use.  */
478       if (0 < result)
479         errno = ENOSYS;
480 # endif
481       if (result == 0 || errno != ENOSYS)
482         {
483           utimensat_works_really = 1;
484           lutimensat_works_really = 1;
485           return result;
486         }
487     }
488   lutimensat_works_really = -1;
489 #endif /* HAVE_UTIMENSAT */
490
491   /* The platform lacks an interface to set file timestamps with
492      nanosecond resolution, so do the best we can, discarding any
493      fractional part of the timestamp.  */
494
495   if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
496     {
497       if (adjustment_needed != 3 && lstat (file, &st))
498         return -1;
499       if (ts && update_timespec (&st, &ts))
500         return 0;
501     }
502
503   /* On Linux, lutimes is a thin wrapper around utimensat, so there is
504      no point trying lutimes if utimensat failed with ENOSYS.  */
505 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
506   {
507     struct timeval timeval[2];
508     struct timeval *t;
509     int result;
510     if (ts)
511       {
512         timeval[0].tv_sec = ts[0].tv_sec;
513         timeval[0].tv_usec = ts[0].tv_nsec / 1000;
514         timeval[1].tv_sec = ts[1].tv_sec;
515         timeval[1].tv_usec = ts[1].tv_nsec / 1000;
516         t = timeval;
517       }
518     else
519       t = NULL;
520
521     result = lutimes (file, t);
522     if (result == 0 || errno != ENOSYS)
523       return result;
524   }
525 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
526
527   /* Out of luck for symlinks, but we still handle regular files.  */
528   if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
529     return -1;
530   if (!S_ISLNK (st.st_mode))
531     return fdutimens (-1, file, ts);
532   errno = ENOSYS;
533   return -1;
534 }