diff -Naur -X diff_ignore rsync-3.0.6_base/acls.c rsync/acls.c
--- rsync-3.0.6_base/acls.c	2009-04-10 19:09:39.000000000 -0400
+++ rsync/acls.c	2015-11-09 21:57:54.000000000 -0500
@@ -21,6 +21,11 @@
 
 #include "rsync.h"
 #include "lib/sysacls.h"
+#ifdef HAVE_OSX_ACLS
+// For _PATH_RSRCFORKSPEC
+#include <sys/paths.h>
+#include <uuid/uuid.h>
+#endif
 
 #ifdef SUPPORT_ACLS
 
@@ -31,6 +36,7 @@
 extern int orig_umask;
 extern int numeric_ids;
 extern int inc_recurse;
+extern int disable_acl_support;
 
 /* Flags used to indicate what items are being transmitted for an entry. */
 #define XMIT_USER_OBJ (1<<0)
@@ -53,7 +59,7 @@
 /* === ACL structures === */
 
 typedef struct {
-	id_t id;
+	unsigned char id[16];
 	uint32 access;
 } id_access;
 
@@ -117,7 +123,8 @@
 #ifdef ACLS_NEED_MASK
 	     + 4;
 #else
-	     + (racl->mask_obj != NO_ENTRY) + 3;
+//	     + (racl->mask_obj != NO_ENTRY) + 3;
+	     + (racl->mask_obj != NO_ENTRY);
 #endif
 }
 
@@ -176,7 +183,16 @@
 	ida1 = ial1->idas;
 	ida2 = ial2->idas;
 	for (; count--; ida1++, ida2++) {
+#ifdef HAVE_OSX_ACLS
+//rprintf(FINFO, "UUID1: %.32p, UUID2: %.32p\n", ida1->id, ida2->id);
+//char uuid_str1[37], uuid_str2[37];
+//if (ida1 != NULL) uuid_unparse(ida1->id, uuid_str1);
+//if (ida2 != NULL) uuid_unparse(ida2->id, uuid_str2);
+//rprintf(FINFO, "UUID1: %s, UUID2: %s\n", uuid_str1, uuid_str2);
+		if (ida1->access != ida2->access || uuid_compare(ida1->id, ida2->id) != 0)
+#else
 		if (ida1->access != ida2->access || ida1->id != ida2->id)
+#endif
 			return False;
 	}
 	return True;
@@ -266,9 +282,9 @@
 	     rc = sys_acl_get_entry(sacl, SMB_ACL_NEXT_ENTRY, &entry)) {
 		SMB_ACL_TAG_T tag_type;
 		uint32 access;
-		id_t g_u_id;
+		unsigned char *uu;
 		id_access *ida;
-		if ((rc = sys_acl_get_info(entry, &tag_type, &access, &g_u_id)) != 0) {
+		if ((rc = sys_acl_get_info(entry, &tag_type, &access, &uu)) != 0) {
 			errfun = "sys_acl_get_info";
 			break;
 		}
@@ -310,8 +326,12 @@
 			continue;
 		}
 		ida = EXPAND_ITEM_LIST(&temp_ida_list, id_access, -10);
-		ida->id = g_u_id;
+		int j;
+		for (j = 0; j < 16; j++)
+			ida->id[j] = uu != NULL ? uu[j] : 0;
 		ida->access = access;
+		if (uu)
+			acl_free(uu);
 	}
 	if (rc) {
 		rsyserr(FERROR_XFER, errno, "unpack_smb_acl: %s()", errfun);
@@ -389,7 +409,7 @@
 	SMB_ACL_ENTRY_T entry;
 
 	if (!(*smb_acl = sys_acl_init(calc_sacl_entries(racl)))) {
-		rsyserr(FERROR_XFER, errno, "pack_smb_acl: sys_acl_init()");
+		rsyserr(FERROR_XFER, errno, "pack_smb_acl: sys_acl_init(%d)", calc_sacl_entries(racl));
 		return False;
 	}
 
@@ -406,7 +426,11 @@
 		COE( sys_acl_create_entry,(smb_acl, &entry) );
 		COE( sys_acl_set_info,
 		    (entry,
+#ifdef HAVE_OSX_ACLS
+		     SMB_ACL_GROUP, // Ignored on OS X, see sys_acl_get_info()
+#else
 		     ida->access & NAME_IS_USER ? SMB_ACL_USER : SMB_ACL_GROUP,
+#endif
 		     ida->access & ~NAME_IS_USER, ida->id) );
 	}
 
@@ -434,7 +458,7 @@
 
 	COE( sys_acl_create_entry,(smb_acl, &entry) );
 	COE( sys_acl_set_info,(entry, SMB_ACL_OTHER, racl->other_obj & ~NO_ENTRY, 0) );
-#endif
+#endif // HAVE_OSX_ACLS
 
 #ifdef DEBUG
 	if (sys_acl_valid(*smb_acl) < 0)
@@ -506,10 +530,18 @@
 			if (!(ida = racl->names.idas = new_array(id_access, cnt)))
 				out_of_memory("get_rsync_acl");
 			racl->names.count = cnt;
+#ifdef HAVE_OSX_ACLS
+			for ( ; cnt--; ida++, bp += 16+4) {
+				//ida->id = IVAL(bp, 0);
+				memcpy(ida->id, bp, 16);
+				ida->access = IVAL(bp, 16);
+			}
+#else
 			for ( ; cnt--; ida++, bp += 4+4) {
 				ida->id = IVAL(bp, 0);
 				ida->access = IVAL(bp, 4);
 			}
+#endif
 		}
 		free(buf);
 		return 0;
@@ -517,19 +549,32 @@
 #endif
 
 	if ((sacl = sys_acl_get_file(fname, type)) != 0) {
+		if (verbose > 1)
+			fprintf(stderr, "Calling unpack_smb_acl() on %s\n", full_fname(fname));
+		errno = 0;
 		BOOL ok = unpack_smb_acl(sacl, racl);
 
 		sys_acl_free_acl(sacl);
 		if (!ok) {
+			rprintf(FERROR, "get_rsync_acl: unpack_smb_acl failed on %s [%s]\n", full_fname(fname), who_am_i());
 			return -1;
+//		} else if (S_ISDIR(mode)) {
+//			fprintf(stderr, "DEBUG: get_rsync_acl() retrieved a directory ACL for %s (%d entries):\n", full_fname(fname), racl->names.count);
+//			size_t count;
+//			id_access *ida;
+//			for (ida = racl->names.idas, count = racl->names.count; count; ida++, count--) {
+//				char uuid_str[37];
+//				uuid_unparse(ida->id, uuid_str);
+//				fprintf(stderr, "DEBUG: \tUUID: %s, access: 0x%.8X\n", uuid_str, ida->access);
+//			}
 		}
 	} else if (no_acl_syscall_error(errno)) {
 		/* ACLs are not supported, so pretend we have a basic ACL. */
 		if (type == SMB_ACL_TYPE_ACCESS)
 			rsync_acl_fake_perms(racl, mode);
 	} else {
-		rsyserr(FERROR_XFER, errno, "get_acl: sys_acl_get_file(%s, %s)",
-			fname, str_acl_type(type));
+		rsyserr(FERROR_XFER, errno, "get_rsync_acl: sys_acl_get_file(%s, %s) [%s]",
+			full_fname(fname), str_acl_type(type), who_am_i());
 		return -1;
 	}
 
@@ -570,6 +615,7 @@
 
 	for (ida = idal->idas; count--; ida++) {
 		uint32 xbits = ida->access << 2;
+#ifndef HAVE_OSX_ACLS
 		const char *name;
 		if (ida->access & NAME_IS_USER) {
 			xbits |= XFLAG_NAME_IS_USER;
@@ -584,6 +630,10 @@
 			write_buf(f, name, len);
 		} else
 			write_varint(f, xbits);
+#else
+		write_buf(f, (char *)ida->id, 16);
+		write_varint(f, xbits);
+#endif
 	}
 }
 
@@ -591,7 +641,8 @@
 			   item_list *racl_list, int f)
 {
 	int ndx = find_matching_rsync_acl(racl, type, racl_list);
-
+	//int ndx = -1;
+	
 	/* Send 0 (-1 + 1) to indicate that literal ACL data follows. */
 	write_varint(f, ndx + 1);
 
@@ -599,6 +650,8 @@
 		rsync_acl *new_racl = EXPAND_ITEM_LIST(racl_list, rsync_acl, 1000);
 		uchar flags = 0;
 
+//		fprintf(stderr, "DEBUG: send_rsync_acl() ndx: %lu, \n", racl_list->count-1);
+
 		if (racl->user_obj != NO_ENTRY)
 			flags |= XMIT_USER_OBJ;
 		if (racl->group_obj != NO_ENTRY)
@@ -640,6 +693,10 @@
 	/* Avoid sending values that can be inferred from other data. */
 	rsync_acl_strip_perms(sxp->acc_acl);
 
+	// DEBUG: Working on an issue related to uncache_duo_acls
+//	int ndx = find_matching_rsync_acl(sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list);
+//	if (ndx < 0)
+//		fprintf(stderr, "DEBUG: [sender] New ACL found for %s [ndx: %zu]\n", fname, (&access_acl_list)->count);
 	send_rsync_acl(sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list, f);
 
 	if (S_ISDIR(sxp->st.st_mode)) {
@@ -692,9 +749,18 @@
 
 	for (i = 0; i < count; i++) {
 		uchar has_name;
+#ifndef HAVE_OSX_ACLS
 		id_t id = read_varint(f);
+#else
+		unsigned char id[16];
+		read_buf(f, (char *)id, 16);
+//char uuid_str[37];
+//uuid_unparse(id, uuid_str);
+//rprintf(FINFO, "recv_ida_entries: UUID %s\n", uuid_str);
+#endif		
 		uint32 access = recv_acl_access(&has_name, f);
 
+#ifndef HAVE_OSX_ACLS
 		if (has_name) {
 			if (access & NAME_IS_USER)
 				id = recv_user_name(f, id);
@@ -707,8 +773,9 @@
 			if (inc_recurse && (!am_root || !numeric_ids))
 				id = match_gid(id, NULL);
 		}
+#endif		
 
-		ent->idas[i].id = id;
+		memcpy(ent->idas[i].id, id, 16);
 		ent->idas[i].access = access;
 		computed_mask_bits |= access;
 	}
@@ -724,8 +791,10 @@
 	int ndx = read_varint(f);
 
 	if (ndx < 0 || (size_t)ndx > racl_list->count) {
-		rprintf(FERROR_XFER, "recv_acl_index: %s ACL index %d > %d\n",
-			str_acl_type(type), ndx, (int)racl_list->count);
+		fprintf(stderr, "[%s]recv_rsync_acl: %s ACL index %d > %d\n",
+				who_am_i(), str_acl_type(type), ndx, (int)racl_list->count);
+		rprintf(FERROR_XFER, "[%s]recv_rsync_acl: %s ACL index %d > %d\n",
+			who_am_i(), str_acl_type(type), ndx, (int)racl_list->count);
 		exit_cleanup(RERR_STREAMIO);
 	}
 
@@ -749,6 +818,8 @@
 	if (flags & XMIT_NAME_LIST)
 		computed_mask_bits |= recv_ida_entries(&duo_item->racl.names, f);
 
+	//fprintf(stderr, "DEBUG: [%s]recv_rsync_acl() ndx: %lu\n", who_am_i(), racl_list->count-1);
+
 #ifdef HAVE_OSX_ACLS
 	/* If we received a superfluous mask, throw it away. */
 	duo_item->racl.mask_obj = NO_ENTRY;
@@ -765,7 +836,12 @@
 /* Receive the ACL info the sender has included for this file-list entry. */
 void receive_acl(struct file_struct *file, int f)
 {
+//	static int last_ndx = -1;
 	F_ACL(file) = recv_rsync_acl(&access_acl_list, SMB_ACL_TYPE_ACCESS, f);
+//	if (F_ACL(file) > last_ndx) {
+//		last_ndx = F_ACL(file);
+//		fprintf(stderr, "DEBUG: Received new ACL for %s [ndx: %d]\n", f_name(file, NULL), last_ndx);
+//	}
 
 	if (S_ISDIR(file->mode))
 		F_DIR_DEFACL(file) = recv_rsync_acl(&default_acl_list, SMB_ACL_TYPE_DEFAULT, f);
@@ -798,6 +874,7 @@
 
 	F_ACL(file) = cache_rsync_acl(sxp->acc_acl,
 				      SMB_ACL_TYPE_ACCESS, &access_acl_list);
+//	fprintf(stderr, "DEBUG: cache_tmp_acls, prior_access_count: %lu, access_acl_list.count: %lu [%s]\n", prior_access_count, access_acl_list.count, f_name(file, NULL));
 
 	if (S_ISDIR(sxp->st.st_mode)) {
 		if (prior_default_count == (size_t)-1)
@@ -826,6 +903,7 @@
 {
 	if (prior_access_count != (size_t)-1) {
 		uncache_duo_acls(&access_acl_list, prior_access_count);
+//		fprintf(stderr, "DEBUG: uncache_tmp_acls, new access_acl_list.count: %lu\n", access_acl_list.count);
 		prior_access_count = (size_t)-1;
 	}
 
@@ -927,8 +1005,8 @@
 #endif
 			rc = sys_acl_delete_def_file(fname);
 		if (rc < 0) {
-			rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_delete_def_file(%s)",
-				fname);
+			rsyserr(FERROR_XFER, errno, "set_rsync_acl: sys_acl_delete_def_file(%s)",
+				full_fname(fname));
 			return -1;
 		}
 #ifdef SUPPORT_XATTRS
@@ -947,10 +1025,20 @@
 		if (cnt) {
 			char *bp = buf + 4*4;
 			id_access *ida = duo_item->racl.names.idas;
+#ifdef HAVE_OSX_ACLS
+			for ( ; cnt--; ida++, bp += 16+4) {
+				SIVAL(bp, 0, ida->id[0]);
+				SIVAL(bp, 4, ida->id[4]);
+				SIVAL(bp, 8, ida->id[8]);
+				SIVAL(bp, 12, ida->id[12]);
+				SIVAL(bp, 16, ida->access);
+			}
+#else
 			for ( ; cnt--; ida++, bp += 4+4) {
 				SIVAL(bp, 0, ida->id);
 				SIVAL(bp, 4, ida->access);
 			}
+#endif
 		}
 		rc = set_xattr_acl(fname, type == SMB_ACL_TYPE_ACCESS, buf, len);
 		free(buf);
@@ -958,9 +1046,22 @@
 #endif
 	} else {
 		mode_t cur_mode = sxp->st.st_mode;
+		if (verbose > 1)
+			fprintf(stderr, "Calling pack_smb_acl() on %s\n", full_fname(fname));
 		if (!duo_item->sacl
-		 && !pack_smb_acl(&duo_item->sacl, &duo_item->racl))
+		 && !pack_smb_acl(&duo_item->sacl, &duo_item->racl)) {
+			// BOMBICH
+			// Print out all ACEs associated with the current file
+			rprintf(FERROR, "set_rsync_acl: pack_smb_acl failed on %s\n", full_fname(fname));
+			int count = duo_item->racl.names.count;
+			int a;
+			for (a = 0; a < count; a++) {
+				char uuid_str[37];
+				uuid_unparse(duo_item->racl.names.idas[a].id, uuid_str);
+				rprintf(FERROR, "\tuuid: %s, access: %u\n", uuid_str, duo_item->racl.names.idas[a].access);
+			}
 			return -1;
+		}
 #ifdef HAVE_OSX_ACLS
 		mode = 0; /* eliminate compiler warning */
 #else
@@ -971,13 +1072,32 @@
 				return 0;
 		}
 #endif
-		if (sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
-			rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_set_file(%s, %s)",
-				fname, str_acl_type(type));
+//		if (S_ISDIR(sxp->st.st_mode)) {
+//			fprintf(stderr, "DEBUG: set_rsync_acl() setting a directory ACL on %s (%d entries):\n", full_fname(fname), duo_item->racl.names.count);
+//			size_t count;
+//			id_access *ida;
+//			for (ida = duo_item->racl.names.idas, count = duo_item->racl.names.count; count; ida++, count--) {
+//				char uuid_str[37];
+//				uuid_unparse(ida->id, uuid_str);
+//				fprintf(stderr, "DEBUG: \tUUID: %s, access: 0x%.8X\n", uuid_str, ida->access);
+//			}
+//		}
+		if (!disable_acl_support && sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
+			rsyserr(FERROR_XFER, errno, "set_rsync_acl: sys_acl_set_file(%s, %s)",
+				full_fname(fname), str_acl_type(type));
+			if (duo_item->sacl) {
+				sys_acl_free_acl(duo_item->sacl);
+				duo_item->sacl = NULL;
+			}
 			return -1;
 		}
 		if (type == SMB_ACL_TYPE_ACCESS)
 			sxp->st.st_mode = cur_mode;
+
+		if (duo_item->sacl) {
+			sys_acl_free_acl(duo_item->sacl);
+			duo_item->sacl = NULL;
+		}
 	}
 
 	return 0;
@@ -1001,13 +1121,14 @@
 		errno = EROFS;
 		return -1;
 	}
-
+	
 	ndx = F_ACL(file);
+//	fprintf(stderr, "DEBUG: set_acl() ndx: %d, %s\n", ndx, fname);
 	if (ndx >= 0 && (size_t)ndx < access_acl_list.count) {
 		acl_duo *duo_item = access_acl_list.items;
 		duo_item += ndx;
 		eq = sxp->acc_acl
-		  && rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, file->mode);
+			&& rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, file->mode);
 		if (!eq) {
 			unchanged = 0;
 			if (!dry_run && fname
@@ -1042,6 +1163,7 @@
  * This is done in a single pass after receiving the whole file-list. */
 static void match_racl_ids(const item_list *racl_list)
 {
+#ifndef HAVE_OSX_ACLS
 	int list_cnt, name_cnt;
 	acl_duo *duo_item = racl_list->items;
 	for (list_cnt = racl_list->count; list_cnt--; duo_item++) {
@@ -1054,6 +1176,7 @@
 				ida->id = match_gid(ida->id, NULL);
 		}
 	}
+#endif
 }
 
 void match_acl_ids(void)
diff -Naur -X diff_ignore rsync-3.0.6_base/backup.c rsync/backup.c
--- rsync-3.0.6_base/backup.c	2009-06-18 17:30:50.000000000 -0400
+++ rsync/backup.c	2019-01-14 17:30:13.000000000 -0500
@@ -38,9 +38,12 @@
 extern char *backup_suffix_dels;
 extern char *backup_dir;
 extern char *backup_dir_dels;
-
+extern int logfile_format_has_i;
+extern int unsupported_fileflags;
 static int deleting;
 
+void strip_sip_flags(const char *fname);
+
 /* make a complete pathname for backup file */
 char *get_backup_name(const char *fname)
 {
@@ -54,7 +57,7 @@
 			return backup_dir_buf;
 	}
 
-	rprintf(FERROR, "backup filename too long\n");
+	rprintf(FERROR, "get_backup_name: backup filename too long (%s)\n", full_fname(fname));
 	return NULL;
 }
 
@@ -70,7 +73,7 @@
 			return backup_dir_dels_buf;
 	}
 
-	rprintf(FERROR, "delete filename too long\n");
+	rprintf(FERROR, "get_delete_name: delete filename too long (%s)\n", full_fname(fname));
 	return NULL;
 }
 
@@ -102,8 +105,8 @@
 		if (errno == ENOTDIR && do_unlink(fnamebak) == 0)
 			continue;
 
-		rsyserr(FERROR, rename_errno, "rename %s to backup %s",
-			fname, fnamebak);
+		rsyserr(FERROR, rename_errno, "make_simple_backup: rename %s to backup %s",
+			full_fname(fname), fnamebak);
 		errno = rename_errno;
 		return 0;
 	}
@@ -140,11 +143,11 @@
 			return -1;
 		if (*p == '/') {
 			*p = '\0';
-			if (mkdir_defmode(fbuf) == 0)
+			if (mkdir_defmode(fbuf) == 0 || errno == EEXIST) // We shouldn't ever get EEXIST (because all calls to make_bak_dir first require errno == ENOENT), but I've seen it happen
 				break;
 			if (errno != ENOENT) {
 				rsyserr(FERROR, errno,
-					"make_bak_dir mkdir %s failed",
+					"make_bak_dir: mkdir %s failed",
 					full_fname(fbuf));
 				return -1;
 			}
@@ -158,7 +161,7 @@
 			 * actual dir that the files are coming from. */
 			if (x_stat(rel, &sx.st, NULL) < 0) {
 				rsyserr(FERROR, errno,
-					"make_bak_dir stat %s failed",
+					"make_bak_dir: stat %s failed",
 					full_fname(rel));
 			} else {
 #ifdef SUPPORT_ACLS
@@ -176,29 +179,32 @@
 					free_acl(&sx);
 				}
 #endif
-#ifdef SUPPORT_XATTRS
-				if (preserve_xattrs) {
-					get_xattr(rel, &sx);
-					cache_tmp_xattr(file, &sx);
-					free_xattr(&sx);
-				}
-#endif
-				set_file_attrs(fbuf, file, NULL, NULL, 0);
+//#ifdef SUPPORT_XATTRS
+//				if (preserve_xattrs) {
+//					get_xattr(rel, &sx);
+//					if (verbose)
+//						fprintf(stderr, "DEBUG: make_bak_dir(): calling cache_tmp_xattr rel: %s, fbuf: %s\n", rel, fbuf);
+//					cache_tmp_xattr(file, &sx);
+//					free_xattr(&sx);
+//				}
+//#endif
+				// TODO: set_file_attrs() won't call set_xattr() if fnamecmp (fourth argument) is NULL
+				set_file_attrs(fbuf, file, NULL, NULL, ATTRS_STRIP_RESTRICTED);
 				unmake_file(file);
 #ifdef SUPPORT_ACLS
 				uncache_tmp_acls();
 #endif
-#ifdef SUPPORT_XATTRS
-				uncache_tmp_xattrs();
-#endif
+//#ifdef SUPPORT_XATTRS
+//				uncache_tmp_xattrs();
+//#endif
 			}
 		}
 		*p = '/';
 		p += strlen(p);
 		if (p == end)
 			break;
-		if (mkdir_defmode(fbuf) < 0) {
-			rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
+		if (mkdir_defmode(fbuf) < 0 && errno != EEXIST) {
+			rsyserr(FERROR, errno, "make_bak_dir: mkdir %s failed",
 				full_fname(fbuf));
 			return -1;
 		}
@@ -211,6 +217,8 @@
 static int robust_move(const char *src, char *dst)
 {
 	if (robust_rename(src, dst, NULL, 0755) < 0) {
+		if (verbose && errno == ENOENT)
+			fprintf(stderr, "DEBUG: robust_move(%s, %s) failed: %d\n", src, dst, errno);
 		int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
 		if (errno == ENOENT && make_bak_dir(dst) == 0) {
 			if (robust_rename(src, dst, NULL, 0755) < 0)
@@ -235,8 +243,8 @@
 	struct file_struct *file;
 	char *buf;
 	int save_preserve_xattrs = preserve_xattrs;
+	int save_preserve_acls = preserve_acls;
 	int kept = 0;
-	int ret_code;
 
 	/* return if no file to keep */
 	if (x_lstat(fname, &sx.st, NULL) < 0)
@@ -251,32 +259,36 @@
 	if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
 		return 1; /* the file could have disappeared */
 
+	// BOMBICH: Some files are just noise when they're archived, so we exclude them here
+	// Ultimately it would be preferable to have a specific filter for items that
+	// should not be archived
+	// We'll have to come up with a better way to avoid these empty-looking folders
+	// http://help.bombich.com/discussions/problems/13468-help-an-error-occurred-while-ccc-was-modifying-this-items-filesystem-entry-on-the-destination
+//	if (strncmp(file->basename, ".DS_Store", 9) == 0)
+//		return 1;
+	
 	buf = deleting ? get_delete_name(fname) : get_backup_name(fname);
 	if (!buf) {
 		unmake_file(file);
-#ifdef SUPPORT_ACLS
-		uncache_tmp_acls();
-#endif
-#ifdef SUPPORT_XATTRS
-		uncache_tmp_xattrs();
-#endif
 		return 0;
 	}
 
-#ifdef SUPPORT_ACLS
-	if (preserve_acls && !S_ISLNK(file->mode)) {
-		get_acl(fname, &sx);
-		cache_tmp_acl(file, &sx);
-		free_acl(&sx);
-	}
-#endif
-#ifdef SUPPORT_XATTRS
-	if (preserve_xattrs) {
-		get_xattr(fname, &sx);
-		cache_tmp_xattr(file, &sx);
-		free_xattr(&sx);
-	}
-#endif
+//#ifdef SUPPORT_ACLS
+//	if (preserve_acls && !S_ISLNK(file->mode)) {
+//		get_acl(fname, &sx);
+//		cache_tmp_acl(file, &sx);
+//		free_acl(&sx);
+//	}
+//#endif
+//#ifdef SUPPORT_XATTRS
+//	if (preserve_xattrs) {
+//		get_xattr(fname, &sx);
+//		if (verbose)
+//			fprintf(stderr, "DEBUG: keep_backup(): calling cache_tmp_xattr |%s\n", buf);
+//		cache_tmp_xattr(file, &sx); // Why do we get xattrs at all if we're going to set preserve_xattrs to 0 before calling set_file_attrs()?
+//		free_xattr(&sx);
+//	}
+//#endif
 
 	/* Check to see if this is a device file, or link */
 	if ((am_root && preserve_devices && IS_DEVICE(file->mode))
@@ -285,6 +297,8 @@
 		do_unlink(buf);
 		if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0) {
 			save_errno = errno ? errno : EINVAL; /* 0 paranoia */
+			if (verbose)
+				fprintf(stderr, "DEBUG: keep_backup: do_mknod() failed: %d |%s\n", errno, buf);
 			if (errno == ENOENT && make_bak_dir(buf) == 0) {
 				if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
 					save_errno = errno ? errno : save_errno;
@@ -292,8 +306,8 @@
 					save_errno = 0;
 			}
 			if (save_errno) {
-				rsyserr(FERROR, save_errno, "mknod %s failed",
-					full_fname(buf));
+				//rsyserr(FERROR, save_errno, "mknod %s failed", full_fname(buf));
+				kept = 0; // I'm going to ignore this error, devices aren't important enough to spew errors.
 			}
 		} else
 			save_errno = 0;
@@ -301,30 +315,21 @@
 			rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
 				fname);
 		}
-		kept = 1;
+		if (save_errno == 0)
+			kept = 1;
 		do_unlink(fname);
 	}
 
+	// BOMBICH
 	if (!kept && S_ISDIR(file->mode)) {
-		/* make an empty directory */
-		if (do_mkdir(buf, file->mode) < 0) {
-			int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
-			if (errno == ENOENT && make_bak_dir(buf) == 0) {
-				if (do_mkdir(buf, file->mode) < 0)
-					save_errno = errno ? errno : save_errno;
-				else
-					save_errno = 0;
-			}
-			if (save_errno) {
-				rsyserr(FINFO, save_errno, "mkdir %s failed",
-					full_fname(buf));
-			}
-		}
-
-		ret_code = do_rmdir(fname);
-		if (verbose > 2) {
-			rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
-				full_fname(fname), ret_code);
+		if (verbose)
+			fprintf(stderr, "DEBUG: keep_backup(): calling robust_move(%s --> %s)\n", fname, buf);
+		if (robust_move(fname, buf) != 0) {
+			rsyserr(FERROR, errno, "keep_backup: failed (directory): %s -> \"%s\"",
+			full_fname(fname), buf);
+		} else if (!(unsupported_fileflags & (SF_RESTRICTED|SF_NOUNLINK))) {
+			// Strip SIP flags
+			strip_sip_flags(buf);
 		}
 		kept = 1;
 	}
@@ -333,7 +338,7 @@
 	if (!kept && preserve_links && S_ISLNK(file->mode)) {
 		const char *sl = F_SYMLINK(file);
 		if (safe_symlinks && unsafe_symlink(sl, fname)) {
-			if (verbose) {
+			if (verbose > 1) {
 				rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
 					full_fname(buf), sl);
 			}
@@ -341,6 +346,8 @@
 		} else {
 			do_unlink(buf);
 			if (do_symlink(sl, buf) < 0) {
+				if (verbose)
+					fprintf(stderr, "DEBUG: keep_backup: do_symlink(%s, %s) failed: %d\n", sl, buf, errno);
 				int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
 				if (errno == ENOENT && make_bak_dir(buf) == 0) {
 					if (do_symlink(sl, buf) < 0)
@@ -349,58 +356,122 @@
 						save_errno = 0;
 				}
 				if (save_errno) {
-					rsyserr(FERROR, save_errno, "link %s -> \"%s\"",
-						full_fname(buf), sl);
+					if (strlen(sl) > 0) {
+						rsyserr(FERROR, save_errno, "keep_backup: link %s -> \"%s\"",
+								full_fname(buf), sl);
+					} else {
+						fprintf(stderr, "DEBUG: keep_backup: do_symlink(%s, %s) failed: %d\n", sl, buf, save_errno);
+						kept = -2;
+					}
 				}
 			}
 			do_unlink(fname);
-			kept = 1;
+			kept++;
 		}
 	}
 #endif
 
 	if (!kept && !S_ISREG(file->mode)) {
-		rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
+		rprintf(FERROR, "make_bak: skipping non-regular file %s\n",
 			fname);
 		unmake_file(file);
-#ifdef SUPPORT_ACLS
-		uncache_tmp_acls();
-#endif
-#ifdef SUPPORT_XATTRS
-		uncache_tmp_xattrs();
-#endif
+//#ifdef SUPPORT_ACLS
+//		uncache_tmp_acls();
+//#endif
+//#ifdef SUPPORT_XATTRS
+//		uncache_tmp_xattrs();
+//#endif
 		return 1;
 	}
 
 	/* move to keep tree if a file */
 	if (!kept) {
-		if (robust_move(fname, buf) != 0) {
-			rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
+		if (verbose > 1)
+			fprintf(stderr, "keep_backup(): calling robust_move(%s --> %s)\n", fname, buf);
+		kept = robust_move(fname, buf) == 0;
+		if (!kept) {
+			rsyserr(FERROR, errno, "keep_backup: failed (file): %s -> \"%s\"",
 				full_fname(fname), buf);
 		} else if (sx.st.st_nlink > 1) {
 			/* If someone has hard-linked the file into the backup
 			 * dir, rename() might return success but do nothing! */
+			 if (verbose > 1)
+				fprintf(stderr, "keep_backup(): calling robust_unlink on %s because link count is > 1\n", full_fname(fname));
 			robust_unlink(fname); /* Just in case... */
 		}
 	}
+	
+	// OK, so we aren't planning to re-apply the xattrs on this file (we're only moving it) --
+	// why did we bother collecting and caching its xattrs in the first place?
 	preserve_xattrs = 0;
-	set_file_attrs(buf, file, NULL, fname, 0);
+	preserve_acls = 0;
+	if (kept > 0)
+		set_file_attrs(buf, file, NULL, fname, ATTRS_STRIP_RESTRICTED);
 	preserve_xattrs = save_preserve_xattrs;
+	preserve_acls = save_preserve_acls;
+
+	if (logfile_format_has_i)
+		log_non_transfer(fname, S_ISDIR(file->mode) ? S_IFDIR : S_IFREG, ITEM_ARCHIVED);
+
 	unmake_file(file);
-#ifdef SUPPORT_ACLS
-	uncache_tmp_acls();
-#endif
-#ifdef SUPPORT_XATTRS
-	uncache_tmp_xattrs();
-#endif
+//#ifdef SUPPORT_ACLS
+//	uncache_tmp_acls();
+//#endif
+//#ifdef SUPPORT_XATTRS
+//	uncache_tmp_xattrs();
+//#endif
 
 	if (verbose > 1) {
 		rprintf(FINFO, "backed up %s to %s\n",
 			fname, buf);
 	}
+
 	return 1;
 }
 
+void strip_sip_flags(const char *dirname)
+{
+	DIR *dir;
+	struct dirent *ent;
+	dir = opendir(dirname);
+	if (dir != NULL) {
+		while((ent = readdir(dir)) != NULL) {
+			BOOL skip = (ent->d_namlen == 1 && ent->d_name[0] == '.') || (ent->d_namlen == 2 && ent->d_name[0] == '.' && ent->d_name[1] == '.');
+			if (!skip) {
+				char *fileName = ent->d_name;
+				char *fullPath;
+				fullPath = malloc(MAXPATHLEN);
+				snprintf(fullPath, MAXPATHLEN, "%s/%s", dirname, fileName);
+
+				struct stat f;
+				int ret = lstat(fullPath, &f);
+				if (ret != 0) {
+					fprintf(stderr, "DEBUG: strip_sip_flags: Failed to stat %s: %d\n", fullPath, errno);
+				} else {
+					int fileflags = f.st_flags;
+					int newflags = fileflags & ~(SF_RESTRICTED|SF_NOUNLINK);
+					if (fileflags != newflags) {
+						if (S_ISLNK(f.st_mode)) {
+							ret = lchflags(fullPath, newflags);
+						} else {
+							ret = chflags(fullPath, newflags);
+						}
+						if (ret != 0)
+							fprintf(stderr, "DEBUG: strip_sip_flags: Failed to strip SIP flags from %s: %d\n", fullPath, errno);
+					}
+					
+					if (S_ISDIR(f.st_mode))
+						strip_sip_flags(fullPath);
+				}
+				free(fullPath);
+			}
+		}
+		closedir(dir);
+	} else {
+		fprintf(stderr, "DEBUG: strip_sip_flags: Failed to open %s: %d\n", dirname, errno);
+	}
+}
+
 
 /* main backup switch routine */
 int make_backup(const char *fname)
diff -Naur -X diff_ignore rsync-3.0.6_base/byteorder.h rsync/byteorder.h
--- rsync-3.0.6_base/byteorder.h	2008-03-01 15:01:41.000000000 -0500
+++ rsync/byteorder.h	2016-12-28 22:47:47.000000000 -0500
@@ -18,10 +18,9 @@
  * with this program; if not, visit the http://fsf.org website.
  */
 
-#undef CAREFUL_ALIGNMENT
-
 /* We know that the x86 can handle misalignment and has the same
  * byte order (LSB-first) as the 32-bit numbers we transmit. */
+/*
 #ifdef __i386__
 #define CAREFUL_ALIGNMENT 0
 #endif
@@ -29,6 +28,8 @@
 #ifndef CAREFUL_ALIGNMENT
 #define CAREFUL_ALIGNMENT 1
 #endif
+*/
+#define CAREFUL_ALIGNMENT 0
 
 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
 #define UVAL(buf,pos) ((uint32)CVAL(buf,pos))
@@ -40,6 +41,9 @@
 #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
 #define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
 #define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
+
+#define IVALu(buf,pos) IVAL(buf,pos)
+#define SIVALu(buf,pos,val) SIVAL(buf,pos,val)
 #else
 /* this handles things for architectures like the 386 that can handle
    alignment errors */
@@ -47,6 +51,72 @@
    WARNING: This section is dependent on the length of int32
    being correct. set CAREFUL_ALIGNMENT if it is not.
 */
+# ifdef AVOID_BYTEORDER_INLINE
+
 #define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
 #define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
+
+#define IVALu(buf,pos) IVAL(buf,pos)
+#define SIVALu(buf,pos,val) SIVAL(buf,pos,val)
+
+# else /* !AVOID_BYTEORDER_INLINE */
+
+static inline uint32
+IVALu(const uchar *buf, int pos)
+{
+	union {
+		const uchar *b;
+		const uint32 *num;
+	} u;
+	u.b = buf + pos;
+	return *u.num;
+}
+
+static inline void
+SIVALu(uchar *buf, int pos, uint32 val)
+{
+	union {
+		uchar *b;
+		uint32 *num;
+	} u;
+	u.b = buf + pos;
+	*u.num = val;
+}
+
+static inline uint32
+IVAL(const char *buf, int pos)
+{
+	return IVALu((uchar*)buf, pos);
+}
+
+static inline void
+SIVAL(char *buf, int pos, uint32 val)
+{
+	SIVALu((uchar*)buf, pos, val);
+}
+
+static inline int64
+IVAL64(const char *buf, int pos)
+{
+	union {
+		const char *b;
+		const int64 *num;
+	} u;
+	u.b = buf + pos;
+	return *u.num;
+}
+
+static inline void
+SIVAL64(char *buf, int pos, int64 val)
+{
+	union {
+		char *b;
+		int64 *num;
+	} u;
+	u.b = buf + pos;
+	*u.num = val;
+}
+
+# endif /* !AVOID_BYTEORDER_INLINE */
+
 #endif
diff -Naur -X diff_ignore rsync-3.0.6_base/checksum.c rsync/checksum.c
--- rsync-3.0.6_base/checksum.c	2009-01-17 16:41:35.000000000 -0500
+++ rsync/checksum.c	2018-09-17 15:35:28.000000000 -0400
@@ -26,6 +26,8 @@
 
 int csum_length = SHORT_SUM_LENGTH; /* initial value */
 
+// BOMBICH
+static time_t last_hb = 0;
 /*
   a simple 32 bit checksum that can be upadted from either end
   (inspired by Mark Adler's Adler-32 checksum)
@@ -58,7 +60,7 @@
 		md5_begin(&m);
 		md5_update(&m, (uchar *)buf, len);
 		if (checksum_seed) {
-			SIVAL(seedbuf, 0, checksum_seed);
+			SIVALu(seedbuf, 0, checksum_seed);
 			md5_update(&m, seedbuf, 4);
 		}
 		md5_result(&m, (uchar *)sum);
@@ -111,8 +113,11 @@
 	memset(sum, 0, MAX_DIGEST_LEN);
 
 	fd = do_open(fname, O_RDONLY, 0);
-	if (fd == -1)
+	if (fd == -1) {
+		if (errno != ENOENT)
+			fprintf(stderr, "[%s] file_checksum: Failed to open %s for reading: %s (%d)\n", who_am_i(), full_fname(fname), strerror(errno), errno);
 		return;
+	}
 
 	buf = map_file(fd, size, MAX_MAP_SIZE, CSUM_CHUNK);
 
@@ -120,6 +125,21 @@
 		md5_begin(&m);
 
 		for (i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
+#ifdef PARSEABLE_OUTPUT
+			if ((0)) {
+				if (last_hb == 0)
+					last_hb = time(NULL);
+				time_t now = time(NULL);
+				if (now - last_hb >= 5) {
+					last_hb = now;
+					rprintf(FINFO, "S;;;CHECKSUM;;;LEN;;;%lld;;;CF;;;%s\n", i + CSUM_CHUNK, fname);
+				}
+			} else {
+				if (((i + CSUM_CHUNK) % (1024*1024*100)) == 0) { // every 100MB
+					rprintf(FINFO, "S;;;CHECKSUM;;;LEN;;;%lld;;;CF;;;%s\n", i + CSUM_CHUNK, fname);
+				}
+			}
+#endif
 			md5_update(&m, (uchar *)map_ptr(buf, i, CSUM_CHUNK),
 				   CSUM_CHUNK);
 		}
diff -Naur -X diff_ignore rsync-3.0.6_base/cleanup.c rsync/cleanup.c
--- rsync-3.0.6_base/cleanup.c	2009-01-17 16:41:35.000000000 -0500
+++ rsync/cleanup.c	2015-11-09 21:57:54.000000000 -0500
@@ -99,6 +99,10 @@
 
 	SIGACTION(SIGUSR1, SIG_IGN);
 	SIGACTION(SIGUSR2, SIG_IGN);
+	fprintf(stderr, "DEBUG: exit_cleanup[%s]: cleanup_child_pid: %d. Error code: %d at %s:%d\n", who_am_i(), cleanup_child_pid, code, file, line);
+	if (code == RERR_SIGNAL)
+		fprintf(stderr, "Terminated by SIGINT, SIGTERM, or SIGHUP\n");
+	fflush(stderr);
 
 	if (exit_code) /* Preserve first error code when recursing. */
 		code = exit_code;
@@ -127,8 +131,10 @@
 		if (cleanup_child_pid != -1) {
 			int status;
 			int pid = wait_process(cleanup_child_pid, &status, WNOHANG);
+			//fprintf(stderr, "DEBUG: exit_cleanup[%s]: pid: %d\n", who_am_i(), pid);
 			if (pid == cleanup_child_pid) {
 				status = WEXITSTATUS(status);
+				//fprintf(stderr, "DEBUG: exit_cleanup[%s]: status: %d\n", who_am_i(), status);
 				if (status > code)
 					code = exit_code = status;
 			}
diff -Naur -X diff_ignore rsync-3.0.6_base/compat.c rsync/compat.c
--- rsync-3.0.6_base/compat.c	2009-06-18 17:30:46.000000000 -0400
+++ rsync/compat.c	2016-11-17 22:38:19.000000000 -0500
@@ -49,6 +49,7 @@
 extern int preserve_fileflags;
 extern int preserve_acls;
 extern int preserve_xattrs;
+extern int preserve_hfs_compression;
 extern int need_messages_from_generator;
 extern int delete_mode, delete_before, delete_during, delete_after;
 extern char *shell_cmd;
@@ -76,6 +77,7 @@
 #define CF_INC_RECURSE	 (1<<0)
 #define CF_SYMLINK_TIMES (1<<1)
 #define CF_SYMLINK_ICONV (1<<2)
+#define CF_HFS_COMPRESSION (1<<3)
 
 static const char *client_info;
 
@@ -262,6 +264,10 @@
 #ifdef ICONV_OPTION
 			compat_flags |= CF_SYMLINK_ICONV;
 #endif
+#ifdef SUPPORT_HFS_COMPRESSION
+			if (preserve_hfs_compression)
+				compat_flags |= CF_HFS_COMPRESSION;
+#endif
 			write_byte(f_out, compat_flags);
 		} else
 			compat_flags = read_byte(f_in);
@@ -271,6 +277,12 @@
 			receiver_symlink_times = am_server
 			    ? strchr(client_info, 'L') != NULL
 			    : !!(compat_flags & CF_SYMLINK_TIMES);
+#ifdef SUPPORT_HFS_COMPRESSION
+			// CF_HFS_COMPRESSION will be set on the remote side as long as preserve_hfs_compression > 1
+			if (preserve_hfs_compression && !(compat_flags & CF_HFS_COMPRESSION))
+				preserve_hfs_compression = 0;
+
+#endif
 		}
 #if defined HAVE_LUTIMES && defined HAVE_UTIMES
 		else
diff -Naur -X diff_ignore rsync-3.0.6_base/config.h rsync/config.h
--- rsync-3.0.6_base/config.h	2010-09-16 18:00:06.000000000 -0400
+++ rsync/config.h	2019-01-14 21:18:34.000000000 -0500
@@ -148,10 +148,10 @@
 /* #undef HAVE_HPUX_ACLS */
 
 /* Define to 1 if you have the <iconv.h> header file. */
-#define HAVE_ICONV_H 1
+//#define HAVE_ICONV_H 1
 
 /* Define to 1 if you have the `iconv_open' function. */
-/* #undef HAVE_ICONV_OPEN */
+#define HAVE_ICONV_OPEN 1
 
 /* Define to 1 if the system has the type `id_t'. */
 #define HAVE_ID_T 1
@@ -172,6 +172,7 @@
 #define HAVE_LANGINFO_H 1
 
 /* Define to 1 if you have the `lchmod' function. */
+/* #undef HAVE_LCHMOD */
 #define HAVE_LCHMOD 1
 
 /* Define to 1 if you have the `lchown' function. */
@@ -214,7 +215,7 @@
 /* #undef HAVE_LINUX_XATTRS */
 
 /* Define to 1 if you have the `locale_charset' function. */
-/* #undef HAVE_LOCALE_CHARSET */
+#define HAVE_LOCALE_CHARSET 1
 
 /* Define to 1 if you have the <locale.h> header file. */
 #define HAVE_LOCALE_H 1
@@ -525,7 +526,7 @@
 
 /* Define if you want the --iconv option. Specifing a value will set the
    default iconv setting (a NULL means no --iconv processing by default). */
-/* #undef ICONV_OPTION */
+#define ICONV_OPTION NULL
 
 /* true if you have IPv6 */
 #define INET6 1
@@ -602,7 +603,7 @@
 #define SIZEOF_INT64_T 8
 
 /* The size of `long', as computed by sizeof. */
-#define SIZEOF_LONG 8
+#define SIZEOF_LONG 4
 
 /* The size of `long long', as computed by sizeof. */
 #define SIZEOF_LONG_LONG 8
@@ -617,7 +618,7 @@
 #define SIZEOF_SHORT 2
 
 /* The size of `time_t', as computed by sizeof. */
-#define SIZEOF_TIME_T 8
+#define SIZEOF_TIME_T 4
 
 /* The size of `uint16_t', as computed by sizeof. */
 #define SIZEOF_UINT16_T 2
@@ -646,10 +647,10 @@
 #define TIME_WITH_SYS_TIME 1
 
 /* Define to 1 if you want rsync to make use of iconv_open() */
-/* #undef USE_ICONV_OPEN */
+#define USE_ICONV_OPEN 1
 
 /* String to pass to iconv() for the UTF-8 charset. */
-/* #undef UTF8_CHARSET */
+#define UTF8_CHARSET "UTF-8"
 
 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
    significant byte first (like Motorola and SPARC, unlike Intel). */
@@ -686,3 +687,6 @@
 
 /* Define to `int' if <sys/types.h> doesn't define. */
 /* #undef uid_t */
+
+// BOMBICH
+#define PARSEABLE_OUTPUT 1
diff -Naur -X diff_ignore rsync-3.0.6_base/exclude.c rsync/exclude.c
--- rsync-3.0.6_base/exclude.c	2009-01-17 16:41:35.000000000 -0500
+++ rsync/exclude.c	2014-12-06 21:12:18.000000000 -0500
@@ -36,6 +36,7 @@
 extern int sanitize_paths;
 extern int protocol_version;
 extern int module_id;
+extern int logfile_format_has_i;
 
 extern char curr_dir[];
 extern unsigned int curr_dir_len;
@@ -629,14 +630,18 @@
 	 * then it is stripped out by add_rule().  So as a special
 	 * case we add it back in here. */
 
-	if (verbose >= 2) {
+	if (verbose >= 2 || logfile_format_has_i) {
 		static char *actions[2][2]
 		    = { {"show", "hid"}, {"risk", "protect"} };
 		const char *w = who_am_i();
-		rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
-		    w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],
-		    name_is_dir ? "directory" : "file", name, ent->pattern,
-		    ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
+		if (logfile_format_has_i) {
+			log_non_transfer(name, name_is_dir ? S_IFDIR : S_IFREG, *w == 's' ? ITEM_EXCLUDED : ITEM_PROTECTED);
+		} else {
+			rprintf(code, "[%s] %sing %s %s because of pattern %s%s%s\n",
+				w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],
+				name_is_dir ? "directory" : "file", name, ent->pattern,
+				ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
+		}
 	}
 }
 
diff -Naur -X diff_ignore rsync-3.0.6_base/fileio.c rsync/fileio.c
--- rsync-3.0.6_base/fileio.c	2009-01-17 16:41:35.000000000 -0500
+++ rsync/fileio.c	2018-09-17 15:35:28.000000000 -0400
@@ -26,6 +26,7 @@
 #endif
 
 extern int sparse_files;
+extern int write_size;
 
 static char last_byte;
 static OFF_T sparse_seek = 0;
@@ -114,12 +115,12 @@
 
 	while (len > 0) {
 		int r1;
-		if (sparse_files > 0) {
+		if ((0) && sparse_files > 0) {
 			int len1 = MIN(len, SPARSE_WRITE_SIZE);
 			r1 = write_sparse(f, buf, len1);
 		} else {
 			if (!wf_writeBuf) {
-				wf_writeBufSize = WRITE_SIZE * 8;
+				wf_writeBufSize = write_size;
 				wf_writeBufCnt  = 0;
 				wf_writeBuf = new_array(char, wf_writeBufSize);
 				if (!wf_writeBuf)
@@ -183,8 +184,9 @@
 	if (len == 0)
 		return NULL;
 	if (len < 0) {
-		rprintf(FERROR, "invalid len passed to map_ptr: %ld\n",
-			(long)len);
+		fprintf(stderr, "rsync: invalid len passed to map_ptr: %ld. File size: %lld, offset: %lld\n", (long)len, map->file_size, offset);
+//		system("/usr/sbin/spindump rsync -file /Library/Logs/DiagnosticReports/rsync_special.txt");
+//		system("/usr/sbin/lsof | /usr/bin/grep rsync > /Library/Logs/DiagnosticReports/rsync.open_files.log");
 		exit_cleanup(RERR_FILEIO);
 	}
 
@@ -244,7 +246,7 @@
 	while (read_size > 0) {
 		nread = read(map->fd, map->p + read_offset, read_size);
 		if (nread <= 0) {
-			if (!map->status)
+			if (map->status == 0)
 				map->status = nread ? errno : ENODATA;
 			/* The best we can do is zero the buffer -- the file
 			 * has changed mid transfer! */
@@ -254,6 +256,8 @@
 		map->p_fd_offset += nread;
 		read_offset += nread;
 		read_size -= nread;
+		if (verbose > 1)
+			fprintf(stderr, "Read %.0f bytes\n", (double)map->p_fd_offset);
 	}
 
 	return map->p;
diff -Naur -X diff_ignore rsync-3.0.6_base/flist.c rsync/flist.c
--- rsync-3.0.6_base/flist.c	2019-01-14 13:23:05.000000000 -0500
+++ rsync/flist.c	2019-01-14 17:30:20.000000000 -0500
@@ -25,6 +25,13 @@
 #include "rounding.h"
 #include "io.h"
 
+// For statfs():
+//#include <sys/param.h>
+//#include <sys/mount.h>
+
+// For _PATH_RSRCFORKSPEC
+#include <sys/paths.h>
+
 extern int verbose;
 extern int am_root;
 extern int am_server;
@@ -48,6 +55,10 @@
 extern int preserve_gid;
 extern int preserve_acls;
 extern int preserve_xattrs;
+extern int preserve_hfs_compression;
+extern int fs_supports_native_xattrs;
+extern uid_t dest_file_owner;
+extern time_t max_age;
 extern int preserve_links;
 extern int preserve_hard_links;
 extern int preserve_devices;
@@ -74,6 +85,9 @@
 extern int unsort_ndx;
 extern struct stats stats;
 extern char *filesfrom_host;
+extern int detect_case_conflicts;
+extern int sparse_files;
+extern const char *srcRoot;
 
 extern char curr_dir[MAXPATHLEN];
 
@@ -131,6 +145,24 @@
 static void flist_sort_and_clean(struct file_list *flist, int strip_root);
 static void output_flist(struct file_list *flist);
 
+// BOMBICH
+struct timeval last_update;
+static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
+{
+	return (t2->tv_sec - t1->tv_sec) * 1000L
+		+ (t2->tv_usec - t1->tv_usec) / 1000;
+}
+
+int knownSIPProtectedDirectory(char *fname)
+{
+	int knownSIPRestrictedDirectory = strstr(fname, "/private/var/folders") != NULL ||
+	strstr(fname, "/private/var/db/ConfigurationProfiles") != NULL ||
+	strstr(fname, "Library/VoiceTrigger/SAT") != NULL ||
+	strstr(fname, "com.apple.mail/Data/DataVaults") != NULL;
+
+	return knownSIPRestrictedDirectory;
+}
+
 void init_flist(void)
 {
 	if (verbose > 4) {
@@ -144,7 +176,7 @@
 
 static int show_filelist_p(void)
 {
-	return verbose && xfer_dirs && !am_server && !inc_recurse;
+	return verbose > 1 && xfer_dirs && !am_server && !inc_recurse;
 }
 
 static void start_filelist_progress(char *kind)
@@ -162,18 +194,40 @@
 
 static void maybe_emit_filelist_progress(int count)
 {
+// BOMBICH
+#ifdef PARSEABLE_OUTPUT
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	unsigned long time_diff = msdiff(&last_update, &now);
+
+
+//	if (!inc_recurse && xfer_dirs && !am_server && !am_generator && (count % 100) == 0 && count > 0)
+	// Update every half second (max). We also want to update on the very first file in case
+	// the first item is a huge file and we're caculating a checksum
+	if (!inc_recurse && xfer_dirs && !am_server && !am_generator && (count == 0 || time_diff > 500)) {
+		last_update = now;
+		rprintf(FINFO, "S;;;BFL;;;NOF;;;%d\n", count);
+	}
+#else
 	if (do_progress && show_filelist_p() && (count % 100) == 0)
 		emit_filelist_progress(count);
+#endif
 }
 
 static void finish_filelist_progress(const struct file_list *flist)
 {
+// BOMBICH
+#ifdef PARSEABLE_OUTPUT
+	if (!inc_recurse)
+		rprintf(FINFO, "S;;;FTC;;;NOF;;;%d;;;BT;;;%.3f;;;TS;;;%s\n", flist->used, (double)stats.flist_buildtime/1000, human_num(stats.total_size));
+#else
 	if (do_progress) {
 		/* This overwrites the progress line */
 		rprintf(FINFO, "%d file%sto consider\n",
 			flist->used, flist->used == 1 ? " " : "s ");
 	} else
 		rprintf(FINFO, "done\n");
+#endif
 }
 
 void show_flist_stats(void)
@@ -379,7 +433,7 @@
 	if (!change_dir(dir, CD_NORMAL)) {
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
-		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
+		rsyserr(FERROR_XFER, errno, "change_pathname: change_dir %s failed", full_fname(dir));
 		if (dir != orig_dir)
 			change_dir(orig_dir, CD_NORMAL);
 		pathname = NULL;
@@ -408,7 +462,7 @@
 	static uint32 rdev_major;
 	static uid_t uid;
 	static gid_t gid;
-	static const char *user_name, *group_name;
+	static const char *user_name=NULL, *group_name=NULL;
 	static char lastname[MAXPATHLEN];
 	int first_hlink_ndx = -1;
 	int l1, l2;
@@ -436,6 +490,8 @@
 			xflags |= XMIT_SAME_FLAGS;
 		else
 			fileflags = F_FFLAGS(file);
+	} else {
+		fileflags = 0;
 	}
 #endif
 
@@ -556,19 +612,41 @@
 
 	if (first_hlink_ndx >= 0) {
 		write_varint(f, first_hlink_ndx);
+		// BOMBICH
+		stats.hard_links_not_copied++;
+		// make_file() adds every hard link's size to total_size,
+		// so decrement the unsent files here
+		stats.total_size -= F_LENGTH(file);
+		if (verbose > 1)
+			fprintf(stderr, "DEBUG: [%s] SENDFE: stats.total_size |%s|-%lu|%lld|\n", who_am_i(), full_fname(fname), (unsigned long)F_LENGTH(file), stats.total_size);
 		if (first_hlink_ndx >= first_ndx)
-			goto the_end;
+ 			goto the_end;
 	}
 
 	write_varlong30(f, F_LENGTH(file), 3);
 	if (!(xflags & XMIT_SAME_TIME)) {
-		if (protocol_version >= 30)
+		if (protocol_version >= 30) {
 			write_varlong(f, modtime, 4);
-		else
+#if SIZEOF_TIME_T < SIZEOF_INT64
+			if ((int64)(time_t)modtime != modtime) {
+				rprintf(FERROR_XFER,
+				    "Modification time value truncated on sender: \"%s\".\n",
+				    lastname);
+			}
+#endif
+		} else
 			write_int(f, modtime);
 	}
-	if (crtimes_ndx && !(xflags & XMIT_CRTIME_EQ_MTIME))
+	if (crtimes_ndx && !(xflags & XMIT_CRTIME_EQ_MTIME)) {
 		write_varlong(f, crtime, 4);
+#if SIZEOF_TIME_T < SIZEOF_INT64
+		if ((int64)(time_t)crtime != crtime) {
+			rprintf(FERROR_XFER,
+				"Create time value truncated on sender: \"%s\".\n",
+				lastname);
+		}
+#endif
+	}
 	if (!(xflags & XMIT_SAME_MODE))
 		write_int(f, to_wire_mode(mode));
 #ifdef SUPPORT_FILEFLAGS
@@ -581,7 +659,7 @@
 		else {
 			write_varint(f, uid);
 			if (xflags & XMIT_USER_NAME_FOLLOWS) {
-				int len = strlen(user_name);
+                int len = user_name ? strlen(user_name) : 0;
 				write_byte(f, len);
 				write_buf(f, user_name, len);
 			}
@@ -593,7 +671,7 @@
 		else {
 			write_varint(f, gid);
 			if (xflags & XMIT_GROUP_NAME_FOLLOWS) {
-				int len = strlen(group_name);
+                int len = group_name ? strlen(group_name) : 0;
 				write_byte(f, len);
 				write_buf(f, group_name, len);
 			}
@@ -652,8 +730,19 @@
   the_end:
 	strlcpy(lastname, fname, MAXPATHLEN);
 
-	if (S_ISREG(mode) || S_ISLNK(mode))
-		stats.total_size += F_LENGTH(file);
+	// BOMBICH
+	// Maintain stats on the sender side
+	if (S_ISDIR(mode))
+		stats.num_dirs++;
+	else if (S_ISREG(mode))
+		stats.num_reg_files++;
+	else if (S_ISLNK(mode))
+		stats.num_symlinks++;
+	else if (IS_DEVICE(mode))
+		stats.num_devices++;
+	else if (IS_SPECIAL(mode))
+		stats.num_special++;
+
 }
 
 static struct file_struct *recv_file_entry(struct file_list *flist,
@@ -776,6 +865,10 @@
 				linkname_len = strlen(F_SYMLINK(first)) + 1;
 			else
 				linkname_len = 0;
+			if (preserve_fileflags)
+				fileflags = F_FFLAGS(first);
+			else
+				fileflags = 0;
 			goto create_object;
 		}
 	}
@@ -788,8 +881,8 @@
 #if SIZEOF_TIME_T < SIZEOF_INT64
 			if (!am_generator && (int64)(time_t)modtime != modtime) {
 				rprintf(FERROR_XFER,
-				    "Time value of %s truncated on receiver.\n",
-				    lastname);
+				    "Modification time value truncated on receiver: %s.\n",
+				    full_fname(lastname));
 			}
 #endif
 		} else
@@ -801,8 +894,8 @@
 #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);
+				    "Create time value truncated on receiver: %s.\n",
+				    full_fname(lastname));
 			}
 #endif
 		} else
@@ -816,6 +909,8 @@
 #ifdef SUPPORT_FILEFLAGS
 	if (preserve_fileflags && !(xflags & XMIT_SAME_FLAGS))
 		fileflags = (uint32)read_int(f);
+	else if (!preserve_fileflags)
+		fileflags = 0;
 #endif
 
 	if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
@@ -961,6 +1056,8 @@
 #ifdef SUPPORT_FILEFLAGS
 	if (preserve_fileflags)
 		F_FFLAGS(file) = fileflags;
+	else
+		F_FFLAGS(file) = 0;
 #endif
 	if (preserve_uid)
 		F_OWNER(file) = uid;
@@ -1109,12 +1206,22 @@
 #endif
 #ifdef SUPPORT_XATTRS
 	if (preserve_xattrs)
-		receive_xattr(file, f );
+		receive_xattr(file, f);
 #endif
 
-	if (S_ISREG(mode) || S_ISLNK(mode))
+	if (S_ISREG(mode))
 		stats.total_size += file_length;
 
+	if (am_generator) {
+		// Maintain stats on the receiver side. This is for the benefit of the 
+		// generator -- the receive generator prints out non-transfer related
+		// progress info several times a second. Having the number of reg_files
+		// is helpful for progess indication
+		// BOMBICH
+		if (S_ISDIR(mode))
+			stats.num_dirs++;
+	}
+	
 	return file;
 }
 
@@ -1131,7 +1238,7 @@
 struct file_struct *make_file(const char *fname, struct file_list *flist,
 			      STRUCT_STAT *stp, int flags, int filter_level)
 {
-	static char *lastdir;
+	static char *lastdir = NULL;
 	static int lastdir_len = -1;
 	struct file_struct *file;
 	char thisname[MAXPATHLEN];
@@ -1148,6 +1255,7 @@
 		rprintf(FERROR_XFER, "skipping overly long name: %s\n", fname);
 		return NULL;
 	}
+	
 	clean_fname(thisname, 0);
 	if (sanitize_paths)
 		sanitize_path(thisname, thisname, "", 0, SP_DEFAULT);
@@ -1181,6 +1289,7 @@
 					full_fname(thisname));
 			} else
 #endif
+
 			{
 				enum logcode c = am_daemon && protocol_version < 28
 					       ? FERROR : FWARNING;
@@ -1189,9 +1298,14 @@
 					full_fname(thisname));
 			}
 		} else {
-			io_error |= IOERR_GENERAL;
-			rsyserr(FERROR_XFER, save_errno, "readlink_stat(%s) failed",
-				full_fname(thisname));
+			int knownSIPRestrictedDirectory = knownSIPProtectedDirectory(full_fname(thisname));
+			if (save_errno == EPERM && knownSIPRestrictedDirectory) {
+				fprintf(stderr, "DEBUG: [%s] SIP prevented access to %s\n", who_am_i(), full_fname(thisname));
+			} else {
+				io_error |= IOERR_GENERAL;
+				rsyserr(FERROR_XFER, save_errno, "[%s] make_file: readlink_stat(%s) failed",
+						who_am_i(), full_fname(thisname));
+			}
 		}
 		return NULL;
 	}
@@ -1237,6 +1351,52 @@
 				return NULL;
 	}
 
+	if (!S_ISDIR(st.st_mode) && max_age > 0 && cmp_time(max_age, st.st_mtime) > 0) {
+		rprintf(FERROR, "DEBUG: %s is over max-age\n", full_fname(thisname));
+		return NULL;
+	}
+
+
+#ifdef SUPPORT_HFS_COMPRESSION
+	// There are two ways to do this math. We can either take the uncompressed file size here and add that to total_size, then do the same in sender:send_file_entry. That gives us a value similar to what the Finder offers on a per-folder basis for folders containing lots of compressed files. That value is higher overall than the actual space consumed, though, so we can get total values > source disk usage, which could be confusing.
+	// The second option is to discard the size here and instead add the size of the decmpfs-related xattrs to total_size. Those values are more realistic, but unfortunately we don't know the size of those xattrs without reading them, and we don't want to read them if we're not actually copying them.
+	// With exclusions, the discrepancy between source size and source disk usage is likely to go unnoticied, so I'm choosing the Finder math method.
+	
+	// Sparse files make this yet more complicated... If this file appears to be a sparse file, we'll include its physical size in total_size rather than its logical size
+	off_t physicalSize, logicalSize, reportedFileSize = st.st_size;
+	
+	if (sparse_files) {
+		physicalSize = 512 * st.st_blocks;
+		logicalSize = st.st_size;
+		if ((logicalSize - physicalSize) > st.st_blksize)
+			reportedFileSize = physicalSize;
+		}
+
+	
+	// To use the non-Finder math method: Move this block of code below the next to discard the uncompressed file size and use only the xattr sizes instead
+	if (S_ISREG(st.st_mode)) {
+		stats.total_size += reportedFileSize;
+		if (verbose > 1)
+			fprintf(stderr, "DEBUG: [%s] MKFILE: stats.total_size |%s|+%llu|%lld|\n", who_am_i(), full_fname(thisname), reportedFileSize, stats.total_size);
+		if (reportedFileSize > stats.largest_file)
+			stats.largest_file = reportedFileSize;
+	}
+	
+	if (st.st_flags & UF_COMPRESSED) {
+		if (verbose > 1)
+			fprintf(stderr, "make_file(%s): Handling compressed file: %s\n", who_am_i(), thisname);
+		if (preserve_hfs_compression > 0) {
+			st.st_size = 0;
+		} else {
+			// If the sender's filesystem supports compression, then we'll be able to send the decompressed data fork
+			// and the decmpfs xattr will be hidden (not sent). As such, we need to strip the compression flag.
+			if (verbose > 1)
+				fprintf(stderr, "make_file(%s): Stripping UF_COMPRESSED from st.st_flags for %s\n", who_am_i(), thisname);
+			st.st_flags &= ~UF_COMPRESSED;
+		}
+	}
+#endif
+
   skip_filters:
 
 	/* Only divert a directory in the main transfer. */
@@ -1287,6 +1447,11 @@
 		extra_len += EXTRA_LEN;
 #endif
 
+	// BOMBICH
+	// Prime the output if we're calculating checksums
+	if (always_checksum && st.st_size > 10000000 && am_sender && S_ISREG(st.st_mode) && inc_recurse)
+		rprintf(FINFO, "S;;;CP;;;CF;;;%s\n", thisname);
+
 	if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
 		file_checksum(thisname, tmp_sum, st.st_size);
 		if (sender_keeps_checksum)
@@ -1349,7 +1514,12 @@
 		F_FFLAGS(file) = st.st_flags;
 #endif
 	if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
+	{
+		if (dest_file_owner != 0)
+			F_OWNER(file) = dest_file_owner;
+		else
 		F_OWNER(file) = st.st_uid;
+	}
 	if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
 		F_GROUP(file) = st.st_gid;
 	if (crtimes_ndx)
@@ -1399,6 +1569,19 @@
 	if (!file)
 		return NULL;
 
+//	rprintf(FINFO, "make_file (%s): %s\n", who_am_i());
+//	// BOMBICH
+//	if (S_ISDIR(file->mode))
+//		stats.num_dirs++;
+//	else if (S_ISREG(file->mode))
+//		stats.num_reg_files++;
+//	else if (S_ISLNK(file->mode))
+//		stats.num_symlinks++;
+//	else if (IS_DEVICE(file->mode))
+//		stats.num_devices++;
+//	else if (IS_SPECIAL(file->mode))
+//		stats.num_special++;
+//
 	if (chmod_modes && !S_ISLNK(file->mode))
 		file->mode = tweak_mode(file->mode, chmod_modes);
 
@@ -1420,7 +1603,7 @@
 			symlink_name = F_SYMLINK(file);
 			symlink_len = strlen(symlink_name);
 			if (symlink_len == 0) {
-				io_error |= IOERR_GENERAL;
+				//io_error |= IOERR_GENERAL; // BOMBICH: I don't want an invalid symlink to prevent deletions from occurring
 				f_name(file, fbuf);
 				rprintf(FERROR_XFER,
 				    "skipping symlink with 0-length value: %s\n",
@@ -1494,10 +1677,33 @@
 #ifdef SUPPORT_XATTRS
 		if (preserve_xattrs) {
 			sx.st.st_mode = file->mode;
+			if (verbose > 1 && preserve_fileflags)
+				fprintf(stderr, "Setting sx.st.st_flags to %d\n", F_FFLAGS(file));
+			if (preserve_fileflags)
+				sx.st.st_flags = F_FFLAGS(file);
 			sx.xattr = NULL;
+			
+			if (one_file_system && (file->flags & FLAG_MOUNT_DIR)) {
+				fprintf(stderr, "DEBUG: [%s] Skipping xattrs on %s because it lies across device boundaries\n", who_am_i(), full_fname(fname));
+				sx.xattr = new(item_list);
+				sx.xattr->items = NULL;
+				sx.xattr->count = 0;
+				sx.xattr->malloced = 0;
+			} else
+			
 			if (get_xattr(fname, &sx) < 0) {
-				io_error |= IOERR_GENERAL;
-				return NULL;
+				// Don't bail on an entire directory for xattr problems!
+				if (S_ISDIR(file->mode)) {
+					sx.xattr = new(item_list);
+					sx.xattr->items = NULL;
+					sx.xattr->count = 0;
+					sx.xattr->malloced = 0;
+					rprintf(FERROR, "DEBUG: send_file_name: get_xattr() failed for directory: %s. Proceeding anyway...\n",
+						full_fname(fbuf));
+				} else {
+					io_error |= IOERR_GENERAL;
+					return NULL;
+				}
 			}
 		}
 #endif
@@ -1510,6 +1716,8 @@
 
 #ifdef SUPPORT_ACLS
 		if (preserve_acls && !S_ISLNK(file->mode)) {
+//			fprintf(stderr, "DEBUG: send_f_name: Calling send_acl() for %s\n", f_name(file, NULL));
+//			send_acl(fbuf, &sx, f);
 			send_acl(&sx, f);
 			free_acl(&sx);
 		}
@@ -1517,6 +1725,8 @@
 #ifdef SUPPORT_XATTRS
 		if (preserve_xattrs) {
 			F_XATTR(file) = send_xattr(&sx, f);
+			if (verbose)
+				fprintf(stderr, "DEBUG: send_f_name: f: %#x, ndx: %d |%s\n", F_FFLAGS(file), F_XATTR(file), f_name(file, NULL));
 			free_xattr(&sx);
 		}
 #endif
@@ -1672,11 +1882,12 @@
 			is_dir ? "directory" : "file", full_fname(fname));
 	} else {
 		io_error |= IOERR_GENERAL;
-		rsyserr(FERROR_XFER, errno, "link_stat %s failed",
-			full_fname(fname));
+		rsyserr(FERROR_XFER, errno, "[%s]link_stat: %s failed",
+			who_am_i(), full_fname(fname));
 	}
 }
 
+
 /* This function is normally called by the sender, but the receiving side also
  * calls it from get_dirlist() with f set to -1 so that we just construct the
  * file list in memory without sending it over the wire.  Also, get_dirlist()
@@ -1692,6 +1903,7 @@
 	int divert_dirs = (flags & FLAG_DIVERT_DIRS) != 0;
 	int start = flist->used;
 	int filter_level = f == -2 ? SERVER_FILTERS : ALL_FILTERS;
+	int saved_filter_level = filter_level;
 
 	assert(flist != NULL);
 
@@ -1701,29 +1913,103 @@
 				interpret_stat_error(fbuf, True);
 			return;
 		}
-		io_error |= IOERR_GENERAL;
-		rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf));
+		int knownSIPRestrictedDirectory = knownSIPProtectedDirectory(full_fname(fbuf));
+		if (errno == EPERM && knownSIPRestrictedDirectory) {
+			fprintf(stderr, "DEBUG: [%s] SIP prevented access to %s\n", who_am_i(), full_fname(fbuf));
+		} else {
+			if (strstr(full_fname(fbuf), "com.apple.TCC") == NULL) // Don't suspend deletions if this is the only item we can't copy
+				io_error |= IOERR_GENERAL;
+			rsyserr(FERROR_XFER, errno, "[%s]send_directory: opendir %s failed", who_am_i(), full_fname(fbuf));
+		}
 		return;
 	}
 
 	p = fbuf + len;
-	if (len != 1 || *fbuf != '/')
+	if (len == 1 && *fbuf == '/')
+		remainder = MAXPATHLEN - 1;
+	else if (len < MAXPATHLEN-1) {
 		*p++ = '/';
-	*p = '\0';
-	remainder = MAXPATHLEN - (p - fbuf);
+		*p = '\0';
+		remainder = MAXPATHLEN - (len + 1);
+	} else
+		remainder = 0;
 
 	for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
+//		// Simulate IO error on the source
+//		int rando = rand();
+//		if (am_sender && (rando % 100) == 0) {
+//			errno = EIO;
+//			break;
+//		}
+		
 		char *dname = d_name(di);
 		if (dname[0] == '.' && (dname[1] == '\0'
 		    || (dname[1] == '.' && dname[2] == '\0')))
 			continue;
-		if (strlcpy(p, dname, remainder) >= remainder) {
+		unsigned name_len = strlcpy(p, dname, remainder);
+		if (name_len >= remainder) {
+			char save = fbuf[len];
+			fbuf[len] = '\0';
 			io_error |= IOERR_GENERAL;
 			rprintf(FERROR_XFER,
-				"cannot send long-named file %s\n",
-				full_fname(fbuf));
+				"send_directory: filename overflows max-path len by %u: %s/%s: (%d)\n",
+				name_len - remainder + 1, full_fname(fbuf), dname, ENAMETOOLONG);
+			fbuf[len] = save;
 			continue;
 		}
+		
+		// If the filename is nearly 255 characters, it could be a mangled
+		// name. In that case, we need to call getattrlist to determine
+		// ATTR_CMN_NAME
+		if (strlen(dname) >= 250) {
+			if (verbose > 1)
+				fprintf(stderr, "strlen(%s): %lu\n", dname, (unsigned long)strlen(dname));
+			char *realname;
+			struct attrlist attrs;
+			struct {
+				u_int32_t len;
+				attrreference_t obj_name_ref;
+				char obj_name_buf[769]; /* Large enough for 255 3-byte characters + '\0' */
+			} attrData;
+			
+			bzero(&attrs, sizeof(attrs));
+			attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
+			attrs.commonattr = ATTR_CMN_NAME;
+
+			bzero(&attrData, sizeof(attrData));
+			int result = getattrlist(fbuf, &attrs, &attrData, sizeof(attrData), FSOPT_NOFOLLOW);
+			if (result == 0) {
+				/* Pick out the [UTF-8 format] name: */
+				realname = ((char *)(&attrData.obj_name_ref) + attrData.obj_name_ref.attr_dataoffset);
+				realname[attrData.obj_name_ref.attr_length] = '\0';
+				dname = realname;
+
+				name_len = strlcpy(p, realname, remainder);
+				if (name_len >= remainder) {
+					char save = fbuf[len];
+					fbuf[len] = '\0';
+					io_error |= IOERR_GENERAL;
+					rprintf(FERROR_XFER,
+						"send_directory: filename overflows max-path len by %u: %s/%s: (%d)\n",
+						name_len - remainder + 1, full_fname(fbuf), realname, ENAMETOOLONG);
+					fbuf[len] = save;
+					continue;
+				}
+
+				if (verbose > 1)
+					fprintf(stderr, "chars: %d, bytes: %lu\n", (int)mbstowcs(0, realname, 0), (unsigned long)strlen(dname));
+
+			} else {
+				fprintf(stderr, "send_directory: getattrlist failed for \"%s\": (%d)\n", fbuf, errno);
+				// continue with dname
+
+				int n;
+				for(n=0; p[n] != 0x0000; n++)
+					printf("%x", p[n]);
+			}
+		}
+
+
 		if (dname[0] == '\0') {
 			io_error |= IOERR_GENERAL;
 			rprintf(FERROR_XFER,
@@ -1732,14 +2018,53 @@
 			continue;
 		}
 
+		// BOMBICH
+		// If this is a ._ file and f == -2, set filter_level to NO_FILTERS
+		// We can't simply protect ._ files, that would prevent otherwise-empty
+		// folders from being deleted. We can't allow a general delete because
+		// in some cases (HFS --> FAT32 for example), the AppleDouble file will
+		// not exist on the source but will exist on the destination 
+		if (f == -2 && dname[0] == '.' && dname[1] == '_') {
+			if (verbose > 1)
+				fprintf(stderr, "send_directory: Setting filter_level to NO_FILTERS for %s\n", dname);
+			filter_level = NO_FILTERS;
+		}
+		
 		send_file_name(f, flist, fbuf, NULL, flags, filter_level);
+		filter_level = saved_filter_level;
+		
+#ifdef PARSEABLE_OUTPUT
+		// If we're using incremental recursion and this directory has a lot of items in it, update the user
+		if (am_sender && inc_recurse && flist->used - start > 128) {
+			struct timeval now;
+			gettimeofday(&now, NULL);
+			unsigned long time_diff = msdiff(&last_update, &now);
+			
+			if (time_diff > 500) {
+				last_update = now;
+				rprintf(FINFO, "S;;;CP;;;CF;;;%s\n", fbuf);
+			}
+		} else {
+			heartbeat(fbuf);
+		}
+#endif
 	}
 
 	fbuf[len] = '\0';
-
+	
 	if (errno) {
 		io_error |= IOERR_GENERAL;
-		rsyserr(FERROR_XFER, errno, "readdir(%s)", full_fname(fbuf));
+		rsyserr(FERROR_XFER, errno, "[%s]send_directory: readdir(%s)", who_am_i(), full_fname(fbuf));
+		// TODO: This is the right time but the wrong place to send the IO error message.
+		// If we're incrementally recursing in a deep directory, the generator could start
+		// deleting before the IO error message is received, causing data loss
+//		if (!ignore_errors)
+//			send_msg_int(MSG_IO_ERROR, io_error);
+		if ((fbuf[0] == '.' && fbuf[1] == '\0') || inc_recurse) {
+			fprintf(stderr, inc_recurse ? "send_directory: Bailing due to IO error during incremental recursion\n" : "send_directory: Bailing due to IO error on the root folder\n");
+			closedir(d);
+			exit_cleanup(RERR_FILESELECT);
+		}
 	}
 
 	closedir(d);
@@ -1910,6 +2235,18 @@
 				interpret_stat_error(fbuf, True);
 				continue;
 			}
+
+#ifdef SUPPORT_HFS_COMPRESSION
+		if (st.st_flags & UF_COMPRESSED) {
+			if (preserve_hfs_compression > 0) {
+				st.st_size = 0;
+			} else
+				// If the sender's filesystem supports compression, then we'll be able to send the decompressed data fork
+				// and the decmpfs xattr will be hidden (not sent). As such, we need to strip the compression flag.
+				st.st_flags &= ~UF_COMPRESSED;
+		}
+#endif
+
 			send_file_name(f, flist, fbuf, &st, FLAG_TOP_DIR | flags, ALL_FILTERS);
 		} else
 			send_file_name(f, flist, fbuf, NULL, FLAG_TOP_DIR | flags, ALL_FILTERS);
@@ -2034,12 +2371,36 @@
 		     | (eol_nulls || reading_remotely ? RL_EOL_NULLS : 0);
 	int implied_dot_dir = 0;
 
-	rprintf(FLOG, "building file list\n");
+	// BOMBICH -- I'd rather not see this message in the log file
+	//rprintf(FLOG, "building file list\n");
 	if (show_filelist_p())
 		start_filelist_progress("building file list");
-	else if (inc_recurse && verbose && !am_server)
+	else if (inc_recurse && verbose > 1 && !am_server)
 		rprintf(FCLIENT, "sending incremental file list\n");
 
+	stats.num_xattrs = 0;
+
+	// BOMBICH
+	stats.num_dirs = 0;
+	stats.num_reg_files = 0;
+	stats.num_symlinks = 0;
+	stats.num_devices = 0;
+	stats.num_special = 0;
+	stats.hard_links_not_copied = 0;
+
+//	// If we are doing incremental recursion, report the amount of space used on the source
+//	// Unfortunately, we don't know the size of compressed xattrs unless we read them, and that
+//	// incurs a significant performance penalty. As a result, however much data is compressed
+//	// would not be reported as processed
+//#ifdef PARSEABLE_OUTPUT
+//	if (inc_recurse) {
+//		struct statfs fsb;
+//		
+//		if (statfs(argv[0], &fsb) == 0)
+//			rprintf(FINFO, "S;;;FTC;;;TS;;;%llu\n", ((unsigned long long)fsb.f_blocks - (unsigned long long)fsb.f_bavail) * (unsigned)fsb.f_bsize);
+//	}
+//#endif
+//
 	start_write = stats.total_written;
 	gettimeofday(&start_tv, NULL);
 
@@ -2061,7 +2422,7 @@
 	disable_buffering = io_start_buffering_out(f);
 	if (filesfrom_fd >= 0) {
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
-			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
+			rsyserr(FERROR_XFER, errno, "send_file_list: change_dir %s failed",
 				full_fname(argv[0]));
 			exit_cleanup(RERR_FILESELECT);
 		}
@@ -2202,11 +2563,22 @@
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
 			io_error |= IOERR_GENERAL;
-			rsyserr(FERROR_XFER, errno, "link_stat %s failed",
-				full_fname(fbuf));
+			rsyserr(FERROR_XFER, errno, "[%s]send_file_list: link_stat %s failed",
+				who_am_i(), full_fname(fbuf));
 			continue;
 		}
 
+#ifdef SUPPORT_HFS_COMPRESSION
+		if (st.st_flags & UF_COMPRESSED) {
+			if (preserve_hfs_compression > 0) {
+				st.st_size = 0;
+			} else
+				// If the sender's filesystem supports compression, then we'll be able to send the decompressed data fork
+				// and the decmpfs xattr will be hidden (not sent). As such, we need to strip the compression flag.
+				st.st_flags &= ~UF_COMPRESSED;
+		}
+#endif
+
 		/* A dot-dir should not be excluded! */
 		if (name_type != DOTDIR_NAME
 		 && is_excluded(fbuf, S_ISDIR(st.st_mode) != 0, ALL_FILTERS))
@@ -2272,7 +2644,10 @@
 		idev_destroy();
 #endif
 
+// BOMBICH
+#ifndef PARSEABLE_OUTPUT
 	if (show_filelist_p())
+#endif
 		finish_filelist_progress(flist);
 
 	gettimeofday(&end_tv, NULL);
@@ -2348,13 +2723,18 @@
 	int64 start_read;
 	int save_verbose = verbose;
 
-	if (!first_flist)
-		rprintf(FLOG, "receiving file list\n");
+	// BOMBICH -- I don't want extraneous items going to the log
+	if (verbose > 1)
+		rprintf(FINFO, "receiving file list\n");
 	if (show_filelist_p())
 		start_filelist_progress("receiving file list");
-	else if (inc_recurse && verbose && !am_server && !first_flist)
+	else if (inc_recurse && verbose > 1 && !am_server && !first_flist)
 		rprintf(FCLIENT, "receiving incremental file list\n");
 
+	// BOMBICH
+	if (!first_flist) 
+		stats.num_dirs = 0;
+	
 	start_read = stats.total_read;
 
 #ifdef SUPPORT_HARD_LINKS
@@ -2902,7 +3282,9 @@
 int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
 {
 	int dif;
+	int case_conflict = 0;
 	const uchar *c1, *c2;
+	uchar ch1, ch2;
 	enum fnc_state state1, state2;
 	enum fnc_type type1, type2;
 	enum fnc_type t_path = protocol_version >= 29 ? t_PATH : t_ITEM;
@@ -3006,15 +3388,35 @@
 			case s_TRAILING:
 				found_prefix = 1;
 				if (!*c1)
-					return 0;
+					return (detect_case_conflicts > 1 && dif == 0 && case_conflict == 0) ? 1 : 0;
 				type2 = t_ITEM;
 				break;
 			}
 			if (type1 != type2)
 				return type1 == t_PATH ? 1 : -1;
 		}
-	} while ((dif = (int)*c1++ - (int)*c2++) == 0);
+		ch1 = *c1++;
+		ch2 = *c2++;
+		if (detect_case_conflicts > 1) {
+			int ch1Upper = isupper(ch1);
+			int ch2Upper = isupper(ch2);
+			if (ch1Upper)
+				ch1 = tolower(ch1);
+			if (ch2Upper)
+				ch2 = tolower(ch2);
+			
+			if (case_conflict == 0) {
+				if ((int)ch1 - (int)ch2 == 0 && ch1Upper != ch2Upper) {
+					case_conflict = 1;
+				}
+			}
+		}
+	} while ((dif = (int)ch1 - (int)ch2) == 0);
 
+	if (detect_case_conflicts > 1 && dif == 0 && case_conflict == 0) {
+		return 1; // No match if we didn't find a case conflict
+	}
+	
 	return dif;
 }
 
diff -Naur -X diff_ignore rsync-3.0.6_base/generator.c rsync/generator.c
--- rsync-3.0.6_base/generator.c	2009-06-18 17:30:50.000000000 -0400
+++ rsync/generator.c	2019-01-14 17:30:40.000000000 -0500
@@ -22,6 +22,8 @@
 
 #include "rsync.h"
 #include "ifuncs.h"
+// For _PATH_RSRCFORKSPEC
+#include <sys/paths.h>
 
 extern int verbose;
 extern int dry_run;
@@ -38,15 +40,21 @@
 extern int keep_dirlinks;
 extern int preserve_acls;
 extern int preserve_xattrs;
+extern int preserve_hfs_compression;
+extern int fs_supports_hfs_compression;
+extern int fs_supports_native_xattrs;
+extern uid_t receiver_uid;
+extern int replace_dirs_with_diff_type;
+extern int delete_deleted;
 extern int preserve_links;
 extern int preserve_devices;
 extern int preserve_specials;
 extern int preserve_fileflags;
 extern int preserve_hard_links;
 extern int preserve_executability;
-extern int preserve_fileflags;
 extern int preserve_perms;
 extern int preserve_times;
+extern int sparse_files;
 extern int force_change;
 extern int uid_ndx;
 extern int gid_ndx;
@@ -105,6 +113,13 @@
 extern int backup_suffix_dels_len;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+extern int detect_case_conflicts;
+
+extern int write_size;
+extern const char *srcRoot;
+extern const char *dstRoot;
+int64 sparseDataCopied = 0;
+int sparseFilesCopied = 0;
 
 int ignore_perishable = 0;
 int non_perishable_cnt = 0;
@@ -121,6 +136,16 @@
 static int need_retouch_dir_times;
 static int need_retouch_dir_perms;
 static const char *solo_file = NULL;
+  
+// BOMBICH
+struct timeval last_update;
+static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
+{
+	return (t2->tv_sec - t1->tv_sec) * 1000L
+		+ (t2->tv_usec - t1->tv_usec) / 1000;
+}
+
+extern time_t last_hb;
 
 /* For calling delete_item() and delete_dir_contents(). */
 #define DEL_NO_UID_WRITE 	(1<<0) /* file/dir has our uid w/o write perm */
@@ -131,6 +156,7 @@
 #define DEL_FOR_SYMLINK 	(1<<5) /* making room for a replacement symlink */
 #define DEL_FOR_DEVICE		(1<<6) /* making room for a replacement device */
 #define DEL_FOR_SPECIAL 	(1<<7) /* making room for a replacement special */
+#define DEL_APPLE_DOUBLES	(1<<8) /* BOMBICH */
 
 #define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
 
@@ -177,6 +203,21 @@
 			fbuf, (int)mode, (int)flags);
 	}
 
+	// BOMBICH -- If we're replacing an item, delete everything in a directory too to avoid the annoying errors (e.g. if the user didn't choose the delete option)
+	if (replace_dirs_with_diff_type && flags & DEL_MAKE_ROOM)
+		flags |= DEL_RECURSE;
+
+	heartbeat(fbuf);
+		
+	// BOMBICH
+	// If an entire folder's contents are going to be archived, just move the whole folder
+	if (S_ISDIR(mode) && make_backups > 0 && delete_deleted == 0) {
+		ok = safe_delete(fbuf);
+		if (ok)
+			ret = DR_SUCCESS;
+		goto check_ret;
+	}	
+
 	if (flags & DEL_NO_UID_WRITE)
 		do_chmod(fbuf, mode | S_IWUSR, NO_FFLAGS);
 
@@ -193,6 +234,10 @@
 				make_mutable(fbuf, st.st_mode, st.st_flags, force_change);
 		}
 #endif
+
+		// BOMBICH -- If we're deleting an entire folder, override the ._ protect rule
+		flags |= DEL_APPLE_DOUBLES;
+
 		ignore_perishable = 1;
 		/* If DEL_RECURSE is not set, this just reports emptiness. */
 		ret = delete_dir_contents(fbuf, flags);
@@ -212,7 +257,7 @@
 	if (S_ISDIR(mode)) {
 		what = "rmdir";
 		ok = do_rmdir(fbuf) == 0;
-	} else if (make_backups > 0 && (backup_dir_dels || !is_backup_file(fbuf))) {
+	} else if (delete_deleted == 0 && make_backups > 0 && (backup_dir_dels || !is_backup_file(fbuf))) {
 		what = "make_backup";
 		ok = safe_delete(fbuf);
 	} else {
@@ -221,17 +266,17 @@
 	}
 
 	if (ok) {
-		if (!(flags & DEL_MAKE_ROOM))
+		if (!(flags & DEL_MAKE_ROOM) && make_backups == 0)
 			log_delete(fbuf, mode);
 		ret = DR_SUCCESS;
 	} else {
 		if (S_ISDIR(mode) && errno == ENOTEMPTY) {
-			rprintf(FINFO, "cannot delete non-empty directory: %s\n",
-				fbuf);
+			rprintf(FERROR, "cannot delete non-empty directory: %s\n",
+				full_fname(fbuf));
 			ret = DR_NOT_EMPTY;
 		} else if (errno != ENOENT) {
-			rsyserr(FERROR, errno, "delete_file: %s(%s) failed",
-				what, fbuf);
+			rsyserr(FERROR, errno, "delete_item: %s(%s) failed",
+				what, full_fname(fbuf));
 			ret = DR_FAILURE;
 		} else {
 			deletion_count--;
@@ -251,7 +296,7 @@
 		default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
 		}
 		rprintf(FERROR_XFER, "could not make way for new %s: %s\n",
-			desc, fbuf);
+			desc, full_fname(fbuf));
 	}
 	return ret;
 }
@@ -269,6 +314,7 @@
 	void *save_filters;
 	int j, dlen;
 	char *p;
+	int ignore_filters = (flags & DEL_APPLE_DOUBLES) > 0 ? 1 : 0; // BOMBICH
 
 	if (verbose > 3) {
 		rprintf(FINFO, "delete_dir_contents(%s) flags=%d\n",
@@ -279,7 +325,7 @@
 	save_filters = push_local_filters(fname, dlen);
 
 	non_perishable_cnt = 0;
-	dirlist = get_dirlist(fname, dlen, 0);
+	dirlist = get_dirlist(fname, dlen, ignore_filters);
 	ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
 
 	if (!dirlist->used)
@@ -335,8 +381,8 @@
 	pop_local_filters(save_filters);
 
 	if (ret == DR_NOT_EMPTY) {
-		rprintf(FINFO, "cannot delete non-empty directory: %s\n",
-			fname);
+		rprintf(FERROR, "cannot delete non-empty directory: %s\n",
+			full_fname(fname));
 	}
 	return ret;
 }
@@ -508,7 +554,10 @@
 	if (allowed_lull)
 		maybe_send_keepalive();
 
-	if (io_error && !ignore_errors) {
+	heartbeat(fbuf);
+
+	// Ignore "file vanished" IO errors by default WRT deleting items on the target -- if a source file is damaged/unreadable, we'll get an IOERR_GENERAL instead
+	if ((io_error & ~IOERR_VANISHED) && !ignore_errors) {
 		if (already_warned)
 			return;
 		rprintf(FINFO,
@@ -534,7 +583,9 @@
 
 	/* If an item in dirlist is not found in flist, delete it
 	 * from the filesystem. */
-	for (i = dirlist->used; i--; ) {
+	// BOMBICH
+	//for (i = dirlist->used; i--; ) {
+	for (i = 0; i < dirlist->used; i++ ) {
 		struct file_struct *fp = dirlist->files[i];
 		if (!F_IS_ACTIVE(fp))
 			continue;
@@ -591,8 +642,17 @@
 		}
 
 		if (verbose > 1 && file->flags & FLAG_TOP_DIR)
-			rprintf(FINFO, "deleting in %s\n", fbuf);
+			rprintf(FINFO, "deleting in %s\n", full_fname(fbuf));
 
+#ifdef PARSEABLE_OUTPUT
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		unsigned long time_diff = msdiff(&last_update, &now);
+		if (time_diff > 100) {
+			last_update = now;
+			rprintf(FINFO, "S;;;DELETE;;;PROG;;;%d;;;CF;;;%s\n", (j * 100) / cur_flist->used, fbuf);
+		}
+#endif
 		if (link_stat(fbuf, &st, keep_dirlinks) < 0
 		 || !S_ISDIR(st.st_mode))
 			continue;
@@ -607,6 +667,9 @@
 
 int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
 {
+	if (verbose > 1)
+		fprintf(stderr, "unchanged_attrs(%s): %s\n", who_am_i(), full_fname(fname));
+
 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
 	if (S_ISLNK(file->mode)) {
 		;
@@ -623,7 +686,7 @@
 		return 0;
 
 #ifdef SUPPORT_FILEFLAGS
-	if (preserve_fileflags && !S_ISLNK(file->mode) && sxp->st.st_flags != F_FFLAGS(file))
+	if (preserve_fileflags /*&& !S_ISLNK(file->mode)*/ && sxp->st.st_flags != F_FFLAGS(file))
 		return 0;
 #endif
 
@@ -664,6 +727,8 @@
 	     stat_x *sxp, int32 iflags, uchar fnamecmp_type,
 	     const char *xname)
 {
+	if (verbose > 1)
+		fprintf(stderr, "itemize(%s): (%d) %s, src flags: %#x, dst flags: %#x\n", who_am_i(), statret, full_fname(fnamecmp), F_FFLAGS(file), sxp->st.st_flags);
 	if (statret >= 0) { /* A from-dest-dir statret can == 1! */
 		int keep_time = !preserve_times ? 0
 		    : S_ISDIR(file->mode) ? preserve_times > 1 :
@@ -706,7 +771,7 @@
 		    && sxp->st.st_gid != (gid_t)F_GROUP(file))
 			iflags |= ITEM_REPORT_GROUP;
 #ifdef SUPPORT_FILEFLAGS
-		if (preserve_fileflags && !S_ISLNK(file->mode)
+		if (preserve_fileflags /*&& !S_ISLNK(file->mode)*/
 		 && sxp->st.st_flags != F_FFLAGS(file))
 			iflags |= ITEM_REPORT_FFLAGS;
 #endif
@@ -722,14 +787,20 @@
 		if (preserve_xattrs) {
 			if (!XATTR_READY(*sxp))
 				get_xattr(fnamecmp, sxp);
-			if (xattr_diff(file, sxp, 1))
+			if (xattr_diff(file, sxp, 1)) {
 				iflags |= ITEM_REPORT_XATTR;
+				if (verbose > 1)
+					fprintf(stderr, "itemize(%s): xattrs differ on (%s)\n", who_am_i(), full_fname(fnamecmp));
+			}
 		}
 #endif
 	} else {
 #ifdef SUPPORT_XATTRS
-		if (preserve_xattrs && xattr_diff(file, NULL, 1))
+		if (preserve_xattrs && xattr_diff(file, NULL, 1)) {
+			if (verbose > 1)
+				fprintf(stderr, "itemize(%s): statret = 0, xattrs differ on (%s)\n", who_am_i(), full_fname(fnamecmp));
 			iflags |= ITEM_REPORT_XATTR;
+		}
 #endif
 		iflags |= ITEM_IS_NEW;
 	}
@@ -763,15 +834,55 @@
 /* Perform our quick-check heuristic for determining if a file is unchanged. */
 int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
 {
-	if (st->st_size != F_LENGTH(file))
+	if (st->st_size != F_LENGTH(file)) {
+		//fprintf(stderr, "DEBUG: size differs||%s||d:%llu||s:%llu\n", full_fname(fn), st->st_size, F_LENGTH(file));
 		return 0;
+	}
+	
+	if (detect_case_conflicts) {
+		int fd = open(fn, O_RDONLY);
+		if (fd > 0) {
+			char realpath[MAXPATHLEN];
+			int ret = fcntl(fd, F_GETPATH, &realpath);
+			close(fd);
+			if (ret == 0) {
+				char *mypath = normalize_path(fn, False, NULL);
+				if (strcmp(mypath, realpath) != 0) {
+					fprintf(stderr, "DEBUG: Case conflict detected at %s. Actual path on destination: %s\n", full_fname(fn), realpath);
+					return 0;
+				}
+			}
+		}
+	}
 
 	/* if always checksum is set then we use the checksum instead
 	   of the file time to determine whether to sync */
-	if (always_checksum > 0 && S_ISREG(st->st_mode)) {
+#ifdef SUPPORT_HFS_COMPRESSION
+	if (always_checksum > 0 && S_ISREG(st->st_mode) && (st->st_flags & UF_COMPRESSED) == 0)
+#else
+	if (always_checksum > 0 && S_ISREG(st->st_mode) )
+#endif
+	{
 		char sum[MAX_DIGEST_LEN];
 		file_checksum(fn, sum, st->st_size);
-		return memcmp(sum, F_SUM(file), checksum_len) == 0;
+		
+		int checksumDiff = memcmp(sum, F_SUM(file), checksum_len);
+		if (cmp_time(st->st_mtime, file->modtime) == 0 && checksumDiff != 0) {
+			char *csumSrc = printableChecksum(F_SUM(file));
+			char *csumDst = printableChecksum(sum);
+			if (strstr(csumSrc, "00000000") != NULL) {
+				char *funkySum = printableChecksum(FUNKY_SUM(file));
+				fprintf(stderr, "DEBUG: Invalid source checksum for %s: %s [will try %s]\n", full_fname(fn), csumSrc, funkySum);
+				checksumDiff = memcmp(sum, FUNKY_SUM(file), checksum_len);
+			}
+
+			if (checksumDiff != 0)
+				fprintf(stderr, "File size and modification date match, but checksums were different: %s [%s vs. %s]\n", full_fname(fn), csumSrc, csumDst);
+			free(csumSrc);
+			free(csumDst);
+		}
+		
+		return checksumDiff == 0;
 	}
 
 	if (size_only > 0)
@@ -779,11 +890,15 @@
 
 	if (ignore_times)
 		return 0;
+	
+//	if (cmp_time(st->st_mtime, file->modtime))
+//		fprintf(stderr, "DEBUG: mod time differs||%s||d:%ld||s:%ld\n", full_fname(fn), st->st_mtime, file->modtime);
+//	else
+//		fprintf(stderr, "DEBUG: unchanged_file: mod time and size match for %s\n", full_fname(fn));
 
 	return cmp_time(st->st_mtime, file->modtime) == 0;
 }
 
-
 /*
  * set (initialize) the size entries in the per-file sum_struct
  * calculating dynamic block and checksum sizes.
@@ -1028,6 +1143,14 @@
 		pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
 		if (link_stat(cmpbuf, &sxp->st, 0) < 0 || !S_ISREG(sxp->st.st_mode))
 			continue;
+#ifdef SUPPORT_HFS_COMPRESSION
+		if (sxp->st.st_flags & UF_COMPRESSED) {
+			if (preserve_hfs_compression > 0) {
+				sxp->st.st_size = 0;
+			} else
+				sxp->st.st_flags &= ~UF_COMPRESSED;
+		}
+#endif
 		switch (match_level) {
 		case 0:
 			best_match = j;
@@ -1089,7 +1212,7 @@
 		if (itemizing)
 			itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
 		if (maybe_ATTRS_REPORT
-		 && ((!itemizing && verbose && match_level == 2)
+		 && ((!itemizing && verbose > 1 && match_level == 2)
 		  || (verbose > 1 && match_level == 3))) {
 			code = match_level == 3 ? FCLIENT : FINFO;
 			rprintf(code, "%s%s\n", fname,
@@ -1220,8 +1343,8 @@
 		 && !S_ISDIR(file->mode)) {
 			if (do_link(cmpbuf, fname) < 0) {
 				rsyserr(FERROR_XFER, errno,
-					"failed to hard-link %s with %s",
-					cmpbuf, fname);
+					"try_dests_non: failed to hard-link %s with %s",
+					cmpbuf, full_fname(fname));
 				return j;
 			}
 			if (preserve_hard_links && F_IS_HLINKED(file))
@@ -1396,6 +1519,8 @@
 					rsyserr(FERROR_XFER, errno,
 						"recv_generator: mkdir %s failed",
 						full_fname(dn));
+					if (errno == ENOSPC)
+						exit_cleanup(RERR_FILEIO);
 				}
 			}
 			if (fuzzy_dirlist) {
@@ -1421,6 +1546,33 @@
 		stat_errno = errno;
 	}
 
+	// BOMBICH
+	// filesystem_dev has to get set for the generator, otherwise make_file (flist.c) will 
+	// flag every directory as a mountpoint (FLAG_MOUNT_DIR), thus preventing delete_dir_contents()
+	// from deleting the item (e.g. to make room for an item of a different type -- doesn't affect --delete-* options)
+	if (one_file_system) {
+		if (file->flags & FLAG_TOP_DIR)
+			filesystem_dev = sx.st.st_dev;
+	}
+
+// BOMBICH
+#ifdef PARSEABLE_OUTPUT
+	size_t saved_file_length = 0;
+	if (statret == 0)
+		saved_file_length = sx.st.st_size; // For stats.total_unchanged_size, so we need the existing file size
+#endif
+
+#ifdef SUPPORT_HFS_COMPRESSION
+	if (statret == 0) {
+		if (sx.st.st_flags & UF_COMPRESSED) {
+			if (preserve_hfs_compression > 0) {
+				sx.st.st_size = 0;
+			} else
+				sx.st.st_flags &= ~UF_COMPRESSED;
+		}
+	}
+#endif
+	
 	if (ignore_non_existing > 0 && statret == -1 && stat_errno == ENOENT) {
 		if (is_dir) {
 			if (is_dir < 0)
@@ -1455,8 +1607,22 @@
 	}
 
 	if (is_dir) {
+		heartbeat(fname);
 		if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
 			goto cleanup;
+
+		int saved_detect_case_conflicts = detect_case_conflicts;
+		if (detect_case_conflicts) {
+			detect_case_conflicts++;
+			int conflict_ndx = flist_find(cur_flist, file);
+			detect_case_conflicts = saved_detect_case_conflicts;
+			if (conflict_ndx > 0) {
+				struct file_struct *cfp = cur_flist->sorted[conflict_ndx];
+				fprintf(stderr, "Case conflict detected at %s: \"%s\"\n", full_fname(fname), cfp->basename);
+				goto skipping_dir_contents;
+			}
+		}
+		
 		if (is_dir < 0) {
 			/* In inc_recurse mode we want to make sure any missing
 			 * directories get created while we're still processing
@@ -1467,7 +1633,7 @@
 			 && (S_ISDIR(sx.st.st_mode)
 			  || delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0))
 				goto cleanup; /* Any errors get reported later. */
-			if (do_mkdir(fname, file->mode & 0700) == 0)
+			if (do_mkdir(fname, file->mode & 0755) == 0)
 				file->flags |= FLAG_DIR_CREATED;
 			goto cleanup;
 		}
@@ -1487,6 +1653,8 @@
 			file->flags |= FLAG_MISSING_DIR;
 		}
 		real_ret = statret;
+//		init_stat_x(&real_sx);
+//		real_sx.st = sx.st;
 		real_sx = sx;
 		if (file->flags & FLAG_DIR_CREATED)
 			statret = -1;
@@ -1497,6 +1665,8 @@
 #ifdef SUPPORT_FORCE_CHANGE
 		if (force_change && !preserve_fileflags)
 			F_FFLAGS(file) = sx.st.st_flags;
+		if (verbose > 1)
+			fprintf(stderr, "recv_generator: F_FFLAGS(file): %#x (%s)\n", F_FFLAGS(file), fname);
 #endif
 		if (statret != 0 && basis_dir[0] != NULL) {
 			int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
@@ -1527,28 +1697,35 @@
 				goto cleanup;
 			}
 		}
-#ifdef SUPPORT_XATTRS
-		if (preserve_xattrs && statret == 1)
-			copy_xattrs(fnamecmpbuf, fname);
-#endif
-		if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
-		    && verbose && code != FNONE && f_out != -1)
-			rprintf(code, "%s/\n", fname);
 
 		/* We need to ensure that the dirs in the transfer have writable
 		 * permissions during the time we are putting files within them.
 		 * This is then fixed after the transfer is done. */
 #ifdef SUPPORT_FORCE_CHANGE
+		//fprintf(stderr, "recv_generator: Calling make_mutable on %s. Mode: %o, fileflags: %d\n", full_fname(fname), file->mode, F_FFLAGS(file));
 		if (force_change && F_FFLAGS(file) & force_change
 		 && make_mutable(fname, file->mode, F_FFLAGS(file), force_change))
 			need_retouch_dir_perms = 1;
 #endif
+
+#ifdef SUPPORT_XATTRS
+		// Copy directory xattrs for a directory that already existed
+		if (preserve_xattrs && statret == 1)
+			copy_xattrs(fnamecmpbuf, fname);
+#endif
+		if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
+		    && verbose > 1 && code != FNONE && f_out != -1)
+			rprintf(code, "%s/\n", fname);
+
 #ifdef HAVE_CHMOD
 		if (!am_root && !(file->mode & S_IWUSR) && dir_tweaking) {
 			mode_t mode = file->mode | S_IWUSR;
-			if (do_chmod(fname, mode, 0) < 0) {
+			// BOMBICH: I set the third argument to NO_FFLAGS to force
+			// a stat of the folder, otherwise do_chmod might not call
+			// make_mutable properly
+			if (do_chmod(fname, mode, NO_FFLAGS) < 0) {
 				rsyserr(FERROR_XFER, errno,
-					"failed to modify permissions on %s",
+					"recv_generator: failed to modify permissions on %s",
 					full_fname(fname));
 			}
 			need_retouch_dir_perms = 1;
@@ -1584,12 +1761,18 @@
 #ifdef SUPPORT_FORCE_CHANGE
 	if (force_change && !preserve_fileflags)
 		F_FFLAGS(file) = sx.st.st_flags;
+	if (verbose > 1)
+		fprintf(stderr, "recv_generator(2): F_FFLAGS(file): %#x (%s)\n", F_FFLAGS(file), fname);
 #endif
 
 #ifdef SUPPORT_HARD_LINKS
+	if (verbose > 1)
+		fprintf(stderr, "recv_generator(%s): F_HLINK_NOT_FIRST(file) is %d for (%s)\n", who_am_i(), F_HLINK_NOT_FIRST(file), full_fname(fname));
+	
 	if (preserve_hard_links && F_HLINK_NOT_FIRST(file)
-	 && hard_link_check(file, ndx, fname, statret, &sx, itemizing, code))
+	 && hard_link_check(file, ndx, fname, statret, &sx, itemizing, code)) {
 		goto cleanup;
+	}
 #endif
 
 	if (preserve_links && S_ISLNK(file->mode)) {
@@ -1652,7 +1835,7 @@
 		}
 #endif
 		if (do_symlink(sl, fname) != 0) {
-			rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed",
+			rsyserr(FERROR_XFER, errno, "recv_generator: symlink %s -> \"%s\" failed",
 				full_fname(fname), sl);
 		} else {
 			set_file_attrs(fname, file, NULL, NULL, 0);
@@ -1660,7 +1843,7 @@
 				itemize(fname, file, ndx, statret, &sx,
 					ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL);
 			}
-			if (code != FNONE && verbose)
+			if (code != FNONE && verbose > 1)
 				rprintf(code, "%s -> %s\n", fname, sl);
 #ifdef SUPPORT_HARD_LINKS
 			if (preserve_hard_links && F_IS_HLINKED(file))
@@ -1740,7 +1923,7 @@
 				(long)major(rdev), (long)minor(rdev));
 		}
 		if (do_mknod(fname, file->mode, rdev) < 0) {
-			rsyserr(FERROR_XFER, errno, "mknod %s failed",
+			rsyserr(FERROR_XFER, errno, "recv_generator: mknod %s failed",
 				full_fname(fname));
 		} else {
 			set_file_attrs(fname, file, NULL, NULL, 0);
@@ -1748,7 +1931,7 @@
 				itemize(fname, file, ndx, statret, &sx,
 					ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL);
 			}
-			if (code != FNONE && verbose)
+			if (code != FNONE && verbose > 1)
 				rprintf(code, "%s\n", fname);
 #ifdef SUPPORT_HARD_LINKS
 			if (preserve_hard_links && F_IS_HLINKED(file))
@@ -1763,16 +1946,16 @@
 	if (!S_ISREG(file->mode)) {
 		if (solo_file)
 			fname = f_name(file, NULL);
-		rprintf(FINFO, "skipping non-regular file \"%s\"\n", fname);
+		rprintf(FERROR, "recv_generator: skipping non-regular file %s\n", fname);
 		goto cleanup;
 	}
 
 	if (max_size > 0 && F_LENGTH(file) > max_size) {
-		if (verbose > 1) {
+//		if (verbose > 1) {
 			if (solo_file)
 				fname = f_name(file, NULL);
-			rprintf(FINFO, "%s is over max-size\n", fname);
-		}
+			rprintf(FERROR, "recv_generator: %s is over max-size (27)\n", full_fname(fname));
+//		}
 		goto cleanup;
 	}
 	if (min_size > 0 && F_LENGTH(file) < min_size) {
@@ -1783,7 +1966,6 @@
 		}
 		goto cleanup;
 	}
-
 	if (update_only > 0 && statret == 0
 	    && cmp_time(sx.st.st_mtime, file->modtime) > 0) {
 		if (verbose > 1)
@@ -1794,10 +1976,118 @@
 #endif
 		goto cleanup;
 	}
-
+	
 	fnamecmp = fname;
 	fnamecmp_type = FNAMECMP_FNAME;
 
+// BOMBICH
+#ifdef PARSEABLE_OUTPUT
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	
+	// The Recv generator gets a list of every single file sent by the sender whether it will
+	// eventually be copied or not. Here we optionally print out the current file that is being
+	// received for consideration to give the user a general idea of where rsync is within their fs
+
+	// Print update information every fifth of a second. If a file changed, print update
+	// information as long as the file is larger than 1MB or time since last update > tenth of a second
+
+	unsigned long time_diff = msdiff(&last_update, &now);
+	if (F_LENGTH(file) > 10000000 && always_checksum) {
+		// If the file is > 10MB and we're calculating a checksum, post an update now 
+		// so the user can see the file that might take a while to read
+		rprintf(FINFO, "S;;;CP;;;CF;;;%s\n", fname);
+	}
+	int fileUnchanged;
+	fileUnchanged = unchanged_file(fnamecmp, file, &sx.st);
+
+	// Sparse file support
+	int fileIsSparse = 0;
+	struct stat sps;
+	char src[MAXPATHLEN];
+	char dst[MAXPATHLEN];
+	off_t physicalSize, logicalSize;
+
+	if (/*sparse_files && */!fileUnchanged && (F_FFLAGS(file) & UF_COMPRESSED) == 0 && srcRoot != NULL && dstRoot != NULL) {
+		// We do this check even when we're not supporting sparse files so we can see what kind of sparse files we aren't supporting properly
+		pathjoin(src, MAXPATHLEN, srcRoot, fname);
+		pathjoin(dst, MAXPATHLEN, dstRoot, fname);
+
+		if (stat(src, &sps) != 0) {
+			fprintf(stderr, "DEBUG: Failed to stat '%s': %d\n", src, errno);
+		} else {
+			physicalSize = S_BLKSIZE * sps.st_blocks;
+			logicalSize = sps.st_size;
+			if (logicalSize > physicalSize) {
+				fileIsSparse = 1;
+				saved_file_length = (S_BLKSIZE * sx.st.st_blocks);
+			}
+		}
+	}
+
+	if (fileUnchanged && !(preserve_hard_links && F_HLINK_NOT_LAST(file))) {
+		stats.total_unchanged_size += saved_file_length;
+		stats.total_unchanged_count++;
+	}
+	
+	static int localNdx = 0; // We'll use this to avoid printing output for redos
+	if (ndx > localNdx && ((fileUnchanged && time_diff > 200) || (!fileUnchanged && (F_LENGTH(file) > 1024000 || time_diff > 100)))) {
+		last_update = now;
+		localNdx = ndx;
+		
+		if (inc_recurse)
+			rprintf(FINFO, "S;;;CP;;;NOI;;;%d;;;TUF;;;%d;;;TUS;;;%s;;;CF;;;%s\n", stats.num_files - stats.num_dirs, stats.total_unchanged_count, human_num(stats.total_unchanged_size), fname);
+		else
+			if (am_server)
+				rprintf(FINFO, "S;;;CP;;;TUF;;;%d;;;TUS;;;%s;;;CF;;;%s\n", stats.total_unchanged_count, human_num(stats.total_unchanged_size), fname);
+			else
+				// Remote source. We don't use this, though, we force incremental recursion with a remote source
+				rprintf(FINFO, "S;;;CP;;;TUF;;;%d;;;TUS;;;%s\n", stats.total_unchanged_count, human_num(stats.total_unchanged_size));
+	}
+#endif
+	
+	if (fileIsSparse && !sparse_files && physicalSize > 0) {
+		// Treat it like an ordinary file. This change is only required for the logic in the free-space-check block that follows
+		fprintf(stderr, "DEBUG: Physical size: %lld, logical size: %lld, difference: %lld [%s]\n", physicalSize, logicalSize, logicalSize - physicalSize, src);
+		fileIsSparse = 0;
+	}
+	
+	// Bail on this file if it is larger than the amount of free space remaining
+	// Only do this check for files larger than 512MB
+	off_t req_len = fileIsSparse ? physicalSize : F_LENGTH(file);
+	if (!inplace && !fileUnchanged && req_len > 512*1024*1024) {
+		struct statfs fsb;
+		const char *parent = file->dirname ? file->dirname : ".";
+		if (statfs(parent, &fsb) == 0) {
+			long long fs = fsb.f_bavail * fsb.f_bsize;
+			if (fs < req_len) {
+				rprintf(FERROR_XFER, "recv_generator: Insufficient space to accommodate %s. ;;;REQ;;;%lld;;; Skipping this file... (%d)\n",
+						full_fname(fname), req_len, ENOSPC);
+				goto cleanup;
+			}
+		} else
+			rprintf(FINFO, "recv_files: Failed to statfs %s: %s\n", full_fname(fname), strerror(errno));
+	}
+	
+	// If this file looks like a sparse file and we have sparse file support, copy it with copy_sparse_file
+	if (fileIsSparse) { // implies !fileUnchanged (that the file will be copied)
+		errno = 0;
+		if (copy_sparse_file(src, dst, sps.st_mode, logicalSize, physicalSize, sparse_files) == 0) {
+			struct stat spd;
+			if (stat(dst, &spd) != 0) {
+				fprintf(stderr, "DEBUG: Copied sparse file '%s' successfully, but failed to stat the resulting file: %d\n", dst, errno);
+			} else {
+				fileUnchanged = 1;
+				sx.st = spd;
+				statret = 0;
+			}
+		} else if (errno == EACCES && physicalSize == 0) {
+			fileUnchanged = 1;
+			goto return_with_success;
+		}
+	}
+
+	
 	if (statret == 0 && !S_ISREG(sx.st.st_mode)) {
 		if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_FILE) != 0)
 			goto cleanup;
@@ -1840,6 +2130,15 @@
 				rprintf(FINFO, "fuzzy basis selected for %s: %s\n",
 					fname, fnamecmpbuf);
 			}
+#ifdef SUPPORT_HFS_COMPRESSION
+		// TODO: This seems misplaced...
+		if (sx.st.st_flags & UF_COMPRESSED) {
+			if (preserve_hfs_compression > 0) {
+				sx.st.st_size = 0;
+			} else
+				sx.st.st_flags &= ~UF_COMPRESSED;
+		} else
+#endif
 			sx.st.st_size = F_LENGTH(fuzzy_file);
 			statret = 0;
 			fnamecmp = fnamecmpbuf;
@@ -1854,7 +2153,7 @@
 			goto cleanup;
 		}
 #endif
-		if (stat_errno == ENOENT)
+		if (stat_errno == ENOENT || stat_errno == ENAMETOOLONG)
 			goto notify_others;
 		rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s",
 			full_fname(fname));
@@ -1865,11 +2164,19 @@
 		;
 	else if (fnamecmp_type == FNAMECMP_FUZZY)
 		;
-	else if (unchanged_file(fnamecmp, file, &sx.st)) {
+#ifdef PARSEABLE_OUTPUT
+	else if (fileUnchanged)
+#else
+	else if (unchanged_file(fnamecmp, file, &sx.st))
+#endif
+	{
 		if (partialptr) {
 			do_unlink(partialptr);
 			handle_partial_dir(partialptr, PDIR_DELETE);
 		}
+
+		if (verbose > 1)
+			fprintf(stderr, "recv_generator: Calling set_file_attrs: ITEM_REPORT_XATTR: %d (%s)\n", file->flags & ITEM_REPORT_XATTR, fname);
 		set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
 		if (itemizing)
 			itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL);
@@ -1899,6 +2206,14 @@
 		fnamecmp = partialptr;
 		fnamecmp_type = FNAMECMP_PARTIAL_DIR;
 		statret = 0;
+#ifdef SUPPORT_HFS_COMPRESSION
+		if (sx.st.st_flags & UF_COMPRESSED) {
+			if (preserve_hfs_compression > 0) {
+				sx.st.st_size = 0;
+			} else
+				sx.st.st_flags &= ~UF_COMPRESSED;
+		}
+#endif
 	}
 
 	if (!do_xfers)
@@ -1927,7 +2242,7 @@
 
 	/* open the file */
 	if ((fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) {
-		rsyserr(FERROR, errno, "failed to open %s, continuing",
+		rsyserr(FERROR, errno, "recv_generator: failed to open %s, continuing",
 			full_fname(fnamecmp));
 	  pretend_missing:
 		/* pretend the file didn't exist */
@@ -1951,7 +2266,7 @@
 			goto pretend_missing;
 		}
 		if (robust_unlink(backupptr) && errno != ENOENT) {
-			rsyserr(FERROR_XFER, errno, "unlink %s",
+			rsyserr(FERROR_XFER, errno, "recv_generator: unlink %s",
 				full_fname(backupptr));
 			unmake_file(back_file);
 			back_file = NULL;
@@ -1960,6 +2275,8 @@
 		}
 		if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
 			int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
+			if (verbose)
+				fprintf(stderr, "DEBUG: recv_generator: do_open() failed: %d |%s\n", errno, backupptr);
 			if (errno == ENOENT && make_bak_dir(backupptr) == 0) {
 				if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)
 					save_errno = errno ? errno : save_errno;
@@ -1967,7 +2284,7 @@
 					save_errno = 0;
 			}
 			if (save_errno) {
-				rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(backupptr));
+				rsyserr(FERROR_XFER, save_errno, "recv_generator: open backup file %s", full_fname(backupptr));
 				unmake_file(back_file);
 				back_file = NULL;
 				close(fd);
@@ -1997,12 +2314,16 @@
 	write_ndx(f_out, ndx);
 	if (itemizing) {
 		int iflags = ITEM_TRANSFER;
-		if (always_checksum > 0)
-			iflags |= ITEM_REPORT_CHANGE;
+//		if (always_checksum > 0)
+//			iflags |= ITEM_REPORT_CHANGE;
 		if (fnamecmp_type != FNAMECMP_FNAME)
 			iflags |= ITEM_BASIS_TYPE_FOLLOWS;
 		if (fnamecmp_type == FNAMECMP_FUZZY)
 			iflags |= ITEM_XNAME_FOLLOWS;
+		if (preserve_xattrs)
+			iflags |= ITEM_REPORT_XATTR; // Must be on any time a file is transferred
+		if (verbose > 1)
+			fprintf(stderr, "recv_generator(%s): itemizing (%s)\n", who_am_i(), full_fname(fnamecmp));
 		itemize(fnamecmp, file, -1, real_ret, &real_sx, iflags, fnamecmp_type,
 			fuzzy_file ? fuzzy_file->basename : NULL);
 #ifdef SUPPORT_ACLS
@@ -2017,20 +2338,39 @@
 
 	if (!do_xfers) {
 #ifdef SUPPORT_HARD_LINKS
-		if (preserve_hard_links && F_IS_HLINKED(file))
+		if (preserve_hard_links && F_IS_HLINKED(file)) {
+			if (verbose > 1)
+				fprintf(stderr, "recv_generator(%s): Calling finish_hard_link for (%s)\n", who_am_i(), full_fname(fname));
 			finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1);
+		}
 #endif
 		goto cleanup;
 	}
 	if (read_batch)
 		goto cleanup;
 
+#ifdef SUPPORT_HFS_COMPRESSION
+	if (F_FFLAGS(file) & UF_COMPRESSED) {
+		// At this point the attrs have already been copied, we don't need to transfer a data fork
+		// If my filesystem doesn't support HFS compression, the existing file's content 
+		// will not be automatically truncated, so we'll do that manually here
+		if (!fs_supports_hfs_compression && sx.st.st_size > 0) {
+			if (verbose > 1)
+				fprintf(stderr, "recv_generator(%s): Truncating file on fs that doesn't support HFS compression (%s)\n", who_am_i(), full_fname(fname));
+			if (ftruncate(fd, 0) == 0)
+				sx.st.st_size = 0;
+		}
+	}
+#endif
+	
 	if (statret != 0 || whole_file)
 		write_sum_head(f_out, NULL);
 	else if (sx.st.st_size <= 0) {
 		write_sum_head(f_out, NULL);
 		close(fd);
 	} else {
+		if (verbose > 1)
+			fprintf(stderr, "recv_generator(%s): Calling generate_and_send_sums for (%s)\n", who_am_i(), full_fname(fname));
 		if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) {
 			rprintf(FWARNING,
 			    "WARNING: file is too large for checksum sending: %s\n",
@@ -2079,6 +2419,8 @@
 	int new_last_ndx;
 	struct file_list *save_flist = cur_flist;
 
+	if (verbose > 1)
+		fprintf(stderr, "handle_skipped_hlink: Calling skip_hard_link()\n");
 	/* If we skip the last item in a chain of links and there was a
 	 * prior non-skipped hard-link waiting to finish, finish it now. */
 	if ((new_last_ndx = skip_hard_link(file, &cur_flist)) < 0)
@@ -2087,6 +2429,8 @@
 	file = cur_flist->files[new_last_ndx - cur_flist->ndx_start];
 	cur_flist->in_progress--; /* undo prior increment */
 	f_name(file, fbuf);
+	if (verbose > 1)
+		fprintf(stderr, "handle_skipped_hlink: Calling recv_generator() with %s\n", full_fname(fbuf));
 	recv_generator(fbuf, file, new_last_ndx, itemizing, code, f_out);
 
 	cur_flist = save_flist;
@@ -2122,13 +2466,33 @@
 		 || (!need_retouch_dir_times && file->mode & S_IWUSR))
 			continue;
 		fname = f_name(file, NULL);
-		if (!(file->mode & S_IWUSR))
-			do_chmod(fname, file->mode, 0);
-		if (need_retouch_dir_times) {
-			STRUCT_STAT st;
-			if (link_stat(fname, &st, 0) == 0
-			 && cmp_time(st.st_mtime, file->modtime) != 0)
-				set_modtime(fname, file->modtime, file->mode, 0);
+
+#ifdef PARSEABLE_OUTPUT
+		if (!inc_recurse) {
+			struct timeval now;
+			gettimeofday(&now, NULL);
+	
+			unsigned long time_diff = msdiff(&last_update, &now);
+			if (time_diff > 200 && end > 0) { // Print update information every fifth of a second, avoid divide by zero crash!
+				last_update = now;
+				rprintf(FINFO, "S;;;TU;;;PROG;;;%d;;;CF;;;%s\n", (i * 100) / end, fname);
+			}
+		}
+#endif
+
+		STRUCT_STAT st;
+		if (link_stat(fname, &st, 0) == 0) {
+			/* Don't change the mode on the root folder of an HFS+ volume */
+			if (file->mode != st.st_mode && st.st_ino != 2)
+				do_chmod(fname, file->mode, 0);
+			if (need_retouch_dir_times) {
+				 if ((receiver_uid == 0 || receiver_uid == st.st_uid)
+				 && cmp_time(st.st_mtime, file->modtime) != 0)
+					// BOMBICH: I set the fourth argument to F_FFLAGS(file) to force
+					// a stat of the folder, otherwise set_modtime might not call
+					// make_mutable properly
+					set_modtime(fname, file->modtime, file->mode, F_FFLAGS(file));
+			}
 		}
 #ifdef SUPPORT_FORCE_CHANGE
 		if (force_change && F_FFLAGS(file) & force_change)
@@ -2157,6 +2521,8 @@
 			flist = flist_for_ndx(ndx, "check_for_finished_files.1");
 			file = flist->files[ndx - flist->ndx_start];
 			assert(file->flags & FLAG_HLINKED);
+			if (verbose > 1)
+				fprintf(stderr, "check_for_finished_files: Calling finish_hard_link() for %s\n", f_name(file, NULL));
 			finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1);
 			flist->in_progress--;
 			continue;
@@ -2301,6 +2667,7 @@
 			else
 				f_name(fp, fbuf);
 			ndx = cur_flist->ndx_start - 1;
+
 			recv_generator(fbuf, fp, ndx, itemizing, code, f_out);
 			if (delete_during && dry_run < 2 && !list_only
 			 && !(fp->flags & FLAG_MISSING_DIR)) {
@@ -2418,3 +2785,131 @@
 	if (verbose > 2)
 		rprintf(FINFO, "generate_files finished\n");
 }
+
+int copy_sparse_file(const char *src, const char *dst, mode_t mode, off_t logicalSize, off_t physicalSize, int sparse_files)
+{
+	int fdin, fdout, result = 0;
+	off_t dataSkipped = 0, dataWritten = 0;
+	char *buf;
+	struct timeval now;
+
+	// We attempt to open the source file even if the physical size is 0. This allows us to capture an
+	// EACCES error from OneDrive placeholder files and then avoid copying them
+	fdin = open(src, O_RDONLY);
+	if (fdin < 0) {
+		if (errno == EACCES && physicalSize == 0) {
+			fprintf(stderr, "DEBUG: Dropping placeholder: %s\n", src);
+		} else {
+			fprintf(stderr, "DEBUG: sparse_open '%s' failed: %s\n", src, strerror(errno));
+		}
+		return 1;
+	}
+	
+	fdout = open(dst, O_RDWR | O_CREAT | O_TRUNC, mode);
+	if (fdout < 0) {
+		fprintf(stderr, "DEBUG: sparse_open '%s' failed: %s\n", dst, strerror(errno));
+		close(fdin);
+		return 1;
+	}
+	
+	if (physicalSize == 0) {
+		if (ftruncate(fdout, sparse_files ? logicalSize : 0) != 0) {
+			fprintf(stderr, "DEBUG: ftruncate(%lld) failed on %s: %s\n", logicalSize, dst, strerror(errno));
+			result = 1;
+		}
+		close(fdin);
+		close(fdout);
+		return result;
+	}
+
+	fprintf(stderr, "DEBUG: Physical size: %lld, logical size: %lld, difference: %lld [%s]\n", physicalSize, logicalSize, logicalSize - physicalSize, src);
+	buf = (char *)malloc(write_size);
+	if (!buf) {
+		fprintf(stderr, "DEBUG: malloc failed: %s\n", strerror(errno));
+		close(fdin);
+		close(fdout);
+		return 1;
+	}
+	
+	off_t in_offset = 0;
+	while (in_offset < logicalSize) {
+		off_t data_offset, hole_offset, chunkSize, availableData;
+		data_offset = lseek(fdin, in_offset, SEEK_DATA);
+		if (data_offset < 0) {
+			if (errno == ENXIO) {
+				dataSkipped += (logicalSize - in_offset);
+				// No more data chunks past the current offset. Truncate the destination file.
+				if (ftruncate(fdout, logicalSize) != 0) {
+					fprintf(stderr, "DEBUG: ftruncate failed on destination file: %s\n", strerror(errno));
+					result = 1;
+				}
+			} else {
+				fprintf(stderr, "DEBUG: lseek failed on source file: %s\n", strerror(errno));
+				result = 1;
+			}
+			break;
+		}
+		
+		if (data_offset > in_offset) {
+			if (verbose)
+				fprintf(stderr, "DEBUG: Skipping an empty chunk of %lld bytes\n", data_offset - in_offset);
+			dataSkipped += (data_offset - in_offset);
+			in_offset = data_offset;
+			if (lseek(fdout, data_offset, SEEK_SET) != data_offset) {
+				fprintf(stderr, "DEBUG: lseek failed on destination file: %s\n", strerror(errno));
+				result = 1;
+				break;
+			}
+		}
+		
+		// Find the offset of the next hole, then reset the offset
+		hole_offset = lseek(fdin, data_offset, SEEK_HOLE);
+		lseek(fdin, data_offset, SEEK_SET);
+		availableData = hole_offset - data_offset;
+		if (verbose)
+			fprintf(stderr, "DEBUG: Reading a data chunk of %lld bytes\n", availableData);
+		
+		// Read data starting at data_offset up to hole_offset in, at most, ioWriteSize chunks
+		while (availableData > 0) {
+			gettimeofday(&now, NULL);
+			unsigned long time_diff = msdiff(&last_update, &now);
+			if (time_diff > 100) {
+				last_update = now;
+				rprintf(FINFO, "S;;;CP;;;SPARSE;;;%lld;;;CF;;;%s\n", sparseDataCopied, src);
+			}
+			
+			chunkSize = (availableData < write_size) ? availableData : write_size;
+			ssize_t readData, writtenData;
+			bzero(buf, write_size);
+			readData = read(fdin, buf, chunkSize);
+			if (readData < 0) {
+				fprintf(stderr, "DEBUG: read failed: %s\n", strerror(errno));
+				result = 1;
+				hole_offset = logicalSize;
+				break;
+			}
+			writtenData = write(fdout, buf, chunkSize);
+			if (writtenData != readData) {
+				fprintf(stderr, "DEBUG: write failed: %s\n", strerror(errno));
+				result = 1;
+				hole_offset = logicalSize;
+				break;
+			}
+			
+			sparseDataCopied += writtenData;
+			dataWritten += writtenData;
+			availableData -= readData;
+		}
+		
+		in_offset = hole_offset;
+	}
+	
+	sparseFilesCopied++;
+	fprintf(stderr, "S;;;CP;;;SPARSE;;;%lld;;;SPCP;;;%d;;;CF;;;%s\n", sparseDataCopied, sparseFilesCopied, src);
+	
+	close(fdin);
+	close(fdout);
+	free(buf);
+	return result;
+}
+
diff -Naur -X diff_ignore rsync-3.0.6_base/hashtable.c rsync/hashtable.c
--- rsync-3.0.6_base/hashtable.c	2009-01-17 16:41:35.000000000 -0500
+++ rsync/hashtable.c	2016-12-28 22:47:47.000000000 -0500
@@ -87,7 +87,7 @@
 		uchar buf[4], *keyp = buf;
 		int i;
 
-		SIVAL(buf, 0, key);
+		SIVALu(buf, 0, key);
 		for (ndx = 0, i = 0; i < 4; i++) {
 			ndx += keyp[i];
 			ndx += (ndx << 10);
diff -Naur -X diff_ignore rsync-3.0.6_base/hlink.c rsync/hlink.c
--- rsync-3.0.6_base/hlink.c	2009-06-18 17:30:46.000000000 -0400
+++ rsync/hlink.c	2018-09-07 12:18:42.000000000 -0400
@@ -31,6 +31,7 @@
 extern int link_dest;
 extern int preserve_acls;
 extern int preserve_xattrs;
+extern int preserve_hfs_compression;
 extern int make_backups;
 extern int protocol_version;
 extern int remove_source_files;
@@ -134,6 +135,7 @@
 				else {
 					/* We skipped all prior files in this
 					 * group, so mark this as a "first". */
+					fprintf(stderr, "DEBUG: Previous hard links were skipped, marking this file as a first: %s\n", file->basename);
 					file->flags |= FLAG_HLINK_FIRST;
 					prev = -1;
 				}
@@ -209,6 +211,8 @@
 			   const char *oldname, STRUCT_STAT *old_stp,
 			   const char *realname, int itemizing, enum logcode code)
 {
+	if (verbose > 1)
+		fprintf(stderr, "maybe_hard_link: %s => %s, statret: %d, size of original: %lld\n", full_fname(fname), oldname, statret, old_stp->st_size);
 	if (statret == 0) {
 		if (sxp->st.st_dev == old_stp->st_dev
 		 && sxp->st.st_ino == old_stp->st_ino) {
@@ -223,22 +227,39 @@
 			return 0;
 		}
 		if (make_backups > 0) {
+			if (verbose > 1)
+				fprintf(stderr, "maybe_hard_link: calling make_backup() on %s\n", full_fname(fname));
 			if (!make_backup(fname))
 				return -1;
 		} else if (robust_unlink(fname)) {
-			rsyserr(FERROR_XFER, errno, "unlink %s failed",
+			rsyserr(FERROR_XFER, errno, "maybe_hard_link: unlink %s failed",
 				full_fname(fname));
 			return -1;
 		}
 	}
 
+	if (verbose > 1)
+		fprintf(stderr, "maybe_hard_link: %s, oldname: %s\n", fname, oldname);
+
 	if (hard_link_one(file, fname, oldname, 0)) {
+		if (verbose > 1)
+			fprintf(stderr, "maybe_hard_link: hard_link_one > 0\n");
+		// If the hard link was successful, restat the destination file
+		statret = link_stat(fname, &sxp->st, 0);
+#ifdef SUPPORT_HFS_COMPRESSION
+		if (sxp->st.st_flags & UF_COMPRESSED) {
+			if (preserve_hfs_compression > 0) {
+				sxp->st.st_size = 0;
+			} else
+				sxp->st.st_flags &= ~UF_COMPRESSED;
+		}
+#endif
 		if (itemizing) {
 			itemize(fname, file, ndx, statret, sxp,
 				ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
 				realname);
 		}
-		if (code != FNONE && verbose)
+		if (code != FNONE && verbose > 1)
 			rprintf(code, "%s => %s\n", fname, realname);
 		return 0;
 	}
@@ -270,6 +291,10 @@
 
 	if (inc_recurse
 	 && (node = hashtable_find(prior_hlinks, gnum, 0)) != NULL) {
+		if (node->data == NULL) {
+			fprintf(stderr, "DEBUG: check_prior: Assertion failure coming, hard link %s\n", full_fname(file->basename));
+			fflush(stderr);
+		}
 		assert(node->data != NULL);
 		if (CVAL(node->data, 0) != 0) {
 			*prev_ndx_p = -1;
@@ -300,6 +325,9 @@
 
 	prev_name = realname = check_prior(file, gnum, &prev_ndx, &flist);
 
+	if (verbose > 1)
+		fprintf(stderr, "hlink(%s): hard_link_check (%s)\n", who_am_i(), full_fname(fname));
+
 	if (!prev_name) {
 		struct file_struct *prev_file;
 
@@ -309,12 +337,19 @@
 			return 0;
 		}
 
+		if (verbose > 1)
+			fprintf(stderr, "hlink(%s): hard_link_check prev file not skipped (%s)\n", who_am_i(), full_fname(fname));
+
 		prev_file = flist->files[prev_ndx - flist->ndx_start];
 
 		/* Is the previous link not complete yet? */
 		if (!(prev_file->flags & FLAG_HLINK_DONE)) {
 			/* Is the previous link being transferred? */
+			if (verbose > 1)
+				fprintf(stderr, "hlink(%s): hard_link_check prev link not done (%s)\n", who_am_i(), full_fname(fname));
 			if (prev_file->flags & FLAG_FILE_SENT) {
+				if (verbose > 1)
+					fprintf(stderr, "hlink(%s): hard_link_check prev file sent (%s)\n", who_am_i(), full_fname(fname));
 				/* Add ourselves to the list of files that will
 				 * be updated when the transfer completes, and
 				 * mark ourself as waiting for the transfer. */
@@ -324,9 +359,14 @@
 				cur_flist->in_progress++;
 				return 1;
 			}
+			if (verbose > 1)
+				fprintf(stderr, "hlink(%s): hard_link_check prev file not sent (%s)\n", who_am_i(), full_fname(fname));
 			return 0;
 		}
 
+		if (verbose > 1)
+			fprintf(stderr, "hlink(%s): hard_link_check prev link is complete (%s)\n", who_am_i(), full_fname(fname));
+
 		/* There is a finished file to link with! */
 		if (!(prev_file->flags & FLAG_HLINK_FIRST)) {
 			/* The previous previous is FIRST when prev is not. */
@@ -355,12 +395,24 @@
 		}
 	}
 
+	if (verbose > 1)
+		fprintf(stderr, "hlink(%s): hard_link_check stating prev_name (%s) for (%s)\n", who_am_i(), prev_name, fname);
+
 	if (link_stat(prev_name, &prev_st, 0) < 0) {
-		rsyserr(FERROR_XFER, errno, "stat %s failed",
+		rsyserr(FERROR_XFER, errno, "hard_link_check: stat %s failed",
 			full_fname(prev_name));
 		return -1;
 	}
 
+#ifdef SUPPORT_HFS_COMPRESSION
+	if (prev_st.st_flags & UF_COMPRESSED) {
+		if (preserve_hfs_compression > 0) {
+			prev_st.st_size = 0;
+		} else
+			prev_st.st_flags &= ~UF_COMPRESSED;
+	}
+#endif
+	
 	if (statret < 0 && basis_dir[0] != NULL) {
 		/* If we match an alt-dest item, we don't output this as a change. */
 		char cmpbuf[MAXPATHLEN];
@@ -377,6 +429,15 @@
 			pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
 			if (link_stat(cmpbuf, &alt_sx.st, 0) < 0)
 				continue;
+#ifdef SUPPORT_HFS_COMPRESSION
+			if (alt_sx.st.st_flags & UF_COMPRESSED) {
+				if (preserve_hfs_compression > 0) {
+					alt_sx.st.st_size = 0;
+				} else
+					alt_sx.st.st_flags &= ~UF_COMPRESSED;
+			}
+#endif
+	
 			if (link_dest) {
 				if (prev_st.st_dev != alt_sx.st.st_dev
 				 || prev_st.st_ino != alt_sx.st.st_ino)
@@ -391,9 +452,17 @@
 				}
 				break;
 			}
+			
+			if (verbose > 1)
+				fprintf(stderr, "hlink(%s): hard_link_check calling unchanged_file(%s)\n", who_am_i(), full_fname(fname));
+
 			if (!unchanged_file(cmpbuf, file, &alt_sx.st))
 				continue;
 			statret = 1;
+
+			if (verbose > 1)
+				fprintf(stderr, "hlink(%s): hard_link_check calling unchanged_attrs(%s)\n", who_am_i(), full_fname(fname));
+
 			if (unchanged_attrs(cmpbuf, file, &alt_sx))
 				break;
 		} while (basis_dir[++j] != NULL);
@@ -455,7 +524,7 @@
 			code = FINFO;
 		} else
 			code = FERROR_XFER;
-		rsyserr(code, errno, "link %s => %s failed",
+		rsyserr(code, errno, "hard_link_one: link %s => %s failed",
 			full_fname(fname), oldname);
 		return 0;
 	}
@@ -476,9 +545,17 @@
 	struct file_list *flist;
 	int prev_statret, ndx, prev_ndx = F_HL_PREV(file);
 
+	if (verbose > 1) {
+		struct stat vst;
+		if (stat(fname, &vst) < 0)
+			fprintf(stderr, "finish_hard_link: Failed to stat %s!\n", full_fname(fname));
+		else 
+			fprintf(stderr, "finish_hard_link: File size at %s is %.0f\n", full_fname(fname), (double)vst.st_size);
+	}
+
 	if (stp == NULL && prev_ndx >= 0) {
 		if (link_stat(fname, &st, 0) < 0) {
-			rsyserr(FERROR_XFER, errno, "stat %s failed",
+			rsyserr(FERROR_XFER, errno, "finish_hard_link: stat %s failed",
 				full_fname(fname));
 			return;
 		}
@@ -511,6 +588,10 @@
 		prev_ndx = F_HL_PREV(file);
 		F_HL_PREV(file) = fin_ndx;
 		prev_statret = link_stat(f_name(file, prev_name), &prev_sx.st, 0);
+		if (verbose > 1) {
+			fprintf(stderr, "finish_hard_link: prev_statret: %d, prev_sx.st.st_size: %lu (%s)\n", prev_statret, (unsigned long)prev_sx.st.st_size, full_fname(prev_name));
+			fprintf(stderr, "finish_hard_link: stp.st_size: %lu (%s)\n", (unsigned long)stp->st_size, full_fname(our_name));
+		}
 		val = maybe_hard_link(file, ndx, prev_name, prev_statret, &prev_sx,
 				      our_name, stp, fname, itemizing, code);
 		flist->in_progress--;
@@ -531,11 +612,19 @@
 	if (inc_recurse) {
 		int gnum = F_HL_GNUM(file);
 		struct ht_int32_node *node = hashtable_find(prior_hlinks, gnum, 0);
+		if (node == NULL || node->data == NULL) {
+			fprintf(stderr, "DEBUG: finish_hard_link: Assertion failure coming, hard link %s => %s\n", full_fname(prev_name), our_name);
+			fflush(stderr);
+//		} else {
+//			fprintf(stderr, "DEBUG: finish_hard_link: hard link %s => %s; node->data: %s\n", full_fname(prev_name), our_name, node->data);
+		}
+		
 		assert(node != NULL && node->data != NULL);
 		assert(CVAL(node->data, 0) == 0);
 		free(node->data);
 		if (!(node->data = strdup(our_name)))
 			out_of_memory("finish_hard_link");
+//		fprintf(stderr, "DEBUG: finish_hard_link: hard link %s => %s; node->data: %s\n", full_fname(prev_name), our_name, node->data);
 	}
 }
 
diff -Naur -X diff_ignore rsync-3.0.6_base/io.c rsync/io.c
--- rsync-3.0.6_base/io.c	2019-01-14 13:23:49.000000000 -0500
+++ rsync/io.c	2016-06-21 10:52:35.000000000 -0400
@@ -59,6 +59,7 @@
 extern int filesfrom_convert;
 extern iconv_t ic_send, ic_recv;
 #endif
+extern int io_buf_size;
 
 const char phase_unknown[] = "unknown";
 int ignore_timeout = 0;
@@ -194,8 +195,8 @@
 
 	if (t - last_io_in >= io_timeout) {
 		if (!am_server && !am_daemon) {
-			rprintf(FERROR, "io timeout after %d seconds -- exiting\n",
-				(int)(t-last_io_in));
+			rprintf(FERROR, "[%s] io timeout after %d seconds -- exiting\n",
+				who_am_i(), (int)(t-last_io_in));
 		}
 		exit_cleanup(RERR_TIMEOUT);
 	}
@@ -373,6 +374,7 @@
 				who_am_i(), IVAL(buf,0));
 		}
 		flist = recv_file_list(fd);
+			//fprintf(stderr, "DEBUG: [%s]read_msg_fd received %d items\n", who_am_i(), flist->used);
 		flist->parent_ndx = IVAL(buf,0);
 #ifdef SUPPORT_HARD_LINKS
 		if (preserve_hard_links)
@@ -391,10 +393,12 @@
 		io_error |= IVAL(buf, 0);
 		break;
 	case MSG_DELETED:
+	case MSG_FILTERED:
+	case MSG_ARCHIVED:
 		if (len >= (int)sizeof buf || !am_generator)
 			goto invalid_msg;
 		readfd(fd, buf, len);
-		send_msg(MSG_DELETED, buf, len, 1);
+		send_msg(tag, buf, len, 1);
 		break;
 	case MSG_SUCCESS:
 		if (len != 4 || !am_generator)
@@ -596,6 +600,8 @@
 	rprintf(FERROR, RSYNC_NAME ": connection unexpectedly closed "
 		"(%.0f bytes received so far) [%s]\n",
 		(double)stats.total_read, who_am_i());
+	fprintf(stderr, "rsync: connection unexpectedly closed (%.0f bytes received so far) [%s]\n", (double)stats.total_read, who_am_i());
+	fflush(stderr);
 
 	exit_cleanup(RERR_STREAMIO);
 }
@@ -897,7 +903,7 @@
 		assert(f_out == iobuf_f_out);
 		return 0;
 	}
-	if (!(iobuf_out = new_array(char, IO_BUFFER_SIZE)))
+	if (!(iobuf_out = new_array(char, io_buf_size)))
 		out_of_memory("io_start_buffering_out");
 	iobuf_out_cnt = 0;
 	iobuf_f_out = f_out;
@@ -910,7 +916,7 @@
 		assert(f_in == iobuf_f_in);
 		return 0;
 	}
-	iobuf_in_siz = 2 * IO_BUFFER_SIZE;
+	iobuf_in_siz = 2 * io_buf_size;
 	if (!(iobuf_in = new_array(char, iobuf_in_siz)))
 		out_of_memory("io_start_buffering_in");
 	iobuf_f_in = f_in;
@@ -1050,6 +1056,8 @@
 			io_error |= IVAL(line, 0);
 			break;
 		case MSG_DELETED:
+		case MSG_FILTERED:
+		case MSG_ARCHIVED:
 			if (msg_bytes >= sizeof line)
 				goto overflow;
 #ifdef ICONV_OPTION
@@ -1084,11 +1092,17 @@
 #endif
 				read_loop(fd, line, msg_bytes);
 			/* A directory name was sent with the trailing null */
-			if (msg_bytes > 0 && !line[msg_bytes-1])
-				log_delete(line, S_IFDIR);
-			else {
+			if (msg_bytes > 0 && !line[msg_bytes-1]) {
+				if (tag == MSG_DELETED)
+					log_delete(line, S_IFDIR);
+				else
+					log_non_transfer(line, S_IFDIR, tag == MSG_ARCHIVED ? ITEM_ARCHIVED : am_generator ? ITEM_EXCLUDED : ITEM_PROTECTED);
+			} else {
 				line[msg_bytes] = '\0';
-				log_delete(line, S_IFREG);
+				if (tag == MSG_DELETED)
+					log_delete(line, S_IFREG);
+				else
+					log_non_transfer(line, S_IFREG, tag == MSG_ARCHIVED ? ITEM_ARCHIVED : am_generator ? ITEM_EXCLUDED : ITEM_PROTECTED);
 			}
 			break;
 		case MSG_SUCCESS:
@@ -1304,8 +1318,8 @@
 		len = (len & ~0x80) * 0x100 + read_byte(f);
 
 	if (len >= bufsize) {
-		rprintf(FERROR, "over-long vstring received (%d > %d)\n",
-			len, bufsize - 1);
+		rprintf(FERROR, "[%s] over-long vstring received (%d > %d)\n",
+			who_am_i(), len, bufsize - 1);
 		return -1;
 	}
 
@@ -1477,6 +1491,7 @@
 		if (count <= 0) {
 			if (count < 0 && errno == EBADF)
 				exit_cleanup(RERR_SOCKETIO);
+			//fprintf(stderr, "DEBUG: writefd_unbuffered: checking for timeout. Count: %d, errno: %d\n", count, errno);
 			check_timeout();
 			continue;
 		}
@@ -1580,7 +1595,7 @@
 	}
 
 	while (len) {
-		int n = MIN((int)len, IO_BUFFER_SIZE - iobuf_out_cnt);
+		int n = MIN((int)len, io_buf_size - iobuf_out_cnt);
 		if (n > 0) {
 			memcpy(iobuf_out+iobuf_out_cnt, buf, n);
 			buf += n;
@@ -1588,7 +1603,7 @@
 			iobuf_out_cnt += n;
 		}
 
-		if (iobuf_out_cnt == IO_BUFFER_SIZE)
+		if (iobuf_out_cnt == io_buf_size)
 			io_flush(NORMAL_FLUSH);
 	}
 }
diff -Naur -X diff_ignore rsync-3.0.6_base/lib/md5.c rsync/lib/md5.c
--- rsync-3.0.6_base/lib/md5.c	2007-07-10 09:55:49.000000000 -0400
+++ rsync/lib/md5.c	2018-01-18 11:22:00.000000000 -0500
@@ -27,6 +27,7 @@
 	ctx->D = 0x10325476;
 
 	ctx->totalN = ctx->totalN2 = 0;
+	memset(ctx->buffer, 0, CSUM_CHUNK);
 }
 
 static void md5_process(md_context *ctx, const uchar data[CSUM_CHUNK])
@@ -38,22 +39,22 @@
 	C = ctx->C;
 	D = ctx->D;
 
-	X[0] = IVAL(data, 0);
-	X[1] = IVAL(data, 4);
-	X[2] = IVAL(data, 8);
-	X[3] = IVAL(data, 12);
-	X[4] = IVAL(data, 16);
-	X[5] = IVAL(data, 20);
-	X[6] = IVAL(data, 24);
-	X[7] = IVAL(data, 28);
-	X[8] = IVAL(data, 32);
-	X[9] = IVAL(data, 36);
-	X[10] = IVAL(data, 40);
-	X[11] = IVAL(data, 44);
-	X[12] = IVAL(data, 48);
-	X[13] = IVAL(data, 52);
-	X[14] = IVAL(data, 56);
-	X[15] = IVAL(data, 60);
+	X[0] = IVALu(data, 0);
+	X[1] = IVALu(data, 4);
+	X[2] = IVALu(data, 8);
+	X[3] = IVALu(data, 12);
+	X[4] = IVALu(data, 16);
+	X[5] = IVALu(data, 20);
+	X[6] = IVALu(data, 24);
+	X[7] = IVALu(data, 28);
+	X[8] = IVALu(data, 32);
+	X[9] = IVALu(data, 36);
+	X[10] = IVALu(data, 40);
+	X[11] = IVALu(data, 44);
+	X[12] = IVALu(data, 48);
+	X[13] = IVALu(data, 52);
+	X[14] = IVALu(data, 56);
+	X[15] = IVALu(data, 60);
 
 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
 
@@ -192,8 +193,8 @@
 	     | (ctx->totalN2 <<  3);
 	low  = (ctx->totalN <<  3);
 
-	SIVAL(msglen, 0, low);
-	SIVAL(msglen, 4, high);
+	SIVALu(msglen, 0, low);
+	SIVALu(msglen, 4, high);
 
 	last = ctx->totalN & 0x3F;
 	padn = last < 56 ? 56 - last : 120 - last;
@@ -201,10 +202,10 @@
 	md5_update(ctx, md5_padding, padn);
 	md5_update(ctx, msglen, 8);
 
-	SIVAL(digest, 0, ctx->A);
-	SIVAL(digest, 4, ctx->B);
-	SIVAL(digest, 8, ctx->C);
-	SIVAL(digest, 12, ctx->D);
+	SIVALu(digest, 0, ctx->A);
+	SIVALu(digest, 4, ctx->B);
+	SIVALu(digest, 8, ctx->C);
+	SIVALu(digest, 12, ctx->D);
 }
 
 void get_md5(uchar *out, const uchar *input, int n)
diff -Naur -X diff_ignore rsync-3.0.6_base/lib/mdigest.h rsync/lib/mdigest.h
--- rsync-3.0.6_base/lib/mdigest.h	2007-03-18 02:00:53.000000000 -0400
+++ rsync/lib/mdigest.h	2018-09-17 15:35:28.000000000 -0400
@@ -4,7 +4,7 @@
 #define MD5_DIGEST_LEN 16
 #define MAX_DIGEST_LEN MD5_DIGEST_LEN
 
-#define CSUM_CHUNK 64
+#define CSUM_CHUNK 64//4096 is ideal, but causes a math issue somewhere with a remote Mac source
 
 typedef struct {
 	uint32 A, B, C, D;
diff -Naur -X diff_ignore rsync-3.0.6_base/lib/sysacls.c rsync/lib/sysacls.c
--- rsync-3.0.6_base/lib/sysacls.c	2008-07-23 00:35:21.000000000 -0400
+++ rsync/lib/sysacls.c	2017-04-10 14:14:23.000000000 -0400
@@ -2585,10 +2585,8 @@
 }
 
 #elif defined(HAVE_OSX_ACLS) /*----------------------------------------------*/
-
-#define OSX_BROKEN_GETENTRY /* returns 0 instead of 1 */
-
-#include <membership.h>
+#pragma mark Mac OS X ACL Support
+#define OSX_BROKEN_GETENTRY /* returns 0 instead of 1 */ // Why is this called "broken"? Returning 0 on success and -1 on error is standard
 
 int sys_acl_get_entry(SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
 {
@@ -2596,7 +2594,8 @@
 #ifdef OSX_BROKEN_GETENTRY
 	if (ret == 0)
 		ret = 1;
-	else if (ret == -1 && errno == 22)
+	//else if (ret == -1 && errno == 22) // In what case is it desirable to return -1?
+	else
 		ret = 0;
 #endif
 	return ret;
@@ -2619,31 +2618,49 @@
 }
 #endif
 
-int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p)
+int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, unsigned char **uup)
 {
-	uuid_t *uup;
 	acl_tag_t tag;
 	acl_flagset_t flagset;
 	acl_permset_t permset;
 	uint32 bits, fb, bb, pb;
-	int id_type = -1;
-	int rc;
-
-	if (acl_get_tag_type(entry, &tag) != 0
-	 || acl_get_flagset_np(entry, &flagset) != 0
-	 || acl_get_permset(entry, &permset) != 0
-	 || (uup = acl_get_qualifier(entry)) == NULL)
-		return -1;
-
-	rc = mbr_uuid_to_id(*uup, u_g_id_p, &id_type);
-	acl_free(uup);
-	if (rc != 0)
-		return rc;
+	int ret = 0;
 
-	if (id_type == ID_TYPE_UID)
-		*tag_type_p = SMB_ACL_USER;
-	else
-		*tag_type_p = SMB_ACL_GROUP;
+	ret = acl_get_tag_type(entry, &tag);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_get_info: acl_get_tag_type failed: %d\n", errno);
+		return -1;
+	}
+	ret = acl_get_flagset_np(entry, &flagset);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_get_info: acl_get_flagset_np failed: %d\n", errno);
+		return -1;
+	}
+	ret = acl_get_permset(entry, &permset);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_get_info: acl_get_permset failed: %d\n", errno);
+		return -1;
+	}
+	
+	if (tag == ACL_UNDEFINED_TAG) {
+		// Apparently it is legal to have an ACE with a NULL qualifier and an invalid tag
+		// Even if it is allowed, though, it does not seem right to propagate the ACE
+		*uup = NULL;
+		//fprintf(stderr, "DEBUG: sys_acl_get_info[%s]: acl_get_qualifier failed with EINVAL. Tag type: %d. This ACE will be dropped by the receiver.\n", who_am_i(), tag);
+	} else {
+		ret = ((*uup = acl_get_qualifier(entry)) == NULL);
+		if (ret != 0) {
+			fprintf(stderr, "DEBUG: sys_acl_get_info: acl_get_qualifier failed: %d\n", errno);
+			return -1;
+		}
+	}
+
+	// OS X uses tag_type differently from other platforms. As far as rsync is concerned,
+	// tag_type is ignored for OS X because ACEs use UUID values, rather than the
+	// more ambiguous uid/gid. OS X never needs to differentiate a uid from a gid.
+	// We use "SMB_ACL_GROUP" here, but the value is ignored. We will stuff the
+	// OS X-proprietary "allow" and "deny" tag types into the access bits below
+	*tag_type_p = SMB_ACL_GROUP;
 
 	bits = tag == ACL_EXTENDED_ALLOW ? 1 : 0;
 
@@ -2672,20 +2689,33 @@
 	return acl_create_entry(pacl, pentry);
 }
 
-int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, id_t u_g_id)
+int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tag_type, uint32 bits, unsigned char *uu)
 {
 	acl_flagset_t flagset;
 	acl_permset_t permset;
 	uint32 fb, bb, pb;
-	int is_user = tag_type == SMB_ACL_USER;
-	uuid_t uu;
-	int rc;
+	int ret;
+
+	// Drop entries with null uuids
+	if (uu[0] == '\0') {
+		//fprintf(stderr, "DEBUG: sys_acl_set_info[%s]: Dropping ACE with NULL UUID\n", who_am_i());
+		return 0;
+	}
 
+	// tag_type (as passed in to this function) is ignored on OS X, see sys_acl_get_info()
+	// We instead infer the OS X-specific tag type from the access bits
 	tag_type = bits & 1 ? ACL_EXTENDED_ALLOW : ACL_EXTENDED_DENY;
 
-	if (acl_get_flagset_np(entry, &flagset) != 0
-	 || acl_get_permset(entry, &permset) != 0)
+	ret = acl_get_flagset_np(entry, &flagset);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_set_info: acl_get_flagset_np failed: %d\n", errno);
 		return -1;
+	}
+	ret = acl_get_permset(entry, &permset);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_set_info: acl_get_permset failed: %d\n", errno);
+		return -1;
+	}
 
 	acl_clear_flags_np(flagset);
 	acl_clear_perms(permset);
@@ -2699,19 +2729,30 @@
 		if (bits & bb)
 			acl_add_perm(permset, pb);
 	}
+	
+	ret = acl_set_tag_type(entry, tag_type);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_set_info: acl_set_tag_type failed: %d\n", errno);
+		return -1;
+	}
 
-	if (is_user)
-		rc = mbr_uid_to_uuid(u_g_id, uu);
-	else
-		rc = mbr_gid_to_uuid(u_g_id, uu);
-	if (rc != 0)
-		return rc;
-
-	if (acl_set_tag_type(entry, tag_type) != 0
-	 || acl_set_qualifier(entry, &uu) != 0
-	 || acl_set_permset(entry, permset) != 0
-	 || acl_set_flagset_np(entry, flagset) != 0)
+	ret = acl_set_qualifier(entry, uu);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_set_info: acl_set_qualifier failed: %d\n", errno);
 		return -1;
+	}
+
+	ret = acl_set_permset(entry, permset);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_set_info: acl_set_permset failed: %d\n", errno);
+		return -1;
+	}
+
+	ret = acl_set_flagset_np(entry, flagset);
+	if (ret != 0) {
+		fprintf(stderr, "sys_acl_set_info: acl_set_flagset_np failed: %d\n", errno);
+		return -1;
+	}
 
 	return 0;
 }
@@ -2742,7 +2783,8 @@
 
 int sys_acl_delete_def_file(const char *name)
 {
-	return acl_delete_def_file(name);
+	//return acl_delete_def_file(name);
+	return 0; /* Not supported on Mac OS X */
 }
 
 int sys_acl_free_acl(SMB_ACL_T the_acl)
diff -Naur -X diff_ignore rsync-3.0.6_base/lib/sysacls.h rsync/lib/sysacls.h
--- rsync-3.0.6_base/lib/sysacls.h	2008-03-01 15:01:41.000000000 -0500
+++ rsync/lib/sysacls.h	2014-12-06 21:12:18.000000000 -0500
@@ -264,6 +264,7 @@
 
 #define SMB_ACL_ENTRY_T		acl_entry_t
 
+// ACL types
 #define SMB_ACL_USER		1
 #define SMB_ACL_GROUP		2
 
@@ -288,12 +289,20 @@
 
 int sys_acl_get_entry(SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p);
 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p);
+#ifdef HAVE_OSX_ACLS
+int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, unsigned char **uup);
+#else
 int sys_acl_get_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T *tag_type_p, uint32 *bits_p, id_t *u_g_id_p);
+#endif
 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type);
 SMB_ACL_T sys_acl_get_fd(int fd);
 SMB_ACL_T sys_acl_init(int count);
 int sys_acl_create_entry(SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry);
+#ifdef HAVE_OSX_ACLS
+int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype, uint32 bits, unsigned char *uu);
+#else
 int sys_acl_set_info(SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype, uint32 bits, id_t u_g_id);
+#endif
 int sys_acl_set_access_bits(SMB_ACL_ENTRY_T entry, uint32 bits);
 int sys_acl_valid(SMB_ACL_T theacl);
 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
diff -Naur -X diff_ignore rsync-3.0.6_base/lib/sysxattrs.c rsync/lib/sysxattrs.c
--- rsync-3.0.6_base/lib/sysxattrs.c	2008-03-01 15:01:41.000000000 -0500
+++ rsync/lib/sysxattrs.c	2018-09-17 15:35:28.000000000 -0400
@@ -22,6 +22,12 @@
 #include "rsync.h"
 #include "sysxattrs.h"
 
+#ifdef HAVE_OSX_XATTRS
+int xattr_options = XATTR_NOFOLLOW;
+#endif
+extern int preserve_hfs_compression;
+static time_t last_hb;
+
 #ifdef SUPPORT_XATTRS
 
 #if defined HAVE_LINUX_XATTRS
@@ -52,30 +58,100 @@
 }
 
 #elif HAVE_OSX_XATTRS
+#pragma mark Mac OS X xattrs
+
+#define XATTR_ROOTLESS_NAME "com.apple.rootless"
 
 ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
 {
-	return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
+	ssize_t len;
+
+	if (strcmp(name, "com.apple.finder.copy.source.checksum#N") == 0) {
+		//fprintf(stderr, "DEBUG: Dropping com.apple.finder.copy.source.checksum#N xattr on %s\n", path);
+		errno = ENOATTR;
+		return -1;
+	}
+
+	if (preserve_hfs_compression > 0)
+		xattr_options |= XATTR_SHOWCOMPRESSION;
+
+	// getxattr() will allow us to fetch up to 64MB of data in one shot.
+	// Some NAS devices, however, fail to deliver more than 1MB at a time,
+	// so we'll loop and read the next chunk until we have everything.
+	// The offset is only applicable when fetching resource forks
+	if (value != NULL && strcmp(name, XATTR_RESOURCEFORK_NAME) == 0) {
+		u_int32_t offset = 0;
+		last_hb = time(NULL);
+		errno = 0;
+		while (offset < size && errno == 0) {
+			time_t now = time(NULL);
+			if (now - last_hb >= 5) {
+				last_hb = now;
+				rprintf(FINFO, "S;;;HRTBT;;;LEN;;;%.0u;;;CF;;;%s\n", offset, path);
+			}
+			errno = 0;
+			len = getxattr(path, name, value + offset, size, offset, xattr_options);
+			if (len > 0)
+				offset += len;
+		}
+		len = offset;
+	} else {
+		len = getxattr(path, name, value, size, 0, xattr_options);
+	}
+
+	return len;
 }
 
 ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
 {
-	return fgetxattr(filedes, name, value, size, 0, 0);
+	return fgetxattr(filedes, name, value, size, 0, (preserve_hfs_compression > 0) ? XATTR_SHOWCOMPRESSION : 0);
 }
 
 int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
 {
-	return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
+	int ret = 0;
+	
+//	if (strcmp(name, XATTR_ROOTLESS_NAME) == 0) {
+//		fprintf(stderr, "DEBUG: Dropping com.apple.rootless xattr on %s\n", path);
+//		return ret;
+//	}
+
+	// If we're transferring a resource fork that is > SETXATTR_CHUNKSIZE, chunk the data to avoid io timeouts
+	if (value != NULL && strcmp(name, XATTR_RESOURCEFORK_NAME) == 0) {
+		u_int32_t offset = 0;
+		u_int32_t nextChunk = size - offset > SETXATTR_CHUNKSIZE ? SETXATTR_CHUNKSIZE : size - offset;
+		last_hb = time(NULL);
+		while (offset < size && ret == 0) {
+			time_t now = time(NULL);
+			if (now - last_hb >= 5) {
+				last_hb = now;
+				rprintf(FINFO, "S;;;HRTBT;;;LEN;;;%.0u;;;CF;;;%s\n", offset, path);
+			}
+			errno = 0;
+			ret = setxattr(path, name, value + offset, nextChunk, offset, xattr_options);
+			offset += nextChunk;
+			nextChunk = size - offset > SETXATTR_CHUNKSIZE ? SETXATTR_CHUNKSIZE : size - offset;
+		}
+
+	} else {
+		ret = setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
+	}
+	
+	return ret;
 }
 
 int sys_lremovexattr(const char *path, const char *name)
 {
-	return removexattr(path, name, XATTR_NOFOLLOW);
+	//if (preserve_hfs_compression > 0)
+		xattr_options |= XATTR_SHOWCOMPRESSION;
+	return removexattr(path, name, xattr_options);
 }
 
 ssize_t sys_llistxattr(const char *path, char *list, size_t size)
 {
-	return listxattr(path, list, size, XATTR_NOFOLLOW);
+	if (preserve_hfs_compression > 0)
+		xattr_options |= XATTR_SHOWCOMPRESSION;
+	return listxattr(path, list, size, xattr_options);
 }
 
 #elif HAVE_FREEBSD_XATTRS
diff -Naur -X diff_ignore rsync-3.0.6_base/log.c rsync/log.c
--- rsync-3.0.6_base/log.c	2010-10-25 14:18:07.000000000 -0400
+++ rsync/log.c	2014-12-06 21:12:18.000000000 -0500
@@ -21,6 +21,7 @@
 
 #include "rsync.h"
 #include "ifuncs.h"
+#include <sys/un.h>
 
 extern int verbose;
 extern int dry_run;
@@ -118,8 +119,7 @@
 	if (logfile_was_closed)
 		logfile_reopen();
 	if (logfile_fp) {
-		fprintf(logfile_fp, "%s [%d] %s",
-			timestring(time(NULL)), (int)getpid(), buf);
+		fprintf(logfile_fp, "%s", buf);
 		fflush(logfile_fp);
 	} else {
 		syslog(priority, "%s", buf);
@@ -152,16 +152,60 @@
 
 static void logfile_open(void)
 {
+	struct stat sf;
+	struct sockaddr_un sa;
+	int sock;
+	sig_t pipeSet;
+#ifdef HAVE_SIGACTION
+	static struct sigaction sigact;
+#endif
+
 	mode_t old_umask = umask(022 | orig_umask);
-	logfile_fp = fopen(logfile_name, "a");
+
+	if (stat(logfile_name, &sf) == 0 && S_ISSOCK(sf.st_mode)) {
+		pipeSet = SIGACTION(SIGPIPE, SIG_IGN);
+		if (pipeSet == SIG_ERR) {
+			fprintf(stderr, "logfile_open: Could not ignore SIGPIPE: %d\n", errno);
+			goto syslog_failover;
+		}
+		if (strlen(logfile_name) > (sizeof(sa.sun_path) - 1)) {
+			fprintf(stderr, "logfile_open: The socket file path is too long (> %u): %s\n", (uint) sizeof(sa.sun_path) - 1, logfile_name);
+			goto syslog_failover;
+		}
+
+		if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+			fprintf(stderr, "logfile_open: socket() failed: %d\n", errno);
+			goto syslog_failover;
+		}
+
+		bzero((char*) &sa, sizeof(sa));
+		sa.sun_family = AF_UNIX;
+		memmove(sa.sun_path, logfile_name, strlen(logfile_name));
+		(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, NULL, 0);
+
+		if ((connect(sock, (struct sockaddr *)(&sa), sizeof(struct sockaddr_un))) == - 1) {
+			fprintf(stderr, "logfile_open: connect() failed: %d\n", errno);
+			close(sock);
+			goto syslog_failover;
+		}
+		
+		logfile_fp = fdopen(sock, "a");
+		if (!logfile_fp)
+			close(sock);
+	} else {
+		logfile_fp = fopen(logfile_name, "a");
+	}
+
 	umask(old_umask);
 	if (!logfile_fp) {
 		int fopen_errno = errno;
-		/* Rsync falls back to using syslog on failure. */
-		syslog_init();
 		rsyserr(FERROR, fopen_errno,
 			"failed to open log-file %s", logfile_name);
 		rprintf(FINFO, "Ignoring \"log file\" setting.\n");
+
+syslog_failover:
+		/* Rsync falls back to using syslog on failure. */
+		syslog_init();
 	}
 }
 
@@ -195,8 +239,9 @@
 	 * rsyncs will have already set logfile_name, as needed.) */
 	if (am_daemon && !logfile_name)
 		logfile_name = lp_log_file(module_id);
-	if (logfile_name && *logfile_name)
+	if (logfile_name && *logfile_name) {
 		logfile_open();
+	}
 	else
 		syslog_init();
 }
@@ -274,7 +319,8 @@
 
 	if (code == FCLIENT)
 		code = FINFO;
-	else if (am_daemon || logfile_name) {
+	// BOMBICH -- added " && (logfile_name && code != FINFO)" -- I don't want FINFO messages going to the log
+	else if (am_daemon || (logfile_name && code == FLOG)) {
 		static int in_block;
 		char msg[2048];
 		int priority = code == FINFO || code == FLOG ? LOG_INFO :  LOG_WARNING;
@@ -467,7 +513,7 @@
 	int64 b;
 
 	*fmt = '%';
-
+	
 	/* We expand % codes one by one in place in buf.  We don't
 	 * copy in the terminating null of the inserted strings, but
 	 * rather keep going until we reach the null of the format. */
@@ -502,8 +548,9 @@
 			break;
 		case 'l':
 			strlcat(fmt, ".0f", sizeof fmt);
+			double flength = stats.total_transferred_size - initial_stats->total_transferred_size;
 			snprintf(buf2, sizeof buf2, fmt,
-				 (double)F_LENGTH(file));
+				 flength);
 			n = buf2;
 			break;
 		case 'U':
@@ -529,9 +576,13 @@
 			n = buf2;
 			break;
 		case 'M':
-			n = c = timestring(file->modtime);
-			while ((c = strchr(c, ' ')) != NULL)
-				*c = '-';
+			strlcat(fmt, ".0lu", sizeof fmt);
+			snprintf(buf2, sizeof buf2, fmt,
+				 (unsigned long)file->modtime);
+			n = buf2;
+//			n = c = timestring(file->modtime);
+//			while ((c = strchr(c, ' ')) != NULL)
+//				*c = '-';
 			break;
 		case 'B':
 			c = buf2 + MAXPATHLEN - PERMSTRING_SIZE - 1;
@@ -658,13 +709,19 @@
 			n = buf2;
 			break;
 		case 'i':
-			if (iflags & ITEM_DELETED) {
-				n = "*deleting  ";
-				break;
-			}
+//			if (iflags & ITEM_DELETED) {
+//				n = "*deleting   ";
+//				break;
+//			}
 			n  = c = buf2 + MAXPATHLEN - 32;
 			c[0] = iflags & ITEM_LOCAL_CHANGE
 			      ? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
+			     : (iflags & ITEM_HAD_ERRORS_SOURCE) ? 'E'
+			     : (iflags & ITEM_HAD_ERRORS_DEST) ? '3'
+			     : (iflags & ITEM_DELETED) ? '*'
+			     : (iflags & ITEM_EXCLUDED) ? 'X'
+			     : (iflags & ITEM_PROTECTED) ? '('
+			     : (iflags & ITEM_ARCHIVED) ? 'A'
 			     : !(iflags & ITEM_TRANSFER) ? '.'
 			     : !local_server && *op == 's' ? '<' : '>';
 			if (S_ISLNK(file->mode)) {
@@ -776,7 +833,7 @@
 {
 	const char *s_or_r = am_sender ? "send" : "recv";
 
-	if (code != FLOG && stdout_format && !am_server) {
+	if (code != FLOG && stdout_format && !am_server && verbose > 1) {
 		log_formatted(FCLIENT, stdout_format, s_or_r,
 			      file, NULL, initial_stats, iflags, hlink);
 	}
@@ -815,25 +872,63 @@
 
 	x.file.mode = mode;
 
-	if (!verbose && !stdout_format)
-		;
-	else if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
+//	if (!verbose && !stdout_format)
+//		;
+	if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
 		if (S_ISDIR(mode))
 			len++; /* directories include trailing null */
 		send_msg(MSG_DELETED, fname, len, am_generator);
-	} else {
+	} else if (verbose) {
 		fmt = stdout_format_has_o_or_i ? stdout_format : "deleting %n";
 		log_formatted(FCLIENT, fmt, "del.", &x.file, fname, &stats,
 			      ITEM_DELETED, NULL);
 	}
 
-	if (!logfile_name || dry_run || !logfile_format)
+	if (!logfile_name || !logfile_format)
 		return;
 
 	fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n";
 	log_formatted(FLOG, fmt, "del.", &x.file, fname, &stats, ITEM_DELETED, NULL);
 }
 
+void log_non_transfer(const char *fname, int mode, int iflags)
+{
+	static struct {
+		union file_extras ex[4]; /* just in case... */
+		struct file_struct file;
+	} x;
+	int len = strlen(fname);
+	const char *fmt, *prefix;
+	int msg;
+
+	x.file.mode = mode;
+	if (iflags & (ITEM_EXCLUDED | ITEM_PROTECTED)) {
+		fmt = stdout_format_has_o_or_i ? stdout_format : "filtering %n";
+		msg = MSG_FILTERED;
+		prefix = "fil.";
+	} else {
+		fmt = stdout_format_has_o_or_i ? stdout_format : "archiving %n";
+		msg = MSG_ARCHIVED;
+		prefix = "arc.";
+	}
+
+	if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
+		if (S_ISDIR(mode))
+			len++; /* directories include trailing null */
+		send_msg(msg, fname, len, am_generator);
+	} else if (verbose) {
+		log_formatted(FCLIENT, fmt, prefix, &x.file, fname, &stats,
+			      iflags, NULL);
+	}
+
+	if (!logfile_name || !logfile_format)
+		return;
+
+	fmt = logfile_format_has_o_or_i ? logfile_format : 
+				iflags & (ITEM_EXCLUDED | ITEM_PROTECTED) ? "filtering %n" : "archiving %n";
+	log_formatted(FLOG, fmt, prefix, &x.file, fname, &stats, iflags, NULL);
+}
+
 /*
  * Called when the transfer is interrupted for some reason.
  *
@@ -843,6 +938,7 @@
 void log_exit(int code, const char *file, int line)
 {
 	if (code == 0) {
+		if (verbose)
 		rprintf(FLOG,"sent %.0f bytes  received %.0f bytes  total size %.0f\n",
 			(double)stats.total_written,
 			(double)stats.total_read,
diff -Naur -X diff_ignore rsync-3.0.6_base/main.c rsync/main.c
--- rsync-3.0.6_base/main.c	2010-10-25 14:18:07.000000000 -0400
+++ rsync/main.c	2019-01-14 13:39:39.000000000 -0500
@@ -27,6 +27,31 @@
 #include <locale.h>
 #endif
 
+#include <math.h>
+#ifndef _PC_XATTR_SIZE_BITS
+#define _PC_XATTR_SIZE_BITS 26
+#endif
+
+
+// For getattrlist()
+#include <sys/attr.h>
+
+// For dirname()
+#include <libgen.h>
+
+// For chflags
+#include <sys/stat.h>
+#include <unistd.h>
+
+// For statfs():
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#ifdef SUPPORT_FORCE_CHANGE
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int list_only;
@@ -35,6 +60,7 @@
 extern int am_sender;
 extern int am_generator;
 extern int am_daemon;
+int rcvr_is_non_local_server = 0;
 extern int inc_recurse;
 extern int blocking_io;
 extern int always_checksum;
@@ -49,6 +75,24 @@
 extern int copy_unsafe_links;
 extern int keep_dirlinks;
 extern int preserve_hard_links;
+extern int preserve_hfs_compression;
+int fs_supports_hfs_compression = 0;
+extern uid_t sender_uid;
+extern uid_t receiver_uid;
+int write_size;
+extern float write_size_multiplier;
+extern int force_change;
+extern int preserve_fileflags;
+extern int preserve_acls;
+extern int preserve_uid;
+extern int preserve_gid;
+int disable_acl_support = 0;
+int ownershipDisabledOnDest = 0;
+int unsupported_fileflags = 0;
+int fs_supports_native_xattrs = 0;
+long pc_name_max = NAME_MAX;
+size_t pc_xattr_max_size = 4096;
+extern int preserve_links;
 extern int protocol_version;
 extern int file_total;
 extern int recurse;
@@ -89,6 +133,8 @@
 mode_t orig_umask = 0;
 int batch_gen_fd = -1;
 int sender_keeps_checksum = 0;
+const char *srcRoot;
+const char *dstRoot;
 
 /* There's probably never more than at most 2 outstanding child processes,
  * but set it higher, just in case. */
@@ -246,6 +292,9 @@
 	if (do_stats) {
 		rprintf(FCLIENT, "\n");
 		rprintf(FINFO,"Number of files: %d\n", stats.num_files);
+		rprintf(FINFO,"Number of extended attributes: %d\n", stats.num_xattrs);
+		rprintf(FINFO,"Size of transferred xattrs: %s bytes\n",
+			human_num(stats.xattr_transfer_size));
 		rprintf(FINFO,"Number of files transferred: %d\n",
 			stats.num_transferred_files);
 		rprintf(FINFO,"Total file size: %s bytes\n",
@@ -272,7 +321,7 @@
 			human_num(total_read));
 	}
 
-	if (verbose || do_stats) {
+	if (verbose > 1 || do_stats) {
 		rprintf(FCLIENT, "\n");
 		rprintf(FINFO,
 			"sent %s bytes  received %s bytes  %s bytes/sec\n",
@@ -584,7 +633,7 @@
 		 && strcmp(flist->files[flist->low]->basename, ".") == 0)
 			flist->files[0]->flags |= FLAG_DIR_CREATED;
 
-		if (verbose)
+		if (verbose > 1)
 			rprintf(FINFO, "created directory %s\n", dest_path);
 
 		if (dry_run) {
@@ -907,6 +956,7 @@
 		recv_additional_file_list(f_in);
 	verbose = save_verbose;
 
+	//fprintf(stderr, "DEBUG: [%s]do_server_recv received %d items\n", who_am_i(), flist->used);
 	if (argc > 0)
 		local_name = get_local_name(flist,argv[0]);
 
@@ -953,25 +1003,355 @@
 }
 
 
+int filesystem_capabilities(const char *path, struct statfs *fsb, u_int32_t *capability_fmt, u_int32_t *capability_int)
+{
+	char *parent;
+	int ret, saved_err;
+	
+	ret = statfs(path, fsb);
+	if (ret != 0) {
+		saved_err = errno;
+		if ((parent = dirname((char *)path)) != NULL)
+			ret = statfs(parent, fsb);
+		errno = saved_err;
+	}
+	
+	if (ret == 0) {
+		struct attrlist attrs;
+		struct {
+			int32_t len;
+			vol_capabilities_set_t caps;
+		} attrData;
+		
+		bzero(&attrs, sizeof(attrs));
+		attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
+		attrs.volattr = ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES;
+		
+		bzero(&attrData, sizeof(attrData));
+		attrData.len = sizeof(attrData);
+		
+		ret = getattrlist(fsb->f_mntonname, &attrs, &attrData, sizeof(attrData), 0);
+		if (ret == 0) {
+			*capability_fmt = attrData.caps[VOL_CAPABILITIES_FORMAT];
+			*capability_int = attrData.caps[VOL_CAPABILITIES_INTERFACES];
+		} else {
+			rprintf(FERROR, "Failure in getattrlist while determining filesystem capabilities on %s (%s): %s\n", path, who_am_i(), strerror(errno));
+		}
+	} else {
+		rprintf(FERROR, "Failure in statfs while determining filesystem capabilities on %s (%s): %s\n", path, who_am_i(), strerror(errno));
+	}
+	return ret;
+}
+
+void do_filesystem_compatibility_checks(const char *path)
+{
+	u_int32_t capability_fmt;
+	u_int32_t capability_int;
+	struct statfs fsb;
+
+	if (verbose > 1)
+		fprintf(stderr, "do_filesystem_compatibility_checks: filesystem_capabilities(%s)\n", path);
+	
+	if (am_sender)
+		srcRoot = path;
+	else
+		dstRoot = path;
+
+	// BOMBICH
+#ifdef ARCH_IS_64
+	fprintf(stderr, "DEBUG: [%s] Running the x86_64 executable\n", who_am_i());
+#endif
+	// Set euid as requested by caller
+	uid_t my_uid = am_sender ? sender_uid : receiver_uid;
+	uid_t savedEuid = geteuid();
+	if (savedEuid == 0 && my_uid != 0) {
+		seteuid(my_uid);
+	}
+	fprintf(stderr, "DEBUG: [dfcc: %s] Effective UID is %d for %s [Saved euid: %d]\n", who_am_i(), geteuid(), path, savedEuid);
+	//sleep(10);
+	
+// I may eventually want to add an argument to modify this behavior,
+// but for now, I want it to be the default
+#define DONT_CREATE_TARGET_ROOT 1
+#if DONT_CREATE_TARGET_ROOT
+	struct stat st;
+	st.st_mode = 0;
+	errno = 0;
+	int doStatRet = do_stat(path, &st);
+	if (doStatRet != 0 && errno == EACCES && savedEuid != my_uid) {
+		fprintf(stderr, "DEBUG: stat on %s root directory failed with EACCES. Setting effective UID back to %d and trying again\n", am_sender ? "source" : "destination", savedEuid);
+		seteuid(savedEuid);
+		st.st_mode = 0;
+		errno = 0;
+		doStatRet = do_stat(path, &st);
+		if (doStatRet == 0) {
+			fprintf(stderr, "DEBUG: stat on %s root directory succeeded with euid of %d\n", am_sender ? "source" : "destination", savedEuid);
+			if (am_sender)
+				sender_uid = savedEuid;
+			else
+				receiver_uid = savedEuid;
+		}
+	}
+
+	if (doStatRet != 0 || !S_ISDIR(st.st_mode)) {
+		rprintf(FERROR, "ERROR: %s root directory does not exist (\"%s\") (%d,%d,%o)\n", am_sender ? "source" : "destination", path, doStatRet, errno, st.st_mode);
+		exit_cleanup(RERR_FILESELECT);
+	} else {
+		fprintf(stderr, "DEBUG: %s: %d:%o\n", path, st.st_uid, st.st_mode);
+	}
+#endif
+
+	if (filesystem_capabilities(path, &fsb, &capability_fmt, &capability_int) != 0) {
+		fprintf(stderr, "DEBUG: [dfcc: %s] Setting effective UID back to %d for %s\n", who_am_i(), savedEuid, am_sender ? "source" : "dest");
+		seteuid(savedEuid);
+		return;
+	}
+
+#ifdef SUPPORT_HFS_COMPRESSION
+	fs_supports_hfs_compression = capability_fmt & VOL_CAP_FMT_DECMPFS_COMPRESSION;
+	if (verbose > 1)
+		fprintf(stderr, "do_filesystem_compatibility_checks: fs_supports_hfs_compression = %d, preserve_hfs_compression: %d\n", fs_supports_hfs_compression, preserve_hfs_compression);
+	if (preserve_hfs_compression > 0) {
+		// If the filesystem doesn't support compression and 
+		// decmpfs protection wasn't requested, disable support for compression
+		if (!fs_supports_hfs_compression && preserve_hfs_compression < 2) {
+			preserve_hfs_compression = 0;
+			unsupported_fileflags |= UF_COMPRESSED;
+			rprintf(FERROR, "DEBUG: %s: Disabling HFS compression support, %s doesn't support it (use --protect-decmpfs to force protection of the com.apple.decmpfs extended attribute).\n", who_am_i(), path);
+		}
+	}
+#endif
+
+#ifdef SUPPORT_ACLS
+	int acls_supported = capability_int & VOL_CAP_INT_EXTENDED_SECURITY;
+	if (verbose)
+		rprintf(FERROR, "DEBUG: ACLs are %s on %s\n", acls_supported ? "supported" : "not supported", path);
+	if (!am_sender && preserve_acls && !acls_supported) {
+		//preserve_acls = 0; // This creates a protocol incompatiblity because we can't communicate it to the other side
+		disable_acl_support = 1;
+		rsyserr(FERROR, ENOTSUP, "Disabling ACL support, \"%s\" doesn't support it", path);
+	}
+#endif
+
+// Determine if the filesystem supports native extended attributes (e.g. vs. stuffing them into AppleDouble files)
+// Not providing native support for extended attributes doesn't mean that support for xattrs should be disabled
+// The setxattr() implementation should automatically handle non-native xattr implementations
+// If the fs supports xattrs natively, then we will handle resource forks like regular files (writing with setxattr at offsets though).
+// If the fs does not support native xattrs, then resource forks will be treated like all other xattrs 
+// Re-enable this block when support for Tiger is dropped (Tiger doesn't report whether xattrs are supported)
+#ifdef SUPPORT_XATTRS
+	fs_supports_native_xattrs = capability_int & VOL_CAP_INT_EXTENDED_ATTR;
+	if (verbose)
+		rprintf(FERROR, "DEBUG: Extended Attributes are %s on %s\n", fs_supports_native_xattrs ? "supported" : "not supported", path);
+#endif
+
+#ifdef SUPPORT_HARD_LINKS
+	int hl_supported = capability_fmt & VOL_CAP_FMT_HARDLINKS;
+	if (verbose)
+		rprintf(FERROR, "DEBUG: Hard Links are %s on %s (%d)\n", hl_supported ? "supported" : "not supported", path, hl_supported);
+	if (preserve_hard_links && !hl_supported) {
+		preserve_hard_links = 0;
+		rsyserr(FERROR, ENOTSUP, "Disabling Hard Link support, \"%s\" doesn't support them", path);
+	}
+	
+	int cs_supported = capability_fmt & VOL_CAP_FMT_CASE_SENSITIVE;
+	rprintf(FERROR, "DEBUG: %s %s case sensitivity (%d)\n", path, cs_supported ? "supports" : "does not support", cs_supported);
+	
+#endif
+
+//#ifdef SUPPORT_LINKS
+//	int sl_supported = capability_fmt & VOL_CAP_FMT_SYMBOLICLINKS;
+//	if (verbose)
+//		rprintf(FINFO, "DEBUG: Symbolic Links are %s on %s (%d)\n", sl_supported ? "supported" : "not supported", path, sl_supported);
+//	if (preserve_hard_links && !sl_supported) {
+//		preserve_links = 0;
+//		rsyserr(FERROR, ENOTSUP, "Disabling Symbolic Link support, \"%s\" doesn't support them", path);
+//	}
+//	
+//#endif
+
+#ifdef SUPPORT_FORCE_CHANGE
+	if (force_change & SYS_IMMUTABLE) {
+		// determine whether we'll be able to unlock a system immutable item
+		int mib[2];
+		int securityLevel = 0;
+		size_t len = sizeof(securityLevel);
+
+		mib[0] = CTL_KERN;
+		mib[1] = KERN_SECURELVL;
+		if (sysctl(mib, 2, &securityLevel, &len, NULL, 0) == 0 && securityLevel > 0) {
+			//rprintf(FINFO, "System security level is too high to force mutability on system immutable files and directories.\n");
+			force_change = force_change & USR_IMMUTABLE ? USR_IMMUTABLE : 0;
+		}
+	}
+#endif
+
+#ifdef SUPPORT_FILEFLAGS
+	if (preserve_fileflags) {
+		if (dry_run != 0) {
+			fprintf(stderr, "DEBUG: [%s] Skipping fileflags test during dry run\n", who_am_i());
+		} else {
+			// Unfortunately there's no way to interrogate the
+			// filesystem directly to learn which flags are supported
+			// Instead, we'll test the available flags (except for
+			// system immutable and system appendable) to see if any flags are unsupported
+			char testfile[MAXPATHLEN];
+			int volIsLocal = fsb.f_flags & MNT_LOCAL;
+			if (snprintf(testfile, MAXPATHLEN, "%s/.fileflags_compat", path) > 0) {
+				// If the filesystem wasn't mounted as root, and I'm running as root,
+				// I need to seteuid() to the fs owner otherwise open(foo, O_CREAT) fails
+				// I also need to add SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND to unsupported_fileflags because those
+				// bits are only settable by root, and I won't be root for this fs
+				if (geteuid() != 0 || !volIsLocal)
+					unsupported_fileflags |= SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND | SF_RESTRICTED | SF_NOUNLINK;
+
+				if (force_change && (st.st_flags & UF_IMMUTABLE) > 0) {
+					errno = 0;
+					int ret = make_mutable(path, st.st_mode, st.st_flags, force_change);
+					if (!am_sender || errno != EROFS)
+						fprintf(stderr, "DEBUG: %s was locked. Attempt to unlock it %s [%d]\n", path, ret == 1 ? "succeeded" : ret == -1 ? "failed" : "was not required", errno);
+				}
+
+				int tfd = do_open(testfile, O_RDONLY | O_CREAT, 0666);
+				if (tfd > 0) {
+					close(tfd);
+					
+					if (chflags(testfile, 0) != 0 && errno == ENOTSUP) {
+						// Disable fileflags altogether
+						rsyserr(FERROR, ENOTSUP, "Disabling File Flags support, \"%s\" doesn't support them", path);
+						// Setting preserve_fileflags to 0 would create a protocol incompatibility, so we just mask them all off instead
+						unsupported_fileflags = ALL_FFLAGS;
+					
+					} else {
+						if (chflags(testfile, UF_NODUMP) != 0 && errno == EINVAL)
+							unsupported_fileflags |= UF_NODUMP;
+						if (chflags(testfile, UF_IMMUTABLE) != 0 && errno == EINVAL)
+							unsupported_fileflags |= UF_IMMUTABLE;
+						if (chflags(testfile, UF_APPEND) != 0 && errno == EINVAL)
+							unsupported_fileflags |= UF_APPEND;
+						if (chflags(testfile, UF_OPAQUE) != 0 && errno == EINVAL)
+							unsupported_fileflags |= UF_OPAQUE;
+						// The UF_COMPRESSED flag is handled above in the HFS compression section
+	//					if (chflags(testfile, UF_COMPRESSED) != 0 && errno == EINVAL)
+	//						unsupported_fileflags |= UF_COMPRESSED;
+						if (chflags(testfile, UF_TRACKED) != 0 && errno == EINVAL)
+							unsupported_fileflags |= UF_TRACKED;
+						if (chflags(testfile, UF_HIDDEN) != 0 && errno == EINVAL)
+							unsupported_fileflags |= UF_HIDDEN;
+
+						if (geteuid() == 0 && chflags(testfile, SF_ARCHIVED) != 0 && errno == EINVAL)
+							unsupported_fileflags |= SF_ARCHIVED;
+						// Don't test the following flags because the system security level may
+						// require single user mode to delete the test file
+						//if (chflags(testfile, SF_APPEND) != 0 && errno == EINVAL)
+						//	unsupported_fileflags |= SF_APPEND;
+						//if (chflags(testfile, SF_IMMUTABLE) != 0 && errno == EINVAL)
+						//	unsupported_fileflags |= SF_IMMUTABLE;
+						
+						chflags(testfile, 0);
+
+						fprintf(stderr, "DEBUG: [%s] Fileflags mask for %s: %d\n", who_am_i(), path, unsupported_fileflags);
+					}
+					
+					unlink(testfile);
+				} else if (errno == EROFS || errno == EACCES) {
+					fprintf(stderr, "DEBUG: [dfcc: %s] Cannot determine the level of fileflags support because the %s is read only or we don't have an adequate level of access\n", who_am_i(), am_sender ? "source" : "dest");
+				} else {
+					// Disable fileflags altogether
+					rsyserr(FERROR, ENOTSUP, "Disabling File Flags support, unable to determine support for them on \"%s\"", path);
+					// Setting preserve_fileflags to 0 would create a protocol incompatibility, so we just mask them all off instead
+					unsupported_fileflags = ALL_FFLAGS;
+				}
+				
+				if (force_change && (st.st_flags & UF_IMMUTABLE) > 0) {
+					errno = 0;
+					int ret = undo_make_mutable(path, st.st_flags);
+					if (!am_sender || errno != EROFS)
+						fprintf(stderr, "DEBUG: Re-locking %s %s. [%d]\n", path, ret > 0 ? "succeeded" : "failed", errno);
+				}
+			}
+		}
+	}
+#endif
+
+	if (!am_sender) {
+		// Determine the maximum number of bytes in a file name 
+		long _name_chars_max = pathconf(path, _PC_NAME_CHARS_MAX);
+		if (_name_chars_max == -1) {
+			fprintf(stderr, "DEBUG: Destination filesystem doesn't support _PC_NAME_CHARS_MAX, will use _PC_NAME_MAX instead\n");
+			_name_chars_max = pathconf(path, _PC_NAME_MAX);
+		}
+		
+		if (_name_chars_max != -1 && _name_chars_max < NAME_MAX)
+			pc_name_max = _name_chars_max;
+
+		if (pc_name_max < NAME_MAX)
+			fprintf(stderr, "DEBUG: Max file name length for the destination filesystem is %ld\n", pc_name_max);
+		
+		// Determine the maximum size allowed for non-resource-fork xattrs
+		long ret = pathconf(path, _PC_XATTR_SIZE_BITS);
+		if (ret > 0) {
+			if (ret == 18 || ret > 31)
+				pc_xattr_max_size = 131072; // 128KB
+			else
+				pc_xattr_max_size = exp2(ret) - 1;
+		}
+		fprintf(stderr, "DEBUG: Max xattr size for the destination filesystem is %ld bytes\n", pc_xattr_max_size);
+		
+		write_size = (int)((float)fsb.f_iosize * write_size_multiplier);
+		if (write_size <= 0)
+			write_size = 1024*1024*write_size_multiplier;
+		fprintf(stderr, "DEBUG: Setting write size to %d (%d * %.2f)\n", write_size, fsb.f_iosize, write_size_multiplier);
+	}
+
+	
+	// Now reset euid back to what it was originally.
+	// If it needs to be something else, start_client() 
+	// will set the required value.
+	fprintf(stderr, "DEBUG: [dfcc: %s] Setting effective UID back to %d for %s\n", who_am_i(), savedEuid, am_sender ? "source" : "dest");
+	seteuid(savedEuid);
+
+	
+	// Determine if we can set ownership on files
+	if (geteuid() == 0 && receiver_uid == 0 && !am_sender) {
+		ownershipDisabledOnDest = (fsb.f_flags & MNT_LOCAL) > 0 ? (fsb.f_flags & MNT_IGNORE_OWNERSHIP) > 0 : 1;
+		if (ownershipDisabledOnDest)
+			rsyserr(FERROR, ENOTSUP, "Disabling Owner and Group support, \"%s\" doesn't support those attributes", path);
+	}
+	
+}
+
 void start_server(int f_in, int f_out, int argc, char *argv[])
 {
 	set_nonblocking(f_in);
 	set_nonblocking(f_out);
 
 	io_set_sock_fds(f_in, f_out);
+	if (!local_server)
+		do_filesystem_compatibility_checks(argv[argc - 1]);
 	setup_protocol(f_out, f_in);
 
 	if (protocol_version >= 23)
 		io_start_multiplex_out();
 
+	// BOMBICH
+	uid_t my_uid = am_sender ? sender_uid : receiver_uid;
+	if (geteuid() == 0 && my_uid != 0) {
+		fprintf(stderr, "DEBUG: [start_server: %s] Setting effective UID to %d\n", who_am_i(), my_uid);
+		seteuid(my_uid);
+		am_root = geteuid() == 0;
+	}
+
 	if (am_sender) {
 		keep_dirlinks = 0; /* Must be disabled on the sender. */
 		if (need_messages_from_generator)
 			io_start_multiplex_in();
 		recv_filter_list(f_in);
 		do_server_sender(f_in, f_out, argc, argv);
-	} else
+	} else {
+		rcvr_is_non_local_server = local_server ? 0 : 1;
 		do_server_recv(f_in, f_out, argc, argv);
+	}
 	exit_cleanup(0);
 }
 
@@ -1008,6 +1388,15 @@
 	if (am_sender) {
 		keep_dirlinks = 0; /* Must be disabled on the sender. */
 
+//#ifdef ARCH_IS_64
+//	fprintf(stderr, "DEBUG: [sender] Running the x86_64 executable\n");
+//#endif
+//
+//		if (src_fs_owner != 0 && geteuid() == 0) {
+//			fprintf(stderr, "DEBUG: [sender] Setting effective UID to the filesystem owner: %d\n", src_fs_owner);
+//			seteuid(src_fs_owner);
+//		}
+
 		if (always_checksum
 		 && (log_format_has(stdout_format, 'C')
 		  || log_format_has(logfile_format, 'C')))
@@ -1028,6 +1417,7 @@
 		flist = send_file_list(f_out, argc, argv);
 		if (verbose > 3)
 			rprintf(FINFO,"file list sent\n");
+		//fprintf(stderr, "DEBUG: send_file_list sent %d items\n", flist->used);
 
 		if (protocol_version >= 23)
 			io_start_multiplex_in();
@@ -1069,6 +1459,7 @@
 	if (inc_recurse && file_total == 1)
 		recv_additional_file_list(f_in);
 
+	//fprintf(stderr, "DEBUG: [%s]client_run received %d items\n", who_am_i(), flist->used);
 	if (flist && flist->used > 0) {
 		local_name = get_local_name(flist, argv[0]);
 
@@ -1156,8 +1547,10 @@
 			am_sender = 0;
 			if (rsync_port)
 				daemon_over_rsh = shell_cmd ? 1 : -1;
+			do_filesystem_compatibility_checks(*argv);
 		} else { /* source is local, check dest arg */
 			am_sender = 1;
+			do_filesystem_compatibility_checks(argv[0]);
 
 			if (argc > 1) {
 				p = argv[--argc];
@@ -1184,7 +1577,11 @@
 					exit_cleanup(RERR_SYNTAX);
 				}
 				shell_machine = NULL;
+				am_sender = 0; // Only while we check the dest path, so dest_fs_owner gets set
+				do_filesystem_compatibility_checks(p);
+				am_sender = 1;
 			} else { /* hostspec was found, so dest is remote */
+				rcvr_is_non_local_server = 1;
 				argv[argc] = path;
 				if (rsync_port)
 					daemon_over_rsh = shell_cmd ? 1 : -1;
@@ -1272,6 +1669,17 @@
 	pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc,
 		     &f_in, &f_out);
 
+	// BOMBICH
+	if (verbose > 1) {
+		fprintf(stderr, "DEBUG: [start_client: %s] rcvr_is_non_local_server: %d\n", who_am_i(), rcvr_is_non_local_server);
+	}
+	uid_t my_uid = am_sender ? sender_uid : receiver_uid;
+	if (geteuid() == 0 && my_uid != 0) {
+		fprintf(stderr, "DEBUG: [start_client: %s] Setting effective UID to %d\n", who_am_i(), my_uid);
+		seteuid(my_uid);
+		am_root = geteuid() == 0;
+	}
+
 	/* if we're running an rsync server on the remote host over a
 	 * remote shell command, we need to do the RSYNCD protocol first */
 	if (daemon_over_rsh) {
diff -Naur -X diff_ignore rsync-3.0.6_base/match.c rsync/match.c
--- rsync-3.0.6_base/match.c	2010-10-25 14:18:07.000000000 -0400
+++ rsync/match.c	2018-05-21 13:20:01.000000000 -0400
@@ -26,6 +26,8 @@
 extern int checksum_seed;
 extern int append_mode;
 extern int checksum_len;
+extern int dont_csum_data_buffer;
+extern int rcvr_is_non_local_server;
 
 int updating_basis_file;
 char sender_file_sum[MAX_DIGEST_LEN];
@@ -41,6 +43,15 @@
 
 extern struct stats stats;
 
+// BOMBICH
+struct timeval last_update_match;
+static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
+{
+	return (t2->tv_sec - t1->tv_sec) * 1000L
+		+ (t2->tv_usec - t1->tv_usec) / 1000;
+}
+
+
 #define TRADITIONAL_TABLESIZE (1<<16)
 
 static uint32 tablesize;
@@ -125,9 +136,11 @@
 		n += s->sums[i].len;
 	}
 
-	for (j = 0; j < n; j += CHUNK_SIZE) {
-		int32 n1 = MIN(CHUNK_SIZE, n - j);
-		sum_update(map_ptr(buf, last_match + j, n1), n1);
+	if (dont_csum_data_buffer == 0) {
+		for (j = 0; j < n; j += CHUNK_SIZE) {
+			int32 n1 = MIN(CHUNK_SIZE, n - j);
+			sum_update(map_ptr(buf, last_match + j, n1), n1);
+		}
 	}
 
 	if (i >= 0)
@@ -137,6 +150,29 @@
 
 	if (buf && do_progress)
 		show_progress(last_match, buf->file_size);
+
+// BOMBICH
+#ifdef PARSEABLE_OUTPUT
+	// This provides updates when we're in the middle of copying a single file (sender)
+	if (buf && rcvr_is_non_local_server) {
+		struct timeval now;
+		gettimeofday(&now, NULL);
+		unsigned long time_diff = msdiff(&last_update_match, &now);
+		if (time_diff > 1000 && offset < buf->file_size) {
+			// sender.c provides updates that include a filename, so don't post an update here if
+			// we've reached EOF. If we had a read error, though, make sure sender updates on the very next file
+			if (buf->status != 0)
+				last_update_match.tv_sec = 0;
+			else
+				last_update_match = now;
+
+			// Presumptively report total_transferred_size + offset as long as we don't have a read error
+			//rprintf(FINFO, "S;;;STATS;;;TTS;;;%lld;;;PROG;;;%d\n", tts, ((100 * tts) / stats.total_size));
+			int64 tts = stats.total_transferred_size + (buf->status == 0 ? offset : 0);
+			rprintf(FINFO, "S;;;STATS;;;TTS;;;%lld;;;FC;;;%d\n", tts, stats.num_transferred_files);
+		}
+	}
+#endif
 }
 
 
@@ -373,9 +409,11 @@
 	} else {
 		OFF_T j;
 		/* by doing this in pieces we avoid too many seeks */
-		for (j = last_match + CHUNK_SIZE; j < len; j += CHUNK_SIZE)
+		// BOMBICH: I added the buf->status == 0 conditions so rsync will bail more quickly on read errors
+		for (j = last_match + CHUNK_SIZE; j < len && buf->status == 0; j += CHUNK_SIZE)
 			matched(f, s, buf, j, -2);
-		matched(f, s, buf, len, -1);
+		if (len == 0 || (buf && buf->status == 0))
+			matched(f, s, buf, len, -1);
 	}
 
 	if (sum_end(sender_file_sum) != checksum_len)
diff -Naur -X diff_ignore rsync-3.0.6_base/options.c rsync/options.c
--- rsync-3.0.6_base/options.c	2010-10-25 14:18:07.000000000 -0400
+++ rsync/options.c	2018-11-15 21:22:44.000000000 -0500
@@ -21,7 +21,7 @@
 
 #include "rsync.h"
 #include "ifuncs.h"
-#include <popt.h>
+#include "popt.h"
 #include "zlib/zlib.h"
 
 extern int module_id;
@@ -43,8 +43,10 @@
  * @sa disable_deltas_p()
  **/
 int whole_file = -1;
-
+float write_size_multiplier = 1.0;
+int io_buf_size = IO_BUFFER_SIZE;
 int append_mode = 0;
+int detect_case_conflicts = 0;
 int keep_dirlinks = 0;
 int copy_dirlinks = 0;
 int copy_links = 0;
@@ -52,6 +54,13 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+int preserve_hfs_compression = 0;
+int replace_dirs_with_diff_type = 0;
+int delete_modified = 0;
+int delete_deleted = 0;
+uid_t dest_file_owner = 0;
+uid_t sender_uid = 0;
+uid_t receiver_uid = 0;
 int preserve_perms = 0;
 int preserve_fileflags = 0;
 int preserve_executability = 0;
@@ -119,6 +128,7 @@
 int max_delete = INT_MIN;
 OFF_T max_size = 0;
 OFF_T min_size = 0;
+time_t max_age = 0;
 int ignore_errors = 0;
 int modify_window = 0;
 int blocking_io = -1;
@@ -192,6 +202,7 @@
 int logfile_format_has_i = 0;
 int logfile_format_has_o_or_i = 0;
 int always_checksum = 0;
+int dont_csum_data_buffer = 0;
 int list_only = 0;
 
 #define MAX_BATCH_NAME_LEN 256	/* Must be less than MAXPATHLEN-13 */
@@ -214,6 +225,7 @@
 static int refused_delete_during;
 static int refused_inplace, refused_no_iconv;
 static char *max_size_arg, *min_size_arg;
+static char *max_age_arg;
 static char tmp_partialdir[] = ".~tmp~";
 
 /** Local address to bind.  As a character string because it's
@@ -331,6 +343,7 @@
   rprintf(F," -q, --quiet                 suppress non-error messages\n");
   rprintf(F,"     --no-motd               suppress daemon-mode MOTD (see manpage caveat)\n");
   rprintf(F," -c, --checksum              skip based on checksum, not mod-time & size\n");
+  rprintf(F,"     --no-csum-data-buf      Don't verify that data written into RAM matches when read back out\n");
   rprintf(F," -a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)\n");
   rprintf(F,"     --no-OPTION             turn off an implied OPTION (e.g. --no-D)\n");
   rprintf(F," -r, --recursive             recurse into directories\n");
@@ -365,6 +378,11 @@
 #ifdef SUPPORT_XATTRS
   rprintf(F," -X, --xattrs                preserve extended attributes\n");
 #endif
+#ifdef SUPPORT_HFS_COMPRESSION
+  rprintf(F,"     --hfs-compression       preserve HFS compression (if source & destination support it)\n");
+  rprintf(F,"     --protect-decmpfs       preserve HFS compression (regardless of volume support)\n");
+#endif
+  rprintf(F,"     --replace-dirs          replace folders with items of a different type (regardless of --delete*)\n");
   rprintf(F," -o, --owner                 preserve owner (super-user only)\n");
   rprintf(F," -g, --group                 preserve group\n");
   rprintf(F,"     --devices               preserve device files (super-user only)\n");
@@ -380,6 +398,7 @@
   rprintf(F," -S, --sparse                handle sparse files efficiently\n");
   rprintf(F," -n, --dry-run               perform a trial run with no changes made\n");
   rprintf(F," -W, --whole-file            copy files whole (without delta-xfer algorithm)\n");
+  rprintf(F," -w, --write-size-mult=SIZE  Write size = dest.f_iosize * multiplier\n");
   rprintf(F," -x, --one-file-system       don't cross filesystem boundaries\n");
   rprintf(F," -B, --block-size=SIZE       force a fixed checksum block-size\n");
   rprintf(F," -e, --rsh=COMMAND           specify the remote shell to use\n");
@@ -470,9 +489,9 @@
 enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
       OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
-      OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
+      OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE, 
       OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
-      OPT_SERVER, OPT_REFUSED_BASE = 9000};
+      OPT_SERVER, OPT_MAX_AGE, OPT_REFUSED_BASE = 9000};
 
 static struct poptOption long_options[] = {
   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
@@ -571,6 +590,7 @@
   {"ignore-existing",  0,  POPT_ARG_NONE,   &ignore_existing, 0, 0, 0 },
   {"max-size",         0,  POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
   {"min-size",         0,  POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
+  {"max-age",          0,  POPT_ARG_STRING, &max_age_arg, OPT_MAX_AGE, 0, 0 },
   {"sparse",          'S', POPT_ARG_VAL,    &sparse_files, 1, 0, 0 },
   {"no-sparse",        0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
   {"no-S",             0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
@@ -586,8 +606,8 @@
   {"delete-delay",     0,  POPT_ARG_VAL,    &delete_during, 2, 0, 0 },
   {"delete-after",     0,  POPT_ARG_NONE,   &delete_after, 0, 0, 0 },
   {"delete-excluded",  0,  POPT_ARG_NONE,   &delete_excluded, 0, 0, 0 },
-  {"remove-sent-files",0,  POPT_ARG_VAL,    &remove_source_files, 2, 0, 0 }, /* deprecated */
-  {"remove-source-files",0,POPT_ARG_VAL,    &remove_source_files, 1, 0, 0 },
+//  {"remove-sent-files",0,  POPT_ARG_VAL,    &remove_source_files, 2, 0, 0 }, /* deprecated */
+//  {"remove-source-files",0,POPT_ARG_VAL,    &remove_source_files, 1, 0, 0 },
   {"force",            0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
   {"no-force",         0,  POPT_ARG_VAL,    &force_delete, 0, 0, 0 },
   {"force-delete",     0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
@@ -598,6 +618,18 @@
   {"force-uchange",    0,  POPT_ARG_VAL,    &force_change, USR_IMMUTABLE, 0, 0 },
   {"force-schange",    0,  POPT_ARG_VAL,    &force_change, SYS_IMMUTABLE, 0, 0 },
 #endif
+#ifdef SUPPORT_HFS_COMPRESSION
+  {"hfs-compression",  0,  POPT_ARG_VAL,    &preserve_hfs_compression, 1, 0, 0 },
+  {"protect-decmpfs",  0,  POPT_ARG_VAL,    &preserve_hfs_compression, 2, 0, 0 },
+  {"no-hfs-compression",0, POPT_ARG_VAL,    &preserve_hfs_compression, 0, 0, 0 },
+  {"no-protect-decmpfs",0, POPT_ARG_VAL,    &preserve_hfs_compression, 0, 0, 0 },
+#endif
+  {"replace-dirs",     0,  POPT_ARG_VAL,    &replace_dirs_with_diff_type, 1, 0, 0 },
+  {"delete-modified",  0,  POPT_ARG_VAL,    &delete_modified, 1, 0, 0 },
+  {"delete-deleted",   0,  POPT_ARG_VAL,    &delete_deleted, 1, 0, 0 },
+  {"dest-file-owner",  0,  POPT_ARG_INT,    &dest_file_owner, 0, 0, 0 },
+  {"sender-uid",	   0,  POPT_ARG_INT,    &sender_uid, 0, 0, 0 },
+  {"receiver-uid",	   0,  POPT_ARG_INT,    &receiver_uid, 0, 0, 0 },
   {"ignore-errors",    0,  POPT_ARG_VAL,    &ignore_errors, 1, 0, 0 },
   {"no-ignore-errors", 0,  POPT_ARG_VAL,    &ignore_errors, 0, 0, 0 },
   {"max-delete",       0,  POPT_ARG_INT,    &max_delete, 0, 0, 0 },
@@ -611,9 +643,14 @@
   {"whole-file",      'W', POPT_ARG_VAL,    &whole_file, 1, 0, 0 },
   {"no-whole-file",    0,  POPT_ARG_VAL,    &whole_file, 0, 0, 0 },
   {"no-W",             0,  POPT_ARG_VAL,    &whole_file, 0, 0, 0 },
+  {"write-size-mult", 'w', POPT_ARG_FLOAT,	&write_size_multiplier, 0, 0, 0 },
+  {"io-buf-size",	   0,  POPT_ARG_INT,	&io_buf_size, 0, 0, 0 },
+  {"case-conflicts",   0,  POPT_ARG_VAL,	&detect_case_conflicts, 1, 0, 0 },
+  {"no-case-conflicts",0,  POPT_ARG_VAL,	&detect_case_conflicts, 0, 0, 0 },
   {"checksum",        'c', POPT_ARG_VAL,    &always_checksum, 1, 0, 0 },
   {"no-checksum",      0,  POPT_ARG_VAL,    &always_checksum, 0, 0, 0 },
   {"no-c",             0,  POPT_ARG_VAL,    &always_checksum, 0, 0, 0 },
+  {"no-csum-data-buf", 0,  POPT_ARG_VAL,	&dont_csum_data_buffer, 1, 0, 0 },
   {"block-size",      'B', POPT_ARG_LONG,   &block_size, 0, 0, 0 },
   {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
   {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
@@ -1221,6 +1258,16 @@
 			}
 			break;
 
+		case OPT_MAX_AGE:
+			errno = 0;
+			if ((max_age = (time_t)strtoull(max_age_arg, NULL, 10)) <= 0 || errno == ERANGE) {
+				snprintf(err_buf, sizeof err_buf,
+					"--max-age value is invalid: %s\n",
+					max_age_arg);
+				return 0;
+			}
+			break;
+
 		case OPT_APPEND:
 			if (am_server)
 				append_mode++;
@@ -1374,6 +1421,30 @@
 	}
 #endif
 
+#ifdef SUPPORT_HFS_COMPRESSION
+	if (preserve_hfs_compression > 0) {
+		if (preserve_xattrs == 0)
+			preserve_xattrs++;
+		if (preserve_fileflags == 0)
+			preserve_fileflags++;
+	}
+#else
+	snprintf(err_buf,sizeof(err_buf),
+		 "HFS compression is not supported on this %s\n",
+		 am_server ? "server" : "client");
+	preserve_hfs_compression = 0;
+#endif
+
+	if (dont_csum_data_buffer) {
+		if (always_checksum) {
+			snprintf(err_buf, sizeof err_buf,
+					 "--no-csum-data-buf and --checksum can not be used together\n");
+			dont_csum_data_buffer = 0;
+		} else {
+			fprintf(stderr, "DEBUG: Copy buffer will not be checksummed\n");
+		}
+	}
+	
 	if (write_batch && read_batch) {
 		snprintf(err_buf, sizeof err_buf,
 			"--write-batch and --read-batch can not be used together\n");
@@ -1598,7 +1669,7 @@
 		backup_dir_dels = backup_dir;
 		backup_dir_dels_len = backup_dir_len;
 		backup_dir_dels_remainder = backup_dir_remainder;
-		strlcpy(backup_dir_dels_buf, backup_dir_buf, sizeof backup_dir_buf);
+		strlcpy(backup_dir_dels_buf, backup_dir_buf, sizeof(backup_dir_dels_buf));
 	} else if (!backup_suffix_dels_len && (!am_server || !am_sender)) {
 		snprintf(err_buf, sizeof err_buf,
 			"--suffix-dels cannot be a null string without --backup-dir-dels\n");
@@ -1973,6 +2044,57 @@
 	if (preserve_fileflags)
 		args[ac++] = "--fileflags";
 
+#ifdef SUPPORT_HFS_COMPRESSION
+	if (preserve_hfs_compression == 1)
+		args[ac++] = "--hfs-compression";
+	else if (preserve_hfs_compression == 2)
+		args[ac++] = "--protect-decmpfs";
+#endif
+	if (replace_dirs_with_diff_type > 0)
+		args[ac++] = "--replace-dirs";
+		
+	if (delete_modified > 0)
+		args[ac++] = "--delete-modified";
+
+	if (delete_deleted > 0)
+		args[ac++] = "--delete-deleted";
+
+	if (dest_file_owner > 0) {
+		if (asprintf(&arg, "--dest-file-owner=%d", dest_file_owner) < 0)
+			goto oom;
+		args[ac++] = arg;
+	}
+	
+	if (sender_uid > 0) {
+		if (asprintf(&arg, "--sender-uid=%d", sender_uid) < 0)
+			goto oom;
+		args[ac++] = arg;
+	}
+	
+	if (receiver_uid > 0) {
+		if (asprintf(&arg, "--receiver-uid=%d", receiver_uid) < 0)
+			goto oom;
+		args[ac++] = arg;
+	}
+	
+	if (dont_csum_data_buffer > 0)
+		args[ac++] = "--no-csum-data-buf";
+	
+	if (write_size_multiplier != 1.0) {
+		if (asprintf(&arg, "-w%.2f", write_size_multiplier) < 0)
+			goto oom;
+		args[ac++] = arg;
+	}
+	
+	if (io_buf_size != IO_BUFFER_SIZE) {
+		if (asprintf(&arg, "--io-buf-size=%d", io_buf_size) < 0)
+			goto oom;
+		args[ac++] = arg;
+	}
+	
+	if (detect_case_conflicts != 0)
+		args[ac++] = "--case-conflicts";
+	
 	if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
 		if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
 			goto oom;
@@ -2042,6 +2164,22 @@
 			goto oom;
 		args[ac++] = arg;
 	}
+
+	// The following options were previously inside of the (am_sender)
+	// block, but we need to send these options to a remote source as 
+	// client/receiver
+	if (max_age) {
+		args[ac++] = "--max-age";
+		args[ac++] = max_age_arg;
+	}
+	if (min_size) {
+		args[ac++] = "--min-size";
+		args[ac++] = min_size_arg;
+	}
+	if (max_size) {
+		args[ac++] = "--max-size";
+		args[ac++] = max_size_arg;
+	}
 	if (am_sender) {
 		if (max_delete > 0) {
 			if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
@@ -2049,14 +2187,6 @@
 			args[ac++] = arg;
 		} else if (max_delete == 0)
 			args[ac++] = "--max-delete=-1";
-		if (min_size) {
-			args[ac++] = "--min-size";
-			args[ac++] = min_size_arg;
-		}
-		if (max_size) {
-			args[ac++] = "--max-size";
-			args[ac++] = max_size_arg;
-		}
 		if (delete_before)
 			args[ac++] = "--delete-before";
 		else if (delete_during == 2)
diff -Naur -X diff_ignore rsync-3.0.6_base/proto.h rsync/proto.h
--- rsync-3.0.6_base/proto.h	2009-06-18 17:30:50.000000000 -0400
+++ rsync/proto.h	2018-10-13 16:17:50.000000000 -0400
@@ -59,6 +59,8 @@
 int daemon_main(void);
 void set_allow_inc_recurse(void);
 void setup_protocol(int f_out,int f_in);
+void do_filesystem_compatibility_checks(const char *path);
+int filesystem_capabilities(const char *path, struct statfs *sfs, u_int32_t *capability_fmt, u_int32_t *capability_int);
 int claim_connection(char *fname, int max_connections);
 void set_filter_dir(const char *dir, unsigned int dirlen);
 void *push_local_filters(const char *dir, unsigned int dirlen);
@@ -106,6 +108,7 @@
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
 	     stat_x *sxp, int32 iflags, uchar fnamecmp_type,
 	     const char *xname);
+char * printableChecksum(char *sum);
 int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st);
 void check_for_finished_files(int itemizing, enum logcode code, int check_redo);
 void generate_files(int f_out, const char *local_name);
@@ -240,6 +243,7 @@
 void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
 		    const char *buf);
 void log_delete(const char *fname, int mode);
+void log_non_transfer(const char *fname, int mode, int iflags);
 void log_exit(int code, const char *file, int line);
 pid_t wait_process(pid_t pid, int *status_ptr, int flags);
 int child_main(int argc, char *argv[]);
@@ -318,7 +322,7 @@
 time_t get_create_time(const char *path);
 int set_create_time(const char *path, time_t crtime);
 void set_compression(const char *fname);
-void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
+void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset, 
 		int32 n, int32 toklen);
 int32 recv_token(int f, char **data);
 void see_token(char *data, int32 toklen);
@@ -330,6 +334,7 @@
 uid_t recv_user_name(int f, uid_t uid);
 gid_t recv_group_name(int f, gid_t gid, uint16 *flags_ptr);
 void recv_id_list(int f, struct file_list *flist);
+void heartbeat(char *fbuf);
 void set_nonblocking(int fd);
 void set_blocking(int fd);
 int fd_pair(int fd[2]);
@@ -342,6 +347,7 @@
 int full_write(int desc, const char *ptr, size_t len);
 int copy_file(const char *source, const char *dest, int ofd,
 	      mode_t mode, int create_bak_dir);
+int copy_sparse_file(const char *src, const char *dst, mode_t mode, off_t logicalSize, off_t physicalSize, int sparse_files);
 int robust_unlink(const char *fname);
 int robust_rename(const char *from, const char *to, const char *partialptr,
 		  int mode);
diff -Naur -X diff_ignore rsync-3.0.6_base/receiver.c rsync/receiver.c
--- rsync-3.0.6_base/receiver.c	2010-10-25 14:18:07.000000000 -0400
+++ rsync/receiver.c	2018-05-21 13:20:01.000000000 -0400
@@ -20,11 +20,22 @@
  */
 
 #include "rsync.h"
+// For statfs():
+#include <sys/param.h>
+#include <sys/mount.h>
+
+// For _PATH_RSRCFORKSPEC
+#include <sys/paths.h>
+// For XATTR_NOFOLLOW
+#include <sys/xattr.h>
+// For dirname()
+#include <libgen.h>
 
 extern int verbose;
 extern int dry_run;
 extern int do_xfers;
 extern int am_server;
+extern int rcvr_is_non_local_server;
 extern int do_progress;
 extern int inc_recurse;
 extern int log_before_transfer;
@@ -39,6 +50,9 @@
 extern int preserve_hard_links;
 extern int preserve_perms;
 extern int preserve_xattrs;
+extern int fs_supports_native_xattrs;
+extern int pc_name_max;
+extern int force_change;
 extern int basis_dir_cnt;
 extern int make_backups;
 extern int cleanup_got_literal;
@@ -58,6 +72,7 @@
 extern char sender_file_sum[MAX_DIGEST_LEN];
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+extern int dont_csum_data_buffer;
 
 static struct bitbag *delayed_bits = NULL;
 static int phase = 0, redoing = 0;
@@ -65,6 +80,17 @@
 /* We're either updating the basis file or an identical copy: */
 static int updating_basis_or_equiv;
 
+#ifdef PARSEABLE_OUTPUT
+struct timeval last_update;
+static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
+{
+	return (t2->tv_sec - t1->tv_sec) * 1000L
+	+ (t2->tv_usec - t1->tv_usec) / 1000;
+}
+#endif
+#define TMPNAME_SUFFIX ".XXXXXX"
+#define TMPNAME_SUFFIX_LEN ((int)sizeof TMPNAME_SUFFIX - 1)
+
 /*
  * get_tmpname() - create a tmp filename for a given filename
  *
@@ -90,6 +116,7 @@
 {
 	int maxname, added, length = 0;
 	const char *f;
+	char *suf;
 
 	if (tmpdir) {
 		/* Note: this can't overflow, so the return value is safe */
@@ -106,14 +133,20 @@
 		}
 	} else
 		f = fname;
-	fnametmp[length++] = '.';
+	
+	// Avoid prepending the temporary file name with a "." if the name already
+	// starts with a dot, and underscore, or starts with "Apple". Some filesystems
+	// reject filenames that start with .., ._, and .Apple
+	if ( f[0] != '.' && f[0] != '_' && strncasecmp(f, "Apple", 5) != 0)
+		fnametmp[length++] = '.';
 
 	/* The maxname value is bufsize, and includes space for the '\0'.
 	 * (Note that NAME_MAX get -8 for the leading '.' above.) */
-	maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
+	maxname = MIN(MAXPATHLEN - length - TMPNAME_SUFFIX_LEN,
+				  pc_name_max - 1 - TMPNAME_SUFFIX_LEN);
 
-	if (maxname < 1) {
-		rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
+	if (maxname < 0) {
+		rprintf(FERROR_XFER, "temporary filename too long: %s\n", full_fname(fname));
 		fnametmp[0] = '\0';
 		return 0;
 	}
@@ -121,7 +154,19 @@
 	added = strlcpy(fnametmp + length, f, maxname);
 	if (added >= maxname)
 		added = maxname - 1;
-	memcpy(fnametmp + length + added, ".XXXXXX", 8);
+	suf = fnametmp + length + added;
+	
+	/* Trim any dangling high-bit chars if the first-trimmed char (if any) is
+	* also a high-bit char, just in case we cut into a multi-byte sequence. */
+	if ((int)f[added] & 0x80) {
+		while ((int)suf[-1] & 0x80)
+			suf--;
+	}
+	/* trim one trailing dot before our suffix's dot */
+	if (suf[-1] == '.')
+		suf--;
+	
+	memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1);
 
 	return 1;
 }
@@ -133,6 +178,7 @@
 int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
 {
 	int fd;
+	char *parent = dirname((char *)fname);
 
 	if (!get_tmpname(fnametmp, fname))
 		return -1;
@@ -155,9 +201,43 @@
 	}
 #endif
 
+#ifdef SUPPORT_FORCE_CHANGE
+	int saved_errno = errno;
+	errno = 0;
+	if (fd == -1) {
+		if (parent == NULL) {
+			rprintf(FINFO, "DEBUG: open_tmpfile: Parent of %s is NULL! (%d)\n", full_fname(fname), errno);
+		} else {
+			stat_x sx;
+			if (do_stat(parent, &sx.st) < 0)
+				rprintf(FINFO, "DEBUG: open_tmpfile: Failed to stat %s! (%d)\n", full_fname(parent), errno);
+			else {
+				
+				if (force_change && make_mutable(parent, sx.st.st_mode, sx.st.st_flags, force_change) > 0) {
+					fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
+					undo_make_mutable(parent, sx.st.st_flags);
+				} else if (force_change && !(force_change & SYS_IMMUTABLE) && sx.st.st_flags & SYS_IMMUTABLE) {
+					rprintf(FINFO, "open_tmpfile: Failed to unlock %s, it is system immutable. Skipping its contents.\n", full_fname(parent));
+					return -1;
+				} else {
+					rprintf(FINFO, "DEBUG: open_tmpfile: Failed to unlock %s (%d)\n", full_fname(parent), errno);
+				}
+			}
+		}
+	}
+	errno = saved_errno;
+#endif
+
 	if (fd == -1) {
-		rsyserr(FERROR_XFER, errno, "mkstemp %s failed",
+		rsyserr(FERROR_XFER, errno, "open_tmpfile: mkstemp %s failed",
 			full_fname(fnametmp));
+		if (errno == EINVAL) {
+			saved_errno = errno;
+			if (unlink(fnametmp) != 0)
+				rsyserr(FERROR_XFER, errno, "open_tmpfile: failed to unlink %s",
+						full_fname(fnametmp));
+			errno = saved_errno;
+		}
 		return -1;
 	}
 
@@ -177,6 +257,13 @@
 	int32 i;
 	char *map = NULL;
 
+	if (verbose > 1) {
+		fprintf(stderr, "receive_data: Receiving data for %s, total size: %.0f.\n", (fd_r >= 0 && size_r > 0) ? fname_r : fname, (double)total_size);
+		if (fd_r >= 0)
+			fprintf(stderr, " Comparing to existing file of size: %.0f\n", (fd_r >= 0 && size_r > 0) ? (double)size_r : (double)total_size);
+		fprintf(stderr, "\n");
+	}
+
 	read_sum_head(f_in, &sum);
 
 	if (fd_r >= 0 && size_r > 0) {
@@ -213,7 +300,7 @@
 		}
 		offset = sum.flength;
 		if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
-			rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",
+			rsyserr(FERROR_XFER, errno, "receive_data: lseek of %s returned %.0f, not %.0f",
 				full_fname(fname), (double)j, (double)offset);
 			exit_cleanup(RERR_FILEIO);
 		}
@@ -232,11 +319,24 @@
 			stats.literal_data += i;
 			cleanup_got_literal = 1;
 
-			sum_update(data, i);
-
+			if (dont_csum_data_buffer == 0)
+				sum_update(data, i);
+			
 			if (fd != -1 && write_file(fd,data,i) != i)
 				goto report_write_error;
 			offset += i;
+			stats.total_transferred_size += i;
+#ifdef PARSEABLE_OUTPUT
+			if (!rcvr_is_non_local_server) {
+				struct timeval now;
+				gettimeofday(&now, NULL);
+				unsigned long time_diff = msdiff(&last_update, &now);
+				if (time_diff > 500) {
+					last_update = now;
+					fprintf(stderr, "S;;;STATS;;;TTS;;;%lld;;;FC;;;%d;;;CF;;;%s\n", stats.total_transferred_size, stats.num_transferred_files, fname);
+				}
+			}
+#endif
 			continue;
 		}
 
@@ -258,7 +358,8 @@
 			map = map_ptr(mapbuf,offset2,len);
 
 			see_token(map, len);
-			sum_update(map, len);
+			if (dont_csum_data_buffer == 0)
+				sum_update(map, len);
 		}
 
 		if (updating_basis_or_equiv) {
@@ -269,7 +370,7 @@
 				offset += len;
 				if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
 					rsyserr(FERROR_XFER, errno,
-						"lseek of %s returned %.0f, not %.0f",
+						"receive_data: lseek of %s returned %.0f, not %.0f",
 						full_fname(fname),
 						(double)pos, (double)offset);
 					exit_cleanup(RERR_FILEIO);
@@ -280,16 +381,29 @@
 		if (fd != -1 && map && write_file(fd, map, len) != (int)len)
 			goto report_write_error;
 		offset += len;
+
+		stats.total_transferred_size += len;
+#ifdef PARSEABLE_OUTPUT
+		if (!rcvr_is_non_local_server) {
+			struct timeval now;
+			gettimeofday(&now, NULL);
+			unsigned long time_diff = msdiff(&last_update, &now);
+			if (time_diff > 500) {
+				last_update = now;
+				fprintf(stderr, "S;;;STATS;;;TTS;;;%lld;;;FC;;;%d;;;CF;;;%s\n", stats.total_transferred_size, stats.num_transferred_files, fname);
+			}
+		}
+#endif
 	}
 
 	if (flush_write_file(fd) < 0)
 		goto report_write_error;
 
 #ifdef HAVE_FTRUNCATE
-	if (inplace && fd != -1
-	 && ftruncate(fd, offset) < 0) {
-		rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
-			full_fname(fname));
+	if (offset == total_size && inplace && fd != -1) {
+		if (ftruncate(fd, offset) < 0)
+			rsyserr(FERROR_XFER, errno, "receive_data: ftruncate failed on %s",
+				full_fname(fname));
 	}
 #endif
 
@@ -298,7 +412,23 @@
 
 	if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
 	    report_write_error:
-		rsyserr(FERROR_XFER, errno, "write failed on %s",
+		// This next line is a temporary hack. It looks like receiver and generator messages sent to rsyserr aren't getting displayed:
+		/*
+receive_data(x): 10A270.dmg [No space left on device]
+rsyserr(x): write failed on %s [No space left on device]
+rsyserr(x): writefd_unbuffered failed to write %ld bytes [%s] [Broken pipe]
+rsync: writefd_unbuffered failed to write 4 bytes [sender]: Broken pipe (32)
+
+		
+		*/
+		fprintf(stderr, "rsync: receive_data: write failed on %s [;;;TTS;;;%lld;;;FC;;;%d;;;]: %s (%d)\n", full_fname(fname), (stats.total_transferred_size - offset), stats.num_transferred_files, strerror(errno), errno);
+		fflush(stderr);
+		usleep(250000); // Sleep for a quarter of a second -- this is temporary, just to see if these problems are caused by calling exit_cleanup() too soon:
+//		05/20 16:30:07	rsync: connection unexpectedly closed (2030 bytes received so far) [sender] (10001)
+//		05/20 16:30:07	Synchronization Engine exited with status 12
+//		05/20 16:30:07	Synchronization Engine exited with a non-zero exit status: 12. (1059)
+
+		rsyserr(FERROR_XFER, errno, "receive_data: write failed on %s",
 			full_fname(fname));
 		exit_cleanup(RERR_FILEIO);
 	}
@@ -312,14 +442,21 @@
 	read_buf(f_in, sender_file_sum, checksum_len);
 	if (verbose > 2)
 		rprintf(FINFO,"got file_sum\n");
+//	char *csumSrc = printableChecksum(sender_file_sum);
+//	char *csumDst = printableChecksum(file_sum1);
+//	fprintf(stderr, "DEBUG: Comparing checksums for %s; source (while sending): %s, dest (while writing): %s\n", full_fname(fname), csumSrc, csumDst);
+//	free(csumSrc);
+//	free(csumDst);
 	if (fd != -1 && memcmp(file_sum1, sender_file_sum, checksum_len) != 0)
 		return 0;
 	return 1;
 }
 
 
+
 static void discard_receive_data(int f_in, OFF_T length)
 {
+	rprintf(FINFO, "S;;;DISCARD;;;LEN;;;%lld\n", length);
 	receive_data(f_in, NULL, -1, 0, NULL, -1, length);
 }
 
@@ -342,7 +479,7 @@
 			 * partial-dir must be on the same drive. */
 			if (do_rename(partialptr, fname) < 0) {
 				rsyserr(FERROR_XFER, errno,
-					"rename failed for %s (from %s)",
+					"handle_delayed_updates: rename failed for %s (from %s)",
 					full_fname(fname), partialptr);
 			} else {
 				if (remove_source_files
@@ -444,9 +581,11 @@
 #endif
 	int ndx, recv_ok;
 
-	if (verbose > 2)
+	if (verbose > 2) {
 		rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
-
+		fprintf(stderr, "DEBUG: [recv_files: %s] rcvr_is_non_local_server: %d\n", who_am_i(), rcvr_is_non_local_server);
+	}
+	
 	if (delay_updates)
 		delayed_bits = bitbag_create(cur_flist->used + 1);
 
@@ -484,14 +623,22 @@
 		if (verbose > 2)
 			rprintf(FINFO, "recv_files(%s)\n", fname);
 
+		initial_stats = stats;
 #ifdef SUPPORT_XATTRS
-		if (iflags & ITEM_REPORT_XATTR && do_xfers)
+		if (iflags & ITEM_REPORT_XATTR && do_xfers) {
 			recv_xattr_request(file, f_in);
+			// BOMBICH: I've added logic to set_file_attrs that will prevent 
+			// it from running set_xattrs unless they've actually changed. So
+			// here we indicate that xattrs should be copied
+			file->flags |= FLAG_XATTRS_SENT;
+		}
 #endif
 
 		if (!(iflags & ITEM_TRANSFER)) {
 			maybe_log_item(file, iflags, itemizing, xname);
 #ifdef SUPPORT_XATTRS
+			if (verbose > 1)
+				fprintf(stderr, "recv_files: Calling set_file_attrs: ITEM_REPORT_XATTR: %d, do_xfers: %d (%s)\n", iflags & ITEM_REPORT_XATTR, do_xfers, file->basename);
 			if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
 				set_file_attrs(fname, file, NULL, fname, 0);
 #endif
@@ -528,8 +675,18 @@
 
 		if (!am_server && do_progress)
 			set_current_file_index(file, ndx);
-		stats.num_transferred_files++;
-		stats.total_transferred_size += F_LENGTH(file);
+		
+#ifdef PARSEABLE_OUTPUT
+		if (!rcvr_is_non_local_server) {
+			struct timeval now;
+			gettimeofday(&now, NULL);
+			unsigned long time_diff = msdiff(&last_update, &now);
+			if (time_diff > 500) {
+				last_update = now;
+				fprintf(stderr, "S;;;STATS;;;TTS;;;%lld;;;FC;;;%d;;;CF;;;%s\n", stats.total_transferred_size, stats.num_transferred_files, fname);
+			}
+		}
+#endif
 
 		cleanup_got_literal = 0;
 
@@ -555,7 +712,7 @@
 		}
 
 		if (!do_xfers) { /* log the transfer */
-			log_item(FCLIENT, file, &stats, iflags, NULL);
+			log_item(FLOG, file, &stats, iflags, NULL);
 			if (read_batch)
 				discard_receive_data(f_in, F_LENGTH(file));
 			continue;
@@ -591,8 +748,8 @@
 			default:
 				if (fnamecmp_type >= basis_dir_cnt) {
 					rprintf(FERROR,
-						"invalid basis_dir index: %d.\n",
-						fnamecmp_type);
+						"invalid basis_dir index: %d. %s\n",
+						fnamecmp_type, full_fname(fname));
 					exit_cleanup(RERR_PROTOCOL);
 				}
 				pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
@@ -619,9 +776,10 @@
 				fnamecmp = fname;
 		}
 
-		initial_stats = stats;
+		if (verbose > 1)
+			fprintf(stderr, "recv_files: Location identified for incoming file: %s of length: %.0f\n", fnamecmp, (double)F_LENGTH(file));
 
-		/* open the file */
+		/* open the (existing) file (at the destination) */
 		fd1 = do_open(fnamecmp, O_RDONLY, 0);
 
 		if (fd1 == -1 && protocol_version < 29) {
@@ -639,14 +797,13 @@
 			}
 		}
 
-		updating_basis_or_equiv = inplace
-		    && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP);
-
 		if (fd1 == -1) {
+			if (verbose > 1 && errno != ENOENT)
+				fprintf(stderr, "recv_files: Failed to open %s for reading (%d), setting size = 0\n", full_fname(fnamecmp), errno);
 			st.st_mode = 0;
 			st.st_size = 0;
 		} else if (do_fstat(fd1,&st) != 0) {
-			rsyserr(FERROR_XFER, errno, "fstat %s failed",
+			rsyserr(FERROR_XFER, errno, "recv_files: fstat %s failed",
 				full_fname(fnamecmp));
 			discard_receive_data(f_in, F_LENGTH(file));
 			close(fd1);
@@ -655,6 +812,9 @@
 			continue;
 		}
 
+		updating_basis_or_equiv = inplace
+		    && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP);
+
 		if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) {
 			/* this special handling for directories
 			 * wouldn't be necessary if robust_rename()
@@ -690,12 +850,30 @@
 			file->mode = dest_mode(file->mode, st.st_mode,
 					       dflt_perms, exists);
 		}
-
+		
 		/* We now check to see if we are writing the file "inplace" */
 		if (inplace)  {
 			fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
+#ifdef SUPPORT_FORCE_CHANGE
 			if (fd2 == -1) {
-				rsyserr(FERROR_XFER, errno, "open %s failed",
+				stat_x sx;
+				char *parent = dirname(fnamecmp);
+				if (!parent && do_stat(parent, &sx.st) < 0)
+					rprintf(FINFO, "recv_files: Failed to stat %s!\n", full_fname(parent));
+				else {
+//					fprintf(stderr, "recv_files: Calling make_mutable on %s. Mode: %o, fileflags: %d\n", full_fname(parent), sx.st.st_mode, sx.st.st_flags);
+					if (force_change && make_mutable(parent, sx.st.st_mode, sx.st.st_flags, force_change) > 0) {
+						fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
+						undo_make_mutable(parent, sx.st.st_flags);
+					} else if (force_change && !(force_change & SYS_IMMUTABLE) && sx.st.st_flags & SYS_IMMUTABLE) {
+						rsyserr(FERROR_XFER, errno, "recv_files: Failed to unlock %s, it is system immutable.", full_fname(parent));
+					}
+				}
+			}
+#endif
+
+			if (fd2 == -1) {
+				rsyserr(FERROR_XFER, errno, "recv_files: open %s failed",
 					full_fname(fname));
 			}
 		} else {
@@ -716,19 +894,29 @@
 		/* log the transfer */
 		if (log_before_transfer)
 			log_item(FCLIENT, file, &initial_stats, iflags, NULL);
-		else if (!am_server && verbose && do_progress)
+		else if (!am_server && verbose > 1 && do_progress)
 			rprintf(FINFO, "%s\n", fname);
 
 		/* recv file data */
 		recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
 				       fname, fd2, F_LENGTH(file));
 
+		if (verbose > 1) {
+			struct stat vst;
+			if (fd2 == -1 || fstat(fd2, &vst) < 0)
+				fprintf(stderr, "recv_files: Failed to stat %s!\n", full_fname(inplace ? fname : fnametmp));
+			else 
+				fprintf(stderr, "recv_files: Finished receive_data, file size at %s is %.0f\n", full_fname(inplace ? fname : fnametmp), (double)vst.st_size);
+		}
+		
+		iflags |= recv_ok ? ITEM_HAD_ERRORS_DEST : 0;
 		log_item(log_code, file, &initial_stats, iflags, NULL);
 
 		if (fd1 != -1)
 			close(fd1);
 		if (close(fd2) < 0) {
-			rsyserr(FERROR, errno, "close failed on %s",
+			fprintf(stderr, "recv_files: close failed on %s (%d)\n", full_fname(fnametmp), errno);
+			rsyserr(FERROR, errno, "recv_files: close failed on %s",
 				full_fname(fnametmp));
 			exit_cleanup(RERR_FILEIO);
 		}
@@ -743,6 +931,7 @@
 				do_unlink(partialptr);
 				handle_partial_dir(partialptr, PDIR_DELETE);
 			}
+			stats.num_transferred_files++;
 		} else if (keep_partial && partialptr) {
 			if (!handle_partial_dir(partialptr, PDIR_CREATE)) {
 				rprintf(FERROR,
@@ -795,7 +984,7 @@
 				}
 				rprintf(msgtype,
 					"%s: %s failed verification -- update %s%s.\n",
-					errstr, local_name ? f_name(file, NULL) : fname,
+					errstr, local_name ? full_fname(f_name(file, NULL)) : full_fname(fname),
 					keptstr, redostr);
 			}
 			if (!redoing) {
@@ -822,5 +1011,6 @@
 	if (verbose > 2)
 		rprintf(FINFO,"recv_files finished\n");
 
+//	rprintf(FINFO, "Performance (receiver): %lu\n", (unsigned long)stats.perf);
 	return 0;
 }
diff -Naur -X diff_ignore rsync-3.0.6_base/rsync.1 rsync/rsync.1
--- rsync-3.0.6_base/rsync.1	2009-06-18 17:30:46.000000000 -0400
+++ rsync/rsync.1	2014-12-06 21:12:18.000000000 -0500
@@ -422,6 +422,8 @@
      \-\-chmod=CHMOD           affect file and/or directory permissions
  \-A, \-\-acls                  preserve ACLs (implies \-p)
  \-X, \-\-xattrs                preserve extended attributes
+     \-\-hfs\-compression       preserve HFS compression (if source & destination support it)
+     \-\-protect\-decmpfs       preserve HFS compression (regardless of volume support)
  \-o, \-\-owner                 preserve owner (super-user only)
  \-g, \-\-group                 preserve group
      \-\-devices               preserve device files (super-user only)
@@ -1119,6 +1121,20 @@
 receiving side.  It does not try to affect user flags.  This option overrides
 \fB\-\-force\-change\fP and \fB\-\-force\-schange\fP.
 .IP 
+.IP "\fB\\-\-hfs\-compression\fP"
+This option causes rsync to preserve HFS+ compression on filesystems that support it. Filesystem compression was introduced to HFS+ in Mac OS 10.6. A file that is compressed has no data in its data fork. Rather, the compressed data is stored in an extended attribute named com.apple.decmpfs and a file flag is set to indicate that the file is compressed (UF_COMPRESSED). HFS+ decompresses this data "on-the-fly" and presents it to the operating system as a normal file. Normal attempts to copy compressed files (e.g. in the Finder, via cp, ditto, etc.) will copy the file's decompressed contents, remove the UF_COMPRESSED file flag, and discard the com.apple.decmpfs extended attribute. This option will preserve the data in the com.apple.decmpfs extended attribute and ignore the synthesized data fork contents as long as both the source and destination filesystems support HFS+ compression.
+.IP 
+If the source or destination filesystem does not support HFS+ compression, this option will be disabled for both ends of the transfer. Compressed files will be decompressed on the destination, data in the com.apple.decmpfs extended attribute will be discarded, and the UF_COMPRESSED flag will not be set. This option is appropriate if viewing the contents of compressed files is required on operating systems that do not support HFS+ compression.
+.IP 
+This option enables \fB\-\-fileflags\fP and \fB\-\-xattrs\fP.
+.IP 
+.IP "\fB\-\-protect\-decmpfs\fP"
+The com.apple.decmpfs extended attribute is hidden by default from list/get xattr calls, therefore normal attempts to copy compressed files will functionally decompress those files. While this is desirable behavior when copying files to filesystems that do not support HFS+ compression, it has serious performance and capacity impacts when backing up or restoring the Mac OS X filesystem.
+.IP 
+This option will transfer the com.apple.decmpfs extended attribute regardless of support on the source or destination. If a source file is compressed and an existing file on the destination is not compressed, the data fork of the destination file will be truncated and the com.apple.decmpfs xattr will be transferred instead. Note that compressed files will not be readable to the operating system of the destination if that operating system does not support HFS+ compression. Once restored (with or without this option) to an operating system that supports HFS+ compression, however, these files will be accessible as usual.
+.IP 
+This option enables \fB\-\-fileflags\fP and \fB\-\-xattrs\fP.
+.IP 
 .IP "\fB\-\-chmod\fP"
 This option tells rsync to apply one or more
 comma-separated \(lqchmod\(rq strings to the permission of the files in the
diff -Naur -X diff_ignore rsync-3.0.6_base/rsync.c rsync/rsync.c
--- rsync-3.0.6_base/rsync.c	2009-06-18 17:30:46.000000000 -0400
+++ rsync/rsync.c	2018-10-13 16:17:50.000000000 -0400
@@ -31,6 +31,7 @@
 extern int dry_run;
 extern int preserve_acls;
 extern int preserve_xattrs;
+extern int force_change;
 extern int preserve_perms;
 extern int preserve_fileflags;
 extern int preserve_executability;
@@ -44,16 +45,21 @@
 extern int protocol_version;
 extern int uid_ndx;
 extern int gid_ndx;
+extern int ownershipDisabledOnDest;
 extern int inc_recurse;
 extern int inplace;
 extern int flist_eof;
 extern int keep_dirlinks;
 extern int make_backups;
+extern int delete_modified;
+extern uid_t receiver_uid;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct chmod_mode_struct *daemon_chmod_modes;
 #ifdef ICONV_OPTION
 extern char *iconv_opt;
 #endif
+extern int detect_case_conflicts;
+
 
 #ifdef ICONV_CONST
 iconv_t ic_chck = (iconv_t)-1;
@@ -297,6 +303,7 @@
 		send_msg_int(MSG_FLIST, ndx);
 		start_flist_forward(f_in);
 		flist = recv_file_list(f_in);
+		//fprintf(stderr, "DEBUG: [%s]read_ndx_and_attrs received %d items\n", who_am_i(), flist->used);
 		flist->parent_ndx = ndx;
 		stop_flist_forward();
 		verbose = save_verbose;
@@ -332,8 +339,8 @@
 		int i = ndx - cur_flist->ndx_start;
 		if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) {
 			rprintf(FERROR,
-				"received request to transfer non-regular file: %d [%s]\n",
-				ndx, who_am_i());
+				"received request to transfer non-regular file (%s): %d [%s]\n",
+				cur_flist->files[i]->basename, ndx, who_am_i());
 			exit_cleanup(RERR_PROTOCOL);
 		}
 	}
@@ -382,12 +389,23 @@
 /* Set a file's st_flags. */
 static int set_fileflags(const char *fname, uint32 fileflags)
 {
-	if (do_chflags(fname, fileflags) != 0) {
-		rsyserr(FERROR_XFER, errno,
-			"failed to set file flags on %s",
-			full_fname(fname));
+//	struct stat sx3;
+//	link_stat(fname, &sx3, 0);
+//	fprintf(stderr, "DEBUG: set_fileflags(): Stat of %s before setting fileflags, mode: %o, fileflags: %d\n", fname, sx3.st_mode, sx3.st_flags);
+	if (do_chflags(fname, fileflags) != 0) { // && !(!am_root && errno == EACCES)
+		int savedErrno = errno;
+		if (errno != EROFS)
+			rsyserr(FERROR_XFER, errno,
+					"set_fileflags: failed to set file flags (%d) on %s", fileflags,
+					full_fname(fname));
+		errno = savedErrno;
+		
+//		link_stat(fname, &sx3, 0);
+//		fprintf(stderr, "DEBUG: set_fileflags(): Stat of %s after FAIL chflags(%s, %d), mode: %o, fileflags: %d\n", fname, fname, fileflags, sx3.st_mode, sx3.st_flags);
 		return 0;
 	}
+//	link_stat(fname, &sx3, 0);
+//	fprintf(stderr, "DEBUG: set_fileflags(): Stat of %s after chflags(%s, %d), mode: %o, fileflags: %d\n", fname, fname, fileflags, sx3.st_mode, sx3.st_flags);
 
 	return 1;
 }
@@ -395,18 +413,25 @@
 /* Remove immutable flags from an object, so it can be altered/removed. */
 int make_mutable(const char *fname, mode_t mode, uint32 fileflags, uint32 iflags)
 {
-	if (S_ISLNK(mode) || !(fileflags & iflags))
+	if (/*S_ISLNK(mode) || */!(fileflags & iflags))
 		return 0;
+//	if (verbose > 1)
+//		fprintf(stderr, "make_mutable[%s]: (%d) %s\n", who_am_i(), fileflags & ~iflags, full_fname(fname));
 	if (!set_fileflags(fname, fileflags & ~iflags))
 		return -1;
+
 	return 1;
 }
 
 /* Undo a prior make_mutable() call that returned a 1. */
 int undo_make_mutable(const char *fname, uint32 fileflags)
 {
-	if (!set_fileflags(fname, fileflags))
+//	if (verbose > 1)
+//		fprintf(stderr, "undo_make_mutable: (%d) %s\n", fileflags, full_fname(fname));
+	if (!set_fileflags(fname, fileflags)) {
+		rsyserr(FERROR, errno, "failed to relock %s", full_fname(fname));
 		return -1;
+	}
 	return 1;
 }
 #endif
@@ -419,12 +444,13 @@
 	int change_uid, change_gid;
 	mode_t new_mode = file->mode;
 	int inherit;
-
+	int became_mutable = 0;
+	
 	if (!sxp) {
 		if (dry_run)
 			return 1;
 		if (link_stat(fname, &sx2.st, 0) < 0) {
-			rsyserr(FERROR_XFER, errno, "stat %s failed",
+			rsyserr(FERROR_XFER, errno, "set_file_attrs: stat %s failed",
 				full_fname(fname));
 			return 0;
 		}
@@ -449,6 +475,12 @@
 	if (daemon_chmod_modes && !S_ISLNK(new_mode))
 		new_mode = tweak_mode(new_mode, daemon_chmod_modes);
 
+#ifdef SUPPORT_FORCE_CHANGE
+//	fprintf(stderr, "set_file_attrs: Calling make_mutable on %s. Mode: %o, fileflags: %d\n", full_fname(fname), sxp->st.st_mode, sxp->st.st_flags);
+	if (force_change)
+		became_mutable = make_mutable(fname, sxp->st.st_mode, sxp->st.st_flags, force_change) > 0;
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
 		get_acl(fname, sxp);
@@ -457,17 +489,41 @@
 #ifdef SUPPORT_XATTRS
 	if (am_root < 0)
 		set_stat_xattr(fname, file, new_mode);
-	if (preserve_xattrs && fnamecmp)
+
+	if (verbose > 1)
+		fprintf(stderr, "set_file_attrs: FLAG_XATTRS_SENT: %d (%s, %s)\n", file->flags & FLAG_XATTRS_SENT, full_fname(fname), fnamecmp);
+	// BOMBICH: I added the "&& file->flags & FLAG_XATTRS_SENT" so rsync doesn't copy xattrs 
+	// in cases where they haven't changed (and the file was not transferred). I also populate 
+	// sxp->st.st_flags with the file_struct's flags so rsync_xal_set has access to the UF_COMPRESSED flag
+	if (preserve_xattrs && fnamecmp && file->flags & FLAG_XATTRS_SENT) {
+		if (verbose > 1)
+			fprintf(stderr, "set_file_attrs: tmpflags: %#x, file flags:%#x (%s)\n", sxp->st.st_flags, F_FFLAGS(file), full_fname(fnamecmp));
+		uint32 tmpflags = sxp->st.st_flags;
+		sxp->st.st_flags = F_FFLAGS(file);
 		set_xattr(fname, file, fnamecmp, sxp);
+		sxp->st.st_flags = tmpflags;
+		if (S_ISDIR(sxp->st.st_mode))
+			link_stat(fname, &sx2.st, 0);
+	}
 #endif
-
 	if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
 		flags |= ATTRS_SKIP_MTIME;
+	/* 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;
+	//fprintf(stderr, "DEBUG: set_file_attrs: mod time on %s: dest: %d, source: %d\n", fname, sxp->st.st_mtime, file->modtime);
 	if (!(flags & ATTRS_SKIP_MTIME)
+#ifdef SUPPORT_HFS_COMPRESSION
+		&& !(sxp->st.st_flags & UF_COMPRESSED) // setting this flag alters mtime, defer setting mtime to after set_fileflags
+#endif
 	    && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
+		//fprintf(stderr, "set_file_attrs: Setting mod time on %s\n", full_fname(fname));
 		int ret = set_modtime(fname, file->modtime, sxp->st.st_mode, ST_FLAGS(sxp->st));
+		if (ret < 0 && (S_ISLNK(sxp->st.st_mode) || (receiver_uid != 0 && receiver_uid == sxp->st.st_uid) || (S_ISDIR(sxp->st.st_mode) && errno == EPERM)))
+			fprintf(stderr, "DEBUG: Failed to set modification date on %s: %d\n", full_fname(fname), errno);
+		else
 		if (ret < 0) {
-			rsyserr(FERROR_XFER, errno, "failed to set times on %s",
+			rsyserr(FERROR_XFER, errno, "set_file_attrs: failed to set times on %s",
 				full_fname(fname));
 			goto cleanup;
 		}
@@ -485,9 +541,14 @@
 			updated = 1;
 	}
 
-	change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
+	change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file)
+		&& !ownershipDisabledOnDest;
+		/* Don't change the ownership of the root folder of an HFS+ volume if the owner is already root */
+		//&& !(sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode) && sxp->st.st_uid == 0);
 	change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
-		  && sxp->st.st_gid != (gid_t)F_GROUP(file);
+		&& sxp->st.st_gid != (gid_t)F_GROUP(file) && !ownershipDisabledOnDest;
+		/* Don't change the group of the root folder of an HFS+ volume if the group is already wheel */
+		//&& !(sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode) && sxp->st.st_gid == 0);
 #if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
 	if (S_ISLNK(sxp->st.st_mode)) {
 		;
@@ -513,7 +574,7 @@
 			    sxp->st.st_mode, ST_FLAGS(sxp->st)) != 0) {
 				/* We shouldn't have attempted to change uid
 				 * or gid unless have the privilege. */
-				rsyserr(FERROR_XFER, errno, "%s %s failed",
+				rsyserr(FERROR_XFER, errno, "set_file_attrs: %s %s failed",
 				    change_uid ? "chown" : "chgrp",
 				    full_fname(fname));
 				goto cleanup;
@@ -541,11 +602,14 @@
 #endif
 
 #ifdef HAVE_CHMOD
-	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)
+		/* Don't change the mode of the root folder of an HFS+ volume if we didn't set its owner or group */
+		&& !(sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode) && !change_uid && !change_gid)
+		&& (receiver_uid == 0 || receiver_uid == sxp->st.st_uid)) {
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode, ST_FLAGS(sxp->st));
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
-				"failed to set permissions on %s",
+				"set_file_attrs: failed to set permissions on %s",
 				full_fname(fname));
 			goto cleanup;
 		}
@@ -554,16 +618,39 @@
 	}
 #endif
 
+#ifdef SUPPORT_FORCE_CHANGE
+	if (became_mutable)
+		undo_make_mutable(fname, sxp->st.st_flags);
+#endif
+
 #ifdef SUPPORT_FILEFLAGS
-	if (preserve_fileflags && !S_ISLNK(sxp->st.st_mode)
-	 && sxp->st.st_flags != F_FFLAGS(file)) {
-		uint32 fileflags = F_FFLAGS(file);
+	uint32 fileflags = F_FFLAGS(file);
+	if (flags & ATTRS_STRIP_RESTRICTED)
+		fileflags &= ~(SF_RESTRICTED|SF_NOUNLINK);
+	if (preserve_fileflags /*&& !S_ISLNK(sxp->st.st_mode)*/
+	 && (receiver_uid == 0 || receiver_uid == sxp->st.st_uid)
+	 && sxp->st.st_flags != fileflags) {
+		if (verbose > 1)
+			fprintf(stderr, "set_file_attrs: Calling set_fileflags: %#x, prev flags: %#x (%s)\n", fileflags, sxp->st.st_flags, full_fname(fname));
 		if (flags & ATTRS_DELAY_IMMUTABLE)
 			fileflags &= ~ALL_IMMUTABLE;
 		if (sxp->st.st_flags != fileflags
 		 && !set_fileflags(fname, fileflags))
 			goto cleanup;
 		updated = 1;
+#ifdef SUPPORT_HFS_COMPRESSION
+		if (verbose > 1)
+			fprintf(stderr, "set_file_attrs: Calling set_modtime on %s\n", full_fname(fname));
+		//fprintf(stderr, "set_file_attrs2: Setting mod time on %s\n", full_fname(fname));
+		int ret = set_modtime(fname, file->modtime, new_mode, fileflags);
+		if (ret < 0 && !(S_ISDIR(sxp->st.st_mode) && errno == EPERM)) {
+			rsyserr(FERROR_XFER, errno, "set_file_attrs: failed to set times on %s",
+				full_fname(fname));
+			goto cleanup;
+		}
+		if (ret != 0)
+			file->flags |= FLAG_TIME_FAILED;
+#endif
 	}
 #endif
 
@@ -621,7 +708,27 @@
 		goto do_set_file_attrs;
 	}
 
-	if (make_backups > 0 && overwriting_basis) {
+	if (detect_case_conflicts) {
+		int fd = open(fname, O_RDONLY);
+		if (fd > 0) {
+			char realpath[MAXPATHLEN];
+			int ret = fcntl(fd, F_GETPATH, &realpath);
+			close(fd);
+			if (ret == 0) {
+				char *mypath = normalize_path((char *)fname, False, NULL);
+				if (strcmp(mypath, realpath) != 0) {
+					fprintf(stderr, "Case conflict detected at %s: \"%s\"\n", full_fname(fname), realpath);
+					char new_fname_buf[MAXPATHLEN];
+					snprintf(new_fname_buf, MAXPATHLEN, "%s.XXXXXX", fname);
+					fname = mktemp(new_fname_buf);
+				}
+				if (mypath != fname)
+					free(mypath);
+			}
+		}
+	}
+	
+	if (delete_modified == 0 && make_backups > 0 && overwriting_basis) {
 		if (!make_backup(fname))
 			return 1;
 		if (fnamecmp == fname)
@@ -639,7 +746,7 @@
 	ret = robust_rename(fnametmp, fname, temp_copy_name,
 			    file->mode & INITACCESSPERMS);
 	if (ret < 0) {
-		rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
+		rsyserr(FERROR_XFER, errno, "finish_transfer: %s %s -> \"%s\"",
 			ret == -2 ? "copy" : "rename",
 			full_fname(fnametmp), fname);
 		if (!partialptr || (ret == -2 && temp_copy_name)
@@ -651,9 +758,13 @@
 	if (ret == 0) {
 		/* The file was moved into place (not copied), so it's done. */
 #ifdef SUPPORT_FILEFLAGS
-		if (preserve_fileflags && F_FFLAGS(file) & ALL_IMMUTABLE)
+		if (preserve_fileflags && F_FFLAGS(file) & ALL_IMMUTABLE /*&& !S_ISLNK(file->mode)*/)
 			set_fileflags(fname, F_FFLAGS(file));
 #endif
+//		struct stat sx3;
+//		link_stat(fname, &sx3, 0);
+//		fprintf(stderr, "DEBUG: finish_transfer(): Restat of %s after move, new modtime: %d\n", fname, sx3.st_mtime);
+	
 		return 1;
 	}
 	/* The file was copied, so tweak the perms of the copied file.  If it
@@ -672,6 +783,9 @@
 		}
 		handle_partial_dir(temp_copy_name, PDIR_DELETE);
 	}
+//	struct stat sx3;
+//	link_stat(fname, &sx3, 0);
+//	fprintf(stderr, "DEBUG: finish_transfer(): Restat of %s after copy, new modtime: %d\n", fname, sx3.st_mtime);
 	return 1;
 }
 
diff -Naur -X diff_ignore rsync-3.0.6_base/rsync.csreqs rsync/rsync.csreqs
--- rsync-3.0.6_base/rsync.csreqs	1969-12-31 19:00:00.000000000 -0500
+++ rsync/rsync.csreqs	2014-12-06 21:12:18.000000000 -0500
@@ -0,0 +1 @@
+designated => certificate root = H"2796bae63f1801e277261ba0d77770028f20eee4" or certificate root = H"611E5B662C593A08FF58D14AE22452D198DF6C60" and certificate leaf[subject.O] = "Bombich Software"* and identifier "rsync"
\ No newline at end of file
diff -Naur -X diff_ignore rsync-3.0.6_base/rsync.h rsync/rsync.h
--- rsync-3.0.6_base/rsync.h	2009-06-18 17:30:46.000000000 -0400
+++ rsync/rsync.h	2018-03-23 12:22:28.000000000 -0400
@@ -81,6 +81,7 @@
 #define FLAG_LENGTH64 (1<<9)	/* sender/receiver/generator */
 #define FLAG_SKIP_GROUP (1<<10)	/* receiver/generator */
 #define FLAG_TIME_FAILED (1<<11)/* generator */
+#define FLAG_XATTRS_SENT (1<<12)/* receiver */
 
 /* These flags are passed to functions but not stored. */
 
@@ -125,10 +126,10 @@
 #define RSYNC_PORT 873
 
 #define SPARSE_WRITE_SIZE (1024)
-#define WRITE_SIZE (32*1024)
-#define CHUNK_SIZE (32*1024)
-#define MAX_MAP_SIZE (256*1024)
-#define IO_BUFFER_SIZE (4092)
+//#define WRITE_SIZE (1*1024*1024) // No longer used
+#define CHUNK_SIZE (16*1024)
+#define MAX_MAP_SIZE (2*1024*1024)
+#define IO_BUFFER_SIZE (2*1024*1024)
 #define MAX_BLOCK_SIZE ((int32)1 << 17)
 
 /* For compatibility with older rsyncs */
@@ -158,6 +159,7 @@
 #define ATTRS_SKIP_MTIME	(1<<1)
 #define ATTRS_DELAY_IMMUTABLE	(1<<2)
 #define ATTRS_SKIP_CRTIME	(1<<3)
+#define ATTRS_STRIP_RESTRICTED	(1<<4)
 
 #define FULL_FLUSH	1
 #define NORMAL_FLUSH	0
@@ -194,6 +196,11 @@
 #define ITEM_MISSING_DATA (1<<16)	   /* used by log_formatted() */
 #define ITEM_DELETED (1<<17)		   /* used by log_formatted() */
 #define ITEM_MATCHED (1<<18)		   /* used by itemize() */
+#define ITEM_EXCLUDED (1<<19)		   /* used by log_formatted() */
+#define ITEM_PROTECTED (1<<20)		   /* used by log_formatted() */
+#define ITEM_ARCHIVED (1<<21)		   /* used by log_formatted() */
+#define ITEM_HAD_ERRORS_SOURCE (1<<24) /* used by log_formatted() */
+#define ITEM_HAD_ERRORS_DEST (1<<25)   /* used by log_formatted() */
 
 #define SIGNIFICANT_ITEM_FLAGS (~(\
 	ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
@@ -237,6 +244,8 @@
 	MSG_SUCCESS=100,/* successfully updated indicated flist index */
 	MSG_DELETED=101,/* successfully deleted a file on receiving side */
 	MSG_NO_SEND=102,/* sender failed to open a file we wanted */
+	MSG_FILTERED=103, /* file was hidden or protected on the sender or receiving side*/
+	MSG_ARCHIVED=104, /* file was hidden or protected on the sender or receiving side*/
 	MSG_DONE=86	/* current phase is done */
 };
 
@@ -485,10 +494,39 @@
 #define SYS_IMMUTABLE (SF_IMMUTABLE|SF_NOUNLINK|SF_APPEND)
 #define ALL_IMMUTABLE (USR_IMMUTABLE|SYS_IMMUTABLE)
 #define ST_FLAGS(st) (st.st_flags)
+#define ALL_FFLAGS (UF_NODUMP | USR_IMMUTABLE | UF_OPAQUE | UF_COMPRESSED | UF_HIDDEN | UF_TRACKED | SF_ARCHIVED | SYS_IMMUTABLE | SF_RESTRICTED | SF_NOUNLINK)
 #else
 #define ST_FLAGS(st) NO_FFLAGS
 #endif
 
+#include <sys/attr.h>
+#ifndef XATTR_SHOWCOMPRESSION
+#define XATTR_SHOWCOMPRESSION 0x0020
+#endif
+#ifndef UF_COMPRESSED
+#define UF_COMPRESSED 0x00000020
+#endif
+#ifndef UF_TRACKED
+#define UF_TRACKED		0x00000040	/* file renames and deletes are tracked */
+#endif
+#ifndef XATTR_DECMPFS_NAME
+#define	XATTR_DECMPFS_NAME	  "com.apple.decmpfs"
+#endif
+#ifndef XATTR_RESOURCEFORK_NAME
+#define	XATTR_RESOURCEFORK_NAME	  "com.apple.ResourceFork"
+#endif
+#ifndef KAUTH_FILESEC_XATTR
+#define	KAUTH_FILESEC_XATTR	  "com.apple.system.Security"
+#endif
+#ifndef VOL_CAP_FMT_DECMPFS_COMPRESSION
+#define VOL_CAP_FMT_DECMPFS_COMPRESSION	0x00010000
+#endif
+#define SETXATTR_CHUNKSIZE (1024*1024*64)
+
+#if defined SUPPORT_XATTRS && defined SUPPORT_FILEFLAGS
+#define SUPPORT_HFS_COMPRESSION 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. */
@@ -626,7 +664,7 @@
 #endif
 
 #ifndef NAME_MAX
-#define NAME_MAX 255
+#define NAME_MAX 238
 #endif
 
 #ifndef INADDR_NONE
@@ -726,6 +764,8 @@
 /* The sum is only present on regular files. */
 #define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
 				    + SUM_EXTRA_CNT - 1))
+#define FUNKY_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) + 1 \
++ SUM_EXTRA_CNT - 1))
 
 /* Some utility defines: */
 #define F_IS_ACTIVE(f) (f)->basename[0]
@@ -853,7 +893,9 @@
 
 struct stats {
 	int64 total_size;
+	int64 total_unchanged_size;
 	int64 total_transferred_size;
+	int64 xattr_transfer_size;
 	int64 total_written;
 	int64 total_read;
 	int64 literal_data;
@@ -861,8 +903,19 @@
 	int64 flist_buildtime;
 	int64 flist_xfertime;
 	int64 flist_size;
+	int64 perf;
+	int64 largest_file;
 	int num_files;
+	int num_xattrs;
 	int num_transferred_files;
+	int total_unchanged_count;
+	// BOMBICH
+	int num_dirs;
+	int num_reg_files;
+	int num_symlinks;
+	int num_devices;
+	int num_special;
+	int hard_links_not_copied;
 };
 
 struct chmod_mode_struct;
@@ -948,6 +1001,10 @@
 #define ACL_READY(sx) ((sx).acc_acl != NULL)
 #define XATTR_READY(sx) ((sx).xattr != NULL)
 
+// For statfs():
+#include <sys/param.h>
+#include <sys/mount.h>
+
 #include "proto.h"
 
 #ifndef SUPPORT_XATTRS
@@ -1148,7 +1205,7 @@
 #define	WIFEXITED(stat)		((int)((stat)&0xFF) == 0)
 #endif
 
-#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
+#define exit_cleanup(code) _exit_cleanup(code, ((strrchr(__FILE__, '/') ?: __FILE__ - 1) + 1), __LINE__)
 
 #ifdef HAVE_GETEUID
 #define MY_UID() geteuid()
diff -Naur -X diff_ignore rsync-3.0.6_base/sender.c rsync/sender.c
--- rsync-3.0.6_base/sender.c	2009-04-12 15:48:59.000000000 -0400
+++ rsync/sender.c	2018-10-13 16:17:50.000000000 -0400
@@ -20,10 +20,12 @@
  */
 
 #include "rsync.h"
+#include <fcntl.h>
 
 extern int verbose;
 extern int do_xfers;
 extern int am_server;
+extern int rcvr_is_non_local_server;
 extern int am_daemon;
 extern int inc_recurse;
 extern int log_before_transfer;
@@ -34,6 +36,7 @@
 extern int io_error;
 extern int allowed_lull;
 extern int preserve_xattrs;
+extern int preserve_hfs_compression;
 extern int protocol_version;
 extern int remove_source_files;
 extern int updating_basis_file;
@@ -45,6 +48,17 @@
 extern struct stats stats;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 
+// BOMBICH
+#define FORCE_SENDER_ERROR 0
+#ifdef PARSEABLE_OUTPUT
+struct timeval last_update;
+static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
+{
+	return (t2->tv_sec - t1->tv_sec) * 1000L
+		+ (t2->tv_usec - t1->tv_usec) / 1000;
+}
+#endif
+
 /**
  * @file
  *
@@ -136,7 +150,7 @@
 		if (verbose > 1)
 			rprintf(FINFO, "sender removed %s\n", fname);
 	} else
-		rsyserr(FERROR, errno, "sender failed to remove %s", fname);
+		rsyserr(FERROR, errno, "successful_send: sender failed to remove %s", full_fname(fname));
 }
 
 static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
@@ -175,8 +189,10 @@
 	int f_xfer = write_batch < 0 ? batch_fd : f_out;
 	int ndx, j;
 
-	if (verbose > 2)
+	if (verbose > 2) {
 		rprintf(FINFO, "send_files starting\n");
+		fprintf(stderr, "DEBUG: [send_files: %s] rcvr_is_non_local_server: %d\n", who_am_i(), rcvr_is_non_local_server);
+	}
 
 	while (1) {
 		if (inc_recurse)
@@ -260,11 +276,9 @@
 
 		if (!am_server && do_progress)
 			set_current_file_index(file, ndx);
-		stats.num_transferred_files++;
-		stats.total_transferred_size += F_LENGTH(file);
 
 		if (!do_xfers) { /* log the transfer */
-			log_item(FCLIENT, file, &stats, iflags, NULL);
+			log_item(FLOG, file, &stats, iflags, NULL);
 			write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
 					    fnamecmp_type, xname, xlen);
 			continue;
@@ -279,6 +293,12 @@
 		}
 
 		fd = do_open(fname, O_RDONLY, 0);
+#if FORCE_SENDER_ERROR
+		if (random() % 10 == 0) {
+			exit(1);
+			return;
+		}
+#endif
 		if (fd == -1) {
 			if (errno == ENOENT) {
 				enum logcode c = am_daemon
@@ -287,11 +307,15 @@
 				io_error |= IOERR_VANISHED;
 				rprintf(c, "file has vanished: %s\n",
 					full_fname(fname));
+			} else if (errno == ENOTSUP && F_LENGTH(file) == 1) {
+				rprintf(FWARNING, "Dropping placeholder file: %s\n", full_fname(fname));
 			} else {
 				io_error |= IOERR_GENERAL;
+				iflags |= ITEM_HAD_ERRORS_SOURCE;
 				rsyserr(FERROR_XFER, errno,
-					"send_files failed to open %s",
+					"send_files: failed to open %s",
 					full_fname(fname));
+				log_item(FLOG, file, &stats, iflags, NULL);
 			}
 			free_sums(s);
 			if (protocol_version >= 30)
@@ -302,13 +326,51 @@
 		/* map the local file */
 		if (do_fstat(fd, &st) != 0) {
 			io_error |= IOERR_GENERAL;
-			rsyserr(FERROR_XFER, errno, "fstat failed");
+			rsyserr(FERROR_XFER, errno, "send_files: fstat failed on %s", full_fname(fname));
 			free_sums(s);
 			close(fd);
 			exit_cleanup(RERR_PROTOCOL);
 		}
 
+// BOMBICH
+// Update the user on total transfer size and the name of the file we're currently copying. 
+// To limit CPU usage, do this 5 times per second
+// We need to do this before stats.total_transferred_size is updated because match_sums() will add the current offset to this amount
+#ifdef PARSEABLE_OUTPUT
+		if (rcvr_is_non_local_server) {
+			struct timeval now;
+			gettimeofday(&now, NULL);
+			unsigned long time_diff = msdiff(&last_update, &now);
+			if (time_diff > 200) {
+				last_update = now;
+				rprintf(FINFO, "S;;;STATS;;;TTS;;;%lld;;;FC;;;%d;;;CF;;;%s\n", stats.total_transferred_size, stats.num_transferred_files, fname);
+			}
+		}
+#endif
+
+		off_t saved_file_length = st.st_size;
+#ifdef SUPPORT_HFS_COMPRESSION
+		if (st.st_flags & UF_COMPRESSED) {
+			if (preserve_hfs_compression > 0) {
+				// We're sending the compression xattr, not the decompressed data fork. Setting rsync's idea of the 
+				// file size to 0 effectively prevents the transfer of the data fork
+				if (verbose > 1)
+					fprintf(stderr, "send_files(%s): Compress flag is set, setting file size to 0 (%s)\n", who_am_i(), full_fname(fname));
+				st.st_size = 0;
+				file->len32 = 0;
+			} else {
+				if (verbose)
+					fprintf(stderr, "DEBUG: send_files(%s): Stripping UF_COMPRESSED file flag (%s)\n", who_am_i(), full_fname(fname));
+				// If the sender's filesystem supports compression, then we'll be able to send the decompressed data fork
+				// and the decmpfs xattr will be hidden (not sent). As such, we need to strip the compression flag.
+				st.st_flags &= ~UF_COMPRESSED;
+			}
+		}
+#endif
+	
 		if (st.st_size) {
+//			struct radvisory rad = {0, st.st_size};
+//			fcntl(fd, F_RDADVISE, rad);
 			int32 read_size = MAX(s->blength * 3, MAX_MAP_SIZE);
 			mbuf = map_file(fd, st.st_size, read_size, s->blength);
 		} else
@@ -328,7 +390,7 @@
 
 		if (log_before_transfer)
 			log_item(FCLIENT, file, &initial_stats, iflags, NULL);
-		else if (!am_server && verbose && do_progress)
+		else if (!am_server && verbose > 1 && do_progress)
 			rprintf(FCLIENT, "%s\n", fname);
 
 		set_compression(fname);
@@ -337,17 +399,27 @@
 		if (do_progress)
 			end_progress(st.st_size);
 
-		log_item(log_code, file, &initial_stats, iflags, NULL);
-
+		// Update the stats after match_sums() so the current file isn't included twice in the output
+		stats.num_transferred_files++;
+		// Non-Finder math method: Use st.st_size instead of saved_file_length
+		stats.total_transferred_size += saved_file_length;
+		//fprintf(stderr, "DEBUG: [%s] SNDFIL: stats.total_transferred_size |%s|+%lld\n", who_am_i(), full_fname(fname), st.st_size);
+		
 		if (mbuf) {
 			j = unmap_file(mbuf);
 			if (j) {
 				io_error |= IOERR_GENERAL;
 				rsyserr(FERROR_XFER, j,
-					"read errors mapping %s",
+					"send_files: read errors mapping %s",
 					full_fname(fname));
+				iflags |= ITEM_HAD_ERRORS_SOURCE;
+				stats.num_transferred_files--;
+				stats.total_transferred_size -= F_LENGTH(file);
 			}
 		}
+
+		log_item(log_code, file, &initial_stats, iflags, NULL);
+
 		close(fd);
 
 		free_sums(s);
@@ -366,5 +438,12 @@
 
 	match_report();
 
+// BOMBICH
+#ifdef PARSEABLE_OUTPUT
+	// Print the grand total
+	rprintf(FINFO, "S;;;SUM_STATS;;;TS;;;%lld;;;TTS;;;%lld;;;FC;;;%d;;;DIRS;;;%d;;;REG;;;%d;;;SYM;;;%d;;;DEV;;;%d;;;SPEC;;;%d;;;HLNK;;;%d;;;XATTR;;;%d;;;XS;;;%lld;;;LF;;;%lld\n", stats.total_size, stats.total_transferred_size, stats.num_transferred_files, stats.num_dirs, stats.num_reg_files, stats.num_symlinks, stats.num_devices, stats.num_special, stats.hard_links_not_copied, stats.num_xattrs, stats.xattr_transfer_size, stats.largest_file);
+//	rprintf(FINFO, "Performance (sender): %lu\n", (unsigned long)stats.perf);
+#endif
+
 	write_ndx(f_out, NDX_DONE);
 }
diff -Naur -X diff_ignore rsync-3.0.6_base/support/cull_options rsync/support/cull_options
--- rsync-3.0.6_base/support/cull_options	1969-12-31 19:00:00.000000000 -0500
+++ rsync/support/cull_options	2014-12-06 21:12:18.000000000 -0500
@@ -0,0 +1,64 @@
+#!/usr/bin/perl
+# This script outputs some perl code that parses all possible options
+# that the code in options.c might send to the server.  This perl code
+# is included in the rrsync script.
+use strict;
+
+our(%short_no_arg, %short_with_num, %long_opt);
+our $last_long_opt;
+
+open(IN, '../options.c') or die "Unable to open ../options.c: $!\n";
+
+while (<IN>) {
+    if (/\Qargstr[x++]\E = '(.)'/) {
+	$short_no_arg{$1} = 1;
+	undef $last_long_opt;
+    } elsif (/\Qasprintf(\E[^,]+, "-([a-zA-Z0-9])\%l?[ud]"/) {
+	$short_with_num{$1} = 1;
+	undef $last_long_opt;
+    } elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
+	$last_long_opt = $1;
+	$long_opt{$1} = 0;
+    } elsif (defined($last_long_opt)
+	&& /\Qargs[ac++]\E = ([^["\s]+);/ && $1 ne 'dest_option') {
+	$long_opt{$last_long_opt} = 2;
+	undef $last_long_opt;
+    } elsif (/dest_option = "--([^"]+)"/) {
+	$long_opt{$1} = 2;
+	undef $last_long_opt;
+    } elsif (/\Qasprintf(\E[^,]+, "--([^"=]+)=/ || /\Qargs[ac++]\E = "--([^"=]+)=/) {
+	$long_opt{$1} = 1;
+	undef $last_long_opt;
+    }
+}
+close IN;
+
+my $short_no_arg = join('', sort keys %short_no_arg);
+my $short_with_num = join('', sort keys %short_with_num);
+
+print <<EOT;
+
+# These options are the only options that rsync might send to the server,
+# and only in the option format that the stock rsync produces.
+
+# To disable a short-named option, add its letter to this string:
+our \$short_disabled = 's';
+
+our \$short_no_arg = '$short_no_arg'; # DO NOT REMOVE ANY
+our \$short_with_num = '$short_with_num'; # DO NOT REMOVE ANY
+
+# To disable a long-named option, change its value to a -1.  The values mean:
+# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
+# check the arg when receiving; and 3 = always check the arg.
+our \%long_opt = (
+EOT
+
+foreach my $opt (sort keys %long_opt) {
+    my $val = $long_opt{$opt};
+    $val = 1 if $opt =~ /^(max-|min-)/;
+    $val = 3 if $opt eq 'files-from';
+    $val = '$ro ? -1 : ' . $val if $opt =~ /^remove-/;
+    print "  '$opt' => $val,\n";
+}
+
+print ");\n\n";
diff -Naur -X diff_ignore rsync-3.0.6_base/support/extern-squish rsync/support/extern-squish
--- rsync-3.0.6_base/support/extern-squish	1969-12-31 19:00:00.000000000 -0500
+++ rsync/support/extern-squish	2014-12-06 21:12:18.000000000 -0500
@@ -0,0 +1,18 @@
+#!/usr/bin/perl
+# This script finds extraneous "extern" variables in the *.c files.
+# Run it from inside the main rsync directory.
+
+use strict;
+
+my @files = glob('*.c');
+
+foreach my $fn (@files) {
+    open(IN, '<', $fn) or die;
+    undef $/; $_ = <IN>; $/ = "\n";
+    close IN;
+    my @externs = /^extern .*?([^[\s(*;&.]+)(?:\[.*?\])?;/mg;
+    foreach my $find (@externs) {
+	my @matches = /(?<!\sstruct )\b(\Q$find\E)\b/g;
+	print $fn, ': ', $find, "\n" if @matches == 1;
+    }
+}
diff -Naur -X diff_ignore rsync-3.0.6_base/support/patch-update rsync/support/patch-update
--- rsync-3.0.6_base/support/patch-update	1969-12-31 19:00:00.000000000 -0500
+++ rsync/support/patch-update	2014-12-06 21:12:18.000000000 -0500
@@ -0,0 +1,157 @@
+#!/usr/bin/perl -w
+# This script is used to turn one or more of the "patch/*" branches
+# into one or more diffs in the "patches" directory.  Pass the option
+# --gen if you want generated files in the diffs.  Pass the name of
+# one or more diffs if you want to just update a subset of all the
+# diffs.
+
+use strict;
+
+my $patches_dir = 'patches';
+my $incl_generated_files;
+
+if (@ARGV && $ARGV[0] =~ /^--gen(?:=(\S+))?$/) {
+    $patches_dir = $1 if defined $1;
+    $incl_generated_files = 1;
+    shift;
+}
+
+die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
+die "No '.git' directory present in the current dir.\n" unless -d '.git';
+
+my @extra_files;
+open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
+while (<IN>) {
+    if (s/^GENFILES=//) {
+	while (s/\\$//) {
+	    $_ .= <IN>;
+	}
+	@extra_files = split(' ', $_);
+	last;
+    }
+}
+close IN;
+
+system "git checkout master" and exit 1;
+if ($incl_generated_files) {
+    die "'a' must not exist in the current directory.\n" if -e 'a';
+    die "'b' must not exist in the current directory.\n" if -e 'b';
+    system "./config.status Makefile && make gen && rsync -a @extra_files a/" and exit 1;
+}
+my $last_touch = time;
+
+my(@patches, %local_patch);
+if (@ARGV) {
+    foreach (@ARGV) {
+	s{^(patches|patch|origin/patch)/} {};
+	s{\.diff$} {};
+	push(@patches, $_);
+    }
+    open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
+} else {
+    open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
+}
+while (<PIPE>) {
+    if (m# origin/patch/(.*)#) {
+	push(@patches, $1);
+    } elsif (m# patch/(.*)#) {
+	$local_patch{$1} = 1;
+    }
+}
+close PIPE;
+
+my(%parent, %description);
+foreach my $patch (@patches) {
+    my $branch = ($local_patch{$patch} ? '' : 'origin/') . "patch/$patch";
+    my $desc = '';
+    open(PIPE, '-|', 'git', 'diff', '-U1000', "master...$branch", '--', "PATCH.$patch") or die $!;
+    while (<PIPE>) {
+	last if /^@@ /;
+    }
+    while (<PIPE>) {
+	next unless s/^[ +]//;
+	if (m#patch -p1 <patches/(\S+)\.diff# && $1 ne $patch) {
+	    $parent{$patch} = $1;
+	}
+	$desc .= $_;
+    }
+    $description{$patch} = $desc;
+}
+
+my %completed;
+foreach my $patch (@patches) {
+    next if $completed{$patch}++;
+    update_patch($patch);
+}
+
+if ($incl_generated_files) {
+    system "rm -rf a b";
+}
+
+sleep 1 if $last_touch == time;
+system "git checkout master";
+
+exit;
+
+
+sub update_patch
+{
+    my($patch) = @_;
+
+    my $parent = $parent{$patch};
+    if (defined $parent) {
+	unless ($completed{$parent}++) {
+	    update_patch($parent);
+	}
+	$parent = "patch/$parent";
+    } else {
+	$parent = 'master';
+    }
+
+    print "======== $patch ========\n";
+
+    sleep 1 if $incl_generated_files && $last_touch == time;
+    if ($local_patch{$patch}) {
+	system "git checkout patch/$patch" and exit 1;
+    } else {
+	system "git checkout --track -b patch/$patch origin/patch/$patch" and exit 1;
+    }
+
+    open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
+    print OUT $description{$patch}, "\n";
+
+    if (system("git rebase -m $parent") != 0) {
+	print qq|"git rebase -m $parent" incomplete -- please fix.\n|;
+	$ENV{PS1} = "[$parent] patch/$patch: ";
+	system $ENV{SHELL} and exit 1;
+    }
+
+    if ($incl_generated_files) {
+	system "./config.status Makefile && make gen && rsync -a @extra_files b/" and exit 1;
+    }
+    $last_touch = time;
+
+    open(PIPE, '-|', 'git', 'diff', $parent) or die $!;
+    DIFF: while (<PIPE>) {
+	while (m{^diff --git a/PATCH}) {
+	    while (<PIPE>) {
+		last if m{^diff --git a/};
+	    }
+	    last DIFF if !defined $_;
+	}
+	next if /^index /;
+	print OUT $_;
+    }
+    close PIPE;
+
+    if ($incl_generated_files) {
+	open(PIPE, '-|', 'diff', '-up', 'a', 'b') or die $!;
+	while (<PIPE>) {
+	    s/^((?:---|\+\+\+) [^\t]+)\t.*/$1/;
+	    print OUT $_;
+	}
+	close PIPE;
+    }
+
+    close OUT;
+}
diff -Naur -X diff_ignore rsync-3.0.6_base/syscall.c rsync/syscall.c
--- rsync-3.0.6_base/syscall.c	2009-06-18 17:30:46.000000000 -0400
+++ rsync/syscall.c	2018-12-18 16:48:07.000000000 -0500
@@ -29,6 +29,9 @@
 #include <sys/attr.h>
 #endif
 
+// For dirname()
+#include <libgen.h>
+
 extern int dry_run;
 extern int am_root;
 extern int read_only;
@@ -36,11 +39,8 @@
 extern int force_change;
 extern int preserve_perms;
 extern int preserve_executability;
-
-struct create_time {
-	unsigned long length;
-	struct timespec crtime;
-};
+extern int unsupported_fileflags;
+extern const char *dstRoot;
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -59,17 +59,31 @@
 	if (unlink(fname) == 0)
 		return 0;
 #ifdef SUPPORT_FORCE_CHANGE
-	if (force_change && errno == EPERM) {
-		STRUCT_STAT st;
+	if (force_change && (errno == EPERM || errno == EACCES)) {
+		STRUCT_STAT st, pst;
+		char *parent;
+		int became_mutable;
+		int saved_errno = errno;
 
-		if (x_lstat(fname, &st, NULL) == 0
-		 && make_mutable(fname, st.st_mode, st.st_flags, force_change) > 0) {
-			if (unlink(fname) == 0)
+		if (x_lstat(fname, &st, NULL) == 0) {
+			became_mutable = make_mutable(fname, st.st_mode, st.st_flags, force_change) > 0;
+			if (became_mutable && unlink(fname) == 0)
 				return 0;
-			undo_make_mutable(fname, st.st_flags);
+
+			/* Attempt to make the parent directory mutable */
+			if ((parent = dirname((char *)fname)) != NULL
+				&& x_lstat(parent, &pst, NULL) == 0) {
+				if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) {
+					if (unlink(fname) == 0) {
+						undo_make_mutable(parent, pst.st_flags);
+						return 0;
+					} else {
+						undo_make_mutable(parent, pst.st_flags);
+					}
+				}
+			}
 		}
-		/* TODO: handle immutable directories */
-		errno = EPERM;
+		errno = saved_errno;
 	}
 #endif
 	return -1;
@@ -77,17 +91,145 @@
 
 int do_symlink(const char *fname1, const char *fname2)
 {
+	int ret;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
-	return symlink(fname1, fname2);
+	ret = symlink(fname1, fname2);
+
+#ifdef SUPPORT_FORCE_CHANGE
+	if (force_change && (errno == EPERM || errno == EACCES)) {
+		STRUCT_STAT pst;
+		char *parent;
+		int saved_errno = errno;
+
+		/* Attempt to make the parent directory mutable */
+		if ((parent = dirname((char *)fname2)) != NULL
+				&& x_lstat(parent, &pst, NULL) == 0) {
+			if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) {
+				if (symlink(fname1, fname2) == 0) {
+					undo_make_mutable(parent, pst.st_flags);
+					return 0;
+				} else {
+					undo_make_mutable(parent, pst.st_flags);
+				}
+			}
+		}
+		errno = saved_errno;
+	}
+#endif
+
+	return ret;
 }
 
 #ifdef HAVE_LINK
 int do_link(const char *fname1, const char *fname2)
 {
+	int ret;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
-	return link(fname1, fname2);
+	ret = link(fname1, fname2);
+
+	if (errno == EPERM) {
+		errno = 0;
+		char fnametmp[MAXPATHLEN];
+		if (!get_tmpname(fnametmp, fname1)) {
+			fprintf(stderr, "DEBUG: Failed to get temporary filename for %s\n", fname1);
+			errno = EPERM;
+		} else {
+			if (!mktemp(fnametmp)) {
+				fprintf(stderr, "DEBUG: mktemp(%s) failed: %d\n", fnametmp, errno);
+				errno = EPERM;
+			} else {
+				ret = link(fname1, fnametmp);
+				if (ret != 0) {
+					fprintf(stderr, "DEBUG: Failed to make temporary hard link at %s: %d\n", fnametmp, errno);
+					if (errno == EPERM) {
+						// Try again, creating the hard link in a folder at the root of the destination
+						char dst_hl_tmp[MAXPATHLEN];
+						pathjoin(dst_hl_tmp, MAXPATHLEN, dstRoot, ".com.bombich.ccc.hl");
+						if (mkdir(dst_hl_tmp, S_IRWXU) != 0) {
+							fprintf(stderr, "DEBUG: Failed to create hard link temp dir at %s: %d\n", dst_hl_tmp, errno);
+							errno = EPERM;
+						} else {
+							char src[MAXPATHLEN], dst[MAXPATHLEN];
+							pathjoin(src, MAXPATHLEN, dst_hl_tmp, "hlink_src");
+							pathjoin(dst, MAXPATHLEN, dst_hl_tmp, "hlink_dst");
+							ret = rename(fname1, src);
+							if (ret != 0) {
+								fprintf(stderr, "DEBUG: Failed to temporarily rename %s -> %s: %d\n", fname1, src, errno);
+								errno = EPERM;
+							} else {
+								ret = link(src, dst);
+								int rename_ret = rename(src, fname1);
+								if (rename_ret != 0)
+									fprintf(stderr, "DEBUG: Failed to rename %s back to %s: %d\n", src, fname1, errno);
+
+								if (ret != 0) {
+									fprintf(stderr, "DEBUG: Failed to make temporary hard link at %s: %d\n", dst, errno);
+									errno = EPERM;
+								} else {
+									ret = rename(dst, fname2);
+									if (ret != 0) {
+										fprintf(stderr, "DEBUG: Failed to rename temporary hard link %s -> %s: %d\n", dst, fname2, errno);
+										unlink(dst);
+										errno = EPERM;
+									}
+								}
+							}
+							if (rmdir(dst_hl_tmp) != 0)
+								fprintf(stderr, "DEBUG: Failed to remove hard link temp dir %s -> %s: %d\n", dst, fname2, errno);
+						}
+					} else {
+						errno = EPERM;
+					}
+				} else {
+					ret = rename(fnametmp, fname2);
+					if (ret != 0) {
+						fprintf(stderr, "DEBUG: Failed to rename temporary hard link %s -> %s: %d\n", fnametmp, fname2, errno);
+						unlink(fnametmp);
+						errno = EPERM;
+					}
+				}
+			}
+		}
+	}
+	
+#ifdef SUPPORT_FORCE_CHANGE
+ 	if (force_change && errno == EACCES) {
+		STRUCT_STAT st, pst;
+		char *parent;
+		int became_mutable;
+		int saved_errno = errno;
+
+		if (x_lstat(fname1, &st, NULL) == 0) {
+			became_mutable = make_mutable(fname1, st.st_mode, st.st_flags, force_change) > 0;
+			if (became_mutable && link(fname1, fname2) == 0) {
+				undo_make_mutable(fname1, st.st_flags);
+				return 0;
+			}
+
+			/* Attempt to make the parent directory mutable */
+			if ((parent = dirname((char *)fname2)) != NULL
+					&& x_lstat(parent, &pst, NULL) == 0) {
+				if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) {
+					if (link(fname1, fname2) == 0) {
+						if (became_mutable)
+							undo_make_mutable(fname1, st.st_flags);
+						undo_make_mutable(parent, pst.st_flags);
+						return 0;
+					} else {
+						if (became_mutable)
+							undo_make_mutable(fname1, st.st_flags);
+						undo_make_mutable(parent, pst.st_flags);
+					}
+				}
+			}
+		}
+		errno = saved_errno;
+	}
+#endif
+
+	return ret;
 }
 #endif
 
@@ -101,7 +243,8 @@
 	if (lchown(path, owner, group) == 0)
 		return 0;
 #ifdef SUPPORT_FORCE_CHANGE
-	if (force_change && errno == EPERM) {
+	if (force_change && (errno == EPERM || errno == EACCES)) {
+		int saved_errno = errno;
 		if (fileflags == NO_FFLAGS) {
 			STRUCT_STAT st;
 			if (x_lstat(path, &st, NULL) == 0) {
@@ -116,7 +259,7 @@
 			if (ret == 0)
 				return 0;
 		}
-		errno = EPERM;
+		errno = saved_errno;
 	}
 #else
 	mode = fileflags = 0; /* avoid compiler warning */
@@ -181,16 +324,35 @@
 	if (rmdir(pathname) == 0)
 		return 0;
 #ifdef SUPPORT_FORCE_CHANGE
-	if (force_change && errno == EPERM) {
-		STRUCT_STAT st;
+	if (force_change && (errno == EPERM || errno == EACCES)) {
+		STRUCT_STAT st, pst;
+		char *parent;
+		int became_mutable;
+		int saved_errno = errno;
 
-		if (x_lstat(pathname, &st, NULL) == 0
-		 && make_mutable(pathname, st.st_mode, st.st_flags, force_change) > 0) {
-			if (rmdir(pathname) == 0)
-				return 0;
-			undo_make_mutable(pathname, st.st_flags);
+		if (x_lstat(pathname, &st, NULL) == 0) {
+			became_mutable = make_mutable(pathname, st.st_mode, st.st_flags, force_change);
+			if (became_mutable >= 0) { // even if this item is not immutable, the parent may be
+				if (rmdir(pathname) == 0)
+					return 0;
+				else {
+					// Attempt to make the parent directory mutable
+					if ((parent = dirname((char *)pathname)) != NULL
+							&& x_lstat(parent, &pst, NULL) == 0) {
+						if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) {
+							if (rmdir(pathname) == 0) {
+								undo_make_mutable(parent, pst.st_flags);
+								return 0;
+							} else
+								undo_make_mutable(parent, pst.st_flags);
+						}
+					}
+				}
+				if (became_mutable)
+					undo_make_mutable(pathname, st.st_flags);
+			}
 		}
-		errno = EPERM;
+		errno = saved_errno;
 	}
 #endif
 	return -1;
@@ -198,12 +360,19 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+	int fd = -1;
+
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
+	
+	fd = open(pathname, flags | O_BINARY, mode);
+	
+	if (fd > 0)
+		fcntl(fd, F_NOCACHE, 1);
 
-	return open(pathname, flags | O_BINARY, mode);
+	return fd;
 }
 
 #ifdef HAVE_CHMOD
@@ -229,7 +398,8 @@
 	} else
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
 #ifdef SUPPORT_FORCE_CHANGE
-	if (code < 0 && force_change && errno == EPERM && !S_ISLNK(mode)) {
+	if (code < 0 && force_change && (errno == EPERM || errno == EACCES) /*&& !S_ISLNK(mode)*/) {
+		int saved_errno = errno;
 		if (fileflags == NO_FFLAGS) {
 			STRUCT_STAT st;
 			if (x_lstat(path, &st, NULL) == 0)
@@ -242,7 +412,7 @@
 			if (code == 0)
 				return 0;
 		}
-		errno = EPERM;
+		errno = saved_errno;
 	}
 #else
 	fileflags = 0; /* avoid compiler warning */
@@ -257,8 +427,13 @@
 int do_chflags(const char *path, uint32 fileflags)
 {
 	if (dry_run) return 0;
+	int _ff = fileflags;
 	RETURN_ERROR_IF_RO_OR_LO;
-	return chflags(path, fileflags);
+	if (unsupported_fileflags == ALL_FFLAGS)
+		return 0;
+	if (unsupported_fileflags > 0)
+		_ff &= ~unsupported_fileflags;
+	return lchflags(path, _ff);
 }
 #endif
 
@@ -269,9 +444,14 @@
 	if (rename(fname1, fname2) == 0)
 		return 0;
 #ifdef SUPPORT_FORCE_CHANGE
-	if (force_change && errno == EPERM) {
-		STRUCT_STAT st1, st2;
-		int became_mutable;
+	if (force_change && (errno == EPERM || errno == EACCES)) {
+		STRUCT_STAT st1, st2, pst1, pst2;
+		int became_mutable=0, p1_mutable = 0, p2_mutable = 0;
+		char *dirtmp, p1[MAXPATHLEN], p2[MAXPATHLEN];
+		int saved_errno = errno;
+
+		if (verbose > 1)
+			fprintf(stderr, "do_rename(%s -> %s): calling make_mutable(%s, %d, %d)\n", fname1, fname2, fname1, st1.st_flags, force_change);
 
 		if (x_lstat(fname1, &st1, NULL) != 0)
 			goto failed;
@@ -280,19 +460,58 @@
 			goto success;
 		if (x_lstat(fname2, &st2, NULL) == 0
 		 && make_mutable(fname2, st2.st_mode, st2.st_flags, force_change) > 0) {
-			if (rename(fname1, fname2) == 0) {
-			  success:
-				if (became_mutable) /* Yes, use fname2 and st1! */
-					undo_make_mutable(fname2, st1.st_flags);
-				return 0;
-			}
-			undo_make_mutable(fname2, st2.st_flags);
+			if (rename(fname1, fname2) == 0)
+			  goto success;
 		}
-		/* TODO: handle immutable directories */
-		if (became_mutable)
-			undo_make_mutable(fname1, st1.st_flags);
+
+		// Now try making the parent directories mutable
+		if ((dirtmp = dirname((char *)fname1)) == NULL)
+			goto failed;
+		strncpy(p1, dirtmp, MAXPATHLEN);
+
+		if (x_lstat(p1, &pst1, NULL) != 0)
+			goto failed;
+
+		p1_mutable = make_mutable(p1, pst1.st_mode, pst1.st_flags, force_change) > 0;
+		if (p1_mutable && rename(fname1, fname2) == 0)
+			goto success;
+
+		if ((dirtmp = dirname((char *)fname2)) == NULL)
+			goto failed;
+		strncpy(p2, dirtmp, MAXPATHLEN);
+
+		if (strcmp(p1, p2) != 0) {
+			if (x_lstat(p2, &pst2, NULL) != 0)
+				goto failed;
+
+			p2_mutable = make_mutable(p2, pst2.st_mode, pst2.st_flags, force_change) > 0;
+			if (p2_mutable && rename(fname1, fname2) == 0)
+				goto success;
+
+		}
+		
 	  failed:
-		errno = EPERM;
+		errno = saved_errno;
+		if (became_mutable) {
+			undo_make_mutable(fname1, st1.st_flags);
+			undo_make_mutable(fname2, st2.st_flags);
+		}
+		if (p1_mutable)
+			undo_make_mutable(p1, pst1.st_flags);
+		if (p2_mutable)
+			undo_make_mutable(p2, pst2.st_flags);
+		return -1;
+		
+	  success:
+		if (became_mutable) /* Yes, use fname2 and st1! */
+			undo_make_mutable(fname2, st1.st_flags);
+		if (p1_mutable)
+			undo_make_mutable(p1, pst1.st_flags);
+		if (p2_mutable)
+			undo_make_mutable(p2, pst2.st_flags);
+		return 0;
+		
+		
 	}
 #endif
 	return -1;
@@ -318,10 +537,34 @@
 
 int do_mkdir(char *fname, mode_t mode)
 {
+	int ret;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
 	trim_trailing_slashes(fname);
-	return mkdir(fname, mode);
+	ret = mkdir(fname, mode);
+
+#ifdef SUPPORT_FORCE_CHANGE
+	if (force_change && (errno == EPERM || errno == EACCES)) {
+		STRUCT_STAT pst;
+		char *parent;
+		int saved_errno = errno;
+
+		// Attempt to make the parent directory mutable
+		if ((parent = (char *)dirname(fname)) != NULL
+				&& x_lstat(parent, &pst, NULL) == 0) {
+			if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) {
+				if (mkdir(fname, mode) == 0) {
+					undo_make_mutable(parent, pst.st_flags);
+					return 0;
+				} else
+					undo_make_mutable(parent, pst.st_flags);
+			}
+		}
+		errno = saved_errno;
+	}
+#endif
+
+	return ret;
 }
 
 /* like mkstemp but forces permissions */
@@ -336,7 +579,10 @@
 		int fd = mkstemp(template);
 		if (fd == -1)
 			return -1;
-		if (fchmod(fd, perms) != 0 && preserve_perms) {
+		// Network filesystems may return EACCES if you try to remove group privileges
+		// We don't want to avoid limiting initial access permissions, but
+		// that particular failure should not be grounds for avoiding the copy
+		if (fchmod(fd, perms) != 0 && preserve_perms && errno != EACCES) {
 			int errno_save = errno;
 			close(fd);
 			unlink(template);
@@ -402,7 +648,8 @@
 
 time_t get_create_time(const char *path)
 {
-	static struct create_time attrBuf;
+	static char attrBuf[sizeof(u_int32_t) + sizeof(struct timespec)];
+	static struct timespec  *crtime = (struct timespec*)&attrBuf[sizeof(u_int32_t)];
 	struct attrlist attrList;
 
 	memset(&attrList, 0, sizeof attrList);
@@ -410,7 +657,7 @@
 	attrList.commonattr = ATTR_CMN_CRTIME;
 	if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
 		return 0;
-	return attrBuf.crtime.tv_sec;
+	return crtime->tv_sec;
 }
 
 int set_create_time(const char *path, time_t crtime)
diff -Naur -X diff_ignore rsync-3.0.6_base/token.c rsync/token.c
--- rsync-3.0.6_base/token.c	2009-01-17 16:41:35.000000000 -0500
+++ rsync/token.c	2019-01-14 13:37:29.000000000 -0500
@@ -193,6 +193,8 @@
 		return;
 
 	while (1) {
+		if (isUpper(&ltr))
+			ltr = toLower(&ltr);
 		while (node->letter != ltr) {
 			if (node->letter > ltr)
 				return;
@@ -244,8 +246,17 @@
 		int32 len = 0;
 		while (len < n) {
 			int32 n1 = MIN(CHUNK_SIZE, n-len);
+			char *window = map_ptr(buf, offset+len, n1);
+			if (buf->status != 0) {
+				// BOMBICH
+				// Rather than sending an empty buffer when we have read errors, send the "finished" token and exit
+				// This specifically allows us to skip past the broken file and attempt to copy the remaining files
+				write_int(f, 0);
+				return;
+			}
+
 			write_int(f, n1);
-			write_buf(f, map_ptr(buf, offset+len, n1), n1);
+			write_buf(f, window, n1);
 			len += n1;
 		}
 	}
@@ -349,8 +360,7 @@
 			if (tx_strm.avail_in == 0 && nb != 0) {
 				/* give it some more input */
 				n = MIN(nb, CHUNK_SIZE);
-				tx_strm.next_in = (Bytef *)
-					map_ptr(buf, offset, n);
+				tx_strm.next_in = (Bytef *)map_ptr(buf, offset, n);
 				tx_strm.avail_in = n;
 				nb -= n;
 				offset += n;
@@ -599,7 +609,7 @@
 		rx_strm.next_out = (Bytef *)dbuf;
 		rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
 		r = inflate(&rx_strm, Z_SYNC_FLUSH);
-		if (r != Z_OK) {
+		if (r != Z_OK && r != Z_BUF_ERROR) {
 			rprintf(FERROR, "inflate (token) returned %d\n", r);
 			exit_cleanup(RERR_STREAMIO);
 		}
@@ -611,8 +621,7 @@
  * If token == -1 then we have reached EOF
  * If n == 0 then don't send a buffer
  */
-void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
-		int32 n, int32 toklen)
+void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset, int32 n, int32 toklen)
 {
 	if (!do_compression)
 		simple_send_token(f, token, buf, offset, n);
diff -Naur -X diff_ignore rsync-3.0.6_base/util.c rsync/util.c
--- rsync-3.0.6_base/util.c	2009-06-18 17:30:42.000000000 -0400
+++ rsync/util.c	2019-01-14 17:36:11.000000000 -0500
@@ -36,6 +36,8 @@
 extern mode_t orig_umask;
 extern char *partial_dir;
 extern struct filter_list_struct daemon_filter_list;
+extern int io_buf_size;
+extern int checksum_len;
 
 int sanitize_paths = 0;
 
@@ -43,6 +45,20 @@
 unsigned int curr_dir_len;
 int curr_dir_depth; /* This is only set for a sanitizing daemon. */
 
+static time_t last_hb = 0;
+void heartbeat(char *fbuf)
+{
+	if (last_hb == 0)
+		last_hb = time(NULL);
+	time_t now = time(NULL);
+	if (now - last_hb > 5) {
+		last_hb = now;
+		rprintf(FINFO, "S;;;HRTBT;;;CF;;;%s\n", fbuf);
+	}
+}
+
+
+
 /* Set a fd into nonblocking mode. */
 void set_nonblocking(int fd)
 {
@@ -78,9 +94,17 @@
 int fd_pair(int fd[2])
 {
 	int ret;
+	int bufsize;
 
 #ifdef HAVE_SOCKETPAIR
 	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
+	bufsize = io_buf_size;
+	fprintf(stderr, "DEBUG: [%s] Setting IO buffer size to %d\n", who_am_i(), io_buf_size);
+	setsockopt(fd[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
+	setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
+	setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
+	setsockopt(fd[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
+
 #else
 	ret = pipe(fd);
 #endif
@@ -297,10 +321,10 @@
 	int ifd;
 	char buf[1024 * 8];
 	int len;   /* Number of bytes read into `buf'. */
-
+	
 	if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
 		int save_errno = errno;
-		rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
+		rsyserr(FERROR_XFER, errno, "copy_file: open %s", full_fname(source));
 		errno = save_errno;
 		return -1;
 	}
@@ -308,13 +332,15 @@
 	if (ofd < 0) {
 		if (robust_unlink(dest) && errno != ENOENT) {
 			int save_errno = errno;
-			rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
+			rsyserr(FERROR_XFER, errno, "copy_file: unlink %s", full_fname(dest));
 			errno = save_errno;
 			return -1;
 		}
 
 		if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
 			int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
+			if (verbose)
+				fprintf(stderr, "DEBUG: copy_file: do_open(%s) failed: %d%s\n", dest, errno, create_bak_dir ? ". Calling make_bak_dir()" : "");
 			if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) {
 				if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)
 					save_errno = errno ? errno : save_errno;
@@ -322,7 +348,7 @@
 					save_errno = 0;
 			}
 			if (save_errno) {
-				rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
+				rsyserr(FERROR_XFER, save_errno, "copy_file: open %s", full_fname(dest));
 				close(ifd);
 				errno = save_errno;
 				return -1;
@@ -333,17 +359,18 @@
 	while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
 		if (full_write(ofd, buf, len) < 0) {
 			int save_errno = errno;
-			rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
+			rsyserr(FERROR_XFER, errno, "copy_file: write %s", full_fname(dest));
 			close(ifd);
 			close(ofd);
 			errno = save_errno;
 			return -1;
 		}
+		heartbeat((char *)source);
 	}
 
 	if (len < 0) {
 		int save_errno = errno;
-		rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
+		rsyserr(FERROR_XFER, errno, "copy_file: read %s", full_fname(source));
 		close(ifd);
 		close(ofd);
 		errno = save_errno;
@@ -351,13 +378,13 @@
 	}
 
 	if (close(ifd) < 0) {
-		rsyserr(FWARNING, errno, "close failed on %s",
+		rsyserr(FWARNING, errno, "copy_file: close failed on %s",
 			full_fname(source));
 	}
 
 	if (close(ofd) < 0) {
 		int save_errno = errno;
-		rsyserr(FERROR_XFER, errno, "close failed on %s",
+		rsyserr(FERROR_XFER, errno, "copy_file: close failed on %s",
 			full_fname(dest));
 		errno = save_errno;
 		return -1;
@@ -1356,6 +1383,9 @@
  **/
 int msleep(int t)
 {
+#ifdef HAVE_USLEEP
+       usleep(t*1000);
+#else
 	int tdiff = 0;
 	struct timeval tval, t1, t2;
 
@@ -1371,8 +1401,10 @@
 		gettimeofday(&t2, NULL);
 		tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
 			(t2.tv_usec - t1.tv_usec)/1000;
+		if (tdiff < 0)
+			t1 = t2; /* Time went backwards, so start over. */
 	}
-
+#endif
 	return True;
 }
 
@@ -1703,11 +1735,30 @@
 				who_am_i(), desc, (double)new_size * item_size,
 				new_ptr == lp->items ? " not" : "");
 		}
-		if (!new_ptr)
+		if (!new_ptr) {
+			fprintf(stderr, "DEBUG: Out of memory in expand_item_list(%s). Current count: %lu\n", desc, lp->count);
 			out_of_memory("expand_item_list");
+		}
 
 		lp->items = new_ptr;
 		lp->malloced = new_size;
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+char * printableChecksum(char *sum)
+{
+	int i, x1, x2;
+	char *c = malloc(checksum_len*2+1);
+	for (i = 0; i < checksum_len; i++) {
+		x1 = CVAL(sum, i);
+		x2 = x1 >> 4;
+		x1 &= 0xF;
+		c[i*2] = x2 <= 9 ? x2 + '0' : x2 + 'a' - 10;
+		c[i*2+1] = x1 <= 9 ? x1 + '0' : x1 + 'a' - 10;
+	}
+	c[checksum_len*2] = '\0';
+	
+	return c;
+}
+
diff -Naur -X diff_ignore rsync-3.0.6_base/xattrs.c rsync/xattrs.c
--- rsync-3.0.6_base/xattrs.c	2009-06-18 17:30:42.000000000 -0400
+++ rsync/xattrs.c	2019-01-14 13:38:36.000000000 -0500
@@ -22,6 +22,8 @@
 #include "rsync.h"
 #include "ifuncs.h"
 #include "lib/sysxattrs.h"
+// For _PATH_RSRCFORKSPEC
+#include <sys/paths.h>
 
 #ifdef SUPPORT_XATTRS
 
@@ -32,7 +34,12 @@
 extern int read_only;
 extern int list_only;
 extern int preserve_xattrs;
+extern int preserve_hfs_compression;
+extern int fs_supports_native_xattrs;
+extern uid_t receiver_uid;
+extern long pc_xattr_max_size;
 extern int checksum_seed;
+extern struct stats stats;
 
 #define RSYNC_XAL_INITIAL 5
 #define RSYNC_XAL_LIST_INITIAL 100
@@ -47,6 +54,7 @@
 #define XSTATE_ABBREV	1
 #define XSTATE_DONE	2
 #define XSTATE_TODO	3
+#define XSTATE_DECMPFS	4
 
 #define USER_PREFIX "user."
 #define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
@@ -69,6 +77,8 @@
 #define XDEF_ACL_SUFFIX "dacl"
 #define XDEF_ACL_ATTR RSYNC_PREFIX "%" XDEF_ACL_SUFFIX
 
+#define FAST_RESOURCE_FORKS 1
+
 typedef struct {
 	char *datum, *name;
 	size_t datum_len, name_len;
@@ -89,7 +99,6 @@
 {
 	size_t i;
 	rsync_xa *rxas = xalp->items;
-
 	for (i = 0; i < xalp->count; i++) {
 		free(rxas[i].datum);
 		/*free(rxas[i].name);*/
@@ -117,7 +126,17 @@
 {
 	ssize_t list_len;
 	double arg;
-
+	
+	/* Determine if this is a ._ AppleDouble file */
+	const char *f;
+	if ((f = strrchr(fname, '/')) != NULL)
+		++f;
+	else
+		f = fname;
+	
+	if ( f[0] == '.' && f[1] == '_')
+		return 0;
+	
 	if (!namebuf) {
 		namebuf_len = 1024;
 		namebuf = new_array(char, namebuf_len);
@@ -131,14 +150,14 @@
 		if (list_len >= 0) {
 			if ((size_t)list_len <= namebuf_len)
 				break;
-		} else if (errno == ENOTSUP)
+		} else if (errno == ENOTSUP || errno == ENOENT || errno == EINVAL || (errno == EACCES && !am_root))
 			return 0;
 		else if (errno != ERANGE) {
 			arg = (double)namebuf_len;
 		  got_error:
 			rsyserr(FERROR_XFER, errno,
-				"get_xattr_names: llistxattr(\"%s\",%.0f) failed",
-				fname, arg);
+				"[%s]get_xattr_names: llistxattr(%s,%.0f) failed",
+				who_am_i(), full_fname(fname), arg);
 			return -1;
 		}
 		list_len = sys_llistxattr(fname, NULL, 0);
@@ -163,18 +182,19 @@
 static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr,
 			    int no_missing_error)
 {
-	size_t datum_len = sys_lgetxattr(fname, name, NULL, 0);
-	size_t extra_len = *len_ptr;
+	ssize_t datum_len = sys_lgetxattr(fname, name, NULL, 0);
+	ssize_t extra_len = *len_ptr;
 	char *ptr;
 
 	*len_ptr = datum_len;
 
-	if (datum_len == (size_t)-1) {
-		if (errno == ENOTSUP || no_missing_error)
+	if (datum_len == -1) {
+		if (errno == ENOTSUP || errno == ENOATTR || errno == ENOENT || no_missing_error)
 			return NULL;
-		rsyserr(FERROR_XFER, errno,
-			"get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed",
-			fname, name);
+		if ((receiver_uid == 0 && strcmp(name, KAUTH_FILESEC_XATTR) != 0) || (errno != EPERM && errno != EACCES))
+			rsyserr(FERROR_XFER, errno,
+				"[%s]get_xattr_data: lgetxattr(%s,\"%s\",0) failed",
+				who_am_i(), full_fname(fname), name);
 		return NULL;
 	}
 
@@ -182,21 +202,30 @@
 		extra_len = 1; /* request non-zero amount of memory */
 	if (datum_len + extra_len < datum_len)
 		overflow_exit("get_xattr_data");
-	if (!(ptr = new_array(char, datum_len + extra_len)))
-		out_of_memory("get_xattr_data");
+	if (!(ptr = new_array(char, datum_len + extra_len))) {
+		fprintf(stderr, "get_xattr_data: Tried to allocate %zd bytes for the %s xattr on %s. This extended attribute was not copied.\n", datum_len, name, full_fname(fname));
+		if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0)
+			return NULL;
+		else
+			out_of_memory("get_xattr_data");
+	}
 
 	if (datum_len) {
-		size_t len = sys_lgetxattr(fname, name, ptr, datum_len);
+		ssize_t len = sys_lgetxattr(fname, name, ptr, datum_len);
+		if (len == -1 && (errno == ENOENT || errno == ENOATTR)) // Potential race condition if source file is deleted after initial successful sys_lgetxattr() call
+			return NULL;
 		if (len != datum_len) {
-			if (len == (size_t)-1) {
+			if (len == -1) {
 				rsyserr(FERROR_XFER, errno,
-				    "get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
-				    " failed", fname, name, (long)datum_len);
+				    "[%s]get_xattr_data: lgetxattr(%s,\"%s\",%zd)"
+				    " failed", who_am_i(), full_fname(fname), name, datum_len);
 			} else {
-				rprintf(FERROR_XFER,
-				    "get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
-				    " returned %ld\n", fname, name,
-				    (long)datum_len, (long)len);
+				// Filter out garbage from the buggy Synology DiskStation file sharing service
+				if (strstr(name, "APIC_") == NULL && strstr(name, "_DSAUDIO") == NULL && strstr(name, "_JPEGTN") == NULL)
+					rprintf(FERROR_XFER,
+							"rsync: [%s]get_xattr_data: lgetxattr(%s,\"%s\",%zd)"
+							" returned %zd (%d)\n", who_am_i(), full_fname(fname), name,
+							datum_len, len, errno);
 			}
 			free(ptr);
 			return NULL;
@@ -206,7 +235,7 @@
 	return ptr;
 }
 
-static int rsync_xal_get(const char *fname, item_list *xalp)
+static int rsync_xal_get(const char *fname, stat_x *sxp)
 {
 	ssize_t list_len, name_len;
 	size_t datum_len, name_offset;
@@ -216,6 +245,12 @@
 #endif
 	rsync_xa *rxa;
 	int count;
+	item_list *xalp;
+	
+	xalp = sxp->xattr;
+
+//	struct timeval start;
+//	gettimeofday(&start, NULL);
 
 	/* This puts the name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(fname)) < 0)
@@ -244,23 +279,80 @@
 				continue;
 		}
 
-		datum_len = name_len; /* Pass extra size to get_xattr_data() */
-		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
-			return -1;
-
-		if (datum_len > MAX_FULL_DATUM) {
-			/* For large datums, we store a flag and a checksum. */
-			name_offset = 1 + MAX_DIGEST_LEN;
-			sum_init(checksum_seed);
-			sum_update(ptr, datum_len);
-			free(ptr);
-
+//		datum_len = name_len; /* Pass extra size to get_xattr_data() */
+//		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
+//			return -1;
+//
+		//if (strcmp(name, XATTR_DECMPFS_NAME) == 0 || strcmp(name, XATTR_RESOURCEFORK_NAME) == 0) {
+		if (strcmp(name, XATTR_DECMPFS_NAME) == 0 || (preserve_hfs_compression && sxp->st.st_flags & UF_COMPRESSED && strcmp(name, XATTR_RESOURCEFORK_NAME) == 0)) {
+			if (verbose)
+				fprintf(stderr, "DEBUG: xal_get[%s]: Special decmpfs handling, name: %s, f: %d |%s\n", who_am_i(), name, sxp->st.st_flags, fname);
+
+			// It's too expensive to calculate checksums for every xattr containing decmpfs payload.
+			// Instead, we'll copy these every time as long as the file modification 
+			// date has changed. This seems to be inline with Apple's intentions
+			// for how fs compression will be used
+			datum_len = 1;
+			name_offset = datum_len;
 			if (!(ptr = new_array(char, name_offset + name_len)))
 				out_of_memory("rsync_xal_get");
-			*ptr = XSTATE_ABBREV;
-			sum_end(ptr + 1);
-		} else
-			name_offset = datum_len;
+			*ptr = XSTATE_DECMPFS;
+		} else {
+			if (verbose > 1)
+				fprintf(stderr, "DEBUG: xal_get[%s]: name: %s, f: %d |%s\n", who_am_i(), name, sxp->st.st_flags, fname);
+		
+			datum_len = name_len; /* Pass extra size to get_xattr_data() */
+			if (!(ptr = get_xattr_data(fname, name, &datum_len, 0))) {
+				//return -1;
+				if (strcmp(name, "com.apple.FinderInfo") == 0)
+					fprintf(stderr, "DEBUG: xal_get[%s]: get_xattr_data(%s, %s) failed, continuing anyway\n", who_am_i(), full_fname(fname), name);
+				continue; // One unreadable xattr doesn't mean they will all be unreadable
+			}
+			
+			if (datum_len > MAX_FULL_DATUM) {
+				/* For large datums, we store a flag and a checksum. */
+				name_offset = 1 + MAX_DIGEST_LEN;
+#ifdef FAST_RESOURCE_FORKS
+				if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0) {
+					// Rather than calculate a checksum of resource forks, we're just going to store the first MAX_DIGEST_LEN bytes for comparison
+					char buf[MAX_DIGEST_LEN];
+					memcpy(buf, ptr, MAX_DIGEST_LEN);
+
+					free(ptr);
+
+					if (!(ptr = new_array(char, name_offset + name_len)))
+						out_of_memory("rsync_xal_get");
+					*ptr = XSTATE_ABBREV;
+					memcpy(ptr + 1, buf, MAX_DIGEST_LEN);
+				} else {
+#endif
+				if (verbose > 1)
+					fprintf(stderr, "DEBUG: xal_get[%s]: abbreviating, name: %s |%s\n", who_am_i(), name, fname);
+
+				sum_init(checksum_seed);
+				sum_update(ptr, datum_len);
+				free(ptr);
+
+				if (!(ptr = new_array(char, name_offset + name_len)))
+					out_of_memory("rsync_xal_get");
+				*ptr = XSTATE_ABBREV;
+				sum_end(ptr + 1);
+#ifdef FAST_RESOURCE_FORKS
+				}
+#endif
+				// Update stats on sender side -- for total_size, we only add the size of xattrs that will be abbreviated. 
+				// We can't include non-abbreviated xattrs in total_transfer_size because the sender doesn't know if they're actually used
+				// Therefore, it's best to just leave unabbreviated xattrs out of the stats so that total_transfer_size matches up with total_size
+				// Abbreviated values can cause trouble too, e.g. if they're attached to hard-linked files. These xattrs get transferred for each instance of the file (and that should be fixed!). A lame workaround for now is to not include the size of xattrs attached to hard linked files in total_size or total_transferred_size
+				stats.total_size += (unsigned long long)datum_len;
+				if (verbose && !am_generator)
+					fprintf(stderr, "DEBUG: [%s] XALGET: stats.total_size |%s|+%lu\n", who_am_i(), full_fname(fname), (unsigned long)datum_len);
+			} else
+				name_offset = datum_len;
+		}
+
+		if (verbose)
+			fprintf(stderr, "DEBUG: xal_get[%s]: name: %s, type: %s, len: %lu |%s\n", who_am_i(), name, (datum_len > MAX_FULL_DATUM || (datum_len == 1 && ptr[0] == XSTATE_ABBREV)) ? "abbrev" : "reg", (unsigned long)datum_len, fname);
 
 		rxa = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL);
 		rxa->name = ptr + name_offset;
@@ -268,6 +360,9 @@
 		rxa->datum = ptr;
 		rxa->name_len = name_len;
 		rxa->datum_len = datum_len;
+
+		// Update stats on sender side
+		stats.num_xattrs++;
 	}
 	count = xalp->count;
 	rxa = xalp->items;
@@ -275,6 +370,7 @@
 		qsort(rxa, count, sizeof (rsync_xa), rsync_xal_compare_names);
 	for (rxa += count-1; count; count--, rxa--)
 		rxa->num = count;
+
 	return 0;
 }
 
@@ -287,7 +383,7 @@
 	if (IS_SPECIAL(sxp->st.st_mode) || IS_DEVICE(sxp->st.st_mode))
 		return 0;
 
-	if (rsync_xal_get(fname, sxp->xattr) < 0) {
+	if (rsync_xal_get(fname, sxp) < 0) {
 		free_xattr(sxp);
 		return -1;
 	}
@@ -303,6 +399,9 @@
 	int user_only = am_root <= 0;
 #endif
 
+	if (verbose)
+		fprintf(stderr, "copy_xattrs: %s\n", dest);
+
 	/* This puts the name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(source)) < 0)
 		return -1;
@@ -322,11 +421,15 @@
 		datum_len = 0;
 		if (!(ptr = get_xattr_data(source, name, &datum_len, 0)))
 			return -1;
+
+		if (verbose)
+			fprintf(stderr, "DEBUG: %s, datum: %p, datum_len: %lu\n", name, ptr, (unsigned long)datum_len);
+
 		if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
 			int save_errno = errno ? errno : EINVAL;
 			rsyserr(FERROR_XFER, errno,
-				"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
-				dest, name);
+				"copy_xattrs: lsetxattr(%s,\"%s\") failed",
+				full_fname(dest), name);
 			errno = save_errno;
 			return -1;
 		}
@@ -336,11 +439,11 @@
 	return 0;
 }
 
+// /*
 static int find_matching_xattr(item_list *xalp)
 {
 	size_t i, j;
 	item_list *lst = rsync_xal_l.items;
-
 	for (i = 0; i < rsync_xal_l.count; i++) {
 		rsync_xa *rxas1 = lst[i].items;
 		rsync_xa *rxas2 = xalp->items;
@@ -383,13 +486,16 @@
 	(void)EXPAND_ITEM_LIST(new_lst, rsync_xa, xalp->count);
 	memcpy(new_lst->items, xalp->items, xalp->count * sizeof (rsync_xa));
 	new_lst->count = xalp->count;
-	xalp->count = 0;
+	xalp->count = 0; // Why?
 }
+// /*
 
 /* Send the make_xattr()-generated xattr list for this flist entry. */
 int send_xattr(stat_x *sxp, int f)
 {
-	int ndx = find_matching_xattr(sxp->xattr);
+	// find_matching_xattr is a waste of cycles for MOSX clients
+	//int ndx = find_matching_xattr(sxp->xattr);
+	int ndx = -1;
 
 	/* Send 0 (-1 + 1) to indicate that literal xattr data follows. */
 	write_varint(f, ndx + 1);
@@ -416,6 +522,9 @@
 				name_len += UPRE_LEN;
 			}
 #endif
+			if (verbose)
+				fprintf(stderr, "DEBUG: send_xattr: name: %s, type: %d, len: %lu, ndx: %ld\n", name, rxa->datum[0], (unsigned long)rxa->datum_len, rsync_xal_l.count);
+
 			write_varint(f, name_len);
 			write_varint(f, rxa->datum_len);
 #ifndef HAVE_LINUX_XATTRS
@@ -429,10 +538,17 @@
 				write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
 			else
 				write_buf(f, rxa->datum, rxa->datum_len);
+
+			stats.num_xattrs++;
 		}
 		ndx = rsync_xal_l.count; /* pre-incremented count */
 		rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */
-	}
+
+		if (verbose && ndx == rsync_xal_l.count)
+			// xal_cnt should always be xndx+1
+			fprintf(stderr, "DEBUG: send_xattr[%s]: rsync_xal_l.count was not incremented!\n", who_am_i());
+		//ndx = rsync_xal_l.count - 1;
+}
 
 	return ndx;
 }
@@ -447,6 +563,15 @@
 	int snd_cnt, rec_cnt;
 	int cmp, same, xattrs_equal = 1;
 
+
+	// If the file is marked compressed, we'll only compare xattrs if the mod date of the files are different
+	if (preserve_hfs_compression && F_FFLAGS(file) & UF_COMPRESSED && sxp != NULL && sxp->st.st_flags & UF_COMPRESSED) {
+		if (verbose)
+			fprintf(stderr, "DEBUG: xattr_diff[compressed]: Source[fl:%s, sz:%.0f, t:%ld], Dest[fl:%s, t:%ld] diff: %s, ndx: %d |%s\n", F_FFLAGS(file) & UF_COMPRESSED ? "Y" : "N", (double)F_LENGTH(file), file->modtime, (sxp != NULL && sxp->st.st_flags & UF_COMPRESSED) ? "Y" : "N", (sxp != NULL && sxp->st.st_mtime) ? sxp->st.st_mtime : 0, (sxp != NULL && cmp_time(sxp->st.st_mtime, file->modtime) == 0) ? "N" : "Y", F_XATTR(file), f_name(file, NULL));
+		if (cmp_time(sxp->st.st_mtime, file->modtime) == 0)
+			return 0;
+	}
+
 	if (sxp && XATTR_READY(*sxp)) {
 		rec_rxa = sxp->xattr->items;
 		rec_cnt = sxp->xattr->count;
@@ -463,6 +588,9 @@
 	snd_rxa = lst->items;
 	snd_cnt = lst->count;
 
+	if (verbose)
+		fprintf(stderr, "DEBUG: xattr_diff: s:%d, r:%d, ndx: %d |%s\n", snd_cnt, rec_cnt, F_XATTR(file), f_name(file, NULL));
+
 	/* If the count of the sender's xattrs is different from our
 	 * (receiver's) xattrs, the lists are not the same. */
 	if (snd_cnt != rec_cnt) {
@@ -475,13 +603,35 @@
 		cmp = rec_cnt ? strcmp(snd_rxa->name, rec_rxa->name) : -1;
 		if (cmp > 0)
 			same = 0;
-		else if (snd_rxa->datum_len > MAX_FULL_DATUM) {
+		else if (snd_rxa->datum_len == 1 && snd_rxa->datum[0] == XSTATE_DECMPFS) { // TODO: had (have?) a SIGBUS crash here, added "snd_rxa->datum_len == 1 && "
+			// If we've gotten this far, we're going to assume the xattrs are different 
+			// because the files are different in size, mod date, or flags
+			same = 0;
+
+			if (verbose)
+				fprintf(stderr, "DEBUG: xattr_diff[TODO]: name: %s |%s\n", snd_rxa->name, f_name(file, NULL));
+
+			snd_rxa->datum[0] = XSTATE_TODO;
+		} else if (snd_rxa->datum_len > MAX_FULL_DATUM) {
 			same = cmp == 0 && snd_rxa->datum_len == rec_rxa->datum_len
 			    && memcmp(snd_rxa->datum + 1, rec_rxa->datum + 1,
 				      MAX_DIGEST_LEN) == 0;
+#ifdef FAST_RESOURCE_FORKS
+			if (same && strcmp(snd_rxa->name, XATTR_RESOURCEFORK_NAME) == 0)
+				same = cmp_time(sxp->st.st_mtime, file->modtime) == 0;
+#endif
+
 			/* Flag unrequested items that we need. */
-			if (!same && find_all && snd_rxa->datum[0] == XSTATE_ABBREV)
+			if (!same && find_all && snd_rxa->datum[0] == XSTATE_ABBREV) {
 				snd_rxa->datum[0] = XSTATE_TODO;
+				if (verbose)
+					fprintf(stderr, "DEBUG: xattr_diff[TODO]: name: %s |%s\n", snd_rxa->name, f_name(file, NULL));
+			} else {
+				// The item remains abbreviated, rsync_xal_set will retrieve this value from the local file that's getting replaced
+				stats.total_unchanged_size += snd_rxa->datum_len; // Only add abbreviated xattrs here to match sender behavior
+				if (verbose > 1)
+					fprintf(stderr, "xattr_diff: stats.total_unchanged_size += %lu = %llu (%s)\n", (unsigned long)snd_rxa->datum_len, stats.total_unchanged_size, f_name(file, NULL));
+			}
 		} else {
 			same = cmp == 0 && snd_rxa->datum_len == rec_rxa->datum_len
 			    && memcmp(snd_rxa->datum, rec_rxa->datum,
@@ -522,14 +672,30 @@
 
 	lst += F_XATTR(file);
 	for (rxa = lst->items, cnt = lst->count; cnt--; rxa++) {
-		if (rxa->datum_len <= MAX_FULL_DATUM)
+		if (verbose)
+			fprintf(stderr, "DEBUG: send_x_request: name: %s, type: %d, len: %lu, fl: %#x%s, ndx: %d |%s\n", rxa->name, rxa->datum[0], (unsigned long)rxa->datum_len, F_FFLAGS(file), !(rxa->datum_len <= MAX_FULL_DATUM && !(preserve_hfs_compression && F_FFLAGS(file) & UF_COMPRESSED)) ? "" : am_generator ? " [Have datum]" : " [No send]", F_XATTR(file), (fname != NULL ? full_fname(fname) : "gen"));
+
+		// For decmpfs xattrs, we artificially set the datum_length to 1 and treat it like an abbreviated xattr. The datum_length is 1 because
+		// we don't calculate a checksum of these xattrs, nor even read them on the source in flist, so we have nothing to put into datum
+		// As a result, we need a special case here to not continue if datum_len is < MAX_FULL_DATUM but the xattr is a decmpfs xattr
+
+		// This has to be errant. If (rxa->datum_len <= MAX_FULL_DATUM), I can't count on the first byte of datum to be an XATTR type flag
+		// What if the UF_COMPRESSED flag is errantly set on a file?
+		// I need to prove that it's possible to have that flag errantly and reproduce this.
+		// TODO: Could it be that the fileflags on disk are correct, but we're somehow not initiating the fileflags correctly in flist?
+		int xattrIsDecmpfsXattr = strcmp(rxa->name, XATTR_DECMPFS_NAME) == 0 || strcmp(rxa->name, XATTR_RESOURCEFORK_NAME) == 0;
+		if (rxa->datum_len <= MAX_FULL_DATUM && !(preserve_hfs_compression && F_FFLAGS(file) & UF_COMPRESSED && xattrIsDecmpfsXattr))
+		//if (rxa->datum_len <= MAX_FULL_DATUM && !(preserve_hfs_compression && strcmp(rxa->name, XATTR_DECMPFS_NAME) == 0)) // Does this accommodate the resource fork case?
+		//if (rxa->datum_len <= MAX_FULL_DATUM && !(preserve_hfs_compression && strcmp(rxa->name, "com.apple.quarantine") == 0)) // DEBUG
 			continue;
 		switch (rxa->datum[0]) {
+		case XSTATE_DECMPFS:
 		case XSTATE_ABBREV:
 			/* Items left abbreviated matched the sender's checksum, so
 			 * the receiver will cache the local data for future use. */
 			if (am_generator)
 				rxa->datum[0] = XSTATE_DONE;
+
 			continue;
 		case XSTATE_TODO:
 			assert(f_out >= 0);
@@ -538,6 +704,9 @@
 			continue;
 		}
 
+		if (verbose)
+			fprintf(stderr, "DEBUG: send_x_request[%s]: Sending %sabbrev xattr: name: %s, type: %d, len: %lu, rxa->num: %d, prior_req: %d, ndx: %d\n", who_am_i(), am_generator ? "request for " : "", rxa->name, rxa->datum[0], rxa->datum_len, rxa->num, prior_req, F_XATTR(file));
+
 		/* Flag that we handled this abbreviated item. */
 		rxa->datum[0] = XSTATE_DONE;
 
@@ -550,7 +719,8 @@
 
 			/* Re-read the long datum. */
 			if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0))) {
-				rprintf(FERROR_XFER, "failed to re-read xattr %s for %s\n", rxa->name, fname);
+				if (errno != ENOTSUP && errno != ENOATTR)
+					rprintf(FERROR_XFER, "failed to re-read xattr %s for %s\n", rxa->name, full_fname(fname));
 				write_varint(f_out, 0);
 				continue;
 			}
@@ -558,6 +728,27 @@
 			write_varint(f_out, len); /* length might have changed! */
 			write_buf(f_out, ptr, len);
 			free(ptr);
+
+			// Update stats on sender side
+#if 0
+			// Non-Finder math method:
+			if (strcmp(rxa->name, XATTR_DECMPFS_NAME) == 0 || (preserve_hfs_compression && F_FFLAGS(file) & UF_COMPRESSED && strcmp(rxa->name, XATTR_RESOURCEFORK_NAME) == 0)) {
+				stats.total_size += len;
+				if (verbose > 1)
+					fprintf(stderr, "DEBUG: [%s] SENDXA: stats.total_size |%s|+%lu|%s|\n", who_am_i(), full_fname(fname), (unsigned long)len, rxa->name);
+			}
+			stats.total_transferred_size += len;
+			if (verbose > 1)
+				fprintf(stderr, "DEBUG: [%s] SENDXA: stats.total_transferred_size |%s|+%lu|%s|\n", who_am_i(), full_fname(fname), (unsigned long)len, rxa->name);
+			stats.xattr_transfer_size += len;
+#else
+			if (!(preserve_hfs_compression && F_FFLAGS(file) & UF_COMPRESSED)) {
+				stats.total_transferred_size += len;
+				if (verbose > 1)
+					fprintf(stderr, "DEBUG: [%s] SENDXA: stats.total_transferred_size |%s|+%lu|%s|\n", who_am_i(), full_fname(fname), (unsigned long)len, rxa->name);
+			}
+			stats.xattr_transfer_size += len;
+#endif
 		}
 	}
 
@@ -585,23 +776,32 @@
 	cnt = lst->count;
 	rxa = lst->items;
 	num = 0;
+
 	while ((rel_pos = read_varint(f_in)) != 0) {
 		num += rel_pos;
+		if (verbose)
+			//if (am_sender || am_generator)
+			fprintf(stderr, "DEBUG: recv_x_request[%s]: abbrev req, rel_pos: %d, ndx: %d |%s\n", who_am_i(), rel_pos, F_XATTR(file), f_name(file, NULL));
 		while (cnt && rxa->num < num) {
 		    rxa++;
 		    cnt--;
 		}
 		if (!cnt || rxa->num != num) {
 			rprintf(FERROR, "[%s] could not find xattr #%d for %s\n",
-				who_am_i(), num, f_name(file, NULL));
+				who_am_i(), num, full_fname(f_name(file, NULL)));
+			// This next line will cause a crash if rxa->name is corrupted
+			fprintf(stderr, "DEBUG: cnt: %d, name: %s, rxa->num: %d (%s)\n", cnt, rxa->name, rxa->num, full_fname(f_name(file, NULL)));
 			exit_cleanup(RERR_STREAMIO);
 		}
-		if (!XATTR_ABBREV(*rxa) || rxa->datum[0] != XSTATE_ABBREV) {
-			rprintf(FERROR, "[%s] internal abbrev error on %s (%s, len=%ld)!\n",
-				who_am_i(), f_name(file, NULL), rxa->name, (long)rxa->datum_len);
+		if ((!XATTR_ABBREV(*rxa) || rxa->datum[0] != XSTATE_ABBREV) && rxa->datum[0] != XSTATE_DECMPFS) {
+			rprintf(FERROR, "[%s] internal abbrev error on %s (%s, len=%ld, datum[0]: %d)!\n",
+				who_am_i(), full_fname(f_name(file, NULL)), rxa->name, (long)rxa->datum_len, rxa->datum[0]);
 			exit_cleanup(RERR_STREAMIO);
 		}
 
+		if (am_sender && verbose)
+			fprintf(stderr, "DEBUG: recv_x_request[snd]: %s: type: %d, rel_pos: %d, ndx: %d\n", rxa->name, rxa->datum[0], rel_pos, F_XATTR(file));
+		
 		if (am_sender) {
 			rxa->datum[0] = XSTATE_TODO;
 			continue;
@@ -609,6 +809,9 @@
 
 		old_datum = rxa->datum;
 		rxa->datum_len = read_varint(f_in);
+		
+		if (verbose > 1)
+			fprintf(stderr, "\t%s: datum_length is %lu\n", rxa->name, (unsigned long)rxa->datum_len);
 
 		if (rxa->name_len + rxa->datum_len < rxa->name_len)
 			overflow_exit("recv_xattr_request");
@@ -621,6 +824,14 @@
 		free(old_datum);
 		read_buf(f_in, rxa->datum, rxa->datum_len);
 		got_xattr_data = 1;
+
+		// We get 0-sized files on the receiver end for compressed file, but the sender tracks uncompressed size. Only for the purpose of progress indication, we fudge the tts value here so it can attempt to keep up with the total_size value presented by the sender.
+		//if (rxa->datum[0] != XSTATE_DECMPFS) {
+			stats.total_transferred_size += rxa->datum_len;
+			if (verbose > 1)
+				fprintf(stderr, "DEBUG: [%s] RECVXA: stats.total_transferred_size += %lu = %llu (%s)\n", who_am_i(), (unsigned long)rxa->datum_len, stats.total_transferred_size, f_name(file, NULL));
+		//}
+		stats.xattr_transfer_size += rxa->datum_len;
 	}
 
 	return got_xattr_data;
@@ -642,7 +853,7 @@
 
 	if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
 		rprintf(FERROR, "receive_xattr: xa index %d out of"
-			" range for %s\n", ndx, f_name(file, NULL));
+			" range for %s\n", ndx, full_fname(f_name(file, NULL)));
 		exit_cleanup(RERR_STREAMIO);
 	}
 
@@ -656,6 +867,10 @@
 		temp_xattr.count = 0;
 	}
 
+	if (verbose)
+		// xal_cnt should always be xndx+1
+		fprintf(stderr, "DEBUG: receive_xattr[%s]: cnt: %d, ndx: %ld |%s\n", who_am_i(), count, rsync_xal_l.count, f_name(file, NULL));
+
 	for (num = 1; num <= count; num++) {
 		char *ptr, *name;
 		rsync_xa *rxa;
@@ -664,7 +879,7 @@
 		size_t dget_len = datum_len > MAX_FULL_DATUM ? 1 + MAX_DIGEST_LEN : datum_len;
 		size_t extra_len = MIGHT_NEED_RPRE ? RPRE_LEN : 0;
 		if ((dget_len + extra_len < dget_len)
-		 || (dget_len + extra_len + name_len < dget_len))
+		 || (dget_len + extra_len + name_len < dget_len + extra_len))
 			overflow_exit("receive_xattr");
 		ptr = new_array(char, dget_len + extra_len + name_len);
 		if (!ptr)
@@ -677,6 +892,8 @@
 			*ptr = XSTATE_ABBREV;
 			read_buf(f, ptr + 1, MAX_DIGEST_LEN);
 		}
+		if (verbose)
+			fprintf(stderr, "DEBUG: receive_xattr, name: %s, type: %s(%d), len: %lu, num: %d\n", name, dget_len == datum_len ? "reg" : "abbrev", ptr[0], (unsigned long)datum_len, num);
 #ifdef HAVE_LINUX_XATTRS
 		/* Non-root can only save the user namespace. */
 		if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) {
@@ -711,12 +928,15 @@
 			free(ptr);
 			continue;
 		}
+		
 		rxa = EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, 1);
 		rxa->name = name;
 		rxa->datum = ptr;
 		rxa->name_len = name_len;
 		rxa->datum_len = datum_len;
 		rxa->num = num;
+
+		stats.num_xattrs++;
 	}
 
 	if (need_sort && count > 1)
@@ -725,6 +945,12 @@
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
 
+	// If we call cache_tmp_xattr(), and then fail to call uncache_tmp_xattrs(), rsync_xal_l.count will not be the correct index value
+	// TODO: We should instead set ndx to rsync_xal_l.count - 1 after adding this file's xattr to the list
+	if (verbose && ndx == rsync_xal_l.count)
+		// xal_cnt should always be xndx+1
+		fprintf(stderr, "DEBUG: receive_xattr[%s]: rsync_xal_l.count was not incremented!\n", who_am_i());
+	//ndx = rsync_xal_l.count - 1;
 	F_XATTR(file) = ndx;
 }
 
@@ -739,9 +965,16 @@
 
 	if (prior_xattr_count == (size_t)-1)
 		prior_xattr_count = rsync_xal_l.count;
-	ndx = find_matching_xattr(sxp->xattr);
-	if (ndx < 0)
-		rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */
+	
+	// find_matching_xattr is a waste of cycles for MOSX clients
+	//ndx = find_matching_xattr(sxp->xattr);
+	ndx = -1;
+	if (ndx < 0) {
+		if (verbose)
+			fprintf(stderr, "DEBUG: cache_tmp_xattr[%s]: Adding a tmp xattr, ndx: %ld\n", who_am_i(), rsync_xal_l.count);
+		rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */ // sxp->xattr->count is 0 coming out of rsync_xal_store
+		//ndx = rsync_xal_l.count - 1; // Right?
+	}
 
 	F_XATTR(file) = ndx;
 }
@@ -752,10 +985,12 @@
 		item_list *xattr_item = rsync_xal_l.items;
 		item_list *xattr_start = xattr_item + prior_xattr_count;
 		xattr_item += rsync_xal_l.count;
+		if (verbose)
+			fprintf(stderr, "DEBUG: uncache_tmp_xattrs[%s]: Removing %ld items from the end of rsync_xal_l. New count: %ld\n", who_am_i(), rsync_xal_l.count - prior_xattr_count, prior_xattr_count);
 		rsync_xal_l.count = prior_xattr_count;
 		while (xattr_item-- > xattr_start) {
 			rsync_xal_free(xattr_item);
-			free(xattr_item);
+			free(xattr_item->items);
 		}
 		prior_xattr_count = (size_t)-1;
 	}
@@ -774,6 +1009,12 @@
 	size_t name_len;
 	int ret = 0;
 
+//	struct timeval start;
+//	gettimeofday(&start, NULL);
+
+	if (verbose > 1)
+		fprintf(stderr, "DEBUG: rsync_xal_set(%s): fname: %s, fnamecmp: %s\n", who_am_i(), fname, fnamecmp);
+
 	/* This puts the current name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(fname)) < 0)
 		return -1;
@@ -781,41 +1022,70 @@
 	for (i = 0; i < xalp->count; i++) {
 		name = rxas[i].name;
 
+		if (verbose > 1)
+			fprintf(stderr, "\t%s: datum_type: %d, datum_len: %lu\n", name, rxas[i].datum[0], (unsigned long)rxas[i].datum_len);
+		
 		if (XATTR_ABBREV(rxas[i])) {
 			/* See if the fnamecmp version is identical. */
 			len = name_len = rxas[i].name_len;
+			if (verbose > 1)
+				fprintf(stderr, "Calling get_xattr_data(%s, %s, &len, 1), am_generator: %d\n", fnamecmp, name, am_generator);
 			if ((ptr = get_xattr_data(fnamecmp, name, &len, 1)) == NULL) {
 			  still_abbrev:
 				if (am_generator)
 					continue;
-				rprintf(FERROR, "Missing abbreviated xattr value, %s, for %s\n",
-					rxas[i].name, full_fname(fname));
+				rprintf(FERROR, "Missing abbreviated xattr value, %s, for %s [%d/%lu/%lu]\n",
+					rxas[i].name, full_fname(fname), errno, (unsigned long)rxas[i].datum_len, (unsigned long)len);
 				ret = -1;
 				continue;
 			}
-			if (len != rxas[i].datum_len) {
+			
+			if (verbose > 1)
+				fprintf(stderr, "\t%s: datum_len: %lu, expected datum_len: %lu\n", name, (unsigned long)len, (unsigned long)rxas[i].datum_len);
+			
+			if (len != rxas[i].datum_len && rxas[i].datum[0] != XSTATE_DECMPFS) { // We expect the length to not match with decmpfs xattrs
 				free(ptr);
 				goto still_abbrev;
 			}
 
-			sum_init(checksum_seed);
-			sum_update(ptr, len);
-			sum_end(sum);
-			if (memcmp(sum, rxas[i].datum + 1, MAX_DIGEST_LEN) != 0) {
-				free(ptr);
-				goto still_abbrev;
+			if (!(preserve_hfs_compression && sxp->st.st_flags & UF_COMPRESSED)) {
+#ifdef FAST_RESOURCE_FORKS
+				if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0) {
+					memcpy(&sum, ptr, MAX_DIGEST_LEN);
+					if (verbose > 1)
+						fprintf(stderr, "\t%s: \"sum\" is %s\n", name, sum);
+				} else {
+#endif
+				if (verbose > 1)
+					fprintf(stderr, "xal_get(%s): Calculating a checksum for %s xattr\n", who_am_i(), name);
+				sum_init(checksum_seed);
+				sum_update(ptr, len);
+				sum_end(sum);
+#ifdef FAST_RESOURCE_FORKS
+				}
+#endif
+				if (memcmp(sum, rxas[i].datum + 1, MAX_DIGEST_LEN) != 0) {
+					free(ptr);
+					goto still_abbrev;
+				}
 			}
-
+			
 			if (fname == fnamecmp)
 				; /* Value is already set when identical */
 			else if (sys_lsetxattr(fname, name, ptr, len) < 0) {
-				rsyserr(FERROR_XFER, errno,
-					"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
-					fname, name);
+				if (strcmp(name, KAUTH_FILESEC_XATTR) != 0 && len > 0) {
+					if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && len > pc_xattr_max_size)
+						errno = E2BIG;
+					rsyserr(FERROR_XFER, errno,
+						"rsync_xal_set: lsetxattr(%s,\"%s\",\"%lu\") failed",
+						full_fname(fname), name, (unsigned long)len);
+				}
 				ret = -1;
-			} else /* make sure caller sets mtime */
+			} else {/* make sure caller sets mtime */
+				if (verbose > 1)
+					fprintf(stderr, "\t%s: Called sys_lsetxattr on %s\n", name, full_fname(fname));
 				sxp->st.st_mtime = (time_t)-1;
-
+			}
 			if (am_generator) { /* generator items stay abbreviated */
 				free(ptr);
 				continue;
@@ -828,14 +1098,22 @@
 			rxas[i].datum = ptr;
 			continue;
 		}
-
-		if (sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len) < 0) {
-			rsyserr(FERROR_XFER, errno,
-				"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
-				fname, name);
+		
+		int result = sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len);
+		if (result < 0) {
+			if (((receiver_uid == 0 || receiver_uid == sxp->st.st_uid) && strcmp(name, KAUTH_FILESEC_XATTR) != 0 && rxas[i].datum_len > 0) || (errno != EPERM && errno != EACCES)) {
+				if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && len > pc_xattr_max_size)
+					errno = E2BIG;
+				rsyserr(FERROR_XFER, errno,
+					"rsync_xal_set: lsetxattr(%s,\"%s\",\"%lu\") failed",
+					full_fname(fname), name, (unsigned long)rxas[i].datum_len);
+			}
 			ret = -1;
-		} else /* make sure caller sets mtime */
+		} else /* make sure caller sets mtime */ {
+			if (verbose > 1)
+				fprintf(stderr, "\trsync_xal_set: sys_lsetxattr(%s, %s, [datum_buf], %lu) returned %d (%d)\n", fname, name, (unsigned long)rxas[i].datum_len, result, errno);
 			sxp->st.st_mtime = (time_t)-1;
+		}
 	}
 
 	/* Remove any extraneous names. */
@@ -859,16 +1137,25 @@
 				break;
 		}
 		if (i == xalp->count) {
+			if (strcmp(name, XATTR_FINDERINFO_NAME) == 0 && (sxp->st.st_flags & UF_HIDDEN) > 0) {
+				//fprintf(stderr, "DEBUG: not removing extraneous %s xattr from this hidden file: %s\n", name, full_fname(fname));
+				continue;
+			}
 			if (sys_lremovexattr(fname, name) < 0) {
-				rsyserr(FERROR_XFER, errno,
-					"rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed",
-					fname, name);
-				ret = -1;
+				if (errno != ENOATTR) {
+					rsyserr(FERROR_XFER, errno,
+						"rsync_xal_set: lremovexattr(%s,\"%s\") failed",
+						full_fname(fname), name);
+					ret = -1;
+				}
 			} else /* make sure caller sets mtime */
 				sxp->st.st_mtime = (time_t)-1;
 		}
 	}
 
+	// Memory leak? This should ease memory pressure, but isn't this dangerous considering that rsync_xal_l still has a reference to it?
+	rsync_xal_free(xalp);
+
 	return ret;
 }
 
@@ -891,8 +1178,13 @@
 		errno = ENOTSUP;
 		return -1;
 	}
+	
+	if (sxp->st.st_ino == 2)
+		return 1;
 
 	ndx = F_XATTR(file);
+	if (verbose)
+		fprintf(stderr, "DEBUG: set_xattr[%s]: ndx: %d | %s\n", who_am_i(), ndx, fname);
 	return rsync_xal_set(fname, lst + ndx, fnamecmp, sxp);
 }
 
@@ -909,8 +1201,8 @@
 	const char *name = is_access_acl ? XACC_ACL_ATTR : XDEF_ACL_ATTR;
 	if (sys_lsetxattr(fname, name, buf, buf_len) < 0) {
 		rsyserr(FERROR_XFER, errno,
-			"set_xattr_acl: lsetxattr(\"%s\",\"%s\") failed",
-			fname, name);
+			"set_xattr_acl: lsetxattr(%s,\"%s\") failed",
+			full_fname(fname), name);
 		return -1;
 	}
 	return 0;
@@ -953,7 +1245,7 @@
 			xst->st_gid = 0;
 			return 0;
 		}
-		rsyserr(FERROR_XFER, errno, "failed to read xattr %s for %s",
+		rsyserr(FERROR_XFER, errno, "get_stat_xattr: failed to read xattr %s for %s",
 			XSTAT_ATTR, full_fname(fname));
 		return -1;
 	}
@@ -984,13 +1276,13 @@
 		return 0;
 
 	if (read_only || list_only) {
-		rsyserr(FERROR_XFER, EROFS, "failed to write xattr %s for %s",
+		rsyserr(FERROR_XFER, EROFS, "set_stat_xattr: failed to write xattr %s for %s",
 			XSTAT_ATTR, full_fname(fname));
 		return -1;
 	}
 
 	if (x_lstat(fname, &fst, &xst) < 0) {
-		rsyserr(FERROR_XFER, errno, "failed to re-stat %s",
+		rsyserr(FERROR_XFER, errno, "set_stat_xattr: failed to re-stat %s",
 			full_fname(fname));
 		return -1;
 	}
@@ -1017,7 +1309,7 @@
 		/* xst.st_mode will be 0 if there's no current stat xattr */
 		if (xst.st_mode && sys_lremovexattr(fname, XSTAT_ATTR) < 0) {
 			rsyserr(FERROR_XFER, errno,
-				"delete of stat xattr failed for %s",
+				"set_stat_xattr: delete of stat xattr failed for %s",
 				full_fname(fname));
 			return -1;
 		}
@@ -1035,7 +1327,7 @@
 			if (errno == EPERM && S_ISLNK(fst.st_mode))
 				return 0;
 			rsyserr(FERROR_XFER, errno,
-				"failed to write xattr %s for %s",
+				"set_stat_xattr: failed to write xattr %s for %s",
 				XSTAT_ATTR, full_fname(fname));
 			return -1;
 		}
@@ -1068,4 +1360,18 @@
 	return ret;
 }
 
+int64 xattr_size(struct file_struct *file)
+{
+	int64 xattrSize = 0;
+	item_list *lst = rsync_xal_l.items;
+	int cnt;
+	rsync_xa *rxa;
+
+	lst += F_XATTR(file);
+	for (rxa = lst->items, cnt = lst->count; cnt--; rxa++)
+		xattrSize += rxa->datum_len;
+
+	return xattrSize;
+}
+
 #endif /* SUPPORT_XATTRS */
