c0b0704eb29d29a50e53bb9b35f9ef41c218249f
[debian/gzip] / lib / utimens.c
1 /* Set file access and modification times.
2
3    Copyright (C) 2003-2018 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 <https://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 #include <utime.h>
34
35 #include "stat-time.h"
36 #include "timespec.h"
37
38 /* On native Windows, use SetFileTime; but avoid this when compiling
39    GNU Emacs, which arranges for this in some other way and which
40    defines WIN32_LEAN_AND_MEAN itself.  */
41
42 #if ((defined _WIN32 || defined __WIN32__) \
43      && ! defined __CYGWIN__ && ! defined EMACS_CONFIGURATION)
44 # define USE_SETFILETIME
45 # define WIN32_LEAN_AND_MEAN
46 # include <windows.h>
47 # if GNULIB_MSVC_NOTHROW
48 #  include "msvc-nothrow.h"
49 # else
50 #  include <io.h>
51 # endif
52 #endif
53
54 /* Avoid recursion with rpl_futimens or rpl_utimensat.  */
55 #undef futimens
56 #undef utimensat
57
58 /* Solaris 9 mistakenly succeeds when given a non-directory with a
59    trailing slash.  Force the use of rpl_stat for a fix.  */
60 #ifndef REPLACE_FUNC_STAT_FILE
61 # define REPLACE_FUNC_STAT_FILE 0
62 #endif
63
64 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
65 /* Cache variables for whether the utimensat syscall works; used to
66    avoid calling the syscall if we know it will just fail with ENOSYS,
67    and to avoid unnecessary work in massaging timestamps if the
68    syscall will work.  Multiple variables are needed, to distinguish
69    between the following scenarios on Linux:
70    utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
71    kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
72    kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
73    kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
74    utimensat completely works
75    For each cache variable: 0 = unknown, 1 = yes, -1 = no.  */
76 static int utimensat_works_really;
77 static int lutimensat_works_really;
78 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
79
80 /* Validate the requested timestamps.  Return 0 if the resulting
81    timespec can be used for utimensat (after possibly modifying it to
82    work around bugs in utimensat).  Return a positive value if the
83    timespec needs further adjustment based on stat results: 1 if any
84    adjustment is needed for utimes, and 2 if any adjustment is needed
85    for Linux utimensat.  Return -1, with errno set to EINVAL, if
86    timespec is out of range.  */
87 static int
88 validate_timespec (struct timespec timespec[2])
89 {
90   int result = 0;
91   int utime_omit_count = 0;
92   if ((timespec[0].tv_nsec != UTIME_NOW
93        && timespec[0].tv_nsec != UTIME_OMIT
94        && ! (0 <= timespec[0].tv_nsec
95              && timespec[0].tv_nsec < TIMESPEC_RESOLUTION))
96       || (timespec[1].tv_nsec != UTIME_NOW
97           && timespec[1].tv_nsec != UTIME_OMIT
98           && ! (0 <= timespec[1].tv_nsec
99                 && timespec[1].tv_nsec < TIMESPEC_RESOLUTION)))
100     {
101       errno = EINVAL;
102       return -1;
103     }
104   /* Work around Linux kernel 2.6.25 bug, where utimensat fails with
105      EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
106      Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
107      fails to bump ctime.  */
108   if (timespec[0].tv_nsec == UTIME_NOW
109       || timespec[0].tv_nsec == UTIME_OMIT)
110     {
111       timespec[0].tv_sec = 0;
112       result = 1;
113       if (timespec[0].tv_nsec == UTIME_OMIT)
114         utime_omit_count++;
115     }
116   if (timespec[1].tv_nsec == UTIME_NOW
117       || timespec[1].tv_nsec == UTIME_OMIT)
118     {
119       timespec[1].tv_sec = 0;
120       result = 1;
121       if (timespec[1].tv_nsec == UTIME_OMIT)
122         utime_omit_count++;
123     }
124   return result + (utime_omit_count == 1);
125 }
126
127 /* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
128    buffer STATBUF to obtain the current timestamps of the file.  If
129    both times are UTIME_NOW, set *TS to NULL (as this can avoid some
130    permissions issues).  If both times are UTIME_OMIT, return true
131    (nothing further beyond the prior collection of STATBUF is
132    necessary); otherwise return false.  */
133 static bool
134 update_timespec (struct stat const *statbuf, struct timespec *ts[2])
135 {
136   struct timespec *timespec = *ts;
137   if (timespec[0].tv_nsec == UTIME_OMIT
138       && timespec[1].tv_nsec == UTIME_OMIT)
139     return true;
140   if (timespec[0].tv_nsec == UTIME_NOW
141       && timespec[1].tv_nsec == UTIME_NOW)
142     {
143       *ts = NULL;
144       return false;
145     }
146
147   if (timespec[0].tv_nsec == UTIME_OMIT)
148     timespec[0] = get_stat_atime (statbuf);
149   else if (timespec[0].tv_nsec == UTIME_NOW)
150     gettime (&timespec[0]);
151
152   if (timespec[1].tv_nsec == UTIME_OMIT)
153     timespec[1] = get_stat_mtime (statbuf);
154   else if (timespec[1].tv_nsec == UTIME_NOW)
155     gettime (&timespec[1]);
156
157   return false;
158 }
159
160 /* Set the access and modification timestamps of FD (a.k.a. FILE) to be
161    TIMESPEC[0] and TIMESPEC[1], respectively.
162    FD must be either negative -- in which case it is ignored --
163    or a file descriptor that is open on FILE.
164    If FD is nonnegative, then FILE can be NULL, which means
165    use just futimes (or equivalent) instead of utimes (or equivalent),
166    and fail if on an old system without futimes (or equivalent).
167    If TIMESPEC is null, set the timestamps to the current time.
168    Return 0 on success, -1 (setting errno) on failure.  */
169
170 int
171 fdutimens (int fd, char const *file, struct timespec const timespec[2])
172 {
173   struct timespec adjusted_timespec[2];
174   struct timespec *ts = timespec ? adjusted_timespec : NULL;
175   int adjustment_needed = 0;
176   struct stat st;
177
178   if (ts)
179     {
180       adjusted_timespec[0] = timespec[0];
181       adjusted_timespec[1] = timespec[1];
182       adjustment_needed = validate_timespec (ts);
183     }
184   if (adjustment_needed < 0)
185     return -1;
186
187   /* Require that at least one of FD or FILE are potentially valid, to avoid
188      a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
189      than failing.  */
190   if (fd < 0 && !file)
191     {
192       errno = EBADF;
193       return -1;
194     }
195
196   /* Some Linux-based NFS clients are buggy, and mishandle timestamps
197      of files in NFS file systems in some cases.  We have no
198      configure-time test for this, but please see
199      <https://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
200      some of the problems with Linux 2.6.16.  If this affects you,
201      compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
202      help in some cases, albeit at a cost in performance.  But you
203      really should upgrade your kernel to a fixed version, since the
204      problem affects many applications.  */
205
206 #if HAVE_BUGGY_NFS_TIME_STAMPS
207   if (fd < 0)
208     sync ();
209   else
210     fsync (fd);
211 #endif
212
213   /* POSIX 2008 added two interfaces to set file timestamps with
214      nanosecond resolution; newer Linux implements both functions via
215      a single syscall.  We provide a fallback for ENOSYS (for example,
216      compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
217      running on Linux 2.6.18 kernel).  */
218 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
219   if (0 <= utimensat_works_really)
220     {
221       int result;
222 # if __linux__ || __sun
223       /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
224          systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
225          but work if both times are either explicitly specified or
226          UTIME_NOW.  Work around it with a preparatory [f]stat prior
227          to calling futimens/utimensat; fortunately, there is not much
228          timing impact due to the extra syscall even on file systems
229          where UTIME_OMIT would have worked.
230
231          The same bug occurs in Solaris 11.1 (Apr 2013).
232
233          FIXME: Simplify this for Linux in 2016 and for Solaris in
234          2024, when file system bugs are no longer common.  */
235       if (adjustment_needed == 2)
236         {
237           if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
238             return -1;
239           if (ts[0].tv_nsec == UTIME_OMIT)
240             ts[0] = get_stat_atime (&st);
241           else if (ts[1].tv_nsec == UTIME_OMIT)
242             ts[1] = get_stat_mtime (&st);
243           /* Note that st is good, in case utimensat gives ENOSYS.  */
244           adjustment_needed++;
245         }
246 # endif
247 # if HAVE_UTIMENSAT
248       if (fd < 0)
249         {
250           result = utimensat (AT_FDCWD, file, ts, 0);
251 #  ifdef __linux__
252           /* Work around a kernel bug:
253              https://bugzilla.redhat.com/show_bug.cgi?id=442352
254              https://bugzilla.redhat.com/show_bug.cgi?id=449910
255              It appears that utimensat can mistakenly return 280 rather
256              than -1 upon ENOSYS failure.
257              FIXME: remove in 2010 or whenever the offending kernels
258              are no longer in common use.  */
259           if (0 < result)
260             errno = ENOSYS;
261 #  endif /* __linux__ */
262           if (result == 0 || errno != ENOSYS)
263             {
264               utimensat_works_really = 1;
265               return result;
266             }
267         }
268 # endif /* HAVE_UTIMENSAT */
269 # if HAVE_FUTIMENS
270       if (0 <= fd)
271         {
272           result = futimens (fd, ts);
273 #  ifdef __linux__
274           /* Work around the same bug as above.  */
275           if (0 < result)
276             errno = ENOSYS;
277 #  endif /* __linux__ */
278           if (result == 0 || errno != ENOSYS)
279             {
280               utimensat_works_really = 1;
281               return result;
282             }
283         }
284 # endif /* HAVE_FUTIMENS */
285     }
286   utimensat_works_really = -1;
287   lutimensat_works_really = -1;
288 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
289
290 #ifdef USE_SETFILETIME
291   /* On native Windows, use SetFileTime(). See
292      <https://msdn.microsoft.com/en-us/library/ms724933.aspx>
293      <https://msdn.microsoft.com/en-us/library/ms724284.aspx>  */
294   if (0 <= fd)
295     {
296       HANDLE handle;
297       FILETIME current_time;
298       FILETIME last_access_time;
299       FILETIME last_write_time;
300
301       handle = (HANDLE) _get_osfhandle (fd);
302       if (handle == INVALID_HANDLE_VALUE)
303         {
304           errno = EBADF;
305           return -1;
306         }
307
308       if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW)
309         {
310           /* GetSystemTimeAsFileTime
311              <https://msdn.microsoft.com/en-us/library/ms724397.aspx>.
312              It would be overkill to use
313              GetSystemTimePreciseAsFileTime
314              <https://msdn.microsoft.com/en-us/library/hh706895.aspx>.  */
315           GetSystemTimeAsFileTime (&current_time);
316         }
317
318       if (ts == NULL || ts[0].tv_nsec == UTIME_NOW)
319         {
320           last_access_time = current_time;
321         }
322       else if (ts[0].tv_nsec == UTIME_OMIT)
323         {
324           last_access_time.dwLowDateTime = 0;
325           last_access_time.dwHighDateTime = 0;
326         }
327       else
328         {
329           ULONGLONG time_since_16010101 =
330             (ULONGLONG) ts[0].tv_sec * 10000000 + ts[0].tv_nsec / 100 + 116444736000000000LL;
331           last_access_time.dwLowDateTime = (DWORD) time_since_16010101;
332           last_access_time.dwHighDateTime = time_since_16010101 >> 32;
333         }
334
335       if (ts == NULL || ts[1].tv_nsec == UTIME_NOW)
336         {
337           last_write_time = current_time;
338         }
339       else if (ts[1].tv_nsec == UTIME_OMIT)
340         {
341           last_write_time.dwLowDateTime = 0;
342           last_write_time.dwHighDateTime = 0;
343         }
344       else
345         {
346           ULONGLONG time_since_16010101 =
347             (ULONGLONG) ts[1].tv_sec * 10000000 + ts[1].tv_nsec / 100 + 116444736000000000LL;
348           last_write_time.dwLowDateTime = (DWORD) time_since_16010101;
349           last_write_time.dwHighDateTime = time_since_16010101 >> 32;
350         }
351
352       if (SetFileTime (handle, NULL, &last_access_time, &last_write_time))
353         return 0;
354       else
355         {
356           DWORD sft_error = GetLastError ();
357           #if 0
358           fprintf (stderr, "fdutimens SetFileTime error 0x%x\n", (unsigned int) sft_error);
359           #endif
360           switch (sft_error)
361             {
362             case ERROR_ACCESS_DENIED: /* fd was opened without O_RDWR */
363               errno = EACCES; /* not specified by POSIX */
364               break;
365             default:
366               errno = EINVAL;
367               break;
368             }
369           return -1;
370         }
371     }
372 #endif
373
374   /* The platform lacks an interface to set file timestamps with
375      nanosecond resolution, so do the best we can, discarding any
376      fractional part of the timestamp.  */
377
378   if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
379     {
380       if (adjustment_needed != 3
381           && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
382         return -1;
383       if (ts && update_timespec (&st, &ts))
384         return 0;
385     }
386
387   {
388 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
389     struct timeval timeval[2];
390     struct timeval *t;
391     if (ts)
392       {
393         timeval[0].tv_sec = ts[0].tv_sec;
394         timeval[0].tv_usec = ts[0].tv_nsec / 1000;
395         timeval[1].tv_sec = ts[1].tv_sec;
396         timeval[1].tv_usec = ts[1].tv_nsec / 1000;
397         t = timeval;
398       }
399     else
400       t = NULL;
401
402     if (fd < 0)
403       {
404 # if HAVE_FUTIMESAT
405         return futimesat (AT_FDCWD, file, t);
406 # endif
407       }
408     else
409       {
410         /* If futimesat or futimes fails here, don't try to speed things
411            up by returning right away.  glibc can incorrectly fail with
412            errno == ENOENT if /proc isn't mounted.  Also, Mandrake 10.0
413            in high security mode doesn't allow ordinary users to read
414            /proc/self, so glibc incorrectly fails with errno == EACCES.
415            If errno == EIO, EPERM, or EROFS, it's probably safe to fail
416            right away, but these cases are rare enough that they're not
417            worth optimizing, and who knows what other messed-up systems
418            are out there?  So play it safe and fall back on the code
419            below.  */
420
421 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
422 #  if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
423 #   undef futimes
424 #   define futimes(fd, t) futimesat (fd, NULL, t)
425 #  endif
426         if (futimes (fd, t) == 0)
427           {
428 #  if __linux__ && __GLIBC__
429             /* Work around a longstanding glibc bug, still present as
430                of 2010-12-27.  On older Linux kernels that lack both
431                utimensat and utimes, glibc's futimes rounds instead of
432                truncating when falling back on utime.  The same bug
433                occurs in futimesat with a null 2nd arg.  */
434             if (t)
435               {
436                 bool abig = 500000 <= t[0].tv_usec;
437                 bool mbig = 500000 <= t[1].tv_usec;
438                 if ((abig | mbig) && fstat (fd, &st) == 0)
439                   {
440                     /* If these two subtractions overflow, they'll
441                        track the overflows inside the buggy glibc.  */
442                     time_t adiff = st.st_atime - t[0].tv_sec;
443                     time_t mdiff = st.st_mtime - t[1].tv_sec;
444
445                     struct timeval *tt = NULL;
446                     struct timeval truncated_timeval[2];
447                     truncated_timeval[0] = t[0];
448                     truncated_timeval[1] = t[1];
449                     if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
450                       {
451                         tt = truncated_timeval;
452                         tt[0].tv_usec = 0;
453                       }
454                     if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
455                       {
456                         tt = truncated_timeval;
457                         tt[1].tv_usec = 0;
458                       }
459                     if (tt)
460                       futimes (fd, tt);
461                   }
462               }
463 #  endif
464
465             return 0;
466           }
467 # endif
468       }
469 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
470
471     if (!file)
472       {
473 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG)          \
474         || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
475         errno = ENOSYS;
476 #endif
477         return -1;
478       }
479
480 #ifdef USE_SETFILETIME
481     return _gl_utimens_windows (file, ts);
482 #elif HAVE_WORKING_UTIMES
483     return utimes (file, t);
484 #else
485     {
486       struct utimbuf utimbuf;
487       struct utimbuf *ut;
488       if (ts)
489         {
490           utimbuf.actime = ts[0].tv_sec;
491           utimbuf.modtime = ts[1].tv_sec;
492           ut = &utimbuf;
493         }
494       else
495         ut = NULL;
496
497       return utime (file, ut);
498     }
499 #endif /* !HAVE_WORKING_UTIMES */
500   }
501 }
502
503 /* Set the access and modification timestamps of FILE to be
504    TIMESPEC[0] and TIMESPEC[1], respectively.  */
505 int
506 utimens (char const *file, struct timespec const timespec[2])
507 {
508   return fdutimens (-1, file, timespec);
509 }
510
511 /* Set the access and modification timestamps of FILE to be
512    TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
513    symlinks.  Fail with ENOSYS if the platform does not support
514    changing symlink timestamps, but FILE was a symlink.  */
515 int
516 lutimens (char const *file, struct timespec const timespec[2])
517 {
518   struct timespec adjusted_timespec[2];
519   struct timespec *ts = timespec ? adjusted_timespec : NULL;
520   int adjustment_needed = 0;
521   struct stat st;
522
523   if (ts)
524     {
525       adjusted_timespec[0] = timespec[0];
526       adjusted_timespec[1] = timespec[1];
527       adjustment_needed = validate_timespec (ts);
528     }
529   if (adjustment_needed < 0)
530     return -1;
531
532   /* The Linux kernel did not support symlink timestamps until
533      utimensat, in version 2.6.22, so we don't need to mimic
534      fdutimens' worry about buggy NFS clients.  But we do have to
535      worry about bogus return values.  */
536
537 #if HAVE_UTIMENSAT
538   if (0 <= lutimensat_works_really)
539     {
540       int result;
541 # if __linux__ || __sun
542       /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
543          systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
544          but work if both times are either explicitly specified or
545          UTIME_NOW.  Work around it with a preparatory lstat prior to
546          calling utimensat; fortunately, there is not much timing
547          impact due to the extra syscall even on file systems where
548          UTIME_OMIT would have worked.
549
550          The same bug occurs in Solaris 11.1 (Apr 2013).
551
552          FIXME: Simplify this for Linux in 2016 and for Solaris in
553          2024, when file system bugs are no longer common.  */
554       if (adjustment_needed == 2)
555         {
556           if (lstat (file, &st))
557             return -1;
558           if (ts[0].tv_nsec == UTIME_OMIT)
559             ts[0] = get_stat_atime (&st);
560           else if (ts[1].tv_nsec == UTIME_OMIT)
561             ts[1] = get_stat_mtime (&st);
562           /* Note that st is good, in case utimensat gives ENOSYS.  */
563           adjustment_needed++;
564         }
565 # endif
566       result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
567 # ifdef __linux__
568       /* Work around a kernel bug:
569          https://bugzilla.redhat.com/show_bug.cgi?id=442352
570          https://bugzilla.redhat.com/show_bug.cgi?id=449910
571          It appears that utimensat can mistakenly return 280 rather
572          than -1 upon ENOSYS failure.
573          FIXME: remove in 2010 or whenever the offending kernels
574          are no longer in common use.  */
575       if (0 < result)
576         errno = ENOSYS;
577 # endif
578       if (result == 0 || errno != ENOSYS)
579         {
580           utimensat_works_really = 1;
581           lutimensat_works_really = 1;
582           return result;
583         }
584     }
585   lutimensat_works_really = -1;
586 #endif /* HAVE_UTIMENSAT */
587
588   /* The platform lacks an interface to set file timestamps with
589      nanosecond resolution, so do the best we can, discarding any
590      fractional part of the timestamp.  */
591
592   if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
593     {
594       if (adjustment_needed != 3 && lstat (file, &st))
595         return -1;
596       if (ts && update_timespec (&st, &ts))
597         return 0;
598     }
599
600   /* On Linux, lutimes is a thin wrapper around utimensat, so there is
601      no point trying lutimes if utimensat failed with ENOSYS.  */
602 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
603   {
604     struct timeval timeval[2];
605     struct timeval *t;
606     int result;
607     if (ts)
608       {
609         timeval[0].tv_sec = ts[0].tv_sec;
610         timeval[0].tv_usec = ts[0].tv_nsec / 1000;
611         timeval[1].tv_sec = ts[1].tv_sec;
612         timeval[1].tv_usec = ts[1].tv_nsec / 1000;
613         t = timeval;
614       }
615     else
616       t = NULL;
617
618     result = lutimes (file, t);
619     if (result == 0 || errno != ENOSYS)
620       return result;
621   }
622 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
623
624   /* Out of luck for symlinks, but we still handle regular files.  */
625   if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
626     return -1;
627   if (!S_ISLNK (st.st_mode))
628     return fdutimens (-1, file, ts);
629   errno = ENOSYS;
630   return -1;
631 }