[SCM] The rsync repository. - branch master updated

Rsync CVS commit messages rsync-cvs at lists.samba.org
Wed Jul 22 20:32:30 UTC 2020


The branch, master has been updated
       via  974f49e2 Add --crtimes option.
       via  9f7506ac Improve --itemize-changes doc.
       via  8779d6c8 Switch to RSYNC_MAX_SKIPPED test setting.
      from  96be713f Update NEWS.

https://git.samba.org/?p=rsync.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 974f49e22ac9f62fcfd750768d0835b900524578
Author: Wayne Davison <wayne at opencoder.net>
Date:   Wed Jul 22 12:12:18 2020 -0700

    Add --crtimes option.

commit 9f7506ac1b48a17a65610ed4a1356c7432cf4da7
Author: Wayne Davison <wayne at opencoder.net>
Date:   Wed Jul 22 11:26:02 2020 -0700

    Improve --itemize-changes doc.

commit 8779d6c8bb23c643c805fc9aaa5873ee64a98cd7
Author: Wayne Davison <wayne at opencoder.net>
Date:   Wed Jul 22 10:59:15 2020 -0700

    Switch to RSYNC_MAX_SKIPPED test setting.

-----------------------------------------------------------------------

Summary of changes:
 .github/workflows/build.yml |  6 +++---
 Makefile.in                 | 18 +++++++++---------
 NEWS.md                     |  3 +++
 compat.c                    |  9 ++++++++-
 flist.c                     | 45 +++++++++++++++++++++++++++++++++++++++++++++
 generator.c                 | 34 +++++++++++++++++++++++++++++-----
 log.c                       |  5 +++--
 options.c                   | 16 ++++++++++++++++
 packaging/auto-Makefile     |  4 ++--
 rsync.1.md                  | 33 +++++++++++++++++++++------------
 rsync.c                     | 17 +++++++++++++++--
 rsync.h                     | 11 ++++++++++-
 runtests.sh                 | 14 +++-----------
 syscall.c                   | 43 +++++++++++++++++++++++++++++++++++++++++++
 testsuite/crtimes.test      | 26 ++++++++++++++++++++++++++
 tls.c                       | 27 +++++++++++++++++++++++++--
 16 files changed, 261 insertions(+), 50 deletions(-)
 create mode 100644 testsuite/crtimes.test


Changeset truncated at 500 lines:

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 812171dc..af45eead 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -27,11 +27,11 @@ jobs:
     - name: info
       run: rsync --version
     - name: check
-      run: sudo make strict_check
+      run: sudo RSYNC_MAX_SKIPPED=1 make check
     - name: check30
-      run: sudo make strict_check30
+      run: sudo RSYNC_MAX_SKIPPED=1 make check30
     - name: check29
-      run: sudo make strict_check29
+      run: sudo RSYNC_MAX_SKIPPED=1 make check29
     - name: ssl file list
       run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
     - name: save artifact
diff --git a/Makefile.in b/Makefile.in
index 513b2f8c..a6ce0366 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -295,17 +295,17 @@ test: check
 # catch Bash-isms earlier even if we're running on GNU.  Of course, we
 # might lose in the future where POSIX diverges from old sh.
 
-.PHONY: check strict_check
-check strict_check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
-	rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh $@
+.PHONY: check
+check: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
+	rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh
 
-.PHONY: check29 strict_check29
-check29 strict_check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
-	rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh $@ --protocol=29
+.PHONY: check29
+check29: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
+	rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=29
 
-.PHONY: check30 strict_check30
-check30 strict_check30: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
-	rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh $@ --protocol=30
+.PHONY: check30
+check30: all $(CHECK_PROGS) $(CHECK_SYMLINKS)
+	rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh --protocol=30
 
 wildtest.o: wildtest.c t_stub.o lib/wildmatch.c rsync.h config.h
 wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
diff --git a/NEWS.md b/NEWS.md
index 3ae5f74c..36d79af9 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -39,6 +39,9 @@
    protocol (so if you used this patch in the past, be sure to update your
    converter script to use newlines instead of null chars).
 
+ - Added `--crtimes` (`-N`) option for preserving the file's create time (on
+   an OS that supports that, such as macOS).
+
  - Added the ability to specify "@netgroup" names to the `hosts allow` and
    `hosts deny` daemon parameters.  This is a finalized version of the
    netgroup-auth patch from the patches repo.
diff --git a/compat.c b/compat.c
index 4719ef56..bbabd117 100644
--- a/compat.c
+++ b/compat.c
@@ -43,6 +43,7 @@ extern int protect_args;
 extern int preserve_uid;
 extern int preserve_gid;
 extern int preserve_atimes;
+extern int preserve_crtimes;
 extern int preserve_acls;
 extern int preserve_xattrs;
 extern int xfer_flags_as_varint;
@@ -76,7 +77,7 @@ int do_negotiated_strings = 0;
 int xmit_id0_names = 0;
 
 /* These index values are for the file-list's extra-attribute array. */
-int pathname_ndx, depth_ndx, atimes_ndx, uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
+int pathname_ndx, depth_ndx, atimes_ndx, crtimes_ndx, uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
 
 int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
 int sender_symlink_iconv = 0;	/* sender should convert symlink content */
@@ -555,6 +556,8 @@ void setup_protocol(int f_out,int f_in)
 	 * aligned for direct int64-pointer memory access. */
 	if (preserve_atimes)
 		atimes_ndx = (file_extra_cnt += EXTRA64_CNT);
+	if (preserve_crtimes)
+		crtimes_ndx = (file_extra_cnt += EXTRA64_CNT);
 	if (am_sender) /* This is most likely in the in64 union as well. */
 		pathname_ndx = (file_extra_cnt += PTR_EXTRA_CNT);
 	else
@@ -719,6 +722,10 @@ void setup_protocol(int f_out,int f_in)
 		proper_seed_order = compat_flags & CF_CHKSUM_SEED_FIX ? 1 : 0;
 		xfer_flags_as_varint = compat_flags & CF_VARINT_FLIST_FLAGS ? 1 : 0;
 		xmit_id0_names = compat_flags & CF_ID0_NAMES ? 1 : 0;
+		if (!xfer_flags_as_varint && preserve_crtimes) {
+			fprintf(stderr, "Both rsync versions must be at least 3.2.0 for --crtimes.\n");
+			exit_cleanup(RERR_PROTOCOL);
+		}
 		if (am_sender) {
 			receiver_symlink_times = am_server
 			    ? strchr(client_info, 'L') != NULL
diff --git a/flist.c b/flist.c
index 6c2543cd..feec96d4 100644
--- a/flist.c
+++ b/flist.c
@@ -56,6 +56,7 @@ extern int delete_during;
 extern int missing_args;
 extern int eol_nulls;
 extern int atimes_ndx;
+extern int crtimes_ndx;
 extern int relative_paths;
 extern int implied_dirs;
 extern int ignore_perishable;
@@ -378,6 +379,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
 			    int ndx, int first_ndx)
 {
 	static time_t modtime, atime;
+#ifdef SUPPORT_CRTIMES
+	static time_t crtime;
+#endif
 	static mode_t mode;
 #ifdef SUPPORT_HARD_LINKS
 	static int64 dev;
@@ -483,6 +487,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
 		else
 			atime = F_ATIME(file);
 	}
+#ifdef SUPPORT_CRTIMES
+	if (crtimes_ndx) {
+		crtime = F_CRTIME(file);
+		if (crtime == modtime)
+			xflags |= XMIT_CRTIME_EQ_MTIME;
+	}
+#endif
 
 #ifdef SUPPORT_HARD_LINKS
 	if (tmp_dev != -1) {
@@ -570,6 +581,10 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
 	}
 	if (xflags & XMIT_MOD_NSEC)
 		write_varint(f, F_MOD_NSEC(file));
+#ifdef SUPPORT_CRTIMES
+	if (crtimes_ndx && !(xflags & XMIT_CRTIME_EQ_MTIME))
+		write_varlong(f, crtime, 4);
+#endif
 	if (!(xflags & XMIT_SAME_MODE))
 		write_int(f, to_wire_mode(mode));
 	if (atimes_ndx && !S_ISDIR(mode) && !(xflags & XMIT_SAME_ATIME))
@@ -662,6 +677,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
 static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags)
 {
 	static int64 modtime, atime;
+#ifdef SUPPORT_CRTIMES
+	static time_t crtime;
+#endif
 	static mode_t mode;
 #ifdef SUPPORT_HARD_LINKS
 	static int64 dev;
@@ -776,6 +794,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
 			mode = first->mode;
 			if (atimes_ndx && !S_ISDIR(mode))
 				atime = F_ATIME(first);
+#ifdef SUPPORT_CRTIMES
+			if (crtimes_ndx)
+				crtime = F_CRTIME(first);
+#endif
 			if (preserve_uid)
 				uid = F_OWNER(first);
 			if (preserve_gid)
@@ -815,6 +837,21 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
 		modtime_nsec = read_varint(f);
 	else
 		modtime_nsec = 0;
+#endif
+#ifdef SUPPORT_CRTIMES
+	if (crtimes_ndx) {
+		if (xflags & XMIT_CRTIME_EQ_MTIME)
+			crtime = modtime;
+		else
+			crtime = read_varlong(f, 4);
+#if SIZEOF_TIME_T < SIZEOF_INT64
+		if (!am_generator && (int64)(time_t)crtime != crtime) {
+			rprintf(FERROR_XFER,
+				"Create time value of %s truncated on receiver.\n",
+				lastname);
+		}
+#endif
+	}
 #endif
 	if (!(xflags & XMIT_SAME_MODE))
 		mode = from_wire_mode(read_int(f));
@@ -997,6 +1034,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
 	}
 	if (atimes_ndx && !S_ISDIR(mode))
 		F_ATIME(file) = atime;
+#ifdef SUPPORT_CRTIMES
+	if (crtimes_ndx)
+		F_CRTIME(file) = crtime;
+#endif
 	if (unsort_ndx)
 		F_NDX(file) = flist->used + flist->ndx_start;
 
@@ -1394,6 +1435,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
 		file->flags |= FLAG_OWNED_BY_US;
 	if (atimes_ndx && !S_ISDIR(file->mode))
 		F_ATIME(file) = st.st_atime;
+#ifdef SUPPORT_CRTIMES
+	if (crtimes_ndx)
+		F_CRTIME(file) = get_create_time(fname);
+#endif
 
 	if (basename != thisname)
 		file->dirname = lastdir;
diff --git a/generator.c b/generator.c
index 1648db1c..f1780838 100644
--- a/generator.c
+++ b/generator.c
@@ -396,6 +396,19 @@ static inline int mtime_differs(STRUCT_STAT *stp, struct file_struct *file)
 #endif
 }
 
+static inline int any_time_differs(stat_x *sxp, struct file_struct *file, UNUSED(const char *fname))
+{
+	int differs = mtime_differs(&sxp->st, file);
+#ifdef SUPPORT_CRTIMES
+	if (!differs && crtimes_ndx) {
+		if (sxp->crtime == 0)
+			sxp->crtime = get_create_time(fname);
+		differs = !same_time(sxp->crtime, 0, F_CRTIME(file), 0);
+	}
+#endif
+	return differs;
+}
+
 static inline int perms_differ(struct file_struct *file, stat_x *sxp)
 {
 	if (preserve_perms)
@@ -450,7 +463,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
 {
 	if (S_ISLNK(file->mode)) {
 #ifdef CAN_SET_SYMLINK_TIMES
-		if (preserve_times & PRESERVE_LINK_TIMES && mtime_differs(&sxp->st, file))
+		if (preserve_times & PRESERVE_LINK_TIMES && any_time_differs(sxp, file, fname))
 			return 0;
 #endif
 #ifdef CAN_CHMOD_SYMLINK
@@ -470,7 +483,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
 			return 0;
 #endif
 	} else {
-		if (preserve_times && mtime_differs(&sxp->st, file))
+		if (preserve_times && any_time_differs(sxp, file, fname))
 			return 0;
 		if (perms_differ(file, sxp))
 			return 0;
@@ -512,6 +525,14 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
 		if (atimes_ndx && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
 		 && !same_time(F_ATIME(file), 0, sxp->st.st_atime, 0))
 			iflags |= ITEM_REPORT_ATIME;
+#ifdef SUPPORT_CRTIMES
+		if (crtimes_ndx) {
+			if (sxp->crtime == 0)
+				sxp->crtime = get_create_time(fnamecmp);
+			if (!same_time(sxp->crtime, 0, F_CRTIME(file), 0))
+				iflags |= ITEM_REPORT_CRTIME;
+		}
+#endif
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
@@ -1131,6 +1152,7 @@ static void list_file_entry(struct file_struct *f)
 	int size_width = human_readable ? 14 : 11;
 	int mtime_width = 1 + strlen(mtime_str);
 	int atime_width = atimes_ndx ? mtime_width : 0;
+	int crtime_width = crtimes_ndx ? mtime_width : 0;
 
 	if (!F_IS_ACTIVE(f)) {
 		/* this can happen if duplicate names were removed */
@@ -1141,10 +1163,11 @@ static void list_file_entry(struct file_struct *f)
 
 	if (missing_args == 2 && f->mode == 0) {
 		rprintf(FINFO, "%-*s %s\n",
-			10 + 1 + size_width + mtime_width + atime_width, "*missing",
+			10 + 1 + size_width + mtime_width + atime_width + crtime_width, "*missing",
 			f_name(f, NULL));
 	} else {
 		const char *atime_str = atimes_ndx && !S_ISDIR(f->mode) ? timestring(F_ATIME(f)) : "";
+		const char *crtime_str = crtimes_ndx ? timestring(F_CRTIME(f)) : "";
 		const char *arrow, *lnk;
 
 		permstring(permbuf, f->mode);
@@ -1157,9 +1180,9 @@ static void list_file_entry(struct file_struct *f)
 #endif
 			arrow = lnk = "";
 
-		rprintf(FINFO, "%s %*s %s%*s %s%s%s\n",
+		rprintf(FINFO, "%s %*s %s%*s%*s %s%s%s\n",
 			permbuf, size_width, human_num(F_LENGTH(f)),
-			timestring(f->modtime), atime_width, atime_str,
+			timestring(f->modtime), atime_width, atime_str, crtime_width, crtime_str,
 			f_name(f, NULL), arrow, lnk);
 	}
 }
@@ -1255,6 +1278,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
 			return;
 		}
 	}
+	sx.crtime = 0;
 
 	if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
 		int i;
diff --git a/log.c b/log.c
index 85eae3d5..0dc26331 100644
--- a/log.c
+++ b/log.c
@@ -720,8 +720,9 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
 			c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
 			c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
 			c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
-			c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.'
-			     : S_ISLNK(file->mode) ? 'U' : 'u';
+			c[8] = !(iflags & (ITEM_REPORT_ATIME|ITEM_REPORT_CRTIME)) ? '.'
+			     : BITS_SET(iflags, ITEM_REPORT_ATIME|ITEM_REPORT_CRTIME) ? 'b'
+			     : iflags & ITEM_REPORT_ATIME ? 'u' : 'n';
 			c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
 			c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
 			c[11] = '\0';
diff --git a/options.c b/options.c
index 0ecabe8d..59335269 100644
--- a/options.c
+++ b/options.c
@@ -64,6 +64,7 @@ int preserve_uid = 0;
 int preserve_gid = 0;
 int preserve_times = 0;
 int preserve_atimes = 0;
+int preserve_crtimes = 0;
 int update_only = 0;
 int open_noatime = 0;
 int cvs_exclude = 0;
@@ -670,6 +671,11 @@ static void print_info_flags(enum logcode f)
 #endif
 			"stop-at",
 
+#ifndef SUPPORT_CRTIMES
+		"no "
+#endif
+			"crtimes",
+
 	"*Optimizations",
 
 #ifndef HAVE_SIMD
@@ -838,6 +844,9 @@ static struct poptOption long_options[] = {
   {"no-U",             0,  POPT_ARG_VAL,    &preserve_atimes, 0, 0, 0 },
   {"open-noatime",     0,  POPT_ARG_VAL,    &open_noatime, 1, 0, 0 },
   {"no-open-noatime",  0,  POPT_ARG_VAL,    &open_noatime, 0, 0, 0 },
+  {"crtimes",         'N', POPT_ARG_VAL,    &preserve_crtimes, 1, 0, 0 },
+  {"no-crtimes",       0,  POPT_ARG_VAL,    &preserve_crtimes, 0, 0, 0 },
+  {"no-N",             0,  POPT_ARG_VAL,    &preserve_crtimes, 0, 0, 0 },
   {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
   {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
   {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
@@ -1211,6 +1220,9 @@ static void set_refuse_options(void)
 #ifndef HAVE_SETVBUF
 	parse_one_refuse_match(0, "outbuf", list_end);
 #endif
+#ifndef SUPPORT_CRTIMES
+	parse_one_refuse_match(0, "crtimes", list_end);
+#endif
 
 	/* Now we use the descrip values to actually mark the options for refusal. */
 	for (op = long_options; op != list_end; op++) {
@@ -2738,6 +2750,10 @@ void server_options(char **args, int *argc_p)
 		if (preserve_atimes > 1)
 			argstr[x++] = 'U';
 	}
+#ifdef SUPPORT_CRTIMES
+	if (preserve_crtimes)
+		argstr[x++] = 'N';
+#endif
 	if (preserve_perms)
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
diff --git a/packaging/auto-Makefile b/packaging/auto-Makefile
index 5e3322a2..e50277cb 100644
--- a/packaging/auto-Makefile
+++ b/packaging/auto-Makefile
@@ -1,6 +1,6 @@
 TARGETS := all install install-ssl-daemon install-all install-strip conf gen gensend reconfigure restatus \
-	proto man clean cleantests distclean test check check29 check30 strict_check strict_check29 strict_check30 \
-	installcheck splint doxygen doxygen-upload
+	proto man clean cleantests distclean test check check29 check30 installcheck splint \
+	doxygen doxygen-upload
 
 .PHONY: $(TARGETS) auto-prep
 
diff --git a/rsync.1.md b/rsync.1.md
index 91942873..dcf69e52 100644
--- a/rsync.1.md
+++ b/rsync.1.md
@@ -372,6 +372,7 @@ detailed description below for a complete description.
 --times, -t              preserve modification times
 --atimes, -U             preserve access (use) times
 --open-noatime           avoid changing the atime on opened files
+--crtimes, -N            preserve create times (newness)
 --omit-dir-times, -O     omit directories from --times
 --omit-link-times, -J    omit symlinks from --times
 --super                  receiver attempts super-user activities
@@ -1341,6 +1342,11 @@ your home directory (remove the '=' for that).
     mounted to avoid updating the atime on read access even without the
     O_NOATIME flag being set.
 
+0.  `--crtimes`, `-N,`
+
+    This tells rsync to set the create times (newness) of +the destination
+    files to the same value as the source files.
+
 0.  `--omit-dir-times`, `-O`
 
     This tells rsync to omit directories when it is preserving modification
@@ -2642,12 +2648,14 @@ your home directory (remove the '=' for that).
     directory, an `L` for a symlink, a `D` for a device, and a `S` for a
     special file (e.g. named sockets and fifos).
 
-    The other letters in the string above are the actual letters that will be
-    output if the associated attribute for the item is being updated or a "."
-    for no change.  Three exceptions to this are: (1) a newly created item
-    replaces each letter with a "+", (2) an identical item replaces the dots
-    with spaces, and (3) an unknown attribute replaces each letter with a "?"
-    (this can happen when talking to an older rsync).
+    The other letters in the string indicate if some attributes of the file
+    have changed, as follows:
+
+    - "`.`" - the attribute is unchanged.
+    - "`+`" - the file is newly created.
+    - "` `" - all the attributes are unchanged (all dots turn to spaces).
+    - "`?`" - the change is unknown (when the remote rsync is old).
+    - A letter indicates an attribute is being updated.
 
     The attribute that is associated with each letter is as follows:
 
@@ -2671,12 +2679,13 @@ your home directory (remove the '=' for that).
       value (requires `--owner` and super-user privileges).
     - A `g` means the group is different and is being updated to the sender's
       value (requires `--group` and the authority to set the group).
-    - A `u` means the access (use) time is different and is being updated to
-      the sender's value (requires `--atimes`).  An alternate value of `U`
-      means that the access time will be set to the transfer time, which
-      happens when a symlink or directory is updated.
-    - The `a` means that the ACL information changed.
-    - The `x` means that the extended attribute information changed.
+    - A `u`|`n`|`b` indicates the following information: `u`  means the access
+      (use) time is different and is being updated to the sender's value
+      (requires `--atimes`); `n` means the create time (newness) is different
+      and is being updated to the sender's value (requires `--crtimes`); `b`
+      means that both the access and create times are being updated.
+    - The `a` means that the ACL information is being changed.
+    - The `x` means that the extended attribute information is being changed.
 
     One other output is possible: when deleting files, the "%i" will output the
     string "`*deleting`" for each item that is being removed (assuming that you
diff --git a/rsync.c b/rsync.c
index e091cbef..e7f1f96a 100644
--- a/rsync.c
+++ b/rsync.c
@@ -584,6 +584,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
 		memcpy(&sx2.st, &sxp->st, sizeof (sx2.st));
 	if (!atimes_ndx || S_ISDIR(sxp->st.st_mode))
 		flags |= ATTRS_SKIP_ATIME;
+	/* Don't set the creation date on the root folder of an HFS+ volume. */
+	if (sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode))
+		flags |= ATTRS_SKIP_CRTIME;
 	if (!(flags & ATTRS_SKIP_MTIME) && !same_mtime(file, &sxp->st, flags & ATTRS_ACCURATE_TIME)) {
 		sx2.st.st_mtime = file->modtime;
 #ifdef ST_MTIME_NSEC
@@ -613,6 +616,16 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
 			file->flags |= FLAG_TIME_FAILED;
 		}
 	}
+#ifdef SUPPORT_CRTIMES
+	if (crtimes_ndx && !(flags & ATTRS_SKIP_CRTIME)) {
+		time_t file_crtime = F_CRTIME(file);
+		if (sxp->crtime == 0)
+			sxp->crtime = get_create_time(fname);
+		if (!same_time(sxp->crtime, 0L, file_crtime, 0L)
+		 && set_create_time(fname, file_crtime) == 0)
+			updated = 1;
+	}
+#endif
 
 #ifdef SUPPORT_ACLS
 	/* It's OK to call set_acl() now, even for a dir, as the generator
@@ -718,7 +731,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
 
 	/* Change permissions before putting the file into place. */
 	set_file_attrs(fnametmp, file, NULL, fnamecmp,
-		       ok_to_set_time ? ATTRS_ACCURATE_TIME : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME);


-- 
The rsync repository.



More information about the rsync-cvs mailing list