document mingw linker fix and close associated bug
[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 __CYGWIN__ && ! defined EMACS_CONFIGURATION
43 # define USE_SETFILETIME
44 # define WIN32_LEAN_AND_MEAN
45 # include <windows.h>
46 # if GNULIB_MSVC_NOTHROW
47 #  include "msvc-nothrow.h"
48 # else
49 #  include <io.h>
50 # endif
51 #endif
52
53 /* Avoid recursion with rpl_futimens or rpl_utimensat.  */
54 #undef futimens
55 #undef utimensat
56
57 /* Solaris 9 mistakenly succeeds when given a non-directory with a
58    trailing slash.  Force the use of rpl_stat for a fix.  */
59 #ifndef REPLACE_FUNC_STAT_FILE
60 # define REPLACE_FUNC_STAT_FILE 0
61 #endif
62
63 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
64 /* Cache variables for whether the utimensat syscall works; used to
65    avoid calling the syscall if we know it will just fail with ENOSYS,
66    and to avoid unnecessary work in massaging timestamps if the
67    syscall will work.  Multiple variables are needed, to distinguish
68    between the following scenarios on Linux:
69    utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
70    kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
71    kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
72    kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
73    utimensat completely works
74    For each cache variable: 0 = unknown, 1 = yes, -1 = no.  */
75 static int utimensat_works_really;
76 static int lutimensat_works_really;
77 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
78
79 /* Validate the requested timestamps.  Return 0 if the resulting
80    timespec can be used for utimensat (after possibly modifying it to
81    work around bugs in utimensat).  Return a positive value if the
82    timespec needs further adjustment based on stat results: 1 if any
83    adjustment is needed for utimes, and 2 if any adjustment is needed
84    for Linux utimensat.  Return -1, with errno set to EINVAL, if
85    timespec is out of range.  */
86 static int
87 validate_timespec (struct timespec timespec[2])
88 {
89   int result = 0;
90   int utime_omit_count = 0;
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_HZ))
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_HZ)))
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 timestamps 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 timestamps 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 timestamps
196      of files in NFS file systems in some cases.  We have no
197      configure-time test for this, but please see
198      <https://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              https://bugzilla.redhat.com/show_bug.cgi?id=442352
253              https://bugzilla.redhat.com/show_bug.cgi?id=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 #ifdef USE_SETFILETIME
290   /* On native Windows, use SetFileTime(). See
291      <https://msdn.microsoft.com/en-us/library/ms724933.aspx>
292      <https://msdn.microsoft.com/en-us/library/ms724284.aspx>  */
293   if (0 <= fd)
294     {
295       HANDLE handle;
296       FILETIME current_time;
297       FILETIME last_access_time;
298       FILETIME last_write_time;
299
300       handle = (HANDLE) _get_osfhandle (fd);
301       if (handle == INVALID_HANDLE_VALUE)
302         {
303           errno = EBADF;
304           return -1;
305         }
306
307       if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW)
308         {
309           /* GetSystemTimeAsFileTime
310              <https://msdn.microsoft.com/en-us/library/ms724397.aspx>.
311              It would be overkill to use
312              GetSystemTimePreciseAsFileTime
313              <https://msdn.microsoft.com/en-us/library/hh706895.aspx>.  */
314           GetSystemTimeAsFileTime (&current_time);
315         }
316
317       if (ts == NULL || ts[0].tv_nsec == UTIME_NOW)
318         {
319           last_access_time = current_time;
320         }
321       else if (ts[0].tv_nsec == UTIME_OMIT)
322         {
323           last_access_time.dwLowDateTime = 0;
324           last_access_time.dwHighDateTime = 0;
325         }
326       else
327         {
328           ULONGLONG time_since_16010101 =
329             (ULONGLONG) ts[0].tv_sec * 10000000 + ts[0].tv_nsec / 100 + 116444736000000000LL;
330           last_access_time.dwLowDateTime = (DWORD) time_since_16010101;
331           last_access_time.dwHighDateTime = time_since_16010101 >> 32;
332         }
333
334       if (ts == NULL || ts[1].tv_nsec == UTIME_NOW)
335         {
336           last_write_time = current_time;
337         }
338       else if (ts[1].tv_nsec == UTIME_OMIT)
339         {
340           last_write_time.dwLowDateTime = 0;
341           last_write_time.dwHighDateTime = 0;
342         }
343       else
344         {
345           ULONGLONG time_since_16010101 =
346             (ULONGLONG) ts[1].tv_sec * 10000000 + ts[1].tv_nsec / 100 + 116444736000000000LL;
347           last_write_time.dwLowDateTime = (DWORD) time_since_16010101;
348           last_write_time.dwHighDateTime = time_since_16010101 >> 32;
349         }
350
351       if (SetFileTime (handle, NULL, &last_access_time, &last_write_time))
352         return 0;
353       else
354         {
355           DWORD sft_error = GetLastError ();
356           #if 0
357           fprintf (stderr, "fdutimens SetFileTime error 0x%x\n", (unsigned int) sft_error);
358           #endif
359           switch (sft_error)
360             {
361             case ERROR_ACCESS_DENIED: /* fd was opened without O_RDWR */
362               errno = EACCES; /* not specified by POSIX */
363               break;
364             default:
365               errno = EINVAL;
366               break;
367             }
368           return -1;
369         }
370     }
371 #endif
372
373   /* The platform lacks an interface to set file timestamps with
374      nanosecond resolution, so do the best we can, discarding any
375      fractional part of the timestamp.  */
376
377   if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
378     {
379       if (adjustment_needed != 3
380           && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
381         return -1;
382       if (ts && update_timespec (&st, &ts))
383         return 0;
384     }
385
386   {
387 #if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
388     struct timeval timeval[2];
389     struct timeval *t;
390     if (ts)
391       {
392         timeval[0].tv_sec = ts[0].tv_sec;
393         timeval[0].tv_usec = ts[0].tv_nsec / 1000;
394         timeval[1].tv_sec = ts[1].tv_sec;
395         timeval[1].tv_usec = ts[1].tv_nsec / 1000;
396         t = timeval;
397       }
398     else
399       t = NULL;
400
401     if (fd < 0)
402       {
403 # if HAVE_FUTIMESAT
404         return futimesat (AT_FDCWD, file, t);
405 # endif
406       }
407     else
408       {
409         /* If futimesat or futimes fails here, don't try to speed things
410            up by returning right away.  glibc can incorrectly fail with
411            errno == ENOENT if /proc isn't mounted.  Also, Mandrake 10.0
412            in high security mode doesn't allow ordinary users to read
413            /proc/self, so glibc incorrectly fails with errno == EACCES.
414            If errno == EIO, EPERM, or EROFS, it's probably safe to fail
415            right away, but these cases are rare enough that they're not
416            worth optimizing, and who knows what other messed-up systems
417            are out there?  So play it safe and fall back on the code
418            below.  */
419
420 # if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
421 #  if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
422 #   undef futimes
423 #   define futimes(fd, t) futimesat (fd, NULL, t)
424 #  endif
425         if (futimes (fd, t) == 0)
426           {
427 #  if __linux__ && __GLIBC__
428             /* Work around a longstanding glibc bug, still present as
429                of 2010-12-27.  On older Linux kernels that lack both
430                utimensat and utimes, glibc's futimes rounds instead of
431                truncating when falling back on utime.  The same bug
432                occurs in futimesat with a null 2nd arg.  */
433             if (t)
434               {
435                 bool abig = 500000 <= t[0].tv_usec;
436                 bool mbig = 500000 <= t[1].tv_usec;
437                 if ((abig | mbig) && fstat (fd, &st) == 0)
438                   {
439                     /* If these two subtractions overflow, they'll
440                        track the overflows inside the buggy glibc.  */
441                     time_t adiff = st.st_atime - t[0].tv_sec;
442                     time_t mdiff = st.st_mtime - t[1].tv_sec;
443
444                     struct timeval *tt = NULL;
445                     struct timeval truncated_timeval[2];
446                     truncated_timeval[0] = t[0];
447                     truncated_timeval[1] = t[1];
448                     if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
449                       {
450                         tt = truncated_timeval;
451                         tt[0].tv_usec = 0;
452                       }
453                     if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
454                       {
455                         tt = truncated_timeval;
456                         tt[1].tv_usec = 0;
457                       }
458                     if (tt)
459                       futimes (fd, tt);
460                   }
461               }
462 #  endif
463
464             return 0;
465           }
466 # endif
467       }
468 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
469
470     if (!file)
471       {
472 #if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG)          \
473         || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
474         errno = ENOSYS;
475 #endif
476         return -1;
477       }
478
479 #ifdef USE_SETFILETIME
480     return _gl_utimens_windows (file, ts);
481 #elif HAVE_WORKING_UTIMES
482     return utimes (file, t);
483 #else
484     {
485       struct utimbuf utimbuf;
486       struct utimbuf *ut;
487       if (ts)
488         {
489           utimbuf.actime = ts[0].tv_sec;
490           utimbuf.modtime = ts[1].tv_sec;
491           ut = &utimbuf;
492         }
493       else
494         ut = NULL;
495
496       return utime (file, ut);
497     }
498 #endif /* !HAVE_WORKING_UTIMES */
499   }
500 }
501
502 /* Set the access and modification timestamps of FILE to be
503    TIMESPEC[0] and TIMESPEC[1], respectively.  */
504 int
505 utimens (char const *file, struct timespec const timespec[2])
506 {
507   return fdutimens (-1, file, timespec);
508 }
509
510 /* Set the access and modification timestamps of FILE to be
511    TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
512    symlinks.  Fail with ENOSYS if the platform does not support
513    changing symlink timestamps, but FILE was a symlink.  */
514 int
515 lutimens (char const *file, struct timespec const timespec[2])
516 {
517   struct timespec adjusted_timespec[2];
518   struct timespec *ts = timespec ? adjusted_timespec : NULL;
519   int adjustment_needed = 0;
520   struct stat st;
521
522   if (ts)
523     {
524       adjusted_timespec[0] = timespec[0];
525       adjusted_timespec[1] = timespec[1];
526       adjustment_needed = validate_timespec (ts);
527     }
528   if (adjustment_needed < 0)
529     return -1;
530
531   /* The Linux kernel did not support symlink timestamps until
532      utimensat, in version 2.6.22, so we don't need to mimic
533      fdutimens' worry about buggy NFS clients.  But we do have to
534      worry about bogus return values.  */
535
536 #if HAVE_UTIMENSAT
537   if (0 <= lutimensat_works_really)
538     {
539       int result;
540 # if __linux__ || __sun
541       /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
542          systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
543          but work if both times are either explicitly specified or
544          UTIME_NOW.  Work around it with a preparatory lstat prior to
545          calling utimensat; fortunately, there is not much timing
546          impact due to the extra syscall even on file systems where
547          UTIME_OMIT would have worked.
548
549          The same bug occurs in Solaris 11.1 (Apr 2013).
550
551          FIXME: Simplify this for Linux in 2016 and for Solaris in
552          2024, when file system bugs are no longer common.  */
553       if (adjustment_needed == 2)
554         {
555           if (lstat (file, &st))
556             return -1;
557           if (ts[0].tv_nsec == UTIME_OMIT)
558             ts[0] = get_stat_atime (&st);
559           else if (ts[1].tv_nsec == UTIME_OMIT)
560             ts[1] = get_stat_mtime (&st);
561           /* Note that st is good, in case utimensat gives ENOSYS.  */
562           adjustment_needed++;
563         }
564 # endif
565       result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
566 # ifdef __linux__
567       /* Work around a kernel bug:
568          https://bugzilla.redhat.com/show_bug.cgi?id=442352
569          https://bugzilla.redhat.com/show_bug.cgi?id=449910
570          It appears that utimensat can mistakenly return 280 rather
571          than -1 upon ENOSYS failure.
572          FIXME: remove in 2010 or whenever the offending kernels
573          are no longer in common use.  */
574       if (0 < result)
575         errno = ENOSYS;
576 # endif
577       if (result == 0 || errno != ENOSYS)
578         {
579           utimensat_works_really = 1;
580           lutimensat_works_really = 1;
581           return result;
582         }
583     }
584   lutimensat_works_really = -1;
585 #endif /* HAVE_UTIMENSAT */
586
587   /* The platform lacks an interface to set file timestamps with
588      nanosecond resolution, so do the best we can, discarding any
589      fractional part of the timestamp.  */
590
591   if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
592     {
593       if (adjustment_needed != 3 && lstat (file, &st))
594         return -1;
595       if (ts && update_timespec (&st, &ts))
596         return 0;
597     }
598
599   /* On Linux, lutimes is a thin wrapper around utimensat, so there is
600      no point trying lutimes if utimensat failed with ENOSYS.  */
601 #if HAVE_LUTIMES && !HAVE_UTIMENSAT
602   {
603     struct timeval timeval[2];
604     struct timeval *t;
605     int result;
606     if (ts)
607       {
608         timeval[0].tv_sec = ts[0].tv_sec;
609         timeval[0].tv_usec = ts[0].tv_nsec / 1000;
610         timeval[1].tv_sec = ts[1].tv_sec;
611         timeval[1].tv_usec = ts[1].tv_nsec / 1000;
612         t = timeval;
613       }
614     else
615       t = NULL;
616
617     result = lutimes (file, t);
618     if (result == 0 || errno != ENOSYS)
619       return result;
620   }
621 #endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
622
623   /* Out of luck for symlinks, but we still handle regular files.  */
624   if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
625     return -1;
626   if (!S_ISLNK (st.st_mode))
627     return fdutimens (-1, file, ts);
628   errno = ENOSYS;
629   return -1;
630 }