]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Integrate time-setting fixes/improvements from the master branch.
authorWayne Davison <wayned@samba.org>
Mon, 21 Feb 2011 17:48:37 +0000 (09:48 -0800)
committerWayne Davison <wayned@samba.org>
Mon, 21 Feb 2011 19:32:48 +0000 (11:32 -0800)
compat.c
configure.ac
generator.c
options.c
rsync.c
rsync.h
syscall.c
t_stub.c
util.c

index 3a4b38e218a754c902b182e316c9bd3d89d7ef04..a7a49cca2071e56e13905ab0cf0c09786a687e73 100644 (file)
--- a/compat.c
+++ b/compat.c
@@ -251,7 +251,7 @@ void setup_protocol(int f_out,int f_in)
        } else if (protocol_version >= 30) {
                if (am_server) {
                        compat_flags = allow_inc_recurse ? CF_INC_RECURSE : 0;
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
                        compat_flags |= CF_SYMLINK_TIMES;
 #endif
 #ifdef ICONV_OPTION
@@ -269,7 +269,7 @@ void setup_protocol(int f_out,int f_in)
                            ? strchr(client_info, 'L') != NULL
                            : !!(compat_flags & CF_SYMLINK_TIMES);
                }
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
                else
                        receiver_symlink_times = 1;
 #endif
@@ -287,7 +287,7 @@ void setup_protocol(int f_out,int f_in)
                }
                use_safe_inc_flist = !!(compat_flags & CF_SAFE_FLIST);
                need_messages_from_generator = 1;
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
        } else if (!am_sender) {
                receiver_symlink_times = 1;
 #endif
index 845ce0fc419b348b7fa50819dc989ee5ac14e5ae..5b18ea3b9885e79e6ee87a0f31f54209ea809461 100644 (file)
@@ -571,7 +571,8 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
     strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
     setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
     seteuid strerror putenv iconv_open locale_charset nl_langinfo getxattr \
-    extattr_get_link sigaction sigprocmask setattrlist)
+    extattr_get_link sigaction sigprocmask setattrlist \
+    utimensat)
 
 dnl cygwin iconv.h defines iconv_open as libiconv_open
 if test x"$ac_cv_func_iconv_open" != x"yes"; then
index 753ff957a4cc3e2178d7b9166d081a3f661bc1ca..ccb40550c58b18bdcc1a21a99a428c480a31d8d0 100644 (file)
@@ -566,12 +566,9 @@ static void do_delete_pass(void)
 
 int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
 {
-#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
-       if (S_ISLNK(file->mode)) {
+       if (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(file->mode)) {
                ;
-       } else
-#endif
-       if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
+       } else if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
                return 0;
 
        if (preserve_perms) {
@@ -613,12 +610,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
 {
        if (statret >= 0) { /* A from-dest-dir statret can == 1! */
                int keep_time = !preserve_times ? 0
-                   : S_ISDIR(file->mode) ? preserve_times > 1 :
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
-                   1;
-#else
-                   !S_ISLNK(file->mode);
-#endif
+                   : S_ISDIR(file->mode) ? preserve_times & PRESERVE_DIR_TIMES
+                   : S_ISLNK(file->mode) ? preserve_times & PRESERVE_LINK_TIMES
+                   : 1;
 
                if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
                        iflags |= ITEM_REPORT_SIZE;
@@ -2185,7 +2179,7 @@ void generate_files(int f_out, const char *local_name)
        }
        solo_file = local_name;
        dir_tweaking = !(list_only || solo_file || dry_run);
-       need_retouch_dir_times = preserve_times > 1;
+       need_retouch_dir_times = preserve_times & PRESERVE_DIR_TIMES;
        loopchk_limit = allowed_lull ? allowed_lull * 5 : 200;
        symlink_timeset_failed_flags = ITEM_REPORT_TIME
            | (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
index 579c4308769d72533fcdbee7da095e6b83f0be23..b0100678b3bf532bccf9478d0f13ab38d1fabefd 100644 (file)
--- a/options.c
+++ b/options.c
@@ -253,7 +253,7 @@ static void print_rsync_version(enum logcode f)
 #ifdef ICONV_OPTION
        iconv = "";
 #endif
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
        symtimes = "";
 #endif
 
@@ -486,7 +486,7 @@ static struct poptOption long_options[] = {
   {"xattrs",          'X', POPT_ARG_NONE,   0, 'X', 0, 0 },
   {"no-xattrs",        0,  POPT_ARG_VAL,    &preserve_xattrs, 0, 0, 0 },
   {"no-X",             0,  POPT_ARG_VAL,    &preserve_xattrs, 0, 0, 0 },
-  {"times",           't', POPT_ARG_VAL,    &preserve_times, 2, 0, 0 },
+  {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
   {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
   {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
   {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
@@ -1064,7 +1064,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        preserve_links = 1;
 #endif
                        preserve_perms = 1;
-                       preserve_times = 2;
+                       preserve_times = 1;
                        preserve_gid = 1;
                        preserve_uid = 1;
                        preserve_devices = 1;
@@ -1515,13 +1515,18 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
 
+       if (preserve_times) {
+               preserve_times = PRESERVE_FILE_TIMES;
+               if (!omit_dir_times)
+                       preserve_times |= PRESERVE_DIR_TIMES;
+#ifdef CAN_SET_SYMLINK_TIMES
+               preserve_times |= PRESERVE_LINK_TIMES;
+#endif
+       }
+
        if (make_backups && !backup_dir) {
                omit_dir_times = 0; /* Implied, so avoid -O to sender. */
-               if (preserve_times > 1)
-                       preserve_times = 1;
-       } else if (omit_dir_times) {
-               if (preserve_times > 1)
-                       preserve_times = 1;
+               preserve_times &= ~PRESERVE_DIR_TIMES;
        }
 
        if (stdout_format) {
@@ -1831,7 +1836,7 @@ void server_options(char **args, int *argc_p)
                        argstr[x++] = '.';
                if (allow_inc_recurse)
                        argstr[x++] = 'i';
-#if defined HAVE_LUTIMES && defined HAVE_UTIMES
+#ifdef CAN_SET_SYMLINK_TIMES
                argstr[x++] = 'L';
 #endif
 #ifdef ICONV_OPTION
diff --git a/rsync.c b/rsync.c
index d029f61ba59648aee2b41c6ec238d14a9bae7572..da605442dccaabd94f710502c50e7c04088ee7f0 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -423,7 +423,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                set_xattr(fname, file, fnamecmp, sxp);
 #endif
 
-       if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
+       if (!preserve_times
+        || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
+        || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
                flags |= ATTRS_SKIP_MTIME;
        if (!(flags & ATTRS_SKIP_MTIME)
            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
diff --git a/rsync.h b/rsync.h
index e6238de3d4eae116799041a84138f5a4bbb17431..3a1bbf7e7125f5724ca2f665dc483e14181ded6f 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -340,6 +340,10 @@ enum msgcode {
 #include <utime.h>
 #endif
 
+#if defined HAVE_LUTIMES || defined HAVE_UTIMENSAT
+#define CAN_SET_SYMLINK_TIMES 1
+#endif
+
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
@@ -1074,6 +1078,10 @@ extern int errno;
 #define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
 #define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
 
+#define PRESERVE_FILE_TIMES    (1<<0)
+#define PRESERVE_DIR_TIMES     (1<<1)
+#define PRESERVE_LINK_TIMES    (1<<2)
+
 /* Initial mask on permissions given to temporary files.  Mask off setuid
      bits and group access because of potential race-condition security
      holes, and mask other access because mode 707 is bizarre */
index ef182d40ff1102070e60112a149f4d6a0cc85f11..f5de86e58725e420578e45a676562ce40c63d536 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -284,3 +284,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
index 103e84621518bf3f818542c9a7848d162df05832..fd57bcc3835523a5289f366e519092219c4bed48 100644 (file)
--- a/t_stub.c
+++ b/t_stub.c
@@ -26,6 +26,7 @@ int module_id = -1;
 int relative_paths = 0;
 int human_readable = 0;
 int module_dirlen = 0;
+int preserve_times = 0;
 int preserve_xattrs = 0;
 mode_t orig_umask = 002;
 char *partial_dir;
diff --git a/util.c b/util.c
index f02a6a1c1557b0dca75c8735a1b7964c6965369d..7f207a3bb83b88ebd2f072e5687533455acf9f69 100644 (file)
--- a/util.c
+++ b/util.c
@@ -28,6 +28,7 @@ extern int dry_run;
 extern int module_id;
 extern int modify_window;
 extern int relative_paths;
+extern int preserve_times;
 extern int human_readable;
 extern int preserve_xattrs;
 extern char *module_dir;
@@ -123,12 +124,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, mode_t mode)
 {
-#if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
-       if (S_ISLNK(mode))
-               return 1;
-#endif
+       static int switch_step = 0;
 
        if (verbose > 2) {
                rprintf(FINFO, "set modtime of %s to (%ld) %s",
@@ -136,38 +136,49 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
                        asctime(localtime(&modtime)));
        }
 
-       if (dry_run)
-               return 0;
+       switch (switch_step) {
+#ifdef HAVE_UTIMENSAT
+#include "case_N.h"
+               if (do_utimensat(fname, modtime, 0) == 0)
+                       break;
+               if (errno != ENOSYS)
+                       return -1;
+               switch_step++;
+               /* FALLTHROUGH */
+#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;
-                       return 0;
+#ifdef HAVE_LUTIMES
+#include "case_N.h"
+               if (do_lutimes(fname, modtime, 0) == 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;
                }
-# 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);
+               /* FALLTHROUGH */
+
+#include "case_N.h"
+#ifdef HAVE_UTIMES
+               if (do_utimes(fname, modtime, 0) == 0)
+                       break;
 #else
-#error No file-time-modification routine found!
+               if (do_utime(fname, modtime, 0) == 0)
+                       break;
 #endif
+
+               return -1;
        }
+
+       return 0;
 }
 
 /* This creates a new directory with default permissions.  Since there