OpenCoverage

utimens.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/utimens.c
Source codeSwitch to Preprocessed file
LineSourceCount
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. */-
76static int utimensat_works_really;-
77static 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. */-
87static int-
88validate_timespec (struct timespec timespec[2])-
89{-
90 int result = 0;-
91 int utime_omit_count = 0;-
92 if ((timespec[0].tv_nsec != UTIME_NOW
timespec[0].tv...l << 30) - 1l)Description
TRUEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37881
93 && timespec[0].tv_nsec != UTIME_OMIT
timespec[0].tv...l << 30) - 2l)Description
TRUEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37881
94 && ! (0 <= timespec[0].tv_nsec
0 <= timespec[0].tv_nsecDescription
TRUEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37881
95 && timespec[0].tv_nsec < TIMESPEC_RESOLUTION))
timespec[0].tv...PEC_RESOLUTIONDescription
TRUEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37881
96 || (timespec[1].tv_nsec != UTIME_NOW
timespec[1].tv...l << 30) - 1l)Description
TRUEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37881
97 && timespec[1].tv_nsec != UTIME_OMIT
timespec[1].tv...l << 30) - 2l)Description
TRUEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37881
98 && ! (0 <= timespec[1].tv_nsec
0 <= timespec[1].tv_nsecDescription
TRUEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37881
99 && timespec[1].tv_nsec < TIMESPEC_RESOLUTION)))
timespec[1].tv...PEC_RESOLUTIONDescription
TRUEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37881
100 {-
101 errno = EINVAL;-
102 return -1;
never executed: return -1;
0
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
timespec[0].tv...l << 30) - 1l)Description
TRUEnever evaluated
FALSEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
0-37881
109 || timespec[0].tv_nsec == UTIME_OMIT)
timespec[0].tv...l << 30) - 2l)Description
TRUEnever evaluated
FALSEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
0-37881
110 {-
111 timespec[0].tv_sec = 0;-
112 result = 1;-
113 if (timespec[0].tv_nsec == UTIME_OMIT)
timespec[0].tv...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
114 utime_omit_count++;
never executed: utime_omit_count++;
0
115 }
never executed: end of block
0
116 if (timespec[1].tv_nsec == UTIME_NOW
timespec[1].tv...l << 30) - 1l)Description
TRUEnever evaluated
FALSEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
0-37881
117 || timespec[1].tv_nsec == UTIME_OMIT)
timespec[1].tv...l << 30) - 2l)Description
TRUEnever evaluated
FALSEevaluated 37881 times by 2 tests
Evaluated by:
  • cp
  • mv
0-37881
118 {-
119 timespec[1].tv_sec = 0;-
120 result = 1;-
121 if (timespec[1].tv_nsec == UTIME_OMIT)
timespec[1].tv...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
122 utime_omit_count++;
never executed: utime_omit_count++;
0
123 }
never executed: end of block
0
124 return result + (utime_omit_count == 1);
executed 37881 times by 2 tests: return result + (utime_omit_count == 1);
Executed by:
  • cp
  • mv
37881
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. */-
133static bool-
134update_timespec (struct stat const *statbuf, struct timespec *ts[2])-
135{-
136 struct timespec *timespec = *ts;-
137 if (timespec[0].tv_nsec == UTIME_OMIT
timespec[0].tv...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
138 && timespec[1].tv_nsec == UTIME_OMIT)
timespec[1].tv...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
139 return true;
never executed: return 1 ;
0
140 if (timespec[0].tv_nsec == UTIME_NOW
timespec[0].tv...l << 30) - 1l)Description
TRUEnever evaluated
FALSEnever evaluated
0
141 && timespec[1].tv_nsec == UTIME_NOW)
timespec[1].tv...l << 30) - 1l)Description
TRUEnever evaluated
FALSEnever evaluated
0
142 {-
143 *ts = NULL;-
144 return false;
never executed: return 0 ;
0
145 }-
146-
147 if (timespec[0].tv_nsec == UTIME_OMIT)
timespec[0].tv...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
148 timespec[0] = get_stat_atime (statbuf);
never executed: timespec[0] = get_stat_atime (statbuf);
0
149 else if (timespec[0].tv_nsec == UTIME_NOW)
timespec[0].tv...l << 30) - 1l)Description
TRUEnever evaluated
FALSEnever evaluated
0
150 gettime (&timespec[0]);
never executed: gettime (&timespec[0]);
0
151-
152 if (timespec[1].tv_nsec == UTIME_OMIT)
timespec[1].tv...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
153 timespec[1] = get_stat_mtime (statbuf);
never executed: timespec[1] = get_stat_mtime (statbuf);
0
154 else if (timespec[1].tv_nsec == UTIME_NOW)
timespec[1].tv...l << 30) - 1l)Description
TRUEnever evaluated
FALSEnever evaluated
0
155 gettime (&timespec[1]);
never executed: gettime (&timespec[1]);
0
156-
157 return false;
never executed: return 0 ;
0
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-
170int-
171fdutimens (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;
timespecDescription
TRUEevaluated 37878 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37878
175 int adjustment_needed = 0;-
176 struct stat st;-
177-
178 if (ts)
tsDescription
TRUEevaluated 37878 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37878
179 {-
180 adjusted_timespec[0] = timespec[0];-
181 adjusted_timespec[1] = timespec[1];-
182 adjustment_needed = validate_timespec (ts);-
183 }
executed 37878 times by 2 tests: end of block
Executed by:
  • cp
  • mv
37878
184 if (adjustment_needed < 0)
adjustment_needed < 0Description
TRUEnever evaluated
FALSEevaluated 37878 times by 2 tests
Evaluated by:
  • cp
  • mv
0-37878
185 return -1;
never executed: return -1;
0
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)
fd < 0Description
TRUEevaluated 33949 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEevaluated 3929 times by 2 tests
Evaluated by:
  • cp
  • mv
!fileDescription
TRUEnever evaluated
FALSEevaluated 33949 times by 2 tests
Evaluated by:
  • cp
  • mv
0-33949
191 {-
192 errno = EBADF;-
193 return -1;
never executed: return -1;
0
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)
0 <= utimensat_works_reallyDescription
TRUEevaluated 37878 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-37878
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)
adjustment_needed == 2Description
TRUEnever evaluated
FALSEevaluated 37878 times by 2 tests
Evaluated by:
  • cp
  • mv
0-37878
236 {-
237 if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
fd < 0 ? stat ...stat (fd, &st)Description
TRUEnever evaluated
FALSEnever evaluated
fd < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
238 return -1;
never executed: return -1;
0
239 if (ts[0].tv_nsec == UTIME_OMIT)
ts[0].tv_nsec ...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
240 ts[0] = get_stat_atime (&st);
never executed: ts[0] = get_stat_atime (&st);
0
241 else if (ts[1].tv_nsec == UTIME_OMIT)
ts[1].tv_nsec ...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
242 ts[1] = get_stat_mtime (&st);
never executed: ts[1] = get_stat_mtime (&st);
0
243 /* Note that st is good, in case utimensat gives ENOSYS. */-
244 adjustment_needed++;-
245 }
never executed: end of block
0
246# endif-
247# if HAVE_UTIMENSAT-
248 if (fd < 0)
fd < 0Description
TRUEevaluated 33949 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEevaluated 3929 times by 2 tests
Evaluated by:
  • cp
  • mv
3929-33949
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)
0 < resultDescription
TRUEnever evaluated
FALSEevaluated 33949 times by 2 tests
Evaluated by:
  • cp
  • mv
0-33949
260 errno = ENOSYS;
never executed: (*__errno_location ()) = 38 ;
0
261# endif /* __linux__ */-
262 if (result == 0 || errno != ENOSYS)
result == 0Description
TRUEevaluated 33949 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
(*__errno_location ()) != 38Description
TRUEnever evaluated
FALSEnever evaluated
0-33949
263 {-
264 utimensat_works_really = 1;-
265 return result;
executed 33949 times by 2 tests: return result;
Executed by:
  • cp
  • mv
33949
266 }-
267 }
never executed: end of block
0
268# endif /* HAVE_UTIMENSAT */-
269# if HAVE_FUTIMENS-
270 if (0 <= fd)
0 <= fdDescription
TRUEevaluated 3929 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-3929
271 {-
272 result = futimens (fd, ts);-
273# ifdef __linux__-
274 /* Work around the same bug as above. */-
275 if (0 < result)
0 < resultDescription
TRUEnever evaluated
FALSEevaluated 3929 times by 2 tests
Evaluated by:
  • cp
  • mv
0-3929
276 errno = ENOSYS;
never executed: (*__errno_location ()) = 38 ;
0
277# endif /* __linux__ */-
278 if (result == 0 || errno != ENOSYS)
result == 0Description
TRUEevaluated 3929 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
(*__errno_location ()) != 38Description
TRUEnever evaluated
FALSEnever evaluated
0-3929
279 {-
280 utimensat_works_really = 1;-
281 return result;
executed 3929 times by 2 tests: return result;
Executed by:
  • cp
  • mv
3929
282 }-
283 }
never executed: end of block
0
284# endif /* HAVE_FUTIMENS */-
285 }
never executed: end of block
0
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))
dead code: fd < 0
adjustment_neededDescription
TRUEnever evaluated
FALSEnever evaluated
-
379 {-
380 if (adjustment_needed != 3
adjustment_needed != 3Description
TRUEnever evaluated
FALSEnever evaluated
0
381 && (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
fd < 0Description
TRUEnever evaluated
FALSEnever evaluated
(fd < 0 ? stat...tat (fd, &st))Description
TRUEnever evaluated
FALSEnever evaluated
0
382 return -1;
never executed: return -1;
0
383 if (ts && update_timespec (&st, &ts))
tsDescription
TRUEnever evaluated
FALSEnever evaluated
update_timespec (&st, &ts)Description
TRUEnever evaluated
FALSEnever evaluated
0
384 return 0;
never executed: return 0;
0
385 }
never executed: end of block
0
386-
387 {-
388#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES-
389 struct timeval timeval[2];-
390 struct timeval *t;-
391 if (ts)
tsDescription
TRUEnever evaluated
FALSEnever evaluated
0
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 }
never executed: end of block
0
399 else-
400 t = NULL;
never executed: t = ((void *)0) ;
0
401-
402 if (fd < 0)
fd < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
403 {-
404# if HAVE_FUTIMESAT-
405 return futimesat (AT_FDCWD, file, t);
never executed: return futimesat ( -100 , file, t);
0
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)
futimesat (fd,...*)0) , t) == 0Description
TRUEnever evaluated
FALSEnever evaluated
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)
tDescription
TRUEnever evaluated
FALSEnever evaluated
0
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)
(abig | mbig)Description
TRUEnever evaluated
FALSEnever evaluated
fstat (fd, &st) == 0Description
TRUEnever evaluated
FALSEnever evaluated
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)
abigDescription
TRUEnever evaluated
FALSEnever evaluated
adiff == 1Description
TRUEnever evaluated
FALSEnever evaluated
get_stat_atime_ns (&st) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
450 {-
451 tt = truncated_timeval;-
452 tt[0].tv_usec = 0;-
453 }
never executed: end of block
0
454 if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
mbigDescription
TRUEnever evaluated
FALSEnever evaluated
mdiff == 1Description
TRUEnever evaluated
FALSEnever evaluated
get_stat_mtime_ns (&st) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
455 {-
456 tt = truncated_timeval;-
457 tt[1].tv_usec = 0;-
458 }
never executed: end of block
0
459 if (tt)
ttDescription
TRUEnever evaluated
FALSEnever evaluated
0
460 futimes (fd, tt);
never executed: futimesat (fd, ((void *)0) , tt);
0
461 }
never executed: end of block
0
462 }
never executed: end of block
0
463# endif-
464-
465 return 0;
never executed: return 0;
0
466 }-
467# endif-
468 }
never executed: end of block
0
469#endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */-
470-
471 if (!file)
!fileDescription
TRUEnever evaluated
FALSEnever evaluated
0
472 {-
473#if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \-
474 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))-
475 errno = ENOSYS;-
476#endif-
477 return -1;
never executed: return -1;
0
478 }-
479-
480#ifdef USE_SETFILETIME-
481 return _gl_utimens_windows (file, ts);-
482#elif HAVE_WORKING_UTIMES-
483 return utimes (file, t);
never executed: return utimes (file, t);
0
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. */-
505int-
506utimens (char const *file, struct timespec const timespec[2])-
507{-
508 return fdutimens (-1, file, timespec);
executed 33949 times by 2 tests: return fdutimens (-1, file, timespec);
Executed by:
  • cp
  • mv
33949
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. */-
515int-
516lutimens (char const *file, struct timespec const timespec[2])-
517{-
518 struct timespec adjusted_timespec[2];-
519 struct timespec *ts = timespec ? adjusted_timespec : NULL;
timespecDescription
TRUEevaluated 3 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-3
520 int adjustment_needed = 0;-
521 struct stat st;-
522-
523 if (ts)
tsDescription
TRUEevaluated 3 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-3
524 {-
525 adjusted_timespec[0] = timespec[0];-
526 adjusted_timespec[1] = timespec[1];-
527 adjustment_needed = validate_timespec (ts);-
528 }
executed 3 times by 2 tests: end of block
Executed by:
  • cp
  • mv
3
529 if (adjustment_needed < 0)
adjustment_needed < 0Description
TRUEnever evaluated
FALSEevaluated 3 times by 2 tests
Evaluated by:
  • cp
  • mv
0-3
530 return -1;
never executed: return -1;
0
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)
0 <= lutimensat_works_reallyDescription
TRUEevaluated 3 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
0-3
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)
adjustment_needed == 2Description
TRUEnever evaluated
FALSEevaluated 3 times by 2 tests
Evaluated by:
  • cp
  • mv
0-3
555 {-
556 if (lstat (file, &st))
lstat (file, &st)Description
TRUEnever evaluated
FALSEnever evaluated
0
557 return -1;
never executed: return -1;
0
558 if (ts[0].tv_nsec == UTIME_OMIT)
ts[0].tv_nsec ...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
559 ts[0] = get_stat_atime (&st);
never executed: ts[0] = get_stat_atime (&st);
0
560 else if (ts[1].tv_nsec == UTIME_OMIT)
ts[1].tv_nsec ...l << 30) - 2l)Description
TRUEnever evaluated
FALSEnever evaluated
0
561 ts[1] = get_stat_mtime (&st);
never executed: ts[1] = get_stat_mtime (&st);
0
562 /* Note that st is good, in case utimensat gives ENOSYS. */-
563 adjustment_needed++;-
564 }
never executed: end of block
0
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)
0 < resultDescription
TRUEnever evaluated
FALSEevaluated 3 times by 2 tests
Evaluated by:
  • cp
  • mv
0-3
576 errno = ENOSYS;
never executed: (*__errno_location ()) = 38 ;
0
577# endif-
578 if (result == 0 || errno != ENOSYS)
result == 0Description
TRUEevaluated 3 times by 2 tests
Evaluated by:
  • cp
  • mv
FALSEnever evaluated
(*__errno_location ()) != 38Description
TRUEnever evaluated
FALSEnever evaluated
0-3
579 {-
580 utimensat_works_really = 1;-
581 lutimensat_works_really = 1;-
582 return result;
executed 3 times by 2 tests: return result;
Executed by:
  • cp
  • mv
3
583 }-
584 }
never executed: end of block
0
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)
adjustment_neededDescription
TRUEnever evaluated
FALSEnever evaluated
0
593 {-
594 if (adjustment_needed != 3 && lstat (file, &st))
adjustment_needed != 3Description
TRUEnever evaluated
FALSEnever evaluated
lstat (file, &st)Description
TRUEnever evaluated
FALSEnever evaluated
0
595 return -1;
never executed: return -1;
0
596 if (ts && update_timespec (&st, &ts))
tsDescription
TRUEnever evaluated
FALSEnever evaluated
update_timespec (&st, &ts)Description
TRUEnever evaluated
FALSEnever evaluated
0
597 return 0;
never executed: return 0;
0
598 }
never executed: end of block
0
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))
adjustment_neededDescription
TRUEnever evaluated
FALSEnever evaluated
lstat (file, &st)Description
TRUEnever evaluated
FALSEnever evaluated
0
626 return -1;
never executed: return -1;
0
627 if (!S_ISLNK (st.st_mode))
! (((( st.st_m... == (0120000))Description
TRUEnever evaluated
FALSEnever evaluated
0
628 return fdutimens (-1, file, ts);
never executed: return fdutimens (-1, file, ts);
0
629 errno = ENOSYS;-
630 return -1;
never executed: return -1;
0
631}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2