1/* Set file access and modification times. 2 3 Copyright (C) 2003-2014 Free Software Foundation, Inc. 4 5 This program is free software: you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published by the 7 Free Software Foundation; either version 3 of the License, or any 8 later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18/* Written by Paul Eggert. */ 19 20/* derived from a function in touch.c */ 21 22#include <config.h> 23 24#define _GL_UTIMENS_INLINE _GL_EXTERN_INLINE 25#include "utimens.h" 26 27#include <assert.h> 28#include <errno.h> 29#include <fcntl.h> 30#include <stdbool.h> 31#include <sys/stat.h> 32#include <sys/time.h> 33#include <unistd.h> 34 35#include "stat-time.h" 36#include "timespec.h" 37 38#if HAVE_UTIME_H 39# include <utime.h> 40#endif 41 42/* Some systems (even some that do have <utime.h>) don't declare this 43 structure anywhere. */ 44#ifndef HAVE_STRUCT_UTIMBUF 45struct 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. */ 74static int utimensat_works_really; 75static 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. */ 85static int 86validate_timespec (struct timespec timespec[2]) 87{ 88 int result = 0; 89 int utime_omit_count = 0; 90 assert (timespec); 91 if ((timespec[0].tv_nsec != UTIME_NOW 92 && timespec[0].tv_nsec != UTIME_OMIT 93 && ! (0 <= timespec[0].tv_nsec 94 && timespec[0].tv_nsec < TIMESPEC_RESOLUTION)) 95 || (timespec[1].tv_nsec != UTIME_NOW 96 && timespec[1].tv_nsec != UTIME_OMIT 97 && ! (0 <= timespec[1].tv_nsec 98 && timespec[1].tv_nsec < TIMESPEC_RESOLUTION))) 99 { 100 errno = EINVAL; 101 return -1; 102 } 103 /* Work around Linux kernel 2.6.25 bug, where utimensat fails with 104 EINVAL if tv_sec is not 0 when using the flag values of tv_nsec. 105 Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT 106 fails to bump ctime. */ 107 if (timespec[0].tv_nsec == UTIME_NOW 108 || timespec[0].tv_nsec == UTIME_OMIT) 109 { 110 timespec[0].tv_sec = 0; 111 result = 1; 112 if (timespec[0].tv_nsec == UTIME_OMIT) 113 utime_omit_count++; 114 } 115 if (timespec[1].tv_nsec == UTIME_NOW 116 || timespec[1].tv_nsec == UTIME_OMIT) 117 { 118 timespec[1].tv_sec = 0; 119 result = 1; 120 if (timespec[1].tv_nsec == UTIME_OMIT) 121 utime_omit_count++; 122 } 123 return result + (utime_omit_count == 1); 124} 125 126/* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat 127 buffer STATBUF to obtain the current timestamps of the file. If 128 both times are UTIME_NOW, set *TS to NULL (as this can avoid some 129 permissions issues). If both times are UTIME_OMIT, return true 130 (nothing further beyond the prior collection of STATBUF is 131 necessary); otherwise return false. */ 132static bool 133update_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 (×pec[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 (×pec[1]); 155 156 return false; 157} 158 159/* Set the access and modification time stamps of FD (a.k.a. FILE) to be 160 TIMESPEC[0] and TIMESPEC[1], respectively. 161 FD must be either negative -- in which case it is ignored -- 162 or a file descriptor that is open on FILE. 163 If FD is nonnegative, then FILE can be NULL, which means 164 use just futimes (or equivalent) instead of utimes (or equivalent), 165 and fail if on an old system without futimes (or equivalent). 166 If TIMESPEC is null, set the time stamps to the current time. 167 Return 0 on success, -1 (setting errno) on failure. */ 168 169int 170fdutimens (int fd, char const *file, struct timespec const timespec[2]) 171{ 172 struct timespec adjusted_timespec[2]; 173 struct timespec *ts = timespec ? adjusted_timespec : NULL; 174 int adjustment_needed = 0; 175 struct stat st; 176 177 if (ts) 178 { 179 adjusted_timespec[0] = timespec[0]; 180 adjusted_timespec[1] = timespec[1]; 181 adjustment_needed = validate_timespec (ts); 182 } 183 if (adjustment_needed < 0) 184 return -1; 185 186 /* Require that at least one of FD or FILE are potentially valid, to avoid 187 a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather 188 than failing. */ 189 if (fd < 0 && !file) 190 { 191 errno = EBADF; 192 return -1; 193 } 194 195 /* Some Linux-based NFS clients are buggy, and mishandle time stamps 196 of files in NFS file systems in some cases. We have no 197 configure-time test for this, but please see 198 <http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to 199 some of the problems with Linux 2.6.16. If this affects you, 200 compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to 201 help in some cases, albeit at a cost in performance. But you 202 really should upgrade your kernel to a fixed version, since the 203 problem affects many applications. */ 204 205#if HAVE_BUGGY_NFS_TIME_STAMPS 206 if (fd < 0) 207 sync (); 208 else 209 fsync (fd); 210#endif 211 212 /* POSIX 2008 added two interfaces to set file timestamps with 213 nanosecond resolution; newer Linux implements both functions via 214 a single syscall. We provide a fallback for ENOSYS (for example, 215 compiling against Linux 2.6.25 kernel headers and glibc 2.7, but 216 running on Linux 2.6.18 kernel). */ 217#if HAVE_UTIMENSAT || HAVE_FUTIMENS 218 if (0 <= utimensat_works_really) 219 { 220 int result; 221# if __linux__ || __sun 222 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file 223 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, 224 but work if both times are either explicitly specified or 225 UTIME_NOW. Work around it with a preparatory [f]stat prior 226 to calling futimens/utimensat; fortunately, there is not much 227 timing impact due to the extra syscall even on file systems 228 where UTIME_OMIT would have worked. 229 230 The same bug occurs in Solaris 11.1 (Apr 2013). 231 232 FIXME: Simplify this for Linux in 2016 and for Solaris in 233 2024, when file system bugs are no longer common. */ 234 if (adjustment_needed == 2) 235 { 236 if (fd < 0 ? stat (file, &st) : fstat (fd, &st)) 237 return -1; 238 if (ts[0].tv_nsec == UTIME_OMIT) 239 ts[0] = get_stat_atime (&st); 240 else if (ts[1].tv_nsec == UTIME_OMIT) 241 ts[1] = get_stat_mtime (&st); 242 /* Note that st is good, in case utimensat gives ENOSYS. */ 243 adjustment_needed++; 244 } 245# endif 246# if HAVE_UTIMENSAT 247 if (fd < 0) 248 { 249 result = utimensat (AT_FDCWD, file, ts, 0); 250# ifdef __linux__ 251 /* Work around a kernel bug: 252 http://bugzilla.redhat.com/442352 253 http://bugzilla.redhat.com/449910 254 It appears that utimensat can mistakenly return 280 rather 255 than -1 upon ENOSYS failure. 256 FIXME: remove in 2010 or whenever the offending kernels 257 are no longer in common use. */ 258 if (0 < result) 259 errno = ENOSYS; 260# endif /* __linux__ */ 261 if (result == 0 || errno != ENOSYS) 262 { 263 utimensat_works_really = 1; 264 return result; 265 } 266 } 267# endif /* HAVE_UTIMENSAT */ 268# if HAVE_FUTIMENS 269 if (0 <= fd) 270 { 271 result = futimens (fd, ts); 272# ifdef __linux__ 273 /* Work around the same bug as above. */ 274 if (0 < result) 275 errno = ENOSYS; 276# endif /* __linux__ */ 277 if (result == 0 || errno != ENOSYS) 278 { 279 utimensat_works_really = 1; 280 return result; 281 } 282 } 283# endif /* HAVE_FUTIMENS */ 284 } 285 utimensat_works_really = -1; 286 lutimensat_works_really = -1; 287#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */ 288 289 /* The platform lacks an interface to set file timestamps with 290 nanosecond resolution, so do the best we can, discarding any 291 fractional part of the timestamp. */ 292 293 if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0)) 294 { 295 if (adjustment_needed != 3 296 && (fd < 0 ? stat (file, &st) : fstat (fd, &st))) 297 return -1; 298 if (ts && update_timespec (&st, &ts)) 299 return 0; 300 } 301 302 { 303#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES 304 struct timeval timeval[2]; 305 struct timeval *t; 306 if (ts) 307 { 308 timeval[0].tv_sec = ts[0].tv_sec; 309 timeval[0].tv_usec = ts[0].tv_nsec / 1000; 310 timeval[1].tv_sec = ts[1].tv_sec; 311 timeval[1].tv_usec = ts[1].tv_nsec / 1000; 312 t = timeval; 313 } 314 else 315 t = NULL; 316 317 if (fd < 0) 318 { 319# if HAVE_FUTIMESAT 320 return futimesat (AT_FDCWD, file, t); 321# endif 322 } 323 else 324 { 325 /* If futimesat or futimes fails here, don't try to speed things 326 up by returning right away. glibc can incorrectly fail with 327 errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0 328 in high security mode doesn't allow ordinary users to read 329 /proc/self, so glibc incorrectly fails with errno == EACCES. 330 If errno == EIO, EPERM, or EROFS, it's probably safe to fail 331 right away, but these cases are rare enough that they're not 332 worth optimizing, and who knows what other messed-up systems 333 are out there? So play it safe and fall back on the code 334 below. */ 335 336# if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES 337# if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG 338# undef futimes 339# define futimes(fd, t) futimesat (fd, NULL, t) 340# endif 341 if (futimes (fd, t) == 0) 342 { 343# if __linux__ && __GLIBC__ 344 /* Work around a longstanding glibc bug, still present as 345 of 2010-12-27. On older Linux kernels that lack both 346 utimensat and utimes, glibc's futimes rounds instead of 347 truncating when falling back on utime. The same bug 348 occurs in futimesat with a null 2nd arg. */ 349 if (t) 350 { 351 bool abig = 500000 <= t[0].tv_usec; 352 bool mbig = 500000 <= t[1].tv_usec; 353 if ((abig | mbig) && fstat (fd, &st) == 0) 354 { 355 /* If these two subtractions overflow, they'll 356 track the overflows inside the buggy glibc. */ 357 time_t adiff = st.st_atime - t[0].tv_sec; 358 time_t mdiff = st.st_mtime - t[1].tv_sec; 359 360 struct timeval *tt = NULL; 361 struct timeval truncated_timeval[2]; 362 truncated_timeval[0] = t[0]; 363 truncated_timeval[1] = t[1]; 364 if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0) 365 { 366 tt = truncated_timeval; 367 tt[0].tv_usec = 0; 368 } 369 if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0) 370 { 371 tt = truncated_timeval; 372 tt[1].tv_usec = 0; 373 } 374 if (tt) 375 futimes (fd, tt); 376 } 377 } 378# endif 379 380 return 0; 381 } 382# endif 383 } 384#endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */ 385 386 if (!file) 387 { 388#if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \ 389 || (HAVE_WORKING_UTIMES && HAVE_FUTIMES)) 390 errno = ENOSYS; 391#endif 392 return -1; 393 } 394 395#if HAVE_WORKING_UTIMES 396 return utimes (file, t); 397#else 398 { 399 struct utimbuf utimbuf; 400 struct utimbuf *ut; 401 if (ts) 402 { 403 utimbuf.actime = ts[0].tv_sec; 404 utimbuf.modtime = ts[1].tv_sec; 405 ut = &utimbuf; 406 } 407 else 408 ut = NULL; 409 410 return utime (file, ut); 411 } 412#endif /* !HAVE_WORKING_UTIMES */ 413 } 414} 415 416/* Set the access and modification time stamps of FILE to be 417 TIMESPEC[0] and TIMESPEC[1], respectively. */ 418int 419utimens (char const *file, struct timespec const timespec[2]) 420{ 421 return fdutimens (-1, file, timespec); 422} 423 424/* Set the access and modification time stamps of FILE to be 425 TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing 426 symlinks. Fail with ENOSYS if the platform does not support 427 changing symlink timestamps, but FILE was a symlink. */ 428int 429lutimens (char const *file, struct timespec const timespec[2]) 430{ 431 struct timespec adjusted_timespec[2]; 432 struct timespec *ts = timespec ? adjusted_timespec : NULL; 433 int adjustment_needed = 0; 434 struct stat st; 435 436 if (ts) 437 { 438 adjusted_timespec[0] = timespec[0]; 439 adjusted_timespec[1] = timespec[1]; 440 adjustment_needed = validate_timespec (ts); 441 } 442 if (adjustment_needed < 0) 443 return -1; 444 445 /* The Linux kernel did not support symlink timestamps until 446 utimensat, in version 2.6.22, so we don't need to mimic 447 fdutimens' worry about buggy NFS clients. But we do have to 448 worry about bogus return values. */ 449 450#if HAVE_UTIMENSAT 451 if (0 <= lutimensat_works_really) 452 { 453 int result; 454# if __linux__ || __sun 455 /* As recently as Linux kernel 2.6.32 (Dec 2009), several file 456 systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, 457 but work if both times are either explicitly specified or 458 UTIME_NOW. Work around it with a preparatory lstat prior to 459 calling utimensat; fortunately, there is not much timing 460 impact due to the extra syscall even on file systems where 461 UTIME_OMIT would have worked. 462 463 The same bug occurs in Solaris 11.1 (Apr 2013). 464 465 FIXME: Simplify this for Linux in 2016 and for Solaris in 466 2024, when file system bugs are no longer common. */ 467 if (adjustment_needed == 2) 468 { 469 if (lstat (file, &st)) 470 return -1; 471 if (ts[0].tv_nsec == UTIME_OMIT) 472 ts[0] = get_stat_atime (&st); 473 else if (ts[1].tv_nsec == UTIME_OMIT) 474 ts[1] = get_stat_mtime (&st); 475 /* Note that st is good, in case utimensat gives ENOSYS. */ 476 adjustment_needed++; 477 } 478# endif 479 result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW); 480# ifdef __linux__ 481 /* Work around a kernel bug: 482 http://bugzilla.redhat.com/442352 483 http://bugzilla.redhat.com/449910 484 It appears that utimensat can mistakenly return 280 rather 485 than -1 upon ENOSYS failure. 486 FIXME: remove in 2010 or whenever the offending kernels 487 are no longer in common use. */ 488 if (0 < result) 489 errno = ENOSYS; 490# endif 491 if (result == 0 || errno != ENOSYS) 492 { 493 utimensat_works_really = 1; 494 lutimensat_works_really = 1; 495 return result; 496 } 497 } 498 lutimensat_works_really = -1; 499#endif /* HAVE_UTIMENSAT */ 500 501 /* The platform lacks an interface to set file timestamps with 502 nanosecond resolution, so do the best we can, discarding any 503 fractional part of the timestamp. */ 504 505 if (adjustment_needed || REPLACE_FUNC_STAT_FILE) 506 { 507 if (adjustment_needed != 3 && lstat (file, &st)) 508 return -1; 509 if (ts && update_timespec (&st, &ts)) 510 return 0; 511 } 512 513 /* On Linux, lutimes is a thin wrapper around utimensat, so there is 514 no point trying lutimes if utimensat failed with ENOSYS. */ 515#if HAVE_LUTIMES && !HAVE_UTIMENSAT 516 { 517 struct timeval timeval[2]; 518 struct timeval *t; 519 int result; 520 if (ts) 521 { 522 timeval[0].tv_sec = ts[0].tv_sec; 523 timeval[0].tv_usec = ts[0].tv_nsec / 1000; 524 timeval[1].tv_sec = ts[1].tv_sec; 525 timeval[1].tv_usec = ts[1].tv_nsec / 1000; 526 t = timeval; 527 } 528 else 529 t = NULL; 530 531 result = lutimes (file, t); 532 if (result == 0 || errno != ENOSYS) 533 return result; 534 } 535#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */ 536 537 /* Out of luck for symlinks, but we still handle regular files. */ 538 if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st)) 539 return -1; 540 if (!S_ISLNK (st.st_mode)) 541 return fdutimens (-1, file, ts); 542 errno = ENOSYS; 543 return -1; 544} 545