From: Wayne Davison Date: Thu, 26 Aug 2010 17:24:37 +0000 (-0700) Subject: Move time setting to syscall.c and add syscall fallback. X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/2a189350f27d092fd05e85d4a08b941a26f13718 Move time setting to syscall.c and add syscall fallback. See bug 5506 and bug 7621. --- diff --git a/syscall.c b/syscall.c index aba0009d..1d72d198 100644 --- a/syscall.c +++ b/syscall.c @@ -327,3 +327,77 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence) return lseek(fd, offset, whence); #endif } + +#ifdef HAVE_UTIMENSAT +int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec) +{ + struct timespec t[2]; + + if (dry_run) return 0; + RETURN_ERROR_IF_RO_OR_LO; + + t[0].tv_sec = 0; + t[0].tv_nsec = UTIME_NOW; + t[1].tv_sec = modtime; + t[1].tv_nsec = mod_nsec; + return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW); +} +#endif + +#ifdef HAVE_LUTIMES +int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec) +{ + struct timeval t[2]; + + if (dry_run) return 0; + RETURN_ERROR_IF_RO_OR_LO; + + t[0].tv_sec = time(NULL); + t[0].tv_usec = 0; + t[1].tv_sec = modtime; + t[1].tv_usec = mod_nsec / 1000; + return lutimes(fname, t); +} +#endif + +#ifdef HAVE_UTIMES +int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec) +{ + struct timeval t[2]; + + if (dry_run) return 0; + RETURN_ERROR_IF_RO_OR_LO; + + t[0].tv_sec = time(NULL); + t[0].tv_usec = 0; + t[1].tv_sec = modtime; + t[1].tv_usec = mod_nsec / 1000; + return utimes(fname, t); +} + +#elif defined HAVE_UTIME +int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec)) +{ +#ifdef HAVE_STRUCT_UTIMBUF + struct utimbuf tbuf; +#else + time_t t[2]; +#endif + + if (dry_run) return 0; + RETURN_ERROR_IF_RO_OR_LO; + +# ifdef HAVE_STRUCT_UTIMBUF + tbuf.actime = time(NULL); + tbuf.modtime = modtime; + return utime(fname, &tbuf); +# else + t[0] = time(NULL); + t[1] = modtime; + return utime(fname, t); +# endif +} + +#else +#error Need utimes or utime function. +#endif diff --git a/util.c b/util.c index ee65f549..a53ea291 100644 --- a/util.c +++ b/util.c @@ -25,7 +25,6 @@ #include "itypes.h" #include "inums.h" -extern int dry_run; extern int module_id; extern int modify_window; extern int relative_paths; @@ -123,10 +122,11 @@ NORETURN void overflow_exit(const char *str) exit_cleanup(RERR_MALLOC); } +/* This returns 0 for success, 1 for a symlink if symlink time-setting + * is not possible, or -1 for any other error. */ int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode) { - if (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(mode)) - return 1; + static int switch_step = 0; if (DEBUG_GTE(TIME, 1)) { rprintf(FINFO, "set modtime of %s to (%ld) %s", @@ -134,42 +134,49 @@ int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode) asctime(localtime(&modtime))); } - if (dry_run) - return 0; - - { + switch (switch_step) { #ifdef HAVE_UTIMENSAT - struct timespec t[2]; - t[0].tv_sec = 0; - t[0].tv_nsec = UTIME_NOW; - t[1].tv_sec = modtime; - t[1].tv_nsec = mod_nsec; - return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW); -#elif defined HAVE_UTIMES || defined HAVE_LUTIMES - struct timeval t[2]; - t[0].tv_sec = time(NULL); - t[0].tv_usec = 0; - t[1].tv_sec = modtime; - t[1].tv_usec = mod_nsec / 1000; -# ifdef HAVE_LUTIMES - return lutimes(fname, t); -# else - return utimes(fname, t); -# endif -#elif defined HAVE_STRUCT_UTIMBUF - struct utimbuf tbuf; - tbuf.actime = time(NULL); - tbuf.modtime = modtime; - return utime(fname,&tbuf); -#elif defined HAVE_UTIME - time_t t[2]; - t[0] = time(NULL); - t[1] = modtime; - return utime(fname,t); +#include "case_N.h" + if (do_utimensat(fname, modtime, mod_nsec) == 0) + break; + if (errno != ENOSYS) + return -1; + switch_step++; + /* FALLTHROUGH */ +#endif + +#ifdef HAVE_LUTIMES +#include "case_N.h" + if (do_lutimes(fname, modtime, mod_nsec) == 0) + break; + if (errno != ENOSYS) + return -1; + switch_step++; + /* FALLTHROUGH */ +#endif + +#include "case_N.h" + switch_step++; + if (preserve_times & PRESERVE_LINK_TIMES) { + preserve_times &= ~PRESERVE_LINK_TIMES; + if (S_ISLNK(mode)) + return 1; + } + /* FALLTHROUGH */ + +#include "case_N.h" +#ifdef HAVE_UTIMES + if (do_utimes(fname, modtime, mod_nsec) == 0) + break; #else -#error No file-time-modification routine found! + if (do_utime(fname, modtime, mod_nsec) == 0) + break; #endif + + return -1; } + + return 0; } /* Create any necessary directories in fname. Any missing directories are