--- a/syscall.c +++ b/syscall.c @@ -174,6 +174,64 @@ int do_chmod(const char *path, mode_t mode) } #endif +#ifdef HAVE_UTIMES +int do_utimes(const char *fname, time_t modtime) +{ + 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 = 0; + + return utimes(fname, t); +} +#endif + +#ifdef HAVE_LUTIMES +int do_lutimes(const char *fname, time_t modtime) +{ + 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 = 0; + + return lutimes(fname, t); +} +#endif + +#ifdef HAVE_UTIME +int do_utime(const char *fname, time_t modtime) +{ +#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 +} +#endif + int do_rename(const char *fname1, const char *fname2) { if (dry_run) return 0; --- a/util.c +++ b/util.c @@ -24,7 +24,6 @@ #include "ifuncs.h" extern int verbose; -extern int dry_run; extern int module_id; extern int modify_window; extern int relative_paths; @@ -123,51 +122,64 @@ NORETURN void overflow_exit(const char *str) exit_cleanup(RERR_MALLOC); } -int set_modtime(const char *fname, time_t modtime, mode_t mode) +#if defined HAVE_UTIMES || defined HAVE_UTIME +static inline void mention_modtime(const char *fname, time_t modtime) { -#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES - if (S_ISLNK(mode)) - return 1; -#endif - if (verbose > 2) { - rprintf(FINFO, "set modtime of %s to (%ld) %s", - fname, (long)modtime, - asctime(localtime(&modtime))); + rprintf(FINFO, "set modtime of %s to (%.0f) %s", + fname, (double)modtime, asctime(localtime(&modtime))); } +} +#else +#error No file-time-modification routine found! +#endif - if (dry_run) - return 0; +/* 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, mode_t mode) +{ +#if defined HAVE_UTIMES && defined HAVE_UTIME + static int try_utimes = 1; - { + if (try_utimes) +#endif #ifdef HAVE_UTIMES - struct timeval t[2]; - t[0].tv_sec = time(NULL); - t[0].tv_usec = 0; - t[1].tv_sec = modtime; - t[1].tv_usec = 0; -# ifdef HAVE_LUTIMES + { if (S_ISLNK(mode)) { - if (lutimes(fname, t) < 0) - return errno == ENOSYS ? 1 : -1; +# ifdef HAVE_LUTIMES + if (do_lutimes(fname, modtime) == 0) { + mention_modtime(fname, modtime); + return 0; + } + if (errno != ENOSYS) + return -1; +# endif + return 1; + } + + if (do_utimes(fname, modtime) == 0) { + mention_modtime(fname, modtime); return 0; } +# ifdef HAVE_UTIME + if (errno != ENOSYS) + return -1; + if (S_ISREG(mode) || S_ISDIR(mode)) + try_utimes = 0; # endif - return utimes(fname, t); -#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); -#else -#error No file-time-modification routine found! + } #endif + +#ifdef HAVE_UTIME + if (S_ISLNK(mode)) + return 1; + if (do_utime(fname, modtime) == 0) { + mention_modtime(fname, modtime); + return 0; } +#endif + + return -1; } /* This creates a new directory with default permissions. Since there