rsync with --flags patch: unable to rsync hardlinks to files w/ schg

Raphael H. Becker rabe at p-i-n.com
Mon Feb 19 14:59:00 UTC 2007


Hi *,

i've contacted Rolf Grossmann, the maintainer of 
net/rsync/work/rsync-2.6.9/patches/flags.diff

He enhanced this patch to handle hardlinks to schg-files gracefully.
This patch is expected to get into 2.6.10.

I've attached the patch to this mail, it works for me.
Just copy it over work/rsync-2.6.9/patches/flags.diff after 
"make extract" and before "make patch" and "make".

Regards
Raphael Becker


On Fri, Dec 08, 2006 at 01:24:22PM +0100, Raphael H. Becker wrote:
> 
> Hi *,
> 
> we're running two jail-hosts with some jails in it. The two hosts (will)
> replicate the active jails to each other to have a fallback.
> 
> On the backup-host I run the following command:
> 
> rsync -avHWx -e ssh --flags --delete root at jailhost1.dmz:/data/jails/ /data/jails
> 
> Doing so brings me the following errors for each jail:
> 
> rsync: link "/data/jails/jail4711/usr/bin/chfn" => jail4711/usr/bin/ypchsh failed: Operation not permitted (1)
> rsync: link "/data/jails/jail4711/usr/bin/chpass" => jail4711/usr/bin/ypchsh failed: Operation not permitted (1)
> rsync: link "/data/jails/jail4711/usr/bin/chsh" => jail4711/usr/bin/ypchsh failed: Operation not permitted (1)
> rsync: link "/data/jails/jail4711/usr/bin/ypchfn" => jail4711/usr/bin/ypchsh failed: Operation not permitted (1)
> rsync: link "/data/jails/jail4711/usr/bin/ypchpass" => jail4711/usr/bin/ypchsh failed: Operation not permitted (1)
> rsync: link "/data/jails/jail4711/usr/bin/passwd" => jail4711/usr/bin/yppasswd failed: Operation not permitted (1)
> 
> These files have the "schg" flag on jailhost1, which get rsynced to
> jailhost2. Theese files are not present on jailhost2 after this:
> 
> ls: /data/jails/jail4711/usr/bin/passwd: No such file or directory
> 
> Any idea how to get rid of this?  
> 
> Regards
> Raphael Becker 

-------------- next part --------------
diff -bru rsync-2.6.9/backup.c rsync-2.6.9.chflags/backup.c
--- rsync-2.6.9/backup.c	Wed Apr 26 01:51:12 2006
+++ rsync-2.6.9.chflags/backup.c	Mon Jan 29 16:09:26 2007
@@ -61,7 +61,17 @@
 		return 0;
 
 	while (1) {
-		if (do_rename(fname, fnamebak) == 0) {
+#ifdef SUPPORT_FLAGS
+		STRUCT_STAT st2;
+		
+		link_stat(fname, &st2, 0);
+		make_mutable(fname, st2.st_mode, st2.st_flags);		
+#endif
+		if (do_rename(fname, fnamebak) == 0)
+		{
+#ifdef SUPPORT_FLAGS
+			undo_make_mutable(fnamebak, st2.st_mode, st2.st_flags);		
+#endif
 			if (verbose > 1) {
 				rprintf(FINFO, "backed up %s to %s\n",
 					fname, fnamebak);
diff -bru rsync-2.6.9/config.h.in rsync-2.6.9.chflags/config.h.in
--- rsync-2.6.9/config.h.in	Tue Nov  7 05:39:47 2006
+++ rsync-2.6.9.chflags/config.h.in	Tue Jan  9 15:25:04 2007
@@ -49,6 +49,9 @@
 /* Define to 1 if vsprintf has a C99-compatible return value */
 #undef HAVE_C99_VSNPRINTF
 
+/* Define if you have the `chflags' function. */
+#undef HAVE_CHFLAGS
+
 /* Define to 1 if you have the `chmod' function. */
 #undef HAVE_CHMOD
 
diff -bru rsync-2.6.9/configure rsync-2.6.9.chflags/configure
--- rsync-2.6.9/configure	Tue Nov  7 05:39:47 2006
+++ rsync-2.6.9.chflags/configure	Sat Dec  9 01:28:24 2006
@@ -13474,7 +13474,7 @@
 
 
 
-for ac_func in waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
+for ac_func in waitpid wait4 getcwd strdup chown chflags chmod lchmod mknod mkfifo \
     fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
     memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
     strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
diff -bru rsync-2.6.9/configure.in rsync-2.6.9.chflags/configure.in
--- rsync-2.6.9/configure.in	Tue Nov  7 05:39:47 2006
+++ rsync-2.6.9.chflags/configure.in	Sat Dec  9 01:29:17 2006
@@ -522,7 +522,7 @@
 
 AC_FUNC_UTIME_NULL
 AC_FUNC_ALLOCA
-AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
+AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chflags chmod lchmod mknod mkfifo \
     fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
     memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
     strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
diff -bru rsync-2.6.9/flist.c rsync-2.6.9.chflags/flist.c
--- rsync-2.6.9/flist.c	Sat Oct 14 03:17:36 2006
+++ rsync-2.6.9.chflags/flist.c	Mon Jan 29 16:24:16 2007
@@ -44,6 +44,7 @@
 extern int preserve_hard_links;
 extern int preserve_devices;
 extern int preserve_specials;
+extern int preserve_flags;
 extern int preserve_uid;
 extern int preserve_gid;
 extern int relative_paths;
@@ -303,6 +304,9 @@
 	unsigned short flags;
 	static time_t modtime;
 	static mode_t mode;
+#ifdef SUPPORT_FLAGS
+	static uint32 fileflags;
+#endif
 	static int64 dev;
 	static dev_t rdev;
 	static uint32 rdev_major;
@@ -321,6 +325,9 @@
 		dev = 0, rdev = MAKEDEV(0, 0);
 		rdev_major = 0;
 		uid = 0, gid = 0;
+#ifdef SUPPORT_FLAGS
+		fileflags = 0;
+#endif
 		*lastname = '\0';
 		return;
 	}
@@ -333,6 +340,12 @@
 		flags |= XMIT_SAME_MODE;
 	else
 		mode = file->mode;
+#ifdef SUPPORT_FLAGS
+ 	if (file->fileflags == fileflags)
+		flags |= XMIT_SAME_FLAGS;
+	else
+		fileflags = file->fileflags;
+#endif
 	if ((preserve_devices && IS_DEVICE(mode))
 	 || (preserve_specials && IS_SPECIAL(mode))) {
 		if (protocol_version < 28) {
@@ -416,6 +429,10 @@
 		write_int(f, modtime);
 	if (!(flags & XMIT_SAME_MODE))
 		write_int(f, to_wire_mode(mode));
+#if SUPPORT_FLAGS
+ 	if (preserve_flags && !(flags & XMIT_SAME_FLAGS))
+		write_int(f, fileflags);
+#endif
 	if (preserve_uid && !(flags & XMIT_SAME_UID)) {
 		if (!numeric_ids)
 			add_uid(uid);
@@ -483,6 +500,9 @@
 {
 	static time_t modtime;
 	static mode_t mode;
+#ifdef SUPPORT_FLAGS
+ 	static uint32 fileflags;
+#endif
 	static int64 dev;
 	static dev_t rdev;
 	static uint32 rdev_major;
@@ -501,6 +521,9 @@
 
 	if (!flist) {
 		modtime = 0, mode = 0;
+#ifdef SUPPORT_FLAGS
+		fileflags = 0;
+#endif
 		dev = 0, rdev = MAKEDEV(0, 0);
 		rdev_major = 0;
 		uid = 0, gid = 0;
@@ -560,6 +583,11 @@
 	if (chmod_modes && !S_ISLNK(mode))
 		mode = tweak_mode(mode, chmod_modes);
 
+#ifdef SUPPORT_FLAGS
+ 	if (preserve_flags && !(flags & XMIT_SAME_FLAGS))
+		fileflags = (uint32)read_int(f);
+#endif
+	
 	if (preserve_uid && !(flags & XMIT_SAME_UID))
 		uid = (uid_t)read_int(f);
 	if (preserve_gid && !(flags & XMIT_SAME_GID))
@@ -609,6 +637,9 @@
 	file->modtime = modtime;
 	file->length = file_length;
 	file->mode = mode;
+#ifdef SUPPORT_FLAGS
+	file->fileflags = fileflags;
+#endif
 	file->uid = uid;
 	file->gid = gid;
 
@@ -862,6 +893,9 @@
 	file->modtime = st.st_mtime;
 	file->length = st.st_size;
 	file->mode = st.st_mode;
+#if SUPPORT_FLAGS
+	file->fileflags = st.st_flags;
+#endif
 	file->uid = st.st_uid;
 	file->gid = st.st_gid;
 
diff -bru rsync-2.6.9/hlink.c rsync-2.6.9.chflags/hlink.c
--- rsync-2.6.9/hlink.c	Tue Oct 17 20:49:04 2006
+++ rsync-2.6.9.chflags/hlink.c	Tue Jan  9 23:53:43 2007
@@ -253,6 +253,12 @@
 		  int statret, STRUCT_STAT *st, char *toname, int terse,
 		  int itemizing, enum logcode code)
 {
+#if SUPPORT_FLAGS
+	STRUCT_STAT st2;
+	
+	link_stat(toname, &st2, 0);
+	make_mutable(toname, st2.st_mode, st2.st_flags);
+#endif
 	if (do_link(toname, fname)) {
 		if (terse) {
 			if (!verbose)
@@ -264,6 +270,9 @@
 			full_fname(fname), toname);
 		return -1;
 	}
+#if SUPPORT_FLAGS
+	undo_make_mutable(toname, st2.st_mode, st2.st_flags);
+#endif
 
 	if (itemizing) {
 		itemize(file, ndx, statret, st,
diff -bru rsync-2.6.9/options.c rsync-2.6.9.chflags/options.c
--- rsync-2.6.9/options.c	Tue Oct 24 02:36:38 2006
+++ rsync-2.6.9.chflags/options.c	Tue Jan  9 17:46:57 2007
@@ -48,6 +48,7 @@
 int preserve_links = 0;
 int preserve_hard_links = 0;
 int preserve_perms = 0;
+int preserve_flags = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
 int preserve_specials = 0;
@@ -201,6 +202,7 @@
 	char const *hardlinks = "no ";
 	char const *links = "no ";
 	char const *ipv6 = "no ";
+	char const *fflags = "no ";
 	STRUCT_STAT *dumstat;
 
 #ifdef HAVE_SOCKETPAIR
@@ -223,6 +225,10 @@
 	ipv6 = "";
 #endif
 
+#if SUPPORT_FLAGS
+	fflags = "";
+#endif
+
 	rprintf(f, "%s  version %s  protocol version %d\n",
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
 	rprintf(f, "Copyright (C) 1996-2006 by Andrew Tridgell, Wayne Davison, and others.\n");
@@ -235,9 +241,9 @@
 	/* Note that this field may not have type ino_t.  It depends
 	 * on the complicated interaction between largefile feature
 	 * macros. */
-	rprintf(f, "              %sinplace, %sIPv6, "
+	rprintf(f, "              %sinplace, %sIPv6, %sfile flags, "
 		"%d-bit system inums, %d-bit internal inums\n",
-		have_inplace, ipv6,
+		have_inplace, ipv6, fflags,
 		(int) (sizeof dumstat->st_ino * 8),
 		(int) (sizeof (int64) * 8));
 #ifdef MAINTAINER_MODE
@@ -304,6 +310,7 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+  rprintf(F,"     --flags                 preserve file flags\n");
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
   rprintf(F," -o, --owner                 preserve owner (super-user only)\n");
@@ -424,6 +431,8 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+  {"flags",            0,  POPT_ARG_VAL,    &preserve_flags, 1, 0, 0 },
+  {"no-flags",         0,  POPT_ARG_VAL,    &preserve_flags, 0, 0, 0 },
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
   {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
@@ -943,6 +952,9 @@
 			preserve_uid = 1;
 			preserve_devices = 1;
 			preserve_specials = 1;
+#if 0 && SUPPORT_FLAGS /* XXX maybe with the next major release */
+			preserve_flags=1;
+#endif
 			break;
 
 		case 'D':
@@ -1128,6 +1140,15 @@
 	}
 #endif
 
+#ifndef SUPPORT_FLAGS
+	if (preserve_flags) {
+		snprintf(err_buf,sizeof err_buf,
+			 "file flags are not supported on this %s\n",
+			 am_server ? "server" : "client");
+		return 0;
+	}
+#endif
+	
 	if (write_batch && read_batch) {
 		snprintf(err_buf, sizeof err_buf,
 			"--write-batch and --read-batch can not be used together\n");
@@ -1580,6 +1601,9 @@
 	 * sans -r because the --no-r option was added at the same time. */
 	if (xfer_dirs && !recurse && delete_mode && am_sender)
 		args[ac++] = "--no-r";
+
+	if (preserve_flags)
+		args[ac++] = "--flags";
 
 	if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
 		if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
diff -bru rsync-2.6.9/proto.h rsync-2.6.9.chflags/proto.h
--- rsync-2.6.9/proto.h	Tue Nov  7 05:39:47 2006
+++ rsync-2.6.9.chflags/proto.h	Tue Jan  9 23:51:45 2007
@@ -224,6 +224,8 @@
 void setup_iconv();
 void free_sums(struct sum_struct *s);
 mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int exists);
+void make_mutable(const char *fname, mode_t mode, uint32 fileflags);
+void undo_make_mutable(const char *fname, mode_t mode, uint32 fileflags);
 int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
 		   int flags);
 RETSIGTYPE sig_int(UNUSED(int val));
@@ -254,6 +256,7 @@
 int do_rmdir(const char *pathname);
 int do_open(const char *pathname, int flags, mode_t mode);
 int do_chmod(const char *path, mode_t mode);
+int do_chflags(const char *path, uint32 flags);
 int do_rename(const char *fname1, const char *fname2);
 void trim_trailing_slashes(char *name);
 int do_mkdir(char *fname, mode_t mode);
diff -bru rsync-2.6.9/rsync.1 rsync-2.6.9.chflags/rsync.1
--- rsync-2.6.9/rsync.1	Tue Nov  7 05:39:51 2006
+++ rsync-2.6.9.chflags/rsync.1	Tue Jan  9 18:22:24 2007
@@ -387,6 +387,7 @@
  \-K, \-\-keep\-dirlinks         treat symlinked dir on receiver as dir
  \-H, \-\-hard\-links            preserve hard links
  \-p, \-\-perms                 preserve permissions
+      \-\-flags                 preserve file flags
  \-E, \-\-executability         preserve executability
      \-\-chmod=CHMOD           affect file and/or directory permissions
  \-o, \-\-owner                 preserve owner (super-user only)
@@ -591,7 +592,9 @@
 .IP 
 Note that \fB\-a\fP \fBdoes not preserve hardlinks\fP, because
 finding multiply-linked files is expensive\&.  You must separately
-specify \fB\-H\fP\&.
+specify \fB\-H\fP\&.  Note also that for compatibility, \fB\-a\fP
+currently \fBdoes not include \-\-flags\fP (see there) to include preserving
+change file flags (if supported by the OS)\&.
 .IP 
 .IP "\-\-no\-OPTION"
 You may turn off one or more implied options by prefixing
@@ -931,6 +934,14 @@
 
 .IP 
 If \fB\-\-perms\fP is enabled, this option is ignored\&.
+.IP 
+.IP "\fB\-\-flags\fP"
+This option causes rsync to update the change file flags
+to be the same as the source file, if your OS supports the \fBchflags\fP(2)
+system call\&.  In any case, an attempt is made to remove flags that would
+prevent a file to be altered\&.  Some flags can only be altered by the
+super-user and can only be unset below a certain secure-level (usually
+single-user mode)\&.
 .IP 
 .IP "\fB\-\-chmod\fP"
 This option tells rsync to apply one or more
diff -bru rsync-2.6.9/rsync.c rsync-2.6.9.chflags/rsync.c
--- rsync-2.6.9/rsync.c	Mon Oct  9 00:02:13 2006
+++ rsync-2.6.9.chflags/rsync.c	Mon Jan 29 17:15:23 2007
@@ -33,6 +33,7 @@
 extern int verbose;
 extern int dry_run;
 extern int preserve_perms;
+extern int preserve_flags;
 extern int preserve_executability;
 extern int preserve_times;
 extern int omit_dir_times;
@@ -123,6 +124,41 @@
 	return new_mode;
 }
 
+#ifdef SUPPORT_FLAGS
+/* Set a file's st_flags. */
+static int set_fileflags(const char *fname, uint32 fileflags)
+{
+	if (do_chflags(fname, fileflags) != 0) {
+		rsyserr(FERROR, errno, "failed to set file flags on %s",
+				full_fname(fname));
+		return 0;
+	}
+	
+	return 1;
+}
+
+#define NOCHANGE_FLAGS    (UF_IMMUTABLE | UF_APPEND | UF_NOUNLINK | SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK)
+/* Remove immutable flags from an object, so it can be altered. */
+void make_mutable(const char *fname, mode_t mode, uint32 fileflags)
+{
+	if (!preserve_flags || S_ISLNK(mode))
+		return;
+	
+	if (fileflags & NOCHANGE_FLAGS)
+		do_chflags(fname, fileflags & ~NOCHANGE_FLAGS);
+}
+
+/* Undo a prior make_mutable() call. */
+void undo_make_mutable(const char *fname, mode_t mode, uint32 fileflags)
+{
+	if (!preserve_flags || S_ISLNK(mode))
+		return;
+
+	if (fileflags & NOCHANGE_FLAGS)
+		set_fileflags(fname, fileflags);
+}
+#endif
+
 int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
 		   int flags)
 {
@@ -152,6 +188,9 @@
 		flags |= ATTRS_SKIP_MTIME;
 	if (!(flags & ATTRS_SKIP_MTIME)
 	    && cmp_time(st->st_mtime, file->modtime) != 0) {
+#ifdef SUPPORT_FLAGS
+		make_mutable(fname, st->st_mode, st->st_flags);
+#endif
 		int ret = set_modtime(fname, file->modtime, st->st_mode);
 		if (ret < 0) {
 			rsyserr(FERROR, errno, "failed to set times on %s",
@@ -185,6 +224,9 @@
 					(long)st->st_gid, (long)file->gid);
 			}
 		}
+#ifdef SUPPORT_FLAGS
+		make_mutable(fname, st->st_mode, st->st_flags);
+#endif
 		if (do_lchown(fname,
 		    change_uid ? file->uid : st->st_uid,
 		    change_gid ? file->gid : st->st_gid) != 0) {
@@ -209,6 +251,9 @@
 		new_mode = tweak_mode(new_mode, daemon_chmod_modes);
 #ifdef HAVE_CHMOD
 	if ((st->st_mode & CHMOD_BITS) != (new_mode & CHMOD_BITS)) {
+#ifdef SUPPORT_FLAGS
+		make_mutable(fname, st->st_mode, st->st_flags);
+#endif
 		int ret = do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR, errno,
@@ -221,6 +266,18 @@
 	}
 #endif
 
+#ifdef SUPPORT_FLAGS
+	/* must be last change, because flags can forbid other changes */
+	if (preserve_flags && !S_ISLNK(st->st_mode) &&
+		(st->st_flags != file->fileflags || file->fileflags != 0)) {
+		if (set_fileflags(fname, file->fileflags) != 0) {
+			return 0;
+		}
+		if (st->st_flags != file->fileflags)
+			updated = 1;
+	}
+#endif
+
 	if (verbose > 1 && flags & ATTRS_REPORT) {
 		if (updated)
 			rprintf(FCLIENT, "%s\n", fname);
@@ -268,6 +325,9 @@
 	set_file_attrs(fnametmp, file, NULL,
 		       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
 
+#ifdef SUPPORT_FLAGS
+	make_mutable(fnametmp, file->mode, file->fileflags);
+#endif
 	/* move tmp file over real file */
 	if (verbose > 2)
 		rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
@@ -282,6 +342,9 @@
 	}
 	if (ret == 0) {
 		/* The file was moved into place (not copied), so it's done. */
+#ifdef SUPPORT_FLAGS
+		undo_make_mutable(fname, file->mode, file->fileflags);
+#endif
 		return;
 	}
 	/* The file was copied, so tweak the perms of the copied file.  If it
diff -bru rsync-2.6.9/rsync.h rsync-2.6.9.chflags/rsync.h
--- rsync-2.6.9/rsync.h	Tue Oct 24 05:31:30 2006
+++ rsync-2.6.9.chflags/rsync.h	Mon Jan 29 17:15:57 2007
@@ -54,6 +54,7 @@
 #define XMIT_HAS_IDEV_DATA (1<<9)
 #define XMIT_SAME_DEV (1<<10)
 #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
+#define XMIT_SAME_FLAGS (1<<12)
 
 /* These flags are used in the live flist data. */
 
@@ -344,6 +345,10 @@
 #define schar char
 #endif
 
+#ifdef HAVE_CHFLAGS
+#define SUPPORT_FLAGS 1
+#endif
+
 /* Find a variable that is either exactly 32-bits or longer.
  * If some code depends on 32-bit truncation, it will need to
  * take special action in a "#if SIZEOF_INT32 > 4" section. */
@@ -530,6 +535,9 @@
 	uid_t uid;
 	gid_t gid;
 	mode_t mode;
+#ifdef SUPPORT_FLAGS
+	uint32 fileflags;
+#endif
 	uchar flags;	/* this item MUST remain last */
 };
 
diff -bru rsync-2.6.9/rsync.yo rsync-2.6.9.chflags/rsync.yo
--- rsync-2.6.9/rsync.yo	Tue Nov  7 05:39:47 2006
+++ rsync-2.6.9.chflags/rsync.yo	Tue Jan  9 18:17:13 2007
@@ -321,6 +321,7 @@
  -K, --keep-dirlinks         treat symlinked dir on receiver as dir
  -H, --hard-links            preserve hard links
  -p, --perms                 preserve permissions
+     --flags                 preserve file flags
  -E, --executability         preserve executability
      --chmod=CHMOD           affect file and/or directory permissions
  -o, --owner                 preserve owner (super-user only)
@@ -509,7 +510,9 @@
 
 Note that bf(-a) bf(does not preserve hardlinks), because
 finding multiply-linked files is expensive.  You must separately
-specify bf(-H).
+specify bf(-H).  Note also that for compatibility, bf(-a)
+currently bf(does not include --flags) (see there) to include preserving
+change file flags (if supported by the OS).
 
 dit(--no-OPTION) You may turn off one or more implied options by prefixing
 the option name with "no-".  Not all options may be prefixed with a "no-":
@@ -804,6 +807,13 @@
 
 If bf(--perms) is enabled, this option is ignored.
 
+dit(bf(--flags)) This option causes rsync to update the change file flags
+to be the same as the source file, if your OS supports the chflags(2)
+system call.  In any case, an attempt is made to remove flags that would
+prevent a file to be altered.  Some flags can only be altered by the
+super-user and can only be unset below a certain securelevel (usually
+single-user mode).
+ 
 dit(bf(--chmod)) This option tells rsync to apply one or more
 comma-separated "chmod" strings to the permission of the files in the
 transfer.  The resulting value is treated as though it was the permissions
diff -bru rsync-2.6.9/syscall.c rsync-2.6.9.chflags/syscall.c
--- rsync-2.6.9/syscall.c	Wed Apr 26 01:51:15 2006
+++ rsync-2.6.9.chflags/syscall.c	Sat Dec  9 03:07:15 2006
@@ -46,6 +46,9 @@
 {
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+#if SUPPORT_FLAGS
+	chflags(fname, 0);
+#endif
 	return unlink(fname);
 }
 
@@ -119,6 +122,9 @@
 {
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+#if SUPPORT_FLAGS
+	chflags(pathname, 0);
+#endif
 	return rmdir(pathname);
 }
 
@@ -152,10 +158,22 @@
 }
 #endif
 
+#if SUPPORT_FLAGS
+int do_chflags(const char *path, uint32 flags)
+{
+	if (dry_run) return 0;
+	RETURN_ERROR_IF_RO_OR_LO;
+	return chflags(path, flags);
+}
+#endif
+
 int do_rename(const char *fname1, const char *fname2)
 {
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+#if SUPPORT_FLAGS
+	chflags(fname2, 0);
+#endif
 	return rename(fname1, fname2);
 }
 


More information about the freebsd-ports mailing list