View Issue Details

IDProjectCategoryView StatusLast Update
0000366RsyncBugpublic2017-11-30 06:16
ReporterSteven LevineAssigned ToSteven Levine 
PrioritynormalSeverityminorReproducibilityalways
Status assignedResolutionopen 
Product Version3.0.9 
Target VersionFixed in Version 
Summary0000366: rsync 3.0.x patch collector
DescriptionThis bug serves as a repository for the rsync 3.0.x source diffs and binary packages built by Steven Levine.

The packages typically have a few more fixes and features than Paul's builds.

The .diff files are the unified diffs agains the pristine 3.0.x sources.

The .zip files contain readme.shl and readme.os2 files with build instructions.
TagsNo tags attached.

Relationships

related to 0000514 resolvedSteven Levine When creating new directories, rsync 3.0.8 sometimes adds libc EAs automatically 

Activities

Steven Levine

2009-09-24 09:01

manager   ~0001409

The rsync-3.0.6-20090918-shl.diff patch set adds native OS/2 permissions support to the existing feature set. See readme.os2 for more details.

2009-09-25 12:21

 

rsync-3.0.6-20090924-shl.diff (79,754 bytes)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/Makefile.in ./Makefile.in
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/Makefile.in	2009-04-10 16:24:48.000000000 -0700
+++ ./Makefile.in	2009-09-24 18:43:14.000000000 -0700
@@ -12,6 +12,7 @@
 CFLAGS=@CFLAGS@
 CPPFLAGS=@CPPFLAGS@
 EXEEXT=@EXEEXT@
+# 14 Jun 09 SHL fixme to do bldlevel strings
 LDFLAGS=@LDFLAGS@
 
 INSTALLCMD=@INSTALL@
@@ -68,6 +69,9 @@
 	-mkdir -p ${DESTDIR}${mandir}/man5
 	if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
 	if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
+	if test -f readme.os2; then ${INSTALLMAN} -m 644 readme.os2 ${DESTDIR}${prefix}; fi
+	if test -f rsync.map; then ${INSTALLMAN} -m 644 rsync.map ${DESTDIR}${prefix}; fi
+	if test -s "${DIFFFILE}"; then if test -f ${DIFFFILE}; then ${INSTALLMAN} -m 644 ${DIFFFILE} ${DESTDIR}${prefix}; fi; fi
 
 install-strip:
 	$(MAKE) INSTALL_STRIP='-s' install
@@ -189,9 +193,10 @@
 	yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
 	-$(srcdir)/tweak_manpage rsyncd.conf.5
 
+# 06 Feb 09 SHL clean maps
 clean: cleantests
 	rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
-		rounding rounding.h *.old
+		rounding rounding.h *.old rsync.map rounding.map
 
 cleantests:
 	rm -rf ./testtmp*
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/access.c ./access.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/access.c	2009-01-17 13:41:34.000000000 -0800
+++ ./access.c	2009-07-22 14:46:50.000000000 -0700
@@ -100,7 +100,9 @@
 	hints.ai_flags = AI_NUMERICHOST;
 #endif
 
-	if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	// if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	if ((gai = getaddrinfo(addr, NULL, &hints, &resa)) != 0) {			// 27 Jul 08 SHL debug
+		// rprintf(FLOG, "* match_address: gai %d %s(%u) [%s]\n", gai, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 		if (p)
 			*p = '/';
 		return 0;
@@ -110,8 +112,8 @@
 	if (p)
 		*p++ = '/';
 	if (gai != 0) {
-		rprintf(FLOG, "error matching address %s: %s\n",
-			tok, gai_strerror(gai));
+		rprintf(FLOG, "* error matching address %s: %s (%d)\n",
+			tok, gai_strerror(gai), gai);
 		freeaddrinfo(resa);
 		return 0;
 	}
@@ -222,7 +224,11 @@
 	if (host)
 		strlower(host);
 
+	// rprintf(FLOG, "* access_match: %s (%s) %s(%u) [%s]\n", host, addr, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
+
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+
+		// rprintf(FLOG, "* access_match: tok %s %s(%u) [%s]\n", tok, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 		if (match_hostname(host, tok) || match_address(addr, tok)) {
 			free(list2);
 			return 1;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/authenticate.c ./authenticate.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/authenticate.c	2009-01-17 13:41:34.000000000 -0800
+++ ./authenticate.c	2009-06-29 14:47:30.000000000 -0700
@@ -96,7 +96,9 @@
 	if (do_stat(fname, &st) == -1) {
 		rsyserr(FLOG, errno, "stat(%s)", fname);
 		ok = 0;
-	} else if (lp_strict_modes(module)) {
+	}
+#ifndef __OS2__	 /* 29 Jun 09 SHL suppress unsupported mode checks */
+	else if (lp_strict_modes(module)) {
 		if ((st.st_mode & 06) != 0) {
 			rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
 			ok = 0;
@@ -105,6 +107,7 @@
 			ok = 0;
 		}
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		rprintf(FLOG, "continuing without secrets file\n");
 		close(fd);
@@ -173,13 +176,16 @@
 	if (do_stat(filename, &st) == -1) {
 		rsyserr(FWARNING, errno, "stat(%s)", filename);
 		ok = 0;
-	} else if ((st.st_mode & 06) != 0) {
+	}
+#ifndef __OS2__	 /* 12 Jun 08 SHL suppress unsupported mode checks */
+	else if ((st.st_mode & 06) != 0) {
 		rprintf(FWARNING, "password file must not be other-accessible\n");
 		ok = 0;
 	} else if (MY_UID() == 0 && st.st_uid != 0) {
 		rprintf(FWARNING, "password file must be owned by root when running as root\n");
 		ok = 0;
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		close(fd);
 		rprintf(FWARNING, "continuing without password file\n");
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/clientname.c ./clientname.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/clientname.c	2009-01-17 13:41:34.000000000 -0800
+++ ./clientname.c	2009-09-18 20:05:48.000000000 -0700
@@ -95,8 +95,10 @@
 	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
-	if (initialised)
+	if (initialised) {
+		// rprintf(FLOG, "* client_name: %s %s(%u) [%s]\n", name_buf, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 		return name_buf;
+	}
 
 	strlcpy(name_buf, default_name, sizeof name_buf);
 	initialised = 1;
@@ -148,6 +150,8 @@
 			port_buf, sizeof port_buf) == 0)
 		check_name(fd, &ss, name_buf, sizeof name_buf);
 
+	// rprintf(FLOG, "* client_name: %s %s(%u) [%s]\n", name_buf, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
+
 	return name_buf;
 }
 
@@ -216,14 +220,17 @@
 	int name_err;
 
 	/* reverse lookup */
+	// rprintf(FLOG, "* lookup_name: %s(%u) [%s]\n", __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
 			       name_buf, name_buf_size,
 			       port_buf, port_buf_size,
 			       NI_NAMEREQD | NI_NUMERICSERV);
 	if (name_err != 0) {
 		strlcpy(name_buf, default_name, name_buf_size);
-		rprintf(FLOG, "name lookup failed for %s: %s\n",
-			client_addr(fd), gai_strerror(name_err));
+		// rprintf(FLOG, "name lookup failed for %s: %s\n",
+		//	client_addr(fd), gai_strerror(name_err));
+		rprintf(FLOG, "lookup_name failed for %s: %s (%d) at %s(%u) [%s]\n",	// 27 Jul 08 SHL debug
+			client_addr(fd), gai_strerror(name_err), name_err, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL
 		return name_err;
 	}
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/clientserver.c ./clientserver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/clientserver.c	2009-01-17 13:41:34.000000000 -0800
+++ ./clientserver.c	2009-07-22 14:47:04.000000000 -0700
@@ -428,6 +428,8 @@
 	iconv_opt = NULL;
 #endif
 
+	if (verbose)
+		rprintf(FINFO, "[%s] rsync_module addr:host is %s:%s\n", who_am_i(), addr, host);	// 28 Jul 08 SHL
 	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
 		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
 			name, host, addr);
@@ -481,6 +483,7 @@
 
 	am_root = (MY_UID() == 0);
 
+#ifndef __OS2__
 	if (am_root) {
 		p = lp_uid(i);
 		if (!name_to_uid(p, &uid)) {
@@ -503,6 +506,7 @@
 		}
 	}
 
+#endif
 	/* TODO: If we're not root, but the configuration requests
 	 * that we change to some uid other than the current one, then
 	 * log a warning. */
@@ -511,6 +515,7 @@
 	 * supplementary groups. */
 
 	module_dir = lp_path(i);
+	// rprintf(FLOG, "* module_dir %s %s(%u)\n", module_dir, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 	if (use_chroot) {
 		if ((p = strstr(module_dir, "/./")) != NULL) {
 			*p = '\0'; /* Temporary... */
@@ -533,6 +538,7 @@
 		if (!(module_chdir = normalize_path(module_dir, False, &module_dirlen)))
 			return path_failure(f_out, module_dir, False);
 		full_module_path = module_dir = module_chdir;
+		// rprintf(FLOG, "* full_module_path %s %s(%u) [%s]\n", full_module_path, __FILE__, __LINE__, who_am_i());	// 06 Feb 09 SHL debug
 	}
 
 	if (module_dirlen == 1) {
@@ -679,8 +685,11 @@
 		module_chdir = module_dir;
 	}
 
-	if (!change_dir(module_chdir, CD_NORMAL))
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+		// rsyserr(FERROR, errno, "[%s] chdir %s failed at %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__);	// 15 Dec 08 SHL debug
+		// rprintf(FINFO, "* chdir module_chdir %s failed %s(%u) [%s]\n", module_chdir, __FILE__, __LINE__, who_am_i());	// 06 Feb 09 SHL debug
 		return path_failure(f_out, module_chdir, True);
+	}
 	if (module_dirlen || !use_chroot)
 		sanitize_paths = 1;
 
@@ -963,6 +972,8 @@
 #endif
 	SIGACTION(SIGCHLD, remember_children);
 
+	// rprintf(FLOG, "* start_daemon: %s %s %s(%u) [%s]\n", addr, host, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
+
 	return rsync_module(f_in, f_out, i, addr, host);
 }
 
@@ -991,6 +1002,7 @@
 	close(fd);
 }
 
+#ifndef __OS2__
 /* Become a daemon, discarding the controlling terminal. */
 static void become_daemon(void)
 {
@@ -1024,6 +1036,7 @@
 		open("/dev/null", O_RDWR);
 	}
 }
+#endif // __OS2__
 
 int daemon_main(void)
 {
@@ -1046,10 +1059,14 @@
 		exit_cleanup(RERR_SYNTAX);
 	}
 
+#ifndef __OS2__
 	if (no_detach)
 		create_pid_file();
 	else
 		become_daemon();
+#else
+	create_pid_file();
+#endif
 
 	if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
 		rsync_port = RSYNC_PORT;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/compat.c ./compat.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/compat.c	2009-03-29 13:25:42.000000000 -0700
+++ ./compat.c	2009-06-18 19:24:26.000000000 -0700
@@ -198,11 +198,12 @@
 			exit_cleanup(RERR_PROTOCOL);
 		}
 		if (preserve_xattrs && !local_server) {
-			rprintf(FERROR,
-			    "--xattrs requires protocol 30 or higher"
+		  	preserve_xattrs = 0;	// 06 Feb 09 SHL force off for old servers
+			rprintf(FWARNING,
+			    "--xattrs requires protocol 30 or higher - option disabled"
 			    " (negotiated %d).\n",
 			    protocol_version);
-			exit_cleanup(RERR_PROTOCOL);
+			// exit_cleanup(RERR_PROTOCOL);	// 06 Feb 09 SHL
 		}
 	}
 
@@ -291,6 +292,7 @@
 	if (need_unsorted_flist && (!am_sender || inc_recurse))
 		unsort_ndx = ++file_extra_cnt;
 
+	// 16 Feb 09 SHL fixme slash?
 	if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
 		int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
 		if (!am_sender || protocol_version >= 30)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/configure.sh ./configure.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/configure.sh	2009-05-08 10:41:12.000000000 -0700
+++ ./configure.sh	2009-07-08 12:27:22.000000000 -0700
@@ -69,6 +69,8 @@
   as_echo='sh -c $as_echo_body as_echo'
 fi
 
+# 18 Jun 09 SHL fixme to not be broken - 3.0.5 worked - maybe autoconf 2.6.3 broke it
+
 # The user is always right.
 if test "${PATH_SEPARATOR+set}" != set; then
   PATH_SEPARATOR=:
@@ -2045,6 +2047,7 @@
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
+  echo SHL $as_dir
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
@@ -16947,6 +16950,15 @@
 _ACEOF
 
 	;;
+    *os2*)
+	{ echo "$as_me:$LINENO: result: Using OS/2 extattrs" >&5
+echo "${ECHO_T}Using OS/2 extattrs" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_XATTRS 1
+_ACEOF
+
+	;;
+
     *)
 	if test x"$enable_xattr_support" = x"yes"; then
 	    { { $as_echo "$as_me:$LINENO: error: Failed to find extended attribute support" >&5
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/exclude.c ./exclude.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/exclude.c	2009-01-17 13:41:34.000000000 -0800
+++ ./exclude.c	2009-06-18 19:24:26.000000000 -0700
@@ -298,7 +298,7 @@
 	unsigned int fn_len;
 
 	if (!parent_dirscan && *merge_file != '/') {
-		/* Return the name unchanged it doesn't have any slashes. */
+		/* Return the name unchanged if it doesn't have any slashes. */
 		if (len_ptr) {
 			const char *p = merge_file + *len_ptr;
 			while (--p > merge_file && *p != '/') {}
@@ -310,6 +310,7 @@
 			return (char *)merge_file;
 	}
 
+	// 16 Feb 09 SHL fixme slash
 	fn = *merge_file == '/' ? buf : tmpbuf;
 	if (sanitize_paths) {
 		const char *r = prefix_skip ? "/" : NULL;
@@ -351,6 +352,7 @@
 void set_filter_dir(const char *dir, unsigned int dirlen)
 {
 	unsigned int len;
+	// 16 Feb 09 SHL fixme slash?
 	if (*dir != '/') {
 		memcpy(dirbuf, curr_dir, curr_dir_len);
 		dirbuf[curr_dir_len] = '/';
@@ -548,6 +550,7 @@
 	int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
 	char *p, *pattern = ex->pattern;
 	const char *strings[16]; /* more than enough */
+	// 16 Feb 09 SHL fixme slash?
 	const char *name = fname + (*fname == '/');
 
 	if (!*name)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/flist.c ./flist.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/flist.c	2009-04-26 07:51:50.000000000 -0700
+++ ./flist.c	2009-07-22 14:45:38.000000000 -0700
@@ -348,8 +348,19 @@
 {
 	if (dirlen < 0) {
 		char *cpy = strdup(dir);
+#ifndef __OS2__ // 06 Mar 09 SHL use is_abs_path...
 		if (*cpy != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (!is_abs_path(cpy)) {
+			if (drive_spec_width(cpy))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), cpy, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+	        }
+#endif
 		if (path_is_daemon_excluded(cpy, 0))
 			goto chdir_error;
 		dir = cpy;
@@ -363,8 +374,19 @@
 				dirlen = strlen(dir);
 		} else if (pathname == dir)
 			return 1;
+#ifndef __OS2__ // 06 Mar 09 SHL use is_abs_path...
 		if (dir && *dir != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (dir && !is_abs_path(dir)) {
+			if (drive_spec_width(dir))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+		}
+#endif
 	}
 
 	pathname = dir;
@@ -377,8 +399,13 @@
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
 		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
-		if (dir != orig_dir)
-			change_dir(orig_dir, CD_NORMAL);
+		rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
+		if (dir != orig_dir) {
+			if (!change_dir(orig_dir, CD_NORMAL)) {
+				if (verbose > 1)
+					rprintf(FLOG, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+		}
 		pathname = NULL;
 		pathname_len = 0;
 		return 0;
@@ -1328,6 +1355,8 @@
 {
 	struct file_struct *file;
 
+	// rprintf(FINFO, "* send_file_name fname %s %s(%u) [%s]\n", fname, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
+
 	file = make_file(fname, flist, stp, flags, filter_level);
 	if (!file)
 		return NULL;
@@ -1952,6 +1981,7 @@
 	int len, dirlen;
 	STRUCT_STAT st;
 	char *p, *dir;
+	static char* the_root = "/";
 	struct file_list *flist;
 	struct timeval start_tv, end_tv;
 	int64 start_write;
@@ -1995,6 +2025,7 @@
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
 			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
 				full_fname(argv[0]));
+			rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), argv[0], __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 		use_ff_fd = 1;
@@ -2014,17 +2045,30 @@
 			if (argc-- == 0)
 				break;
 			strlcpy(fbuf, *argv++, MAXPATHLEN);
+			// rprintf(FINFO, "* send_file_list fbuf %s %s(%u) [%s]\n", fbuf, __FILE__, __LINE__, who_am_i());	// 06 Feb 09 SHL debug
 			if (sanitize_paths)
 				sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
+#if 0 // 16 May 09 SHL fixme to be gone
+#ifdef __OS2__
+			else {
+				// 16 May 09 SHL switch to use normalize_dir_slashes
+				normalize_dir_slashes(fbuf);
+			}
+#endif
+#endif
 		}
 
+		// rprintf(FINFO, "* send_file_list fbuf %s %s(%u) [%s]\n", fbuf, __FILE__, __LINE__, who_am_i());	// 06 Feb 09 SHL debug
+
 		len = strlen(fbuf);
 		if (relative_paths) {
 			/* We clean up fbuf below. */
 			name_type = NORMAL_NAME;
 		} else if (!len || fbuf[len - 1] == '/') {
-			if (len == 2 && fbuf[0] == '.') {
-				/* Turn "./" into just "." rather than "./." */
+			// Empty path or trailing /
+			// 06 Mar 09 SHL
+			if (len == 2 + drive_spec_width(fbuf) && fbuf[drive_spec_width(fbuf)] == '.') {
+				/* Turn trailing "./" into just "." rather than "./." */
 				fbuf[--len] = '\0';
 			} else {
 				if (len + 1 >= MAXPATHLEN)
@@ -2035,6 +2079,7 @@
 			name_type = DOTDIR_NAME;
 		} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
 		    && (len == 2 || fbuf[len-3] == '/')) {
+			// Got ..  or trailing /..
 			if (len + 2 >= MAXPATHLEN)
 				overflow_exit("send_file_list");
 			fbuf[len++] = '/';
@@ -2053,18 +2098,39 @@
 			if (p) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 06 Mar 09 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else
 					dir = fbuf;
-				len -= p - fbuf + 1;
-				fn = p + 1;
+				fn = p + 1;		// Point at filename part
+				len -= fn - fbuf;	//  fn length
+				// rprintf(FINFO, "* send_file_list fn %s len %d %s(%u) [%s]\n", fn, len, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
 			} else
 				fn = fbuf;
 		} else {
 			if ((p = strstr(fbuf, "/./")) != NULL) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 06 Mar 09 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else {
 					dir = fbuf;
 					clean_fname(dir, 0);
@@ -2086,6 +2152,8 @@
 			}
 			len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
 					    | CFN_DROP_TRAILING_DOT_DIR);
+			// rprintf(FINFO, "* send_file_list fn %s len %d %s(%u) [%s]\n", fn, len, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
+			// 06 Mar 09 SHL fixme?
 			if (len == 1) {
 				if (fn[0] == '/') {
 					fn = "/.";
@@ -2118,6 +2186,8 @@
 			name_type = DOTDIR_NAME;
 		}
 
+		// rprintf(FINFO, "* send_file_list dir %s fn %s len %d %s(%u) [%s]\n", dir ? dir : "(null)", fn, len, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
+
 		dirlen = dir ? strlen(dir) : 0;
 		if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
 			if (!change_pathname(NULL, dir, -dirlen))
@@ -2127,9 +2197,16 @@
 		} else if (!change_pathname(NULL, lastdir, lastdir_len))
 			continue;
 
+		// 06 Mar 09 SHL
+		if (dir && dir != the_root && dir != fbuf)
+			free(dir);	// We allocated it
+
 		if (fn != fbuf)
 			memmove(fbuf, fn, len + 1);
 
+		// rprintf(FINFO, "* send_file_list fn %s %s(%u) [%s]\n", fn, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
+		// rprintf(FINFO, "* send_file_list fbuf %s len %d %s(%u) [%s]\n", fbuf, len, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
+
 		if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
@@ -2150,12 +2227,14 @@
 		}
 
 		if (inc_recurse && relative_paths && *fbuf) {
+			// 06 Mar 09 SHL fixme
 			if ((p = strchr(fbuf+1, '/')) != NULL) {
 				if (p - fbuf == 1 && *fbuf == '.') {
 					if ((fn = strchr(p+1, '/')) != NULL)
 						p = fn;
 				} else
 					fn = p;
+			        // rprintf(FINFO, "* send_file_list %s %s(%u) [%s]\n", fbuf, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
 				send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
 				if (fn == p)
 					continue;
@@ -2163,6 +2242,7 @@
 		} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
 			/* Send the implied directories at the start of the
 			 * source spec, so we get their permissions right. */
+			// rprintf(FINFO, "* send_file_list %s %s(%u) [%s]\n", fbuf, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
 			send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
 		}
 
@@ -2171,6 +2251,7 @@
 
 		if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
 			struct file_struct *file;
+			// rprintf(FINFO, "* send_file_list fbuf %s %s(%u) [%s]\n", fbuf, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
 			file = send_file_name(f, flist, fbuf, &st,
 					      FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
 					      NO_FILTERS);
@@ -2186,9 +2267,11 @@
 				}
 			} else
 				send_if_directory(f, flist, file, fbuf, len, flags);
-		} else
+		} else {
+			// rprintf(FINFO, "* send_file_list %s %s(%u) [%s]\n", fbuf, __FILE__, __LINE__, who_am_i());	// 06 Mar 09 SHL debug
 			send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
 	}
+	}
 
 	gettimeofday(&end_tv, NULL);
 	stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/generator.c ./generator.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/generator.c	2009-04-26 07:51:50.000000000 -0700
+++ ./generator.c	2009-09-18 19:59:54.000000000 -0700
@@ -272,6 +272,7 @@
 	}
 
 	p = fname + dlen;
+	// 16 Feb 09 SHL fixme slash?
 	if (dlen != 1 || *fname != '/')
 		*p++ = '/';
 	remainder = MAXPATHLEN - (p - fname);
@@ -590,7 +591,7 @@
 	} else
 #endif
 	if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
-		return 0;
+		return 0;		// Changed
 
 	if (preserve_perms) {
 		if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
@@ -622,7 +623,7 @@
 	}
 #endif
 
-	return 1;
+	return 1;			// No change
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -646,19 +647,26 @@
 		} else if (keep_time
 		 ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
 		 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
-		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
+			// rprintf(FINFO, "* itemize fnamecmp %s file->modtime %u sxp->st.st_mtime %u %s(%u) [%s]\n", fnamecmp, file->modtime, sxp->st.st_mtime, __FILE__, __LINE__, who_am_i());	// 17 Sep 09 SHL fixme times
 			iflags |= ITEM_REPORT_TIME;
+		}
+
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
 		} else
 #endif
 		if (preserve_perms) {
-			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) {
+				// rprintf(FINFO, "* itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u) [%s]\n", fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__, who_am_i());	// 17 Sep 09 SHL fixme perms
 				iflags |= ITEM_REPORT_PERMS;
+			}
 		} else if (preserve_executability
-		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0))) {
+			// rprintf(FINFO, "* itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u) [%s]\n", fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__, who_am_i());	// 17 Sep 09 SHL fixme perms
 			iflags |= ITEM_REPORT_PERMS;
+		 }
 		if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 			iflags |= ITEM_REPORT_OWNER;
 		if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
@@ -2057,8 +2065,18 @@
 		 || (!need_retouch_dir_times && file->mode & S_IWUSR))
 			continue;
 		fname = f_name(file, NULL);
+// 17 Sep 09 SHL add os2_perms special case logic
+#ifndef __OS__
 		if (!(file->mode & S_IWUSR))
 			do_chmod(fname, file->mode);
+#else
+		// If os/2 perms and not writable by group need to turn off archived flag
+		// See map_os2_attributes
+		// Other flags should already be OK
+		if (!(file->mode & S_IWUSR) ||
+		    (preserve_perms && os2_perms && ~file->mode & S_IWGRP))
+			do_chmod(fname, file->mode);
+#endif
 		if (need_retouch_dir_times) {
 			STRUCT_STAT st;
 			if (link_stat(fname, &st, 0) == 0
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/getaddrinfo.c ./lib/getaddrinfo.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/getaddrinfo.c	2008-10-25 08:39:40.000000000 -0700
+++ ./lib/getaddrinfo.c	2009-07-22 14:48:00.000000000 -0700
@@ -404,12 +404,16 @@
 	int ret = -1;
 	char *p = NULL;
 
+	// rprintf(FLOG, "* gethostnameinfo: NI_NUMERICHOST %u %s(%u) [%s]\n", flags & NI_NUMERICHOST, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 	if (!(flags & NI_NUMERICHOST)) {
+		// rprintf(FLOG, "* gethostnameinfo: %s(%u) [%s]\n", __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 		struct hostent *hp = gethostbyaddr(
 				(void *)&((struct sockaddr_in *)sa)->sin_addr,
 				sizeof (struct in_addr),
 				sa->sa_family);
+		// rprintf(FLOG, "* gethostnameinfo: hp %p %s(%u) [%s]\n", hp, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 		ret = check_hostent_err(hp);
+		// rprintf(FLOG, "* ret %d %s(%u) [%s]\n", ret, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 		if (ret == 0) {
 			/* Name looked up successfully. */
 			ret = snprintf(node, nodelen, "%s", hp->h_name);
@@ -425,6 +429,7 @@
 			return 0;
 		}
 
+		// rprintf(FLOG, "* %s(%u) [%s]\n", __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 		if (flags & NI_NAMEREQD) {
 			/* If we require a name and didn't get one,
 			 * automatically fail. */
@@ -432,6 +437,7 @@
 		}
 		/* Otherwise just fall into the numeric host code... */
 	}
+	// rprintf(FLOG, "* %s(%u) [%s]\n", __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 	p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
 	ret = snprintf(node, nodelen, "%s", p);
 	if (ret < 0 || (size_t)ret >= nodelen) {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/sysxattrs.c ./lib/sysxattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/sysxattrs.c	2008-03-01 12:01:40.000000000 -0800
+++ ./lib/sysxattrs.c	2009-09-19 08:17:54.000000000 -0700
@@ -126,6 +126,412 @@
 	return len;
 }
 
+#elif defined(__OS2__)
+
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+
+static void map_os2_apiret(APIRET rc)
+{
+	switch (rc) {
+	case ERROR_SHARING_VIOLATION:
+		errno = EACCES;
+		break;
+	case 0:
+		// Should not have been called - try to do no harm
+		break;
+	default:
+		// 31 Jul 09 SHL fixme to map better
+		// if (verbose > 2)
+		rprintf(FINFO, "[%s] can not map OS/2 error %lu to errno\n", who_am_i(), rc);	// 31 Jul 09 SHL
+		/* Ensure non-zero */
+		if (!errno)
+			errno = EINVAL;
+
+	}
+}
+
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+	return unisetxattr (path, 0, name, value, size, 0);
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	EAOP2       eaop2 = {0,0,0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+
+	if ((!path && !file) || !name)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;
+	do
+	{
+		if (path)
+		{
+#if 0 // 16 May 09 SHL fixme to be gone
+			char npath[CCHMAXPATH + 1] = {0};
+			strncpy(npath, path, CCHMAXPATH);
+			for (p = npath; *p; p++)
+			{
+				if (*p == '/') *p = '\\';	// 29 Jul 08 SHL fixme to be gone? - OS/2 does not care?
+			}
+#endif
+			rc = DosQueryPathInfo(path, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryPathInfo(%s, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] %s has %lu EA bytes\n", who_am_i(), path, eaop2.fpFEA2List->cbList);	// 28 Jul 08 SHL
+		}
+		else
+		{
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryFileInfo(%u, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] handle %d has %lu EA bytes\n", who_am_i(), file, eaop2.fpFEA2List->cbList);	// 28 Jul 08 SHL
+		}
+		if (rc)
+		{
+			break;
+		}
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
+		{
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value)
+		{
+			if ((size_t)rc > size)
+			{
+				errno = ERANGE;
+				rc = -1;
+			}
+			else
+			{
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+	{
+		free(pgea2list);
+	}
+	if (pgea2list)
+	{
+		free(pfea2list);
+	}
+
+	return rc;
+}
+
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat;
+	// char npath[CCHMAXPATH + 1] = {0};	// 17 May 09 SHL fixme to be gone
+	// memset(&stat, 0, sizeof(stat));	// 17 May 09 SHL fixme to be gone
+	if (!path && !file)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	if (path)
+	{
+#if 0 // 16 May 09 SHL fixme to be gone
+		char * p;
+		strncpy(npath, path, CCHMAXPATH);
+		for (p = npath; *p; p++)
+		{
+			if (*p == '/') *p = '\\';
+		}
+#endif
+		rc = DosQueryPathInfo(path, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryPathInfo(%s, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] %s has %lu EA bytes\n", who_am_i(), path, stat.cbList);	// 28 Jul 08 SHL
+	}
+	else
+	{
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryFilInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] handle %d has %lu EA bytes\n", who_am_i(), file, stat.cbList);	// 28 Jul 08 SHL
+	}
+	if (rc)
+	{
+		map_os2_apiret(rc);
+		return -1;
+	}
+	if (stat.cbList <= 4)
+	{
+		// NO ea
+		return 0;
+	}
+	//YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
+	buf = (char *)_tmalloc(stat.cbList * 2);
+	// 19 Sep 09 SHL was trapping on large copies
+	if (!buf) {
+		rprintf(FERROR, "out of memory allocating %lu at %s(%u)\n", stat.cbList * 2, __FILE__, __LINE__);	// 19 Sep 09 SHL fixme gone debug
+		return -1;
+	}
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc)
+	{
+		rprintf(FERROR, "[%s] unilistxattr DosEnumAttribute failed with error %u at %s(%u)\n", who_am_i(), rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		_tfree(buf);
+		map_os2_apiret(rc);	// 31 Jul 09 SHL moved here to ensure errno returned
+		return -1;
+	}
+	else if (verbose > 2) {
+		if (path)
+			rprintf(FINFO, "[%s] %s has %lu EA items\n", who_am_i(), path, ulCount);	// 28 Jul 08 SHL
+		else
+			rprintf(FINFO, "[%s] handle %d has %lu EA items\n", who_am_i(), file, ulCount);	// 28 Jul 08 SHL
+	}
+	if (ulCount > 0) {
+		for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
+		{
+			if (pfea->cbName > 0)
+			{
+				gotsize += pfea->cbName + 1;
+				// Avoid overflow
+				if (p && (size_t)gotsize <= size)
+				{
+					pfea->szName[pfea->cbName] = 0;
+					strcpy(p, pfea->szName);
+					p += strlen(p) + 1;
+				}
+			}
+			if (!pfea->oNextEntryOffset)
+			{
+				break;
+			}
+		}
+	}
+	_tfree(buf);
+	if ((size_t)gotsize > size)
+	{
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	if (verbose > 2)
+		rprintf(FINFO, "[%s] returning %ld EA list bytes\n", who_am_i(), (unsigned long)gotsize);	// 28 Jul 08 SHL
+	return gotsize;
+}
+
+int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0,0,0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path)
+	{
+#if 0 // 16 May 09 SHL fixme to be gone
+		char npath[CCHMAXPATH + 1];
+		char * p;
+		strncpy(npath, path, CCHMAXPATH);
+		for (p = npath; *p; p++)
+		{
+			if (*p == '/') *p = '\\';
+		}
+#endif
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else
+	{
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosFileInfo(%u, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from handle %d \n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	if (rc)
+	{
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0,0,0};
+	PFEA2LIST   pfea2list = NULL;
+	// char * p;			// 17 May 09 SHL  fixme
+
+	if ((!path && !file) || !name || (!value && size))
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE))
+	{
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0)
+		{
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0)
+		{
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(FEA2LIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value)
+	{
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path)
+	{
+#if 0 // 16 May 09 SHL fixme to be gone
+		char npath[CCHMAXPATH + 1] = {0};
+		strncpy(npath, path, CCHMAXPATH);
+		for (p = npath; *p; p++)
+		{
+			if (*p == '/') *p = '\\';
+		}
+#endif
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else
+	{
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetFileInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	free(pfea2list);
+	if (rc)
+	{
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
 #else
 
 #error You need to create xattr compatibility functions.
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/sysxattrs.h ./lib/sysxattrs.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/sysxattrs.h	2007-04-07 10:22:24.000000000 -0700
+++ ./lib/sysxattrs.h	2009-06-18 19:24:26.000000000 -0700
@@ -19,6 +19,13 @@
 int sys_lremovexattr(const char *path, const char *name);
 ssize_t sys_llistxattr(const char *path, char *list, size_t size);
 
+#ifdef __OS2__
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size);
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size);
+int uniremovexattr (const char *path, int file, const char *name);
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags);
+#endif
+
 #else
 
 /* No xattrs available */
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/loadparm.c ./loadparm.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/loadparm.c	2009-01-17 13:41:34.000000000 -0800
+++ ./loadparm.c	2009-06-18 19:24:26.000000000 -0700
@@ -654,10 +654,23 @@
 	    *(char *)dest_ptr = *(char *)src_ptr;
 	    break;
 
+#ifndef __OS2__
 	  case P_PATH:
 	  case P_STRING:
 	    string_set(dest_ptr,*(char **)src_ptr);
 	    break;
+#else
+	  case P_PATH:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    // 06 Mar 09 SHL Force unix slashes
+	    // 16 May 09 SHL Use normalize_dir_slashes
+	    normalize_dir_slashes(*(char **)dest_ptr);
+	    break;
+
+	  case P_STRING:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    break;
+#endif
 
 	  default:
 	    break;
@@ -726,7 +739,12 @@
        string_set(parm_ptr,parmvalue);
        if ((cp = *(char**)parm_ptr) != NULL) {
 	   int len = strlen(cp);
+#ifndef __OS2__
 	   while (len > 1 && cp[len-1] == '/') len--;
+#else
+	   int drive_letter_adj = *(cp + 1) == ':' && isalpha(*cp) ? 2 : 0;
+	   while (len > 1 + drive_letter_adj && cp[len-1] == '/') len--;
+#endif
 	   cp[len] = '\0';
        }
        break;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/log.c ./log.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/log.c	2009-01-17 13:41:34.000000000 -0800
+++ ./log.c	2009-06-18 19:24:26.000000000 -0700
@@ -371,6 +371,7 @@
 	va_list ap;
 	char buf[BIGPATHBUFLEN];
 	size_t len;
+	int e = errno;			// 27 Apr 09 SHL preserve errno
 
 	va_start(ap, format);
 	len = vsnprintf(buf, sizeof buf, format, ap);
@@ -403,6 +404,7 @@
 	}
 
 	rwrite(code, buf, len, 0);
+	errno = e;
 }
 
 /* This is like rprintf, but it also tries to print some
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/main.c ./main.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/main.c	2009-02-04 18:27:06.000000000 -0800
+++ ./main.c	2009-07-22 14:45:30.000000000 -0700
@@ -531,6 +531,8 @@
 			if (!change_dir(dest_path, CD_NORMAL)) {
 				rsyserr(FERROR, errno, "change_dir#1 %s failed",
 					full_fname(dest_path));
+				// 22 Jul 09 SHL was FLOG?  why?
+				rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 				exit_cleanup(RERR_FILESELECT);
 			}
 			return NULL;
@@ -591,6 +593,8 @@
 		if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
 			rsyserr(FERROR, errno, "change_dir#2 %s failed",
 				full_fname(dest_path));
+			// 22 Jul 09 SHL was FLOG?  why?
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 
@@ -611,6 +615,8 @@
 	if (!change_dir(dest_path, CD_NORMAL)) {
 		rsyserr(FERROR, errno, "change_dir#3 %s failed",
 			full_fname(dest_path));
+		// 22 Jul 09 SHL was FLOG?  why?
+		rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 		exit_cleanup(RERR_FILESELECT);
 	}
 	*cp = '/';
@@ -702,8 +708,9 @@
 
 	if (!relative_paths) {
 		if (!change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#3 %s failed",
+			rsyserr(FERROR, errno, "change_dir#4 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -872,8 +879,9 @@
 		argc--;
 		argv++;
 		if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#4 %s failed",
+			rsyserr(FERROR, errno, "change_dir#5 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -1086,7 +1094,7 @@
 
 	for (i = 0; argv[i]; i++) {
 		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
+			rprintf (FERROR, "out of memory at %s(%u)\n",
 				 __FILE__, __LINE__);
 			return RERR_MALLOC;
 		}
@@ -1117,6 +1125,14 @@
 	 * command line. */
 	if ((ret = copy_argv(argv)) != 0)
 		return ret;
+#ifdef __OS2__
+	{
+		int i;
+		for (i = 0; i < argc; i++) {
+			normalize_dir_slashes(argv[i]);
+		}
+	}
+#endif
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -1440,6 +1456,7 @@
 	 * (implemented by forking "pwd" and reading its output) doesn't
 	 * work when there are other child processes.  Also, on all systems
 	 * that implement getcwd that way "pwd" can't be found after chroot. */
+	// rprintf(FLOG, "* %s %s(%u) [%s]\n", "(null)", __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
 	change_dir(NULL, CD_NORMAL);
 
 	init_flist();
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/options.c ./options.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/options.c	2009-04-12 13:01:14.000000000 -0700
+++ ./options.c	2009-09-17 11:57:36.000000000 -0700
@@ -52,6 +52,10 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+// 13 Jun 09 SHL Added
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -117,7 +121,11 @@
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
+#ifndef __OS2__
 int modify_window = 0;
+#else
+int modify_window = 1;			// 28 Jul 09 SHL allow for 2 second resolution
+#endif
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
@@ -263,6 +271,9 @@
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
 	rprintf(f, "Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.\n");
 	rprintf(f, "Web site: http://rsync.samba.org/\n");
+#ifdef __OS2__ // 22 Jul 09 SHL
+	rprintf(f, "Built by Steven H. Levine " __DATE__ " " __TIME__ "\n");
+#endif
 	rprintf(f, "Capabilities:\n");
 	rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
 		(int)(sizeof (OFF_T) * 8),
@@ -339,6 +350,9 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+#ifdef __OS2__
+  rprintf(F," -2, --os2-perms             preserve native OS/2 permissions\n");
+#endif
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
 #ifdef SUPPORT_ACLS
@@ -481,6 +495,10 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+#ifdef __OS2__
+  {"os2-perms",       '2', POPT_ARG_NONE,   0, '2', 0, 0 },
+  {"no-os2-perms",     0,  POPT_ARG_VAL,    &os2_perms, 0, 0, 0 },
+#endif
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
@@ -1034,6 +1052,7 @@
 		case OPT_EXCLUDE_FROM:
 		case OPT_INCLUDE_FROM:
 			arg = poptGetOptArg(pc);
+			// printf("PS - pc = %s\n",arg);	// 16 Feb 09 SHL fixme debug PS = Paul?
 			if (sanitize_paths)
 				arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 			if (daemon_filter_list.head) {
@@ -1141,6 +1160,13 @@
 			}
 			break;
 
+// 14 Jun 09 SHL
+#ifdef __OS2__
+		case '2':
+			os2_perms = 1;
+			preserve_perms = 1;
+			break;
+#endif
 		case OPT_WRITE_BATCH:
 			/* batch_name is already set */
 			write_batch = 1;
@@ -1784,6 +1810,12 @@
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
 		argstr[x++] = 'E';
+// 13 Jun 09 SHL
+#ifdef __OS2__
+	if (os2_perms)
+		argstr[x++] = '2';
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls)
 		argstr[x++] = 'A';
@@ -2103,6 +2135,10 @@
 			break;
 		}
 		if (*s == ':' || *s == '/') {
+#			ifdef __OS2__	// 29 Jun 09 SHL don't confuse drive letter with host spec
+			if (*s == ':' && s == str + 1 && drive_spec_width(s - 1) != 0)
+				continue;
+#			endif
 			if (!hostlen)
 				hostlen = s - host_start;
 			if (*s++ == '/') {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/params.c ./params.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/params.c	2007-11-22 09:51:20.000000000 -0800
+++ ./params.c	2009-06-18 19:24:28.000000000 -0700
@@ -168,6 +168,7 @@
   while( pos >= 0 && isSpace(line + pos) )
      pos--;
 
+  // 16 May 09 SHL fixme to not be confused by trailing \ in path
   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
   } /* Continuation */
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/proto.h ./proto.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/proto.h	2009-05-08 10:43:22.000000000 -0700
+++ ./proto.h	2009-09-18 20:01:40.000000000 -0700
@@ -108,6 +108,13 @@
 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);
+int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp);
+void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
+	     stat_x *sxp, int32 iflags, uchar fnamecmp_type,
+	     const char *xname);
+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);
 struct hashtable *hashtable_create(int size, int key64);
 void hashtable_destroy(struct hashtable *tbl);
 void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing);
@@ -311,6 +318,38 @@
 int do_lstat(const char *fname, STRUCT_STAT *st);
 int do_fstat(int fd, STRUCT_STAT *st);
 OFF_T do_lseek(int fd, OFF_T offset, int whence);
+int do_unlink(const char *fname);
+int do_symlink(const char *fname1, const char *fname2);
+int do_link(const char *fname1, const char *fname2);
+int do_lchown(const char *path, uid_t owner, gid_t group);
+int do_mknod(const char *pathname, mode_t mode, dev_t dev);
+int do_rmdir(const char *pathname);
+int do_open(const char *pathname, int flags, mode_t mode);
+int do_chmod(const char *path, mode_t mode);
+int do_rename(const char *fname1, const char *fname2);
+void trim_trailing_slashes(char *name);
+int do_mkdir(char *fname, mode_t mode);
+int do_mkstemp(char *template, mode_t perms);
+int do_stat(const char *fname, STRUCT_STAT *st);
+int do_lstat(const char *fname, STRUCT_STAT *st);
+int do_fstat(int fd, STRUCT_STAT *st);
+OFF_T do_lseek(int fd, OFF_T offset, int whence);
+int do_unlink(const char *fname);
+int do_symlink(const char *fname1, const char *fname2);
+int do_link(const char *fname1, const char *fname2);
+int do_lchown(const char *path, uid_t owner, gid_t group);
+int do_mknod(const char *pathname, mode_t mode, dev_t dev);
+int do_rmdir(const char *pathname);
+int do_open(const char *pathname, int flags, mode_t mode);
+int do_chmod(const char *path, mode_t mode);
+int do_rename(const char *fname1, const char *fname2);
+void trim_trailing_slashes(char *name);
+int do_mkdir(char *fname, mode_t mode);
+int do_mkstemp(char *template, mode_t perms);
+int do_stat(const char *fname, STRUCT_STAT *st);
+int do_lstat(const char *fname, STRUCT_STAT *st);
+int do_fstat(int fd, STRUCT_STAT *st);
+OFF_T do_lseek(int fd, OFF_T offset, int whence);
 void set_compression(const char *fname);
 void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
 		int32 n, int32 toklen);
@@ -378,6 +417,8 @@
 int flist_ndx_pop(flist_ndx_list *lp);
 void *expand_item_list(item_list *lp, size_t item_size,
 		       const char *desc, int incr);
+void normalize_dir_slashes(char *path);
+void assert_no_dir_slashes(char *path);
 void free_xattr(stat_x *sxp);
 int get_xattr(const char *fname, stat_x *sxp);
 int copy_xattrs(const char *source, const char *dest);
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/readme.os2 ./readme.os2
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/readme.os2	2106-02-06 22:28:16.000000000 
+++ ./readme.os2	2009-09-24 18:49:14.000000000 -0700
@@ -0,0 +1,85 @@
+Rsync v3.0.6 compiled with GCC 3.4.6 & kLibc v0.6.3
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+We (Paul and Steven) are using this as both client and server for backups
+
+Changes in this version:
+- Updated to v3.0.6
+- Incorporated a bunch of patches from Steven Levine
+- Move to GCC 3.4.6 as a compiler
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 permissions
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke a some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+  Run make install
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Cheers,
+
+Paul Smedley
+Adelaide, Australia
+
+and
+
+Steven Levine
+Costa Mesa, California, USA
+
+24 Sep 2009
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/rsync.c ./rsync.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/rsync.c	2009-01-17 13:41:34.000000000 -0800
+++ ./rsync.c	2009-07-22 13:03:44.000000000 -0700
@@ -386,6 +386,8 @@
 	mode_t new_mode = file->mode;
 	int inherit;
 
+	// rprintf(FINFO, "* set_file_attrs fname %s mode %o file %p sxp %p %s(%u) [%s]\n", fname, file->mode, file, sxp, __FILE__, __LINE__, who_am_i());	// 27 Apr 09 SHL debug perms
+
 	if (!sxp) {
 		if (dry_run)
 			return 1;
@@ -498,6 +500,7 @@
 
 #ifdef HAVE_CHMOD
 	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+		// rprintf(FINFO, "* set_file_attrs fname %s sxp->st.st_mode %o new_mode %o %s(%u) [%s]\n", fname, sxp->st.st_mode, new_mode, __FILE__, __LINE__, who_am_i());	// 27 Apr 09 SHL debug perms
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
@@ -555,6 +558,7 @@
 		    int overwriting_basis)
 {
 	int ret;
+	// 16 Feb 09 SHL fixme slash?
 	const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
 	if (inplace) {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/rsync.h ./rsync.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/rsync.h	2009-02-14 07:57:50.000000000 -0800
+++ ./rsync.h	2009-06-18 19:24:28.000000000 -0700
@@ -1144,3 +1144,20 @@
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+// 05 Mar 09 SHL
+#ifndef __OS2__
+#define drive_spec_width(p) 0
+#define is_path_sep(p) (*(p) == '/')
+// 16 May 09 SHL fixme to be gone
+// #define is_path_sep2(p) (*(p) == '/')
+#define is_abs_path(p) (*(p) == '/')
+// #define is_abs_path2(p) (*(p) == '/')
+#else
+#define drive_spec_width(p) ((isalpha(*(p)) && *((p) + 1) == ':') ? 2 : 0)
+#define is_path_sep(p) (*(p) == '/')	// Unix only
+// #define is_path_sep2(p) (*(p) == '/' || *(p) == '\\')	// Unix or OS/2
+#define is_abs_path(p) (*((p) + drive_spec_width(p)) == '/')	// Unix only
+// Unix or OS/2
+// #define is_abs_path2(p) ((*((p) + drive_spec_width(p)) == '/') || (*((p) + drive_spec_width(p)) == '\\'))
+#endif
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/sender.c ./sender.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/sender.c	2009-04-12 12:48:58.000000000 -0700
+++ ./sender.c	2009-06-18 19:24:28.000000000 -0700
@@ -362,7 +362,7 @@
 		make_backups = -make_backups;
 
 	if (verbose > 2)
-		rprintf(FINFO, "send files finished\n");
+		rprintf(FINFO, "send_files finished\n");	// 06 Mar 09 SHL
 
 	match_report();
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/syscall.c ./syscall.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/syscall.c	2009-01-17 13:41:34.000000000 -0800
+++ ./syscall.c	2009-09-18 19:51:58.000000000 -0700
@@ -28,6 +28,24 @@
 #ifdef HAVE_SYS_ATTR_H
 #include <sys/attr.h>
 #endif
+// 06 Mar 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define setmode
+#if defined HAVE_SETMODE && O_BINARY && __OS2__
+// From gcc io.h
+int setmode (int, int);
+// From gcc os2emx.h
+#endif
+#ifdef __OS2__ // 01 Aug 09 SHL
+// 01 Aug 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define _sopen
+int _sopen (__const__ char *, int, int, ...);	// hack cough
+#include "share.h"			// SH_DENYNO
+#endif
+
+#if defined __OS2__
+// 27 Apr 09 SHL Need definitions for FILE_...
+#define INCL_DOS
+// #include <os2.h>
+#include <os2emx.h>
+#endif
 
 extern int dry_run;
 extern int am_root;
@@ -35,6 +53,10 @@
 extern int list_only;
 extern int preserve_perms;
 extern int preserve_executability;
+// 13 Jun 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -138,12 +160,32 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+#ifdef __OS2__
+	int fd;
+#endif
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
 
+#ifndef __OS2__
 	return open(pathname, flags | O_BINARY, mode);
+#else
+	// 31 Jul 09 SHL if open fails, try shared open in case file already opened for write
+	fd = open(pathname, flags | O_BINARY, mode);
+	if (fd == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
+		fd = _sopen(pathname, flags | O_BINARY, SH_DENYNO, mode);
+		if (fd != -1)
+			rprintf(FINFO, "[%s] opened %s for shared write - file may change during sync\n", who_am_i(), pathname);
+		else if (verbose) {
+			int e = errno;
+			rsyserr(FINFO, errno, "do_open _sopen fallback failed for %s", pathname);
+			errno = e;
+		}
+
+	}
+	return fd;
+#endif
 }
 
 #ifdef HAVE_CHMOD
@@ -152,6 +194,9 @@
 	int code;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+
+	// rprintf(FINFO, "* do_chmod path %s requested mode %o %s(%u)\n", path, mode, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	if (S_ISLNK(mode)) {
 #ifdef HAVE_LCHMOD
 		code = lchmod(path, mode & CHMOD_BITS);
@@ -167,7 +212,65 @@
 		code = 1;
 #endif
 	} else
+#ifndef __OS2__
+		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+#else
+	{
+		ULONG attributes = 0;
+		if (os2_perms) {
+			// Unmap mode to recover native OS/2 attributes
+			// See map_os2_attributes
+			// If not readable by owner, hidden
+			if (~mode & S_IRUSR)
+				attributes |= FILE_HIDDEN;
+			// If readable by group, system
+			if (mode & S_IRGRP)
+				attributes |= FILE_SYSTEM;
+			// If writable by group, archived
+			if (mode & S_IWGRP)
+				attributes |= FILE_ARCHIVED;
+			// Reset group rw bits to match other rw bits - hack cough
+			if (mode & S_IROTH)
+				mode |= S_IRGRP;
+			else
+				mode &= ~S_IRGRP;
+			if (mode & S_IWOTH)
+				mode |= S_IWGRP;
+			else
+				mode &= ~S_IWGRP;
+		}
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+		if (!code && os2_perms) {
+			// Adjust native attributes not handled by chmod - system, hidden, archived
+			// Maybe libc will do this someday
+			// chmod already handles readonly
+			// Adjust attributes if any but archived set or if archived not set in requested attributes
+			FILESTATUS3 fs3;
+			APIRET apiret = DosQueryPathInfo((PCSZ)path,
+							 FIL_STANDARD,
+							 &fs3,
+							 sizeof(fs3));
+			if (apiret)
+				rprintf(FERROR, "[%s] DosQueryPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+			else {
+				ULONG m = attributes | (fs3.attrFile & ~(FILE_SYSTEM | FILE_HIDDEN | FILE_ARCHIVED));
+				if (m != fs3.attrFile) {
+					ULONG old_attrFile = fs3.attrFile;
+					fs3.attrFile = m;
+					apiret = DosSetPathInfo((PCSZ)path,
+								 FIL_STANDARD,
+								 &fs3, sizeof(fs3),
+								 0);
+					if (apiret)
+						rprintf(FERROR, "[%s] DosSetPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+					// 17 Sep 09 SHL fixme perms
+					else if (verbose > 1)
+						rprintf(FINFO, "[%s] changed %s attrFile from %lx to %lx (attributes %lx)\n", who_am_i(), path, old_attrFile, fs3.attrFile, attributes);	// 21 Jul 09 SHL
+				}
+			}
+		}
+	}
+#endif
 	if (code != 0 && (preserve_perms || preserve_executability))
 		return code;
 	return 0;
@@ -238,12 +341,55 @@
 #endif
 }
 
+#ifdef __OS2__
+
+/**
+ * Map native OS/2 attributes to something rsync can send
+ * See do_chmod for unmap logic
+ */
+
+static void map_os2_attributes(STRUCT_STAT *st)
+{
+	// If hidden, readable by none
+	if (st->st_attr & FILE_HIDDEN)
+		st->st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+	// If readonly, writable by none
+	if (st->st_attr & FILE_READONLY)
+		st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+
+	// Steal group bits for native attributes without obvious mappings - hack cough
+	// If system, readable by group
+	if (st->st_attr & FILE_SYSTEM)
+		st->st_mode |= S_IRGRP;
+	else
+		st->st_mode &= ~S_IRGRP;
+	// If archived, writable by group
+	if (st->st_attr & FILE_ARCHIVED)
+		st->st_mode |= S_IWGRP;
+	else
+		st->st_mode &= ~S_IWGRP;
+}
+
+#endif
+
 int do_stat(const char *fname, STRUCT_STAT *st)
 {
 #ifdef USE_STAT64_FUNCS
 	return stat64(fname, st);
 #else
+#ifndef __OS2__
 	return stat(fname, st);
+#else
+	int code;
+	code = stat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
@@ -253,7 +399,19 @@
 # ifdef USE_STAT64_FUNCS
 	return lstat64(fname, st);
 # else
+#ifndef __OS2__
 	return lstat(fname, st);
+#else
+	// 27 Apr 09 SHL map OS/2 permissions
+	int code = lstat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 # endif
 #else
 	return do_stat(fname, st);
@@ -265,7 +423,19 @@
 #ifdef USE_STAT64_FUNCS
 	return fstat64(fd, st);
 #else
+#ifndef __OS2__
 	return fstat(fd, st);
+#else
+	int code;
+	code = fstat(fd, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %u mode from %o to %o (st_attr %o)\n", who_am_i(), fd, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/util.c ./util.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/util.c	2009-03-03 08:57:42.000000000 -0800
+++ ./util.c	2009-07-22 14:39:52.000000000 -0700
@@ -23,6 +23,10 @@
 #include "rsync.h"
 #include "ifuncs.h"
 
+#ifdef __OS2__
+#include <os2emx.h>
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int module_id;
@@ -191,6 +195,10 @@
 	char *p;
 	int ret = 0;
 
+#ifdef __OS2__ // 06 Mar 09 SHL use drive_spec_width
+	fname += drive_spec_width(fname);		/* Bypass drive letter */
+#endif /* __OS2__ */
+
 	while (*fname == '/')
 		fname++;
 	while (strncmp(fname, "./", 2) == 0)
@@ -420,6 +428,8 @@
 {
 	int tries = 4;
 
+	// rprintf(FINFO, "* robust_rename %s->%s %s(%u)\n", from, to, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	while (tries--) {
 		if (do_rename(from, to) == 0)
 			return 0;
@@ -444,6 +454,27 @@
 				return -2;
 			do_unlink(from);
 			return 1;
+#ifdef __OS2__ // 27 Apr 09 SHL
+		// libc rename semantics differs from linux
+		// clear readonly if this caused rename to fail
+		case EACCES:
+		{
+			STRUCT_STAT st;
+			int code;
+			if (verbose)
+				rprintf(FINFO, "[%s] robust_rename retrying %s after EACCES\n", who_am_i(), to);	// 22 Jul 09 SHL
+			code = do_stat(to, &st);
+			if (!code) {
+				// 27 Apr 09 SHL fixme to use st_mode when libc fixed
+				if (st.st_attr & FILE_READONLY) {
+					st.st_mode |= S_IWUSR;
+					code = do_chmod(to, st.st_mode);
+					if (!code)
+						break;	// Try again
+				}
+			}
+		}
+#endif
 		default:
 			return -1;
 		}
@@ -818,10 +849,18 @@
 {
 	char *limit = name - 1, *t = name, *f = name;
 	int anchored;
+#ifdef __OS2__
+	int drive_letter_adj;	// 0 if not, 2 if yes 15 Dec 08 SHL
+#endif
 
 	if (!name)
 		return 0;
 
+#ifdef __OS2__ // 06 Mar 09 SHL use drive_spec_width...
+	drive_letter_adj = drive_spec_width(name);
+	f += drive_letter_adj;			// Keep drive letter
+	t += drive_letter_adj;
+#endif /* __OS2__ */
 	if ((anchored = *f == '/') != 0) {
 		*t++ = *f++;
 #ifdef __CYGWIN__
@@ -869,10 +908,18 @@
 		while (*f && (*t++ = *f++) != '/') {}
 	}
 
+#ifndef __OS2__ // 06 Feb 09 SHL
 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 		t--;
 	if (t == name)
 		*t++ = '.';
+#else
+	if (t > name + anchored + drive_letter_adj && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
+		t--;
+	if (t == name + drive_letter_adj)
+		*t++ = '.';		// Ensure not empty
+#endif
+
 	*t = '\0';
 
 	return t - name;
@@ -906,14 +953,28 @@
 	char *start, *sanp;
 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 
+	// rprintf(FINFO, "sanitize_path p %s %s(%u) [%s]\n", p, __FILE__, __LINE__, who_am_i());	// 06 Feb 09 SHL
 	if (dest != p) {
 		int plen = strlen(p);
-		if (*p == '/') {
+		int drive_letter_adj = drive_spec_width(p);	// 0 if not, 2 if yes 15 Dec 08 SHL
+#ifndef __OS2__
+		if (*p == '/')
+#else // 06 Feb 09 SHL use is_abs_path...
+		if (!is_abs_path(p)) {
+			if (drive_letter_adj)
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 06 Feb 09 SHL
+		} else
+#endif
+		{
 			if (!rootdir)
 				rootdir = module_dir;
 			rlen = strlen(rootdir);
 			depth = 0;
+#ifndef __OS2__
 			p++;
+#else
+			p += drive_spec_width(p) + 1;
+#endif
 		}
 		if (dest) {
 			if (rlen + plen + 1 >= MAXPATHLEN)
@@ -922,12 +983,19 @@
 			out_of_memory("sanitize_path");
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
+#ifndef __OS2__
 			if (rlen > 1)
 				dest[rlen++] = '/';
+#else
+			if (rlen > 1 + drive_letter_adj)
+				dest[rlen++] = '/';
+#endif
 		}
 	}
 
 	if (drop_dot_dirs) {
+		// 06 Mar 09 SHL Use is_path_sep2 - fixme to be gone
+		// while (*p == '.' && (is_path_sep2(p + 1)))
 		while (*p == '.' && p[1] == '/')
 			p += 2;
 	}
@@ -937,17 +1005,23 @@
 	 * the start of the name (past any prior slash) for each iteration. */
 	while (*p) {
 		/* discard leading or extra slashes */
+		// 06 Mar 09 SHL - fixme to be gone
+		// if (is_path_sep2(p)) { }
 		if (*p == '/') {
 			p++;
 			continue;
 		}
 		if (drop_dot_dirs) {
+			// 06 Mar 09 SHL - fixme to be gone
+			// if (*p == '.' && (is_path_sep2(p + 1) || p[1] == '\0')) { }
 			if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
 				/* skip "." component */
 				p++;
 				continue;
 			}
 		}
+		// 16 May 09 SHL fixme to be gone
+		// if (*p == '.' && p[1] == '.' && (is_path_sep2(p + 2) || p[2] == '\0')) { }
 		if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
 			/* ".." component followed by slash or end */
 			if (depth <= 0 || sanp != start) {
@@ -955,6 +1029,8 @@
 				if (sanp != start) {
 					/* back up sanp one level */
 					--sanp; /* now pointing at slash */
+					// 06 Mar 09 SHL fixme to be gone
+					// while (sanp > start && !is_path_sep2(sanp -1))
 					while (sanp > start && sanp[-1] != '/')
 						sanp--;
 				}
@@ -967,6 +1043,20 @@
 		}
 		/* copy one component through next slash */
 		while (*p && (*sanp++ = *p++) != '/') {}
+#if 0 // 16 May 09 SHL fixme to be gone
+#ifndef __OS2__
+		while (*p && (*sanp++ = *p++) != '/') {}
+#else
+		while(*p) {
+			char c = *p++;
+			if (c == '\\')
+				c = '/';
+			*sanp++ = c;
+			if (c == '/')
+				break;
+		}
+#endif
+#endif
 	}
 	if (sanp == dest) {
 		/* ended up with nothing, so put in "." component */
@@ -974,16 +1064,23 @@
 	}
 	*sanp = '\0';
 
+	// rprintf(FINFO, "sanitize_path dest %s %s(%u) [%s]\n", dest, __FILE__, __LINE__, who_am_i());	// 06 Feb 09 SHL
+
+	// 16 May 09 SHL  fixme to be gone
+	assert_no_dir_slashes(dest);
+
 	return dest;
 }
 
 /* Like chdir(), but it keeps track of the current directory (in the
  * global "curr_dir"), and ensures that the path size doesn't overflow.
- * Also cleans the path using the clean_fname() function. */
+ * Also cleans the path using the clean_fname() function.
+ * Returns 1 of change OK.  Otherwise 0 */
 int change_dir(const char *dir, int set_path_only)
 {
 	static int initialised;
 	unsigned int len;
+	// rprintf(FINFO, "* change_dir dir %s %s(%u) [%s]\n", dir ? dir : "(null)", __FILE__, __LINE__, who_am_i());	// 27 Apr 09 SHL debug perms
 
 	if (!initialised) {
 		initialised = 1;
@@ -992,6 +1089,7 @@
 			exit_cleanup(RERR_FILESELECT);
 		}
 		curr_dir_len = strlen(curr_dir);
+		// rprintf(FINFO, "* change_dir curr_dir %s %s(%u) [%s]\n", curr_dir, __FILE__, __LINE__, who_am_i());	// 06 Feb 09 SHL debug
 	}
 
 	if (!dir)	/* this call was probably just to initialize */
@@ -1001,23 +1099,49 @@
 	if (len == 1 && *dir == '.')
 		return 1;
 
-	if (*dir == '/') {
+	// 06 Mar 09 SHL use is_abs_path
+	if (is_abs_path(dir)) {
+		// Absolute path
 		if (len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifndef __OS2__ // 28 Jul 08 SHL
 		if (!set_path_only && chdir(dir))
 			return 0;
 		memcpy(curr_dir, dir, len + 1);
+#else
+		if (!set_path_only) {
+			if (chdir(dir)) {
+				rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL
+				return 0;
+			}
+			if (drive_spec_width(dir) && _chdrive(*dir)) {
+				rprintf(FERROR, "[%s] change_dir _chdrive failed for dir %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL
+				return 0;
+			}
+		}
+		memcpy(curr_dir, dir, len + 1);
+		// rprintf(FLOG, "* change_dir curr_dir %s %s(%u) [%s]\n", curr_dir, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug
+#endif
 	} else {
+		// Relative path
 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifdef __OS2__
+		if (drive_spec_width(dir)) {
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			errno = EINVAL;
+			return -1;
+		}
+#endif
 		curr_dir[curr_dir_len] = '/';
 		memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
 
 		if (!set_path_only && chdir(curr_dir)) {
+			rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 			curr_dir[curr_dir_len] = '\0';
 			return 0;
 		}
@@ -1042,12 +1166,15 @@
 {
 	unsigned int len;
 
-	if (*path != '/') { /* Make path absolute. */
+	// 06 Mar 09 SHL use is_abs_path
+	if (!is_abs_path(path)) { /* Make path absolute. */
 		int len = strlen(path);
+		if (drive_spec_width(path))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 28 Jul 08 SHL
 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
-		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
+		memcpy(curr_dir + curr_dir_len + 1, path + drive_spec_width(path), len + 1);
 		if (!(path = strdup(curr_dir)))
 			out_of_memory("normalize_path");
 		curr_dir[curr_dir_len] = '\0';
@@ -1078,9 +1205,14 @@
 	if (result)
 		free(result);
 
-	if (*fn == '/')
+	// 06 Mar 09 SHL use is_abs_path
+	if (is_abs_path(fn))
 		p1 = p2 = "";
 	else {
+#ifdef __OS2__
+		if (drive_spec_width(fn))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 06 Feb 09 SHL
+#endif
 		p1 = curr_dir + module_dirlen;
 		for (p2 = p1; *p2 == '/'; p2++) {}
 		if (*p2)
@@ -1690,3 +1822,27 @@
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+#ifdef __OS2__ // 16 May 09 SHL added
+/* Convert OS/2 backslashes to unix forward slashes */
+void normalize_dir_slashes(char *path)
+{
+	char *p;
+	if (path && (p = strchr(path, '\\')) != 0) {
+		char ch;
+		*p++ = '/';
+		for (; (ch = *p) != 0; p++)
+		{
+			if (ch == '\\') *p = '/';
+		}
+	}
+}
+
+#if 1
+void assert_no_dir_slashes(char *path)
+{
+	if (path && strchr(path, '\\') != 0)
+		rprintf(FERROR, "[%s] unexpected backslash in path %s %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 06 Feb 09 SHL
+}
+#endif
+#endif // __OS2__
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h I:/sla_dev2_browse/rsync/rsync-3.0.6/xattrs.c ./xattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/xattrs.c	2009-04-26 07:51:50.000000000 -0700
+++ ./xattrs.c	2009-09-19 07:52:36.000000000 -0700
@@ -48,17 +48,28 @@
 #define XSTATE_DONE	2
 #define XSTATE_TODO	3
 
+#ifndef __OS2__
 #define USER_PREFIX "user."
 #define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
 #define SYSTEM_PREFIX "system."
 #define SPRE_LEN ((int)sizeof SYSTEM_PREFIX - 1)
+#else
+#define USER_PREFIX ""
+#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
+#define SYSTEM_PREFIX ""
+#define SPRE_LEN ((int)sizeof SYSTEM_PREFIX - 1)
+#endif
 
 #ifdef HAVE_LINUX_XATTRS
 #define MIGHT_NEED_RPRE (am_root < 0)
 #define RSYNC_PREFIX USER_PREFIX "rsync."
 #else
 #define MIGHT_NEED_RPRE am_root
+#ifndef __OS2__
 #define RSYNC_PREFIX "rsync."
+#else 
+# define RSYNC_PREFIX ""
+#endif
 #endif
 #define RPRE_LEN ((int)sizeof RSYNC_PREFIX - 1)
 
@@ -110,6 +121,8 @@
 {
 	const rsync_xa *xa1 = x1;
 	const rsync_xa *xa2 = x2;
+	// rprintf(FLOG, "* rsync_xal_compare_names: xa1.name %p xa2.name %p %s(%u) [%s]\n", xa1->name, xa2->name, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug xattrs
+
 	return strcmp(xa1->name, xa2->name);
 }
 
@@ -141,7 +154,9 @@
 				fname, arg);
 			return -1;
 		}
+		/* Expand buffer - get size */
 		list_len = sys_llistxattr(fname, NULL, 0);
+		/* Should not occur */
 		if (list_len < 0) {
 			arg = 0;
 			goto got_error;
@@ -715,8 +730,10 @@
 		rxa->num = num;
 	}
 
-	if (need_sort && count > 1)
-		qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
+	// rprintf(FLOG, "* receive_xattr: temp_xattr.items %p count %u %s(%u) [%s]\n", temp_xattr.items, count, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL debug xattrs
+	// 28 Jul 08 SHL sort number used not number malloced
+	if (need_sort && temp_xattr.count > 1)
+		qsort(temp_xattr.items, temp_xattr.count, sizeof (rsync_xa), rsync_xal_compare_names);
 
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */

2009-09-25 12:21

 

rsync-3.0.6-20090924-shl.zip (293,486 bytes)

2009-10-15 10:54

 

rsync-3.0.6-20091014-shl.diff (85,248 bytes)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/Makefile.in ./Makefile.in
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/Makefile.in	2009-04-10 16:24:48.000000000 -0700
+++ ./Makefile.in	2009-09-24 18:43:14.000000000 -0700
@@ -12,6 +12,7 @@
 CFLAGS=@CFLAGS@
 CPPFLAGS=@CPPFLAGS@
 EXEEXT=@EXEEXT@
+# 14 Jun 09 SHL fixme to do bldlevel strings
 LDFLAGS=@LDFLAGS@
 
 INSTALLCMD=@INSTALL@
@@ -68,6 +69,9 @@
 	-mkdir -p ${DESTDIR}${mandir}/man5
 	if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
 	if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
+	if test -f readme.os2; then ${INSTALLMAN} -m 644 readme.os2 ${DESTDIR}${prefix}; fi
+	if test -f rsync.map; then ${INSTALLMAN} -m 644 rsync.map ${DESTDIR}${prefix}; fi
+	if test -s "${DIFFFILE}"; then if test -f ${DIFFFILE}; then ${INSTALLMAN} -m 644 ${DIFFFILE} ${DESTDIR}${prefix}; fi; fi
 
 install-strip:
 	$(MAKE) INSTALL_STRIP='-s' install
@@ -189,9 +193,10 @@
 	yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
 	-$(srcdir)/tweak_manpage rsyncd.conf.5
 
+# 06 Feb 09 SHL clean maps
 clean: cleantests
 	rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
-		rounding rounding.h *.old
+		rounding rounding.h *.old rsync.map rounding.map
 
 cleantests:
 	rm -rf ./testtmp*
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/access.c ./access.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/access.c	2009-01-17 13:41:34.000000000 -0800
+++ ./access.c	2009-10-14 09:55:06.000000000 -0700
@@ -100,7 +100,9 @@
 	hints.ai_flags = AI_NUMERICHOST;
 #endif
 
-	if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	// if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	if ((gai = getaddrinfo(addr, NULL, &hints, &resa)) != 0) {			// 27 Jul 08 SHL debug
+		// rprintf(FINFO, "* [%s] match_address gai %d %s(%u)\n", who_am_i(), gai, __FILE__, __LINE__);	// 28 Jul 08 SHL debug addrinfo
 		if (p)
 			*p = '/';
 		return 0;
@@ -110,8 +112,8 @@
 	if (p)
 		*p++ = '/';
 	if (gai != 0) {
-		rprintf(FLOG, "error matching address %s: %s\n",
-			tok, gai_strerror(gai));
+		rprintf(FLOG, "* error matching address %s: %s (%d)\n",
+			tok, gai_strerror(gai), gai);
 		freeaddrinfo(resa);
 		return 0;
 	}
@@ -222,7 +224,11 @@
 	if (host)
 		strlower(host);
 
+	// rprintf(FINFO, "* [%s] access_match %s (%s) %s(%u)\n", who_am_i(), host, addr, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
+
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+
+		// rprintf(FINFO, "* [%s] access_match tok %s %s(%u)\n", who_am_i(), tok, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
 		if (match_hostname(host, tok) || match_address(addr, tok)) {
 			free(list2);
 			return 1;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/authenticate.c ./authenticate.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/authenticate.c	2009-01-17 13:41:34.000000000 -0800
+++ ./authenticate.c	2009-06-29 14:47:30.000000000 -0700
@@ -96,7 +96,9 @@
 	if (do_stat(fname, &st) == -1) {
 		rsyserr(FLOG, errno, "stat(%s)", fname);
 		ok = 0;
-	} else if (lp_strict_modes(module)) {
+	}
+#ifndef __OS2__	 /* 29 Jun 09 SHL suppress unsupported mode checks */
+	else if (lp_strict_modes(module)) {
 		if ((st.st_mode & 06) != 0) {
 			rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
 			ok = 0;
@@ -105,6 +107,7 @@
 			ok = 0;
 		}
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		rprintf(FLOG, "continuing without secrets file\n");
 		close(fd);
@@ -173,13 +176,16 @@
 	if (do_stat(filename, &st) == -1) {
 		rsyserr(FWARNING, errno, "stat(%s)", filename);
 		ok = 0;
-	} else if ((st.st_mode & 06) != 0) {
+	}
+#ifndef __OS2__	 /* 12 Jun 08 SHL suppress unsupported mode checks */
+	else if ((st.st_mode & 06) != 0) {
 		rprintf(FWARNING, "password file must not be other-accessible\n");
 		ok = 0;
 	} else if (MY_UID() == 0 && st.st_uid != 0) {
 		rprintf(FWARNING, "password file must be owned by root when running as root\n");
 		ok = 0;
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		close(fd);
 		rprintf(FWARNING, "continuing without password file\n");
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/clientname.c ./clientname.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/clientname.c	2009-01-17 13:41:34.000000000 -0800
+++ ./clientname.c	2009-10-14 09:15:58.000000000 -0700
@@ -95,8 +95,10 @@
 	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
-	if (initialised)
+	if (initialised) {
+		// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		return name_buf;
+	}
 
 	strlcpy(name_buf, default_name, sizeof name_buf);
 	initialised = 1;
@@ -148,6 +150,8 @@
 			port_buf, sizeof port_buf) == 0)
 		check_name(fd, &ss, name_buf, sizeof name_buf);
 
+	// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
+
 	return name_buf;
 }
 
@@ -216,14 +220,17 @@
 	int name_err;
 
 	/* reverse lookup */
+	// rprintf(FINFO, "* [%s] lookup_name %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
 			       name_buf, name_buf_size,
 			       port_buf, port_buf_size,
 			       NI_NAMEREQD | NI_NUMERICSERV);
 	if (name_err != 0) {
 		strlcpy(name_buf, default_name, name_buf_size);
-		rprintf(FLOG, "name lookup failed for %s: %s\n",
-			client_addr(fd), gai_strerror(name_err));
+		// rprintf(FINFO, "name lookup failed for %s: %s\n",
+		//	client_addr(fd), gai_strerror(name_err));
+		rprintf(FLOG, "lookup_name failed for %s: %s (%d) at %s(%u) [%s]\n",	// 27 Jul 08 SHL debug
+			client_addr(fd), gai_strerror(name_err), name_err, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL
 		return name_err;
 	}
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/clientserver.c ./clientserver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/clientserver.c	2009-01-17 13:41:34.000000000 -0800
+++ ./clientserver.c	2009-10-14 09:20:54.000000000 -0700
@@ -428,6 +428,8 @@
 	iconv_opt = NULL;
 #endif
 
+	if (verbose)
+		rprintf(FINFO, "[%s] rsync_module addr:host is %s:%s\n", who_am_i(), addr, host);	// 28 Jul 08 SHL
 	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
 		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
 			name, host, addr);
@@ -481,6 +483,7 @@
 
 	am_root = (MY_UID() == 0);
 
+#ifndef __OS2__
 	if (am_root) {
 		p = lp_uid(i);
 		if (!name_to_uid(p, &uid)) {
@@ -503,6 +506,7 @@
 		}
 	}
 
+#endif
 	/* TODO: If we're not root, but the configuration requests
 	 * that we change to some uid other than the current one, then
 	 * log a warning. */
@@ -511,6 +515,7 @@
 	 * supplementary groups. */
 
 	module_dir = lp_path(i);
+	// rprintf(FINFO, "* [%s] module_dir %s %s(%u)\n", who_am_i(), module_dir, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 	if (use_chroot) {
 		if ((p = strstr(module_dir, "/./")) != NULL) {
 			*p = '\0'; /* Temporary... */
@@ -533,6 +538,7 @@
 		if (!(module_chdir = normalize_path(module_dir, False, &module_dirlen)))
 			return path_failure(f_out, module_dir, False);
 		full_module_path = module_dir = module_chdir;
+		// rprintf(FINFO, "* [%s] full_module_path %s %s(%u)\n", who_am_i(), full_module_path, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 	}
 
 	if (module_dirlen == 1) {
@@ -679,8 +685,11 @@
 		module_chdir = module_dir;
 	}
 
-	if (!change_dir(module_chdir, CD_NORMAL))
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+		// rsyserr(FERROR, errno, "[%s] chdir %s failed at %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__);	// 15 Dec 08 SHL debug
+		// rprintf(FINFO, "* [%s] chdir module_chdir %s failed %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 		return path_failure(f_out, module_chdir, True);
+	}
 	if (module_dirlen || !use_chroot)
 		sanitize_paths = 1;
 
@@ -991,6 +1000,7 @@
 	close(fd);
 }
 
+#ifndef __OS2__
 /* Become a daemon, discarding the controlling terminal. */
 static void become_daemon(void)
 {
@@ -1024,6 +1034,7 @@
 		open("/dev/null", O_RDWR);
 	}
 }
+#endif // __OS2__
 
 int daemon_main(void)
 {
@@ -1046,10 +1057,14 @@
 		exit_cleanup(RERR_SYNTAX);
 	}
 
+#ifndef __OS2__
 	if (no_detach)
 		create_pid_file();
 	else
 		become_daemon();
+#else
+	create_pid_file();
+#endif
 
 	if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
 		rsync_port = RSYNC_PORT;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/compat.c ./compat.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/compat.c	2009-03-29 13:25:42.000000000 -0700
+++ ./compat.c	2009-09-25 19:13:10.000000000 -0700
@@ -198,11 +198,12 @@
 			exit_cleanup(RERR_PROTOCOL);
 		}
 		if (preserve_xattrs && !local_server) {
-			rprintf(FERROR,
-			    "--xattrs requires protocol 30 or higher"
+		  	preserve_xattrs = 0;	// 06 Feb 09 SHL force off for old servers
+			rprintf(FWARNING,
+			    "--xattrs requires protocol 30 or higher - option disabled"
 			    " (negotiated %d).\n",
 			    protocol_version);
-			exit_cleanup(RERR_PROTOCOL);
+			// exit_cleanup(RERR_PROTOCOL);	// 06 Feb 09 SHL
 		}
 	}
 
@@ -291,6 +292,7 @@
 	if (need_unsorted_flist && (!am_sender || inc_recurse))
 		unsort_ndx = ++file_extra_cnt;
 
+	// 16 Feb 09 SHL fixme slashes?
 	if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
 		int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
 		if (!am_sender || protocol_version >= 30)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/configure.sh ./configure.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/configure.sh	2009-05-08 10:41:12.000000000 -0700
+++ ./configure.sh	2009-07-08 12:27:22.000000000 -0700
@@ -69,6 +69,8 @@
   as_echo='sh -c $as_echo_body as_echo'
 fi
 
+# 18 Jun 09 SHL fixme to not be broken - 3.0.5 worked - maybe autoconf 2.6.3 broke it
+
 # The user is always right.
 if test "${PATH_SEPARATOR+set}" != set; then
   PATH_SEPARATOR=:
@@ -2045,6 +2047,7 @@
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
+  echo SHL $as_dir
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
@@ -16947,6 +16950,15 @@
 _ACEOF
 
 	;;
+    *os2*)
+	{ echo "$as_me:$LINENO: result: Using OS/2 extattrs" >&5
+echo "${ECHO_T}Using OS/2 extattrs" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_XATTRS 1
+_ACEOF
+
+	;;
+
     *)
 	if test x"$enable_xattr_support" = x"yes"; then
 	    { { $as_echo "$as_me:$LINENO: error: Failed to find extended attribute support" >&5
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/exclude.c ./exclude.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/exclude.c	2009-01-17 13:41:34.000000000 -0800
+++ ./exclude.c	2009-06-18 19:24:26.000000000 -0700
@@ -298,7 +298,7 @@
 	unsigned int fn_len;
 
 	if (!parent_dirscan && *merge_file != '/') {
-		/* Return the name unchanged it doesn't have any slashes. */
+		/* Return the name unchanged if it doesn't have any slashes. */
 		if (len_ptr) {
 			const char *p = merge_file + *len_ptr;
 			while (--p > merge_file && *p != '/') {}
@@ -310,6 +310,7 @@
 			return (char *)merge_file;
 	}
 
+	// 16 Feb 09 SHL fixme slash
 	fn = *merge_file == '/' ? buf : tmpbuf;
 	if (sanitize_paths) {
 		const char *r = prefix_skip ? "/" : NULL;
@@ -351,6 +352,7 @@
 void set_filter_dir(const char *dir, unsigned int dirlen)
 {
 	unsigned int len;
+	// 16 Feb 09 SHL fixme slash?
 	if (*dir != '/') {
 		memcpy(dirbuf, curr_dir, curr_dir_len);
 		dirbuf[curr_dir_len] = '/';
@@ -548,6 +550,7 @@
 	int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
 	char *p, *pattern = ex->pattern;
 	const char *strings[16]; /* more than enough */
+	// 16 Feb 09 SHL fixme slash?
 	const char *name = fname + (*fname == '/');
 
 	if (!*name)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/flist.c ./flist.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/flist.c	2009-04-26 07:51:50.000000000 -0700
+++ ./flist.c	2009-10-14 09:22:44.000000000 -0700
@@ -348,8 +348,19 @@
 {
 	if (dirlen < 0) {
 		char *cpy = strdup(dir);
+#ifndef __OS2__ // 06 Mar 09 SHL use is_abs_path...
 		if (*cpy != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (!is_abs_path(cpy)) {
+			if (drive_spec_width(cpy))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), cpy, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+	        }
+#endif
 		if (path_is_daemon_excluded(cpy, 0))
 			goto chdir_error;
 		dir = cpy;
@@ -363,8 +374,19 @@
 				dirlen = strlen(dir);
 		} else if (pathname == dir)
 			return 1;
+#ifndef __OS2__ // 06 Mar 09 SHL use is_abs_path...
 		if (dir && *dir != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (dir && !is_abs_path(dir)) {
+			if (drive_spec_width(dir))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+		}
+#endif
 	}
 
 	pathname = dir;
@@ -377,8 +399,13 @@
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
 		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
-		if (dir != orig_dir)
-			change_dir(orig_dir, CD_NORMAL);
+		rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
+		if (dir != orig_dir) {
+			if (!change_dir(orig_dir, CD_NORMAL)) {
+				if (verbose > 1)
+					rprintf(FLOG, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+		}
 		pathname = NULL;
 		pathname_len = 0;
 		return 0;
@@ -1328,6 +1355,8 @@
 {
 	struct file_struct *file;
 
+	// rprintf(FINFO, "* [%s] send_file_name fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+
 	file = make_file(fname, flist, stp, flags, filter_level);
 	if (!file)
 		return NULL;
@@ -1952,6 +1981,7 @@
 	int len, dirlen;
 	STRUCT_STAT st;
 	char *p, *dir;
+	static char* the_root = "/";
 	struct file_list *flist;
 	struct timeval start_tv, end_tv;
 	int64 start_write;
@@ -1995,6 +2025,7 @@
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
 			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
 				full_fname(argv[0]));
+			rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), argv[0], __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 		use_ff_fd = 1;
@@ -2014,17 +2045,22 @@
 			if (argc-- == 0)
 				break;
 			strlcpy(fbuf, *argv++, MAXPATHLEN);
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 			if (sanitize_paths)
 				sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Feb 09 SHL debug xattrs
+
 		len = strlen(fbuf);
 		if (relative_paths) {
 			/* We clean up fbuf below. */
 			name_type = NORMAL_NAME;
 		} else if (!len || fbuf[len - 1] == '/') {
-			if (len == 2 && fbuf[0] == '.') {
-				/* Turn "./" into just "." rather than "./." */
+			// Empty path or trailing /
+			// 06 Mar 09 SHL
+			if (len == 2 + drive_spec_width(fbuf) && fbuf[drive_spec_width(fbuf)] == '.') {
+				/* Turn trailing "./" into just "." rather than "./." */
 				fbuf[--len] = '\0';
 			} else {
 				if (len + 1 >= MAXPATHLEN)
@@ -2035,6 +2071,7 @@
 			name_type = DOTDIR_NAME;
 		} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
 		    && (len == 2 || fbuf[len-3] == '/')) {
+			// Got ..  or trailing /..
 			if (len + 2 >= MAXPATHLEN)
 				overflow_exit("send_file_list");
 			fbuf[len++] = '/';
@@ -2053,18 +2090,39 @@
 			if (p) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 06 Mar 09 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else
 					dir = fbuf;
-				len -= p - fbuf + 1;
-				fn = p + 1;
+				fn = p + 1;		// Point at filename part
+				len -= fn - fbuf;	//  fn length
+				// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			} else
 				fn = fbuf;
 		} else {
 			if ((p = strstr(fbuf, "/./")) != NULL) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 06 Mar 09 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else {
 					dir = fbuf;
 					clean_fname(dir, 0);
@@ -2086,6 +2144,8 @@
 			}
 			len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
 					    | CFN_DROP_TRAILING_DOT_DIR);
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+			// 06 Mar 09 SHL fixme?
 			if (len == 1) {
 				if (fn[0] == '/') {
 					fn = "/.";
@@ -2118,6 +2178,8 @@
 			name_type = DOTDIR_NAME;
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list dir %s fn %s len %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug xattrs
+
 		dirlen = dir ? strlen(dir) : 0;
 		if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
 			if (!change_pathname(NULL, dir, -dirlen))
@@ -2127,9 +2189,16 @@
 		} else if (!change_pathname(NULL, lastdir, lastdir_len))
 			continue;
 
+		// 06 Mar 09 SHL
+		if (dir && dir != the_root && dir != fbuf)
+			free(dir);	// We allocated it
+
 		if (fn != fbuf)
 			memmove(fbuf, fn, len + 1);
 
+		// rprintf(FINFO, "* [%s] send_file_list fn %s %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s len %d %s(%u)\n", who_am_i(), fbuf, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+
 		if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
@@ -2150,12 +2219,14 @@
 		}
 
 		if (inc_recurse && relative_paths && *fbuf) {
+			// 06 Mar 09 SHL fixme
 			if ((p = strchr(fbuf+1, '/')) != NULL) {
 				if (p - fbuf == 1 && *fbuf == '.') {
 					if ((fn = strchr(p+1, '/')) != NULL)
 						p = fn;
 				} else
 					fn = p;
+			        // rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 				send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
 				if (fn == p)
 					continue;
@@ -2163,6 +2234,7 @@
 		} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
 			/* Send the implied directories at the start of the
 			 * source spec, so we get their permissions right. */
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
 		}
 
@@ -2171,6 +2243,7 @@
 
 		if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
 			struct file_struct *file;
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			file = send_file_name(f, flist, fbuf, &st,
 					      FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
 					      NO_FILTERS);
@@ -2186,9 +2259,11 @@
 				}
 			} else
 				send_if_directory(f, flist, file, fbuf, len, flags);
-		} else
+		} else {
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
 	}
+	}
 
 	gettimeofday(&end_tv, NULL);
 	stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/generator.c ./generator.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/generator.c	2009-04-26 07:51:50.000000000 -0700
+++ ./generator.c	2009-10-14 13:12:40.000000000 -0700
@@ -98,6 +98,10 @@
 extern int backup_suffix_len;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+// 14 Oct 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 int ignore_perishable = 0;
 int non_perishable_cnt = 0;
@@ -272,6 +276,7 @@
 	}
 
 	p = fname + dlen;
+	// 16 Feb 09 SHL fixme slash?
 	if (dlen != 1 || *fname != '/')
 		*p++ = '/';
 	remainder = MAXPATHLEN - (p - fname);
@@ -590,7 +595,7 @@
 	} else
 #endif
 	if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
-		return 0;
+		return 0;		// Changed
 
 	if (preserve_perms) {
 		if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
@@ -622,7 +627,7 @@
 	}
 #endif
 
-	return 1;
+	return 1;			// No change
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -646,19 +651,26 @@
 		} else if (keep_time
 		 ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
 		 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
-		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s file->modtime %u sxp->st.st_mtime %u %s(%u)\n", who_am_i(), fnamecmp, file->modtime, sxp->st.st_mtime, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme times
 			iflags |= ITEM_REPORT_TIME;
+		}
+
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
 		} else
 #endif
 		if (preserve_perms) {
-			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) {
+				rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
 				iflags |= ITEM_REPORT_PERMS;
+			}
 		} else if (preserve_executability
-		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0))) {
+			rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
 			iflags |= ITEM_REPORT_PERMS;
+		 }
 		if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 			iflags |= ITEM_REPORT_OWNER;
 		if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
@@ -1492,6 +1504,17 @@
 			}
 			need_retouch_dir_perms = 1;
 		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If source directory not archived (i.e. not writable by group)
+		// may need to touch up after file operations complete
+		// see map_os2_attributes
+		if (!need_retouch_dir_perms && os2_perms &&
+		    ~file->mode & S_IWGRP) {
+			// rprintf(FINFO, "* [%s] recv_generator dir %s needs retouch mode %o %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 14 Oct 09 SHL fixme dir perms
+			need_retouch_dir_perms = 1;
+		}
+#endif
 #endif
 
 		if (real_ret != 0 && one_file_system)
@@ -1511,7 +1534,7 @@
 				change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
 		}
 		goto cleanup;
-	}
+	} // is_dir
 
 	/* If we're not preserving permissions, change the file-list's
 	 * mode based on the local permissions and some heuristics. */
@@ -2041,10 +2064,14 @@
 	} else
 		start = end = ndx;
 
+	// rprintf(FINFO, "* [%s] touch_up_dirs start %u end %u %s(%u)\n", who_am_i(), start, end,  __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
+
 	/* Fix any directory permissions that were modified during the
 	 * transfer and/or re-set any tweaked modified-time values. */
 	for (i = start; i <= end; i++, counter++) {
 		file = flist->files[i];
+		fname = f_name(file, NULL); // 14 Oct 09 SHL debug dir perms
+		// rprintf(FINFO, "* [%s] touch_up_dirs dir %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 		if (!S_ISDIR(file->mode)
 		 || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))
 			continue;
@@ -2053,18 +2080,55 @@
 			rprintf(FINFO, "touch_up_dirs: %s (%d)\n",
 				NS(fname), i);
 		}
+#ifndef __OS2__
 		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
 		 || (!need_retouch_dir_times && file->mode & S_IWUSR))
 			continue;
+else
+		// 14 Oct 09 SHL
+		// If os/2 perms and want want archived on (i.e. writable by group)
+		// See map_os2_attributes
+		if (!F_IS_ACTIVE(file) ||
+		    file->flags & FLAG_MISSING_DIR ||
+		    (!need_retouch_dir_times && file->mode & S_IWUSR &&
+		     os2_perms && file->mode & S_IWGRP))
+			continue;
+#endif
 		fname = f_name(file, NULL);
+#ifdef __OS2__
+		// 14 Oct 09 SHL Need to set time before clearing archive bit
+		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);
+		}
+#endif
 		if (!(file->mode & S_IWUSR))
 			do_chmod(fname, file->mode);
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived off (i.e. not writable by group)
+		// See map_os2_attributes
+		// Other os/2 perms should already be OK
+		// There is not way to know for sure if directory was modified so we check
+		else if (os2_perms && ~file->mode & S_IWGRP) {
+			STRUCT_STAT st;
+			if (link_stat(fname, &st, 0) == 0 &&
+			    ((file->mode ^ st.st_mode) & S_IWGRP)) {
+				// rprintf(FINFO, "* [%s] touch_up_dirs chmod(%s, 0%o) %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
+				do_chmod(fname, file->mode);
+			}
+		}
+#endif
+#ifndef __OS2__
 		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);
 		}
+#endif
 		if (counter >= loopchk_limit) {
 			if (allowed_lull)
 				maybe_send_keepalive();
@@ -2335,6 +2399,7 @@
 	if (delete_after && !solo_file && file_total > 0)
 		do_delete_pass();
 
+	// rprintf(FINFO, "* [%s] generate_files need_retouch_dir_perms %u need_retouch_dir_times %u %s(%u)\n", who_am_i(), need_retouch_dir_perms, need_retouch_dir_times, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme dir perms
 	if ((need_retouch_dir_perms || need_retouch_dir_times)
 	 && dir_tweaking && (!inc_recurse || delete_during == 2))
 		touch_up_dirs(dir_flist, -1);
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/getaddrinfo.c ./lib/getaddrinfo.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/getaddrinfo.c	2008-10-25 08:39:40.000000000 -0700
+++ ./lib/getaddrinfo.c	2009-10-14 09:55:14.000000000 -0700
@@ -404,12 +404,16 @@
 	int ret = -1;
 	char *p = NULL;
 
+	// rprintf(FINFO, "* [%s] gethostnameinfo NI_NUMERICHOST %u %s(%u)\n", who_am_i(), flags & NI_NUMERICHOST, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	if (!(flags & NI_NUMERICHOST)) {
+		// rprintf(FINFO, "* [%s] gethostnameinfo %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		struct hostent *hp = gethostbyaddr(
 				(void *)&((struct sockaddr_in *)sa)->sin_addr,
 				sizeof (struct in_addr),
 				sa->sa_family);
+		// rprintf(FINFO, "* [%s] gethostnameinfo hp %p %s(%u)\n", who_am_i(), hp, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		ret = check_hostent_err(hp);
+		// rprintf(FINFO, "* [%s] ret %d %s(%u)\n", who_am_i(), ret, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (ret == 0) {
 			/* Name looked up successfully. */
 			ret = snprintf(node, nodelen, "%s", hp->h_name);
@@ -425,6 +429,7 @@
 			return 0;
 		}
 
+		// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (flags & NI_NAMEREQD) {
 			/* If we require a name and didn't get one,
 			 * automatically fail. */
@@ -432,6 +437,7 @@
 		}
 		/* Otherwise just fall into the numeric host code... */
 	}
+	// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
 	ret = snprintf(node, nodelen, "%s", p);
 	if (ret < 0 || (size_t)ret >= nodelen) {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/sysxattrs.c ./lib/sysxattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/sysxattrs.c	2008-03-01 12:01:40.000000000 -0800
+++ ./lib/sysxattrs.c	2009-10-04 18:33:34.000000000 -0700
@@ -126,6 +126,336 @@
 	return len;
 }
 
+#elif defined(__OS2__)
+
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+
+static void map_os2_apiret(APIRET rc)
+{
+	switch (rc) {
+	case ERROR_SHARING_VIOLATION:
+		errno = EACCES;
+		break;
+	case 0:
+		// Should not have been called - try to do no harm
+		break;
+	default:
+		// 31 Jul 09 SHL fixme to map better
+		// if (verbose > 2)
+		rprintf(FINFO, "[%s] can not map OS/2 error %lu to errno\n", who_am_i(), rc);	// 31 Jul 09 SHL
+		/* Ensure non-zero */
+		if (!errno)
+			errno = EINVAL;
+
+	}
+}
+
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+	return unisetxattr (path, 0, name, value, size, 0);
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	EAOP2       eaop2 = {0,0,0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+	pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;
+	do {
+		if (path) {
+			rc = DosQueryPathInfo(path, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryPathInfo(%s, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] %s requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), path, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		else {
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryFileInfo(%u, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] handle %d requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), file, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		if (rc)
+			break;
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0) {
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value) {
+			if ((size_t)rc > size) {
+				errno = ERANGE;
+				rc = -1;
+			}
+			else {
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+		free(pgea2list);
+	if (pgea2list)
+		free(pfea2list);
+
+	return rc;
+}
+
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat;
+	if (!path && !file) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (path) {
+		rc = DosQueryPathInfo(path, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryPathInfo(%s, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] %s reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), path, stat.cbList);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryFilInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] handle %d reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), file, stat.cbList);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	if (stat.cbList <= 4) {
+		// NO ea
+		return 0;
+	}
+	//YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
+	buf = (char *)_tmalloc(stat.cbList * 2);
+	// 19 Sep 09 SHL was trapping on large copies
+	if (!buf) {
+		rprintf(FERROR, "out of memory allocating %lu at %s(%u)\n", stat.cbList * 2, __FILE__, __LINE__);	// 19 Sep 09 SHL fixme gone debug
+		return -1;
+	}
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc) {
+		rprintf(FERROR, "[%s] unilistxattr DosEnumAttribute failed with error %u at %s(%u)\n", who_am_i(), rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		_tfree(buf);
+		map_os2_apiret(rc);	// 31 Jul 09 SHL moved here to ensure errno returned
+		return -1;
+	}
+	else if (verbose > 2) {
+		if (path)
+			rprintf(FINFO, "[%s] %s has %lu DosEnumAttribute items\n", who_am_i(), path, ulCount);	// 28 Jul 08 SHL
+		else
+			rprintf(FINFO, "[%s] handle %d has %lu DosEnumAttribute items\n", who_am_i(), file, ulCount);	// 28 Jul 08 SHL
+	}
+	if (ulCount > 0) {
+		for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset)) {
+			if (pfea->cbName > 0) {
+				gotsize += pfea->cbName + 1;
+				// Avoid overflow
+				if (p && (size_t)gotsize <= size) {
+					pfea->szName[pfea->cbName] = 0;
+					strcpy(p, pfea->szName);
+					p += strlen(p) + 1;
+				}
+			}
+			if (!pfea->oNextEntryOffset)
+				break;
+		}
+	}
+	_tfree(buf);
+	if ((size_t)gotsize > size) {
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	if (verbose > 2)
+		rprintf(FINFO, "[%s] returning %ld EA list bytes\n", who_am_i(), (unsigned long)gotsize);	// 28 Jul 08 SHL
+	return gotsize;
+}
+
+int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0,0,0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosFileInfo(%u, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0,0,0};
+	PFEA2LIST   pfea2list = NULL;
+	// char * p;			// 17 May 09 SHL  fixme
+
+	if ((!path && !file) || !name || (!value && size)) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0) {
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0) {
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(FEA2LIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value) {
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetFileInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	free(pfea2list);
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
 #else
 
 #error You need to create xattr compatibility functions.
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/sysxattrs.h ./lib/sysxattrs.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/lib/sysxattrs.h	2007-04-07 10:22:24.000000000 -0700
+++ ./lib/sysxattrs.h	2009-06-18 19:24:26.000000000 -0700
@@ -19,6 +19,13 @@
 int sys_lremovexattr(const char *path, const char *name);
 ssize_t sys_llistxattr(const char *path, char *list, size_t size);
 
+#ifdef __OS2__
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size);
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size);
+int uniremovexattr (const char *path, int file, const char *name);
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags);
+#endif
+
 #else
 
 /* No xattrs available */
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/loadparm.c ./loadparm.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/loadparm.c	2009-01-17 13:41:34.000000000 -0800
+++ ./loadparm.c	2009-06-18 19:24:26.000000000 -0700
@@ -654,10 +654,23 @@
 	    *(char *)dest_ptr = *(char *)src_ptr;
 	    break;
 
+#ifndef __OS2__
 	  case P_PATH:
 	  case P_STRING:
 	    string_set(dest_ptr,*(char **)src_ptr);
 	    break;
+#else
+	  case P_PATH:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    // 06 Mar 09 SHL Force unix slashes
+	    // 16 May 09 SHL Use normalize_dir_slashes
+	    normalize_dir_slashes(*(char **)dest_ptr);
+	    break;
+
+	  case P_STRING:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    break;
+#endif
 
 	  default:
 	    break;
@@ -726,7 +739,12 @@
        string_set(parm_ptr,parmvalue);
        if ((cp = *(char**)parm_ptr) != NULL) {
 	   int len = strlen(cp);
+#ifndef __OS2__
 	   while (len > 1 && cp[len-1] == '/') len--;
+#else
+	   int drive_letter_adj = *(cp + 1) == ':' && isalpha(*cp) ? 2 : 0;
+	   while (len > 1 + drive_letter_adj && cp[len-1] == '/') len--;
+#endif
 	   cp[len] = '\0';
        }
        break;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/log.c ./log.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/log.c	2009-01-17 13:41:34.000000000 -0800
+++ ./log.c	2009-06-18 19:24:26.000000000 -0700
@@ -371,6 +371,7 @@
 	va_list ap;
 	char buf[BIGPATHBUFLEN];
 	size_t len;
+	int e = errno;			// 27 Apr 09 SHL preserve errno
 
 	va_start(ap, format);
 	len = vsnprintf(buf, sizeof buf, format, ap);
@@ -403,6 +404,7 @@
 	}
 
 	rwrite(code, buf, len, 0);
+	errno = e;
 }
 
 /* This is like rprintf, but it also tries to print some
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/main.c ./main.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/main.c	2009-02-04 18:27:06.000000000 -0800
+++ ./main.c	2009-10-14 09:16:26.000000000 -0700
@@ -531,6 +531,8 @@
 			if (!change_dir(dest_path, CD_NORMAL)) {
 				rsyserr(FERROR, errno, "change_dir#1 %s failed",
 					full_fname(dest_path));
+				// 22 Jul 09 SHL was FLOG?  why?
+				rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 				exit_cleanup(RERR_FILESELECT);
 			}
 			return NULL;
@@ -591,6 +593,8 @@
 		if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
 			rsyserr(FERROR, errno, "change_dir#2 %s failed",
 				full_fname(dest_path));
+			// 22 Jul 09 SHL was FLOG?  why?
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 
@@ -611,6 +615,8 @@
 	if (!change_dir(dest_path, CD_NORMAL)) {
 		rsyserr(FERROR, errno, "change_dir#3 %s failed",
 			full_fname(dest_path));
+		// 22 Jul 09 SHL was FLOG?  why?
+		rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 		exit_cleanup(RERR_FILESELECT);
 	}
 	*cp = '/';
@@ -702,8 +708,9 @@
 
 	if (!relative_paths) {
 		if (!change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#3 %s failed",
+			rsyserr(FERROR, errno, "change_dir#4 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -872,8 +879,9 @@
 		argc--;
 		argv++;
 		if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#4 %s failed",
+			rsyserr(FERROR, errno, "change_dir#5 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -928,6 +936,7 @@
 			if (check_filter(elp, FLOG, dir, 1) < 0)
 				goto options_rejected;
 		}
+		// 25 Sep 09 SHL fixme slashes
 		if (partial_dir && *partial_dir == '/'
 		 && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
 		    options_rejected:
@@ -1086,7 +1095,7 @@
 
 	for (i = 0; argv[i]; i++) {
 		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
+			rprintf (FERROR, "out of memory at %s(%u)\n",
 				 __FILE__, __LINE__);
 			return RERR_MALLOC;
 		}
@@ -1117,6 +1126,14 @@
 	 * command line. */
 	if ((ret = copy_argv(argv)) != 0)
 		return ret;
+#ifdef __OS2__
+	{
+		int i;
+		for (i = 0; i < argc; i++) {
+			normalize_dir_slashes(argv[i]);
+		}
+	}
+#endif
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -1440,6 +1457,7 @@
 	 * (implemented by forking "pwd" and reading its output) doesn't
 	 * work when there are other child processes.  Also, on all systems
 	 * that implement getcwd that way "pwd" can't be found after chroot. */
+	// rprintf(FINFO, "* [%s] %s %s(%u)\n", who_am_i(), "(null)", __FILE__, __LINE__);	// 28 Jul 08 SHL debug chdir
 	change_dir(NULL, CD_NORMAL);
 
 	init_flist();
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/options.c ./options.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/options.c	2009-04-12 13:01:14.000000000 -0700
+++ ./options.c	2009-10-14 11:46:06.000000000 -0700
@@ -52,6 +52,10 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+// 13 Jun 09 SHL Added
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -117,7 +121,11 @@
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
+#ifndef __OS2__
 int modify_window = 0;
+#else
+int modify_window = 1;			// 28 Jul 09 SHL allow for 2 second resolution
+#endif
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
@@ -263,6 +271,10 @@
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
 	rprintf(f, "Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.\n");
 	rprintf(f, "Web site: http://rsync.samba.org/\n");
+#ifdef __OS2__ // 22 Jul 09 SHL
+	rprintf(f, "Built by Steven H. Levine " __DATE__ " " __TIME__ "\n");
+	rprintf(f, "Built with GCC " __VERSION__ "\n");
+#endif
 	rprintf(f, "Capabilities:\n");
 	rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
 		(int)(sizeof (OFF_T) * 8),
@@ -339,6 +351,9 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+#ifdef __OS2__
+  rprintf(F," -2, --os2-perms             preserve native OS/2 permissions\n");
+#endif
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
 #ifdef SUPPORT_ACLS
@@ -481,6 +496,10 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+#ifdef __OS2__
+  {"os2-perms",       '2', POPT_ARG_NONE,   0, '2', 0, 0 },
+  {"no-os2-perms",     0,  POPT_ARG_VAL,    &os2_perms, 0, 0, 0 },
+#endif
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
@@ -1034,6 +1053,7 @@
 		case OPT_EXCLUDE_FROM:
 		case OPT_INCLUDE_FROM:
 			arg = poptGetOptArg(pc);
+			// printf("PS - pc = %s\n",arg);	// 16 Feb 09 SHL fixme debug PS = Paul?
 			if (sanitize_paths)
 				arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 			if (daemon_filter_list.head) {
@@ -1141,6 +1161,13 @@
 			}
 			break;
 
+// 14 Jun 09 SHL
+#ifdef __OS2__
+		case '2':
+			os2_perms = 1;
+			preserve_perms = 1;	// Implied
+			break;
+#endif
 		case OPT_WRITE_BATCH:
 			/* batch_name is already set */
 			write_batch = 1;
@@ -1476,6 +1503,7 @@
 			char *dir;
 			if (!*backup_dir)
 				goto options_rejected;
+			// 25 Sep 09 SHL fixme slashes
 			dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
 			clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
 			if (check_filter(elp, FLOG, dir, 1) < 0)
@@ -1784,6 +1812,12 @@
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
 		argstr[x++] = 'E';
+// 13 Jun 09 SHL
+#ifdef __OS2__
+	if (os2_perms)
+		argstr[x++] = '2';
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls)
 		argstr[x++] = 'A';
@@ -2103,6 +2137,10 @@
 			break;
 		}
 		if (*s == ':' || *s == '/') {
+#			ifdef __OS2__	// 29 Jun 09 SHL don't confuse drive letter with host spec
+			if (*s == ':' && s == str + 1 && drive_spec_width(s - 1) != 0)
+				continue;
+#			endif
 			if (!hostlen)
 				hostlen = s - host_start;
 			if (*s++ == '/') {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/params.c ./params.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/params.c	2007-11-22 09:51:20.000000000 -0800
+++ ./params.c	2009-06-18 19:24:28.000000000 -0700
@@ -168,6 +168,7 @@
   while( pos >= 0 && isSpace(line + pos) )
      pos--;
 
+  // 16 May 09 SHL fixme to not be confused by trailing \ in path
   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
   } /* Continuation */
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/proto.h ./proto.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/proto.h	2009-05-08 10:43:22.000000000 -0700
+++ ./proto.h	2009-09-18 20:01:40.000000000 -0700
@@ -108,6 +108,13 @@
 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);
+int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp);
+void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
+	     stat_x *sxp, int32 iflags, uchar fnamecmp_type,
+	     const char *xname);
+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);
 struct hashtable *hashtable_create(int size, int key64);
 void hashtable_destroy(struct hashtable *tbl);
 void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing);
@@ -311,6 +318,38 @@
 int do_lstat(const char *fname, STRUCT_STAT *st);
 int do_fstat(int fd, STRUCT_STAT *st);
 OFF_T do_lseek(int fd, OFF_T offset, int whence);
+int do_unlink(const char *fname);
+int do_symlink(const char *fname1, const char *fname2);
+int do_link(const char *fname1, const char *fname2);
+int do_lchown(const char *path, uid_t owner, gid_t group);
+int do_mknod(const char *pathname, mode_t mode, dev_t dev);
+int do_rmdir(const char *pathname);
+int do_open(const char *pathname, int flags, mode_t mode);
+int do_chmod(const char *path, mode_t mode);
+int do_rename(const char *fname1, const char *fname2);
+void trim_trailing_slashes(char *name);
+int do_mkdir(char *fname, mode_t mode);
+int do_mkstemp(char *template, mode_t perms);
+int do_stat(const char *fname, STRUCT_STAT *st);
+int do_lstat(const char *fname, STRUCT_STAT *st);
+int do_fstat(int fd, STRUCT_STAT *st);
+OFF_T do_lseek(int fd, OFF_T offset, int whence);
+int do_unlink(const char *fname);
+int do_symlink(const char *fname1, const char *fname2);
+int do_link(const char *fname1, const char *fname2);
+int do_lchown(const char *path, uid_t owner, gid_t group);
+int do_mknod(const char *pathname, mode_t mode, dev_t dev);
+int do_rmdir(const char *pathname);
+int do_open(const char *pathname, int flags, mode_t mode);
+int do_chmod(const char *path, mode_t mode);
+int do_rename(const char *fname1, const char *fname2);
+void trim_trailing_slashes(char *name);
+int do_mkdir(char *fname, mode_t mode);
+int do_mkstemp(char *template, mode_t perms);
+int do_stat(const char *fname, STRUCT_STAT *st);
+int do_lstat(const char *fname, STRUCT_STAT *st);
+int do_fstat(int fd, STRUCT_STAT *st);
+OFF_T do_lseek(int fd, OFF_T offset, int whence);
 void set_compression(const char *fname);
 void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
 		int32 n, int32 toklen);
@@ -378,6 +417,8 @@
 int flist_ndx_pop(flist_ndx_list *lp);
 void *expand_item_list(item_list *lp, size_t item_size,
 		       const char *desc, int incr);
+void normalize_dir_slashes(char *path);
+void assert_no_dir_slashes(char *path);
 void free_xattr(stat_x *sxp);
 int get_xattr(const char *fname, stat_x *sxp);
 int copy_xattrs(const char *source, const char *dest);
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/readme.os2 ./readme.os2
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/readme.os2	2106-02-06 22:28:16.000000000 
+++ ./readme.os2	2009-10-14 09:34:58.000000000 -0700
@@ -0,0 +1,86 @@
+Rsync v3.0.6 compiled with GCC 3.4.6 & kLibc v0.6.3
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+We (Paul and Steven) are using this as both client and server for backups
+
+Changes in this version:
+- Updated to v3.0.6
+- Incorporated a bunch of patches from Steven Levine
+- Move to GCC 3.4.6 as a compiler
+- --xattrs now works for remote servers
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 permissions
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke a some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+  Run make install
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Cheers,
+
+Paul Smedley
+Adelaide, Australia
+
+and
+
+Steven Levine
+Costa Mesa, California, USA
+
+24 Sep 2009
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/rsync.c ./rsync.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/rsync.c	2009-01-17 13:41:34.000000000 -0800
+++ ./rsync.c	2009-10-13 19:20:20.000000000 -0700
@@ -386,6 +386,8 @@
 	mode_t new_mode = file->mode;
 	int inherit;
 
+	// rprintf(FINFO, "* [%s] set_file_attrs fname %s mode %o file %p sxp %p %s(%u)\n", who_am_i(), fname, file->mode, file, sxp, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	if (!sxp) {
 		if (dry_run)
 			return 1;
@@ -498,6 +500,7 @@
 
 #ifdef HAVE_CHMOD
 	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+		// rprintf(FINFO, "* [%s] set_file_attrs fname %s sxp->st.st_mode %o new_mode %o %s(%u)\n", who_am_i(), fname, sxp->st.st_mode, new_mode, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
@@ -555,8 +558,12 @@
 		    int overwriting_basis)
 {
 	int ret;
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
 	const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
+	if (partialptr && drive_spec_width(partialptr))
+		rprintf(FINFO, "* [%s] finish_transfer partialptr %s fname %s fnamecmp %s %s(%u)\n", who_am_i(), partialptr, fname, fnamecmp, __FILE__, __LINE__);	// 25 Sep 09 SHL debug slashes
+
 	if (inplace) {
 		if (verbose > 2)
 			rprintf(FINFO, "finishing %s\n", fname);
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/rsync.h ./rsync.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/rsync.h	2009-02-14 07:57:50.000000000 -0800
+++ ./rsync.h	2009-09-25 19:38:06.000000000 -0700
@@ -1144,3 +1144,12 @@
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+// 05 Mar 09 SHL support drive letters
+#ifndef __OS2__
+#define drive_spec_width(p) 0
+#define is_abs_path(p) (*(p) == '/')
+#else
+#define drive_spec_width(p) ((isalpha(*(p)) && *((p) + 1) == ':') ? 2 : 0)
+#define is_abs_path(p) (*((p) + drive_spec_width(p)) == '/')
+#endif
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/sender.c ./sender.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/sender.c	2009-04-12 12:48:58.000000000 -0700
+++ ./sender.c	2009-06-18 19:24:28.000000000 -0700
@@ -362,7 +362,7 @@
 		make_backups = -make_backups;
 
 	if (verbose > 2)
-		rprintf(FINFO, "send files finished\n");
+		rprintf(FINFO, "send_files finished\n");	// 06 Mar 09 SHL
 
 	match_report();
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/syscall.c ./syscall.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/syscall.c	2009-01-17 13:41:34.000000000 -0800
+++ ./syscall.c	2009-10-14 09:18:24.000000000 -0700
@@ -28,6 +28,24 @@
 #ifdef HAVE_SYS_ATTR_H
 #include <sys/attr.h>
 #endif
+// 06 Mar 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define setmode
+#if defined HAVE_SETMODE && O_BINARY && __OS2__
+// From gcc io.h
+int setmode (int, int);
+// From gcc os2emx.h
+#endif
+#ifdef __OS2__ // 01 Aug 09 SHL
+// 01 Aug 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define _sopen
+int _sopen (__const__ char *, int, int, ...);	// hack cough
+#include "share.h"			// SH_DENYNO
+#endif
+
+#if defined __OS2__
+// 27 Apr 09 SHL Need definitions for FILE_...
+#define INCL_DOS
+// #include <os2.h>
+#include <os2emx.h>
+#endif
 
 extern int dry_run;
 extern int am_root;
@@ -35,6 +53,10 @@
 extern int list_only;
 extern int preserve_perms;
 extern int preserve_executability;
+// 13 Jun 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -138,12 +160,32 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+#ifdef __OS2__
+	int fd;
+#endif
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
 
+#ifndef __OS2__
 	return open(pathname, flags | O_BINARY, mode);
+#else
+	// 31 Jul 09 SHL if open fails, try shared open in case file already opened for write
+	fd = open(pathname, flags | O_BINARY, mode);
+	if (fd == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
+		fd = _sopen(pathname, flags | O_BINARY, SH_DENYNO, mode);
+		if (fd != -1)
+			rprintf(FINFO, "[%s] opened %s for shared write - file may change during sync\n", who_am_i(), pathname);
+		else if (verbose) {
+			int e = errno;
+			rsyserr(FINFO, errno, "do_open _sopen fallback failed for %s", pathname);
+			errno = e;
+		}
+
+	}
+	return fd;
+#endif
 }
 
 #ifdef HAVE_CHMOD
@@ -152,6 +194,9 @@
 	int code;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+
+	// rprintf(FINFO, "* [%s] do_chmod path %s requested mode %o %s(%u)\n", who_am_i(), path, mode, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	if (S_ISLNK(mode)) {
 #ifdef HAVE_LCHMOD
 		code = lchmod(path, mode & CHMOD_BITS);
@@ -164,10 +209,69 @@
 		attrList.commonattr = ATTR_CMN_ACCESSMASK;
 		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
 #else
-		code = 1;
+		code = 1;		// Can not set symlink
 #endif
 	} else
+#ifndef __OS2__
+		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+#else
+	{
+		ULONG attributes = 0;
+		if (os2_perms) {
+			// Unmap mode to recover native OS/2 attributes
+			// See map_os2_attributes
+			// If not readable by owner, hidden
+			if (~mode & S_IRUSR)
+				attributes |= FILE_HIDDEN;
+			// If readable by group, system
+			if (mode & S_IRGRP)
+				attributes |= FILE_SYSTEM;
+			// If writable by group, archived
+			if (mode & S_IWGRP)
+				attributes |= FILE_ARCHIVED;
+			// Reset group rw bits to match other rw bits - hack cough
+			if (mode & S_IROTH)
+				mode |= S_IRGRP;
+			else
+				mode &= ~S_IRGRP;
+			if (mode & S_IWOTH)
+				mode |= S_IWGRP;
+			else
+				mode &= ~S_IWGRP;
+		}
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+		if (!code && os2_perms) {
+			// Adjust native attributes not handled by chmod - system, hidden, archived
+			// Maybe libc will do this someday
+			// chmod already handles readonly
+			// Adjust attributes if any but archived set or if archived not set in requested attributes
+			FILESTATUS3 fs3;
+			APIRET apiret = DosQueryPathInfo((PCSZ)path,
+							 FIL_STANDARD,
+							 &fs3,
+							 sizeof(fs3));
+			// 26 Sep 09 SHL fixme perms - set code on failure - need map_apiret_errno()
+			if (apiret)
+				rprintf(FERROR, "[%s] DosQueryPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+			else {
+				ULONG m = attributes | (fs3.attrFile & ~(FILE_SYSTEM | FILE_HIDDEN | FILE_ARCHIVED));
+				if (m != fs3.attrFile) {
+					ULONG old_attrFile = fs3.attrFile;
+					fs3.attrFile = m;
+					apiret = DosSetPathInfo((PCSZ)path,
+								 FIL_STANDARD,
+								 &fs3, sizeof(fs3),
+								 0);
+					if (apiret)
+						rprintf(FERROR, "[%s] DosSetPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+					// 17 Sep 09 SHL os2_perms
+					else if (verbose > 1)
+						rprintf(FINFO, "[%s] changed %s attrFile from %lx to %lx (attributes %lx)\n", who_am_i(), path, old_attrFile, fs3.attrFile, attributes);	// 21 Jul 09 SHL
+				}
+			}
+		}
+	}
+#endif
 	if (code != 0 && (preserve_perms || preserve_executability))
 		return code;
 	return 0;
@@ -238,12 +342,55 @@
 #endif
 }
 
+#ifdef __OS2__
+
+/**
+ * Map native OS/2 attributes to something rsync can send
+ * See do_chmod for unmap logic
+ */
+
+static void map_os2_attributes(STRUCT_STAT *st)
+{
+	// If hidden, readable by none
+	if (st->st_attr & FILE_HIDDEN)
+		st->st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+	// If readonly, writable by none
+	if (st->st_attr & FILE_READONLY)
+		st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+
+	// Steal group bits for native attributes without obvious mappings - hack cough
+	// If system, readable by group
+	if (st->st_attr & FILE_SYSTEM)
+		st->st_mode |= S_IRGRP;
+	else
+		st->st_mode &= ~S_IRGRP;
+	// If archived, writable by group
+	if (st->st_attr & FILE_ARCHIVED)
+		st->st_mode |= S_IWGRP;
+	else
+		st->st_mode &= ~S_IWGRP;
+}
+
+#endif
+
 int do_stat(const char *fname, STRUCT_STAT *st)
 {
 #ifdef USE_STAT64_FUNCS
 	return stat64(fname, st);
 #else
+#ifndef __OS2__
 	return stat(fname, st);
+#else
+	int code;
+	code = stat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
@@ -253,7 +400,19 @@
 # ifdef USE_STAT64_FUNCS
 	return lstat64(fname, st);
 # else
+#ifndef __OS2__
 	return lstat(fname, st);
+#else
+	// 27 Apr 09 SHL map OS/2 permissions
+	int code = lstat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 # endif
 #else
 	return do_stat(fname, st);
@@ -265,7 +424,19 @@
 #ifdef USE_STAT64_FUNCS
 	return fstat64(fd, st);
 #else
+#ifndef __OS2__
 	return fstat(fd, st);
+#else
+	int code;
+	code = fstat(fd, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %u mode from %o to %o (st_attr %o)\n", who_am_i(), fd, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/util.c ./util.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/util.c	2009-03-03 08:57:42.000000000 -0800
+++ ./util.c	2009-10-14 09:18:48.000000000 -0700
@@ -23,6 +23,10 @@
 #include "rsync.h"
 #include "ifuncs.h"
 
+#ifdef __OS2__
+#include <os2emx.h>
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int module_id;
@@ -191,6 +195,10 @@
 	char *p;
 	int ret = 0;
 
+#ifdef __OS2__ // 06 Mar 09 SHL use drive_spec_width
+	fname += drive_spec_width(fname);		/* Bypass drive letter */
+#endif /* __OS2__ */
+
 	while (*fname == '/')
 		fname++;
 	while (strncmp(fname, "./", 2) == 0)
@@ -420,6 +428,8 @@
 {
 	int tries = 4;
 
+	// rprintf(FINFO, "* [%s] robust_rename %s->%s %s(%u)\n", who_am_i(), from, to, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	while (tries--) {
 		if (do_rename(from, to) == 0)
 			return 0;
@@ -444,6 +454,27 @@
 				return -2;
 			do_unlink(from);
 			return 1;
+#ifdef __OS2__ // 27 Apr 09 SHL
+		// libc rename semantics differs from linux
+		// clear readonly if this caused rename to fail
+		case EACCES:
+		{
+			STRUCT_STAT st;
+			int code;
+			if (verbose)
+				rprintf(FINFO, "[%s] robust_rename retrying %s after EACCES\n", who_am_i(), to);	// 22 Jul 09 SHL
+			code = do_stat(to, &st);
+			if (!code) {
+				// 27 Apr 09 SHL fixme to use st_mode when libc fixed
+				if (st.st_attr & FILE_READONLY) {
+					st.st_mode |= S_IWUSR;
+					code = do_chmod(to, st.st_mode);
+					if (!code)
+						break;	// Try again
+				}
+			}
+		}
+#endif
 		default:
 			return -1;
 		}
@@ -818,10 +849,18 @@
 {
 	char *limit = name - 1, *t = name, *f = name;
 	int anchored;
+#ifdef __OS2__
+	int drive_letter_adj;	// 0 if not, 2 if yes 15 Dec 08 SHL
+#endif
 
 	if (!name)
 		return 0;
 
+#ifdef __OS2__ // 06 Mar 09 SHL use drive_spec_width...
+	drive_letter_adj = drive_spec_width(name);
+	f += drive_letter_adj;			// Keep drive letter
+	t += drive_letter_adj;
+#endif /* __OS2__ */
 	if ((anchored = *f == '/') != 0) {
 		*t++ = *f++;
 #ifdef __CYGWIN__
@@ -869,10 +908,18 @@
 		while (*f && (*t++ = *f++) != '/') {}
 	}
 
+#ifndef __OS2__ // 06 Feb 09 SHL
 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 		t--;
 	if (t == name)
 		*t++ = '.';
+#else
+	if (t > name + anchored + drive_letter_adj && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
+		t--;
+	if (t == name + drive_letter_adj)
+		*t++ = '.';		// Ensure not empty
+#endif
+
 	*t = '\0';
 
 	return t - name;
@@ -906,14 +953,28 @@
 	char *start, *sanp;
 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 
+	// rprintf(FINFO, "* [%s] sanitize_path p %s %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 06 Feb 09 SHL
 	if (dest != p) {
 		int plen = strlen(p);
-		if (*p == '/') {
+		int drive_letter_adj = drive_spec_width(p);	// 0 if not, 2 if yes 15 Dec 08 SHL
+#ifndef __OS2__
+		if (*p == '/')
+#else // 06 Feb 09 SHL use is_abs_path...
+		if (!is_abs_path(p)) {
+			if (drive_letter_adj)
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 06 Feb 09 SHL
+		} else
+#endif
+		{
 			if (!rootdir)
 				rootdir = module_dir;
 			rlen = strlen(rootdir);
 			depth = 0;
+#ifndef __OS2__
 			p++;
+#else
+			p += drive_spec_width(p) + 1;
+#endif
 		}
 		if (dest) {
 			if (rlen + plen + 1 >= MAXPATHLEN)
@@ -922,8 +983,13 @@
 			out_of_memory("sanitize_path");
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
+#ifndef __OS2__
 			if (rlen > 1)
 				dest[rlen++] = '/';
+#else
+			if (rlen > 1 + drive_letter_adj)
+				dest[rlen++] = '/';
+#endif
 		}
 	}
 
@@ -967,6 +1033,20 @@
 		}
 		/* copy one component through next slash */
 		while (*p && (*sanp++ = *p++) != '/') {}
+#if 0 // 16 May 09 SHL fixme to be gone
+#ifndef __OS2__
+		while (*p && (*sanp++ = *p++) != '/') {}
+#else
+		while(*p) {
+			char c = *p++;
+			if (c == '\\')
+				c = '/';
+			*sanp++ = c;
+			if (c == '/')
+				break;
+		}
+#endif
+#endif
 	}
 	if (sanp == dest) {
 		/* ended up with nothing, so put in "." component */
@@ -974,16 +1054,23 @@
 	}
 	*sanp = '\0';
 
+	// rprintf(FINFO, "* [%s] sanitize_path dest %s %s(%u)\n", who_am_i(), dest, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
+
+	// 16 May 09 SHL  fixme to be gone
+	assert_no_dir_slashes(dest);
+
 	return dest;
 }
 
 /* Like chdir(), but it keeps track of the current directory (in the
  * global "curr_dir"), and ensures that the path size doesn't overflow.
- * Also cleans the path using the clean_fname() function. */
+ * Also cleans the path using the clean_fname() function.
+ * Returns 1 of change OK.  Otherwise 0 */
 int change_dir(const char *dir, int set_path_only)
 {
 	static int initialised;
 	unsigned int len;
+	// rprintf(FINFO, "* [%s] change_dir dir %s %s(%u)\n", who_am_i(), dir ? dir : "(null)", __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
 
 	if (!initialised) {
 		initialised = 1;
@@ -992,6 +1079,7 @@
 			exit_cleanup(RERR_FILESELECT);
 		}
 		curr_dir_len = strlen(curr_dir);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 	}
 
 	if (!dir)	/* this call was probably just to initialize */
@@ -1001,23 +1089,49 @@
 	if (len == 1 && *dir == '.')
 		return 1;
 
-	if (*dir == '/') {
+	// 06 Mar 09 SHL use is_abs_path
+	if (is_abs_path(dir)) {
+		// Absolute path
 		if (len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifndef __OS2__ // 28 Jul 08 SHL
 		if (!set_path_only && chdir(dir))
 			return 0;
 		memcpy(curr_dir, dir, len + 1);
+#else
+		if (!set_path_only) {
+			if (chdir(dir)) {
+				rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL
+				return 0;
+			}
+			if (drive_spec_width(dir) && _chdrive(*dir)) {
+				rprintf(FERROR, "[%s] change_dir _chdrive failed for dir %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL
+				return 0;
+			}
+		}
+		memcpy(curr_dir, dir, len + 1);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
+#endif
 	} else {
+		// Relative path
 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifdef __OS2__
+		if (drive_spec_width(dir)) {
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			errno = EINVAL;
+			return -1;
+		}
+#endif
 		curr_dir[curr_dir_len] = '/';
 		memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
 
 		if (!set_path_only && chdir(curr_dir)) {
+			rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 			curr_dir[curr_dir_len] = '\0';
 			return 0;
 		}
@@ -1042,12 +1156,15 @@
 {
 	unsigned int len;
 
-	if (*path != '/') { /* Make path absolute. */
+	// 06 Mar 09 SHL use is_abs_path
+	if (!is_abs_path(path)) { /* Make path absolute. */
 		int len = strlen(path);
+		if (drive_spec_width(path))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 28 Jul 08 SHL
 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
-		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
+		memcpy(curr_dir + curr_dir_len + 1, path + drive_spec_width(path), len + 1);
 		if (!(path = strdup(curr_dir)))
 			out_of_memory("normalize_path");
 		curr_dir[curr_dir_len] = '\0';
@@ -1078,9 +1195,14 @@
 	if (result)
 		free(result);
 
-	if (*fn == '/')
+	// 06 Mar 09 SHL use is_abs_path
+	if (is_abs_path(fn))
 		p1 = p2 = "";
 	else {
+#ifdef __OS2__
+		if (drive_spec_width(fn))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 06 Feb 09 SHL
+#endif
 		p1 = curr_dir + module_dirlen;
 		for (p2 = p1; *p2 == '/'; p2++) {}
 		if (*p2)
@@ -1109,6 +1231,9 @@
 
 	if ((fn = strrchr(fname, '/')) != NULL) {
 		fn++;
+		// 25 Sep 09 SHL fixme slashes - handle drive letter if needed
+		if (partial_dir && drive_spec_width(partial_dir))
+			rprintf(FINFO, "* [%s] partial_dir_fname partial_dir %s fname %s %s(%u)\n", who_am_i(), partial_dir, fname, __FILE__, __LINE__);	// 25 Sep 09 SHL debug slashes
 		if (*partial_dir != '/') {
 			int len = fn - fname;
 			strncpy(t, fname, len); /* safe */
@@ -1140,6 +1265,7 @@
 
 	if (fname != partial_fname)
 		return 1;
+	// 25 Sep 09 SHL fixme slashes?
 	if (!create && *partial_dir == '/')
 		return 1;
 	if (!(fn = strrchr(partial_fname, '/')))
@@ -1690,3 +1816,27 @@
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+#ifdef __OS2__ // 16 May 09 SHL added
+/* Convert OS/2 backslashes to unix forward slashes */
+void normalize_dir_slashes(char *path)
+{
+	char *p;
+	if (path && (p = strchr(path, '\\')) != 0) {
+		char ch;
+		*p++ = '/';
+		for (; (ch = *p) != 0; p++)
+		{
+			if (ch == '\\') *p = '/';
+		}
+	}
+}
+
+#if 1
+void assert_no_dir_slashes(char *path)
+{
+	if (path && strchr(path, '\\') != 0)
+		rprintf(FERROR, "[%s] unexpected backslash in path %s %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 06 Feb 09 SHL
+}
+#endif
+#endif // __OS2__
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-2009[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' I:/sla_dev2_browse/rsync/rsync-3.0.6/xattrs.c ./xattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.6/xattrs.c	2009-04-26 07:51:50.000000000 -0700
+++ ./xattrs.c	2009-10-14 09:55:20.000000000 -0700
@@ -110,6 +110,8 @@
 {
 	const rsync_xa *xa1 = x1;
 	const rsync_xa *xa2 = x2;
+	// rprintf(FINFO, "* [%s] rsync_xal_compare_names xa1.name %s xa2.name %s %s(%u)\n", who_am_i(), xa1->name, xa2->name, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
+
 	return strcmp(xa1->name, xa2->name);
 }
 
@@ -141,7 +143,9 @@
 				fname, arg);
 			return -1;
 		}
+		/* Expand buffer - get size */
 		list_len = sys_llistxattr(fname, NULL, 0);
+		/* Should not occur */
 		if (list_len < 0) {
 			arg = 0;
 			goto got_error;
@@ -240,9 +244,11 @@
 			 || (am_root < 0
 			  && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
 			   || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
-			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
+			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) {
+				rprintf(FINFO, "* [%s] rsync_xal_get skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
 				continue;
 		}
+		}
 
 		datum_len = name_len; /* Pass extra size to get_xattr_data() */
 		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -283,10 +289,12 @@
 {
 	sxp->xattr = new(item_list);
 	*sxp->xattr = empty_xattr;
+	// rprintf(FINFO, "* [%s] get_xattr fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
 	if (rsync_xal_get(fname, sxp->xattr) < 0) {
 		free_xattr(sxp);
 		return -1;
 	}
+	// rprintf(FINFO, "* [%s] get_xattr count %d %s(%u)\n", who_am_i(), sxp->xattr ? sxp->xattr->count : -1, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
 	return 0;
 }
 
@@ -459,11 +467,13 @@
 	snd_rxa = lst->items;
 	snd_cnt = lst->count;
 
+	// rprintf(FINFO, "* [%s] xattr_diff fname %s rec_cnt %u snd_cnt %u find_all %u %s(%u)\n", who_am_i(), file->basename, rec_cnt, snd_cnt, find_all, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
+
 	/* 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) {
 		if (!find_all)
-			return 1;
+			return 1;	// Say different
 		xattrs_equal = 0;
 	}
 
@@ -485,7 +495,7 @@
 		}
 		if (!same) {
 			if (!find_all)
-				return 1;
+				return 1;	// Say different
 			xattrs_equal = 0;
 		}
 
@@ -502,6 +512,8 @@
 	if (rec_cnt)
 		xattrs_equal = 0;
 
+	// rprintf(FINFO, "* [%s] xattr_diff xattrs_equal %u %s(%u)\n", who_am_i(), xattrs_equal, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
+
 	return !xattrs_equal;
 }
 
@@ -652,6 +664,8 @@
 		temp_xattr.count = 0;
 	}
 
+	// rprintf(FINFO, "* [%s] receive_xattr %s read count %u am_root %u %s(%u)\n", who_am_i(), file->basename, count, am_root, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
+
 	for (num = 1; num <= count; num++) {
 		char *ptr, *name;
 		rsync_xa *rxa;
@@ -698,12 +712,14 @@
 			memcpy(name, RSYNC_PREFIX, RPRE_LEN);
 		} else {
 			free(ptr);
+			rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
 			continue;
 		}
 #endif
 		/* No rsync.%FOO attributes are copied w/o 2 -X options. */
 		if (preserve_xattrs < 2 && name_len > RPRE_LEN
 		 && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
+			rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
 			free(ptr);
 			continue;
 		}
@@ -715,13 +731,17 @@
 		rxa->num = num;
 	}
 
-	if (need_sort && count > 1)
-		qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
+	// rprintf(FINFO, "* [%s] receive_xattr temp_xattr.items %p temp_xattr.count %u %s(%u)\n", who_am_i(), temp_xattr.items, temp_xattr.count, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
+
+	// 28 Jul 08 SHL sort number used not number malloced
+	if (need_sort && temp_xattr.count > 1)
+		qsort(temp_xattr.items, temp_xattr.count, sizeof (rsync_xa), rsync_xal_compare_names);
 
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
 
 	F_XATTR(file) = ndx;
+	// rprintf(FINFO, "* [%s] receive_xattr %s ndx %u count %d %s(%u)\n", who_am_i(), file->basename, ndx, rsync_xal_l.count, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
 }
 
 /* Turn the xattr data in stat_x into cached xattr data, setting the index

2009-10-15 10:55

 

rsync-3.0.6-20091014-shl.zip (295,869 bytes)

Steven Levine

2009-10-15 10:55

manager   ~0001420

The rsync-3.0.6-20091014-shl patch set corrects xattrs support to a remote server and optimizes some directory operations.

Steven Levine

2010-04-14 04:29

manager  

rsync-3.0.7-20100413-shl.diff (100,279 bytes)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/Makefile.in ./Makefile.in
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/Makefile.in	2009-12-12 17:22:42.000000000 -0800
+++ ./Makefile.in	2010-04-13 11:04:48.000000000 -0700
@@ -12,6 +12,7 @@
 CFLAGS=@CFLAGS@
 CPPFLAGS=@CPPFLAGS@
 EXEEXT=@EXEEXT@
+# 14 Jun 09 SHL fixme to do bldlevel strings
 LDFLAGS=@LDFLAGS@
 
 INSTALLCMD=@INSTALL@
@@ -42,7 +43,8 @@
 	popt/popthelp.o popt/poptparse.o
 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
 
-TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
+# 25 Mar 10 SHL
+TLS_OBJ = tls.o t_stub.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
@@ -68,6 +70,10 @@
 	-mkdir -p ${DESTDIR}${mandir}/man5
 	if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
 	if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
+	if test -f readme.os2; then ${INSTALLMAN} -m 644 readme.os2 ${DESTDIR}${prefix}; fi
+	if test -f readme.shl; then ${INSTALLMAN} -m 644 readme.shl ${DESTDIR}${prefix}; fi
+	if test -f rsync.map; then ${INSTALLMAN} -m 644 rsync.map ${DESTDIR}${prefix}; fi
+	if test -s "${DIFFFILE}"; then if test -f ${DIFFFILE}; then ${INSTALLMAN} -m 644 ${DIFFFILE} ${DESTDIR}${prefix}; fi; fi
 
 install-strip:
 	$(MAKE) INSTALL_STRIP='-s' install
@@ -107,11 +113,11 @@
 getfsdev$(EXEEXT): getfsdev.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
 
-TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
+TRIMSLASH_OBJ = trimslash.o t_stub.o syscall.o lib/compat.o lib/snprintf.o
 trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
-T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
+T_UNSAFE_OBJ = t_unsafe.o t_stub.o syscall.o util.o lib/compat.o lib/snprintf.o lib/wildmatch.o
 t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
 
@@ -189,9 +195,10 @@
 	yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
 	-$(srcdir)/tweak_manpage rsyncd.conf.5
 
+# 06 Feb 09 SHL clean maps
 clean: cleantests
 	rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
-		rounding rounding.h *.old
+		rounding rounding.h *.old rsync.map rounding.map
 
 cleantests:
 	rm -rf ./testtmp*
@@ -243,11 +250,13 @@
 wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
 
+# 25 Mar 10 SHL
+
 testsuite/chown-fake.test:
-	ln -s chown.test $(srcdir)/testsuite/chown-fake.test
+	echo ln -s chown.test $(srcdir)/testsuite/chown-fake.test
 
 testsuite/devices-fake.test:
-	ln -s devices.test $(srcdir)/testsuite/devices-fake.test
+	echo ln -s devices.test $(srcdir)/testsuite/devices-fake.test
 
 # This does *not* depend on building or installing: you can use it to
 # check a version installed from a binary or some other source tree,
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/access.c ./access.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/access.c	2009-01-17 13:41:34.000000000 -0800
+++ ./access.c	2010-03-25 15:21:32.000000000 -0700
@@ -100,7 +100,9 @@
 	hints.ai_flags = AI_NUMERICHOST;
 #endif
 
-	if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	// if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	if ((gai = getaddrinfo(addr, NULL, &hints, &resa)) != 0) {			// 27 Jul 08 SHL debug
+		// rprintf(FINFO, "* [%s] match_address gai %d %s(%u)\n", who_am_i(), gai, __FILE__, __LINE__);	// 28 Jul 08 SHL debug addrinfo
 		if (p)
 			*p = '/';
 		return 0;
@@ -110,8 +112,8 @@
 	if (p)
 		*p++ = '/';
 	if (gai != 0) {
-		rprintf(FLOG, "error matching address %s: %s\n",
-			tok, gai_strerror(gai));
+		rprintf(FLOG, "* error matching address %s: %s (%d)\n",
+			tok, gai_strerror(gai), gai);
 		freeaddrinfo(resa);
 		return 0;
 	}
@@ -222,7 +224,11 @@
 	if (host)
 		strlower(host);
 
+	// rprintf(FINFO, "* [%s] access_match %s (%s) %s(%u)\n", who_am_i(), host, addr, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
+
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+
+		// rprintf(FINFO, "* [%s] access_match tok %s %s(%u)\n", who_am_i(), tok, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
 		if (match_hostname(host, tok) || match_address(addr, tok)) {
 			free(list2);
 			return 1;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/authenticate.c ./authenticate.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/authenticate.c	2009-01-17 13:41:34.000000000 -0800
+++ ./authenticate.c	2010-03-25 15:21:32.000000000 -0700
@@ -96,7 +96,9 @@
 	if (do_stat(fname, &st) == -1) {
 		rsyserr(FLOG, errno, "stat(%s)", fname);
 		ok = 0;
-	} else if (lp_strict_modes(module)) {
+	}
+#ifndef __OS2__	 /* 29 Jun 09 SHL suppress unsupported mode checks */
+	else if (lp_strict_modes(module)) {
 		if ((st.st_mode & 06) != 0) {
 			rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
 			ok = 0;
@@ -105,6 +107,7 @@
 			ok = 0;
 		}
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		rprintf(FLOG, "continuing without secrets file\n");
 		close(fd);
@@ -173,13 +176,16 @@
 	if (do_stat(filename, &st) == -1) {
 		rsyserr(FWARNING, errno, "stat(%s)", filename);
 		ok = 0;
-	} else if ((st.st_mode & 06) != 0) {
+	}
+#ifndef __OS2__	 /* 12 Jun 08 SHL suppress unsupported mode checks */
+	else if ((st.st_mode & 06) != 0) {
 		rprintf(FWARNING, "password file must not be other-accessible\n");
 		ok = 0;
 	} else if (MY_UID() == 0 && st.st_uid != 0) {
 		rprintf(FWARNING, "password file must be owned by root when running as root\n");
 		ok = 0;
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		close(fd);
 		rprintf(FWARNING, "continuing without password file\n");
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/clientname.c ./clientname.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/clientname.c	2009-01-17 13:41:34.000000000 -0800
+++ ./clientname.c	2010-03-25 15:21:32.000000000 -0700
@@ -95,8 +95,10 @@
 	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
-	if (initialised)
+	if (initialised) {
+		// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		return name_buf;
+	}
 
 	strlcpy(name_buf, default_name, sizeof name_buf);
 	initialised = 1;
@@ -148,6 +150,8 @@
 			port_buf, sizeof port_buf) == 0)
 		check_name(fd, &ss, name_buf, sizeof name_buf);
 
+	// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
+
 	return name_buf;
 }
 
@@ -216,14 +220,17 @@
 	int name_err;
 
 	/* reverse lookup */
+	// rprintf(FINFO, "* [%s] lookup_name %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
 			       name_buf, name_buf_size,
 			       port_buf, port_buf_size,
 			       NI_NAMEREQD | NI_NUMERICSERV);
 	if (name_err != 0) {
 		strlcpy(name_buf, default_name, name_buf_size);
-		rprintf(FLOG, "name lookup failed for %s: %s\n",
-			client_addr(fd), gai_strerror(name_err));
+		// rprintf(FINFO, "name lookup failed for %s: %s\n",
+		//	client_addr(fd), gai_strerror(name_err));
+		rprintf(FLOG, "lookup_name failed for %s: %s (%d) at %s(%u) [%s]\n",	// 27 Jul 08 SHL debug
+			client_addr(fd), gai_strerror(name_err), name_err, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL
 		return name_err;
 	}
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/clientserver.c ./clientserver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/clientserver.c	2009-12-12 22:43:50.000000000 -0800
+++ ./clientserver.c	2010-03-25 15:21:32.000000000 -0700
@@ -426,6 +426,8 @@
 	iconv_opt = NULL;
 #endif
 
+	if (verbose)
+		rprintf(FINFO, "[%s] rsync_module addr:host is %s:%s\n", who_am_i(), addr, host);	// 28 Jul 08 SHL
 	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
 		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
 			name, host, addr);
@@ -479,6 +481,7 @@
 
 	am_root = (MY_UID() == 0);
 
+#ifndef __OS2__
 	if (am_root) {
 		p = lp_uid(i);
 		if (!name_to_uid(p, &uid)) {
@@ -501,6 +504,7 @@
 		}
 	}
 
+#endif
 	/* TODO: If we're not root, but the configuration requests
 	 * that we change to some uid other than the current one, then
 	 * log a warning. */
@@ -509,6 +513,7 @@
 	 * supplementary groups. */
 
 	module_dir = lp_path(i);
+	// rprintf(FINFO, "* [%s] module_dir %s %s(%u)\n", who_am_i(), module_dir, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 	if (use_chroot) {
 		if ((p = strstr(module_dir, "/./")) != NULL) {
 			*p = '\0'; /* Temporary... */
@@ -531,6 +536,7 @@
 		if (!(module_chdir = normalize_path(module_dir, False, &module_dirlen)))
 			return path_failure(f_out, module_dir, False);
 		full_module_path = module_dir = module_chdir;
+		// rprintf(FINFO, "* [%s] full_module_path %s %s(%u)\n", who_am_i(), full_module_path, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 	}
 
 	if (module_dirlen == 1) {
@@ -677,8 +683,11 @@
 		module_chdir = module_dir;
 	}
 
-	if (!change_dir(module_chdir, CD_NORMAL))
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+		// rsyserr(FERROR, errno, "[%s] chdir %s failed at %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__);	// 15 Dec 08 SHL debug
+		// rprintf(FINFO, "* [%s] chdir module_chdir %s failed %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 		return path_failure(f_out, module_chdir, True);
+	}
 	if (module_dirlen || !use_chroot)
 		sanitize_paths = 1;
 
@@ -993,6 +1002,7 @@
 	close(fd);
 }
 
+#ifndef __OS2__
 /* Become a daemon, discarding the controlling terminal. */
 static void become_daemon(void)
 {
@@ -1026,6 +1036,7 @@
 		open("/dev/null", O_RDWR);
 	}
 }
+#endif // __OS2__
 
 int daemon_main(void)
 {
@@ -1048,10 +1059,14 @@
 		exit_cleanup(RERR_SYNTAX);
 	}
 
+#ifndef __OS2__
 	if (no_detach)
 		create_pid_file();
 	else
 		become_daemon();
+#else
+	create_pid_file();
+#endif
 
 	if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
 		rsync_port = RSYNC_PORT;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/compat.c ./compat.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/compat.c	2009-12-21 14:40:40.000000000 -0800
+++ ./compat.c	2010-03-25 15:21:32.000000000 -0700
@@ -200,11 +200,12 @@
 			exit_cleanup(RERR_PROTOCOL);
 		}
 		if (preserve_xattrs && !local_server) {
-			rprintf(FERROR,
-			    "--xattrs requires protocol 30 or higher"
+		  	preserve_xattrs = 0;	// 06 Feb 09 SHL force off for old servers
+			rprintf(FWARNING,
+			    "--xattrs requires protocol 30 or higher - option disabled"
 			    " (negotiated %d).\n",
 			    protocol_version);
-			exit_cleanup(RERR_PROTOCOL);
+			// exit_cleanup(RERR_PROTOCOL);	// 06 Feb 09 SHL
 		}
 	}
 
@@ -296,6 +297,7 @@
 	if (need_unsorted_flist && (!am_sender || inc_recurse))
 		unsort_ndx = ++file_extra_cnt;
 
+	// 16 Feb 09 SHL fixme slashes?
 	if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
 		int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
 		if (!am_sender || protocol_version >= 30)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/configure.sh ./configure.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/configure.sh	2009-12-31 13:15:44.000000000 -0800
+++ ./configure.sh	2010-03-25 15:21:32.000000000 -0700
@@ -69,6 +69,8 @@
   as_echo='sh -c $as_echo_body as_echo'
 fi
 
+# 18 Jun 09 SHL fixme to not be broken - 3.0.5 worked - maybe autoconf 2.6.3 broke it
+
 # The user is always right.
 if test "${PATH_SEPARATOR+set}" != set; then
   PATH_SEPARATOR=:
@@ -2088,6 +2090,7 @@
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
+  echo SHL $as_dir
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     $as_echo "PATH: $as_dir"
@@ -8333,6 +8336,15 @@
 	$as_echo "#define SUPPORT_XATTRS 1" >>confdefs.h
 
 	;;
+    *os2*)
+	{ echo "$as_me:$LINENO: result: Using OS/2 extattrs" >&5
+echo "${ECHO_T}Using OS/2 extattrs" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_XATTRS 1
+_ACEOF
+
+	;;
+
     *)
 	if test x"$enable_xattr_support" = x"yes"; then
 	    as_fn_error "Failed to find extended attribute support" "$LINENO" 5
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/exclude.c ./exclude.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/exclude.c	2009-12-30 12:25:32.000000000 -0800
+++ ./exclude.c	2010-03-25 15:21:32.000000000 -0700
@@ -298,7 +298,7 @@
 	unsigned int fn_len;
 
 	if (!parent_dirscan && *merge_file != '/') {
-		/* Return the name unchanged it doesn't have any slashes. */
+		/* Return the name unchanged if it doesn't have any slashes. */
 		if (len_ptr) {
 			const char *p = merge_file + *len_ptr;
 			while (--p > merge_file && *p != '/') {}
@@ -310,6 +310,7 @@
 			return (char *)merge_file;
 	}
 
+	// 16 Feb 09 SHL fixme slash
 	fn = *merge_file == '/' ? buf : tmpbuf;
 	if (sanitize_paths) {
 		const char *r = prefix_skip ? "/" : NULL;
@@ -351,6 +352,7 @@
 void set_filter_dir(const char *dir, unsigned int dirlen)
 {
 	unsigned int len;
+	// 16 Feb 09 SHL fixme slash?
 	if (*dir != '/') {
 		memcpy(dirbuf, curr_dir, curr_dir_len);
 		dirbuf[curr_dir_len] = '/';
@@ -548,6 +550,7 @@
 	int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
 	char *p, *pattern = ex->pattern;
 	const char *strings[16]; /* more than enough */
+	// 16 Feb 09 SHL fixme slash?
 	const char *name = fname + (*fname == '/');
 
 	if (!*name)
@@ -605,8 +608,15 @@
 		if (litmatch_array(pattern, strings, slash_handling))
 			return ret_match;
 	} else if (anchored_match) {
+#ifndef __OS2__
 		if (strcmp(name, pattern) == 0)
 			return ret_match;
+#else
+		// 18 Oct 09 SHL Case insensitive
+		if (stricmp(name, pattern) == 0)
+			return ret_match;
+#endif
+
 	} else {
 		int l1 = strlen(name);
 		int l2 = strlen(pattern);
@@ -988,6 +998,17 @@
 				cp = ".cvsignore";
 				pat_len = 10;
 			}
+#ifdef __OS2__
+			else {
+				// 19 Oct 09 SHL normalize
+				char ch;
+				p = cp + pat_len;
+				ch = *p;
+				normalize_dir_slashes((char *)cp);	// Hack cough - override const
+				*(char *)p = ch;
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len, cp, strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
+			}
+#endif
 			len = pat_len;
 			if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
 				const char *name = cp + len;
@@ -998,6 +1019,8 @@
 				len = pat_len;
 			}
 			if (new_mflags & MATCHFLG_PERDIR_MERGE) {
+				// 19 Oct 09 SHL fixme to complain if have drive letter?
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 				if (parent_dirscan) {
 					if (!(p = parse_merge_name(cp, &len,
 								module_dirlen)))
@@ -1014,6 +1037,7 @@
 			}
 		}
 
+		// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 		add_rule(listp, cp, pat_len, new_mflags, xflags);
 
 		if (new_mflags & MATCHFLG_CVS_IGNORE
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/flist.c ./flist.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/flist.c	2009-12-21 14:40:40.000000000 -0800
+++ ./flist.c	2010-03-25 15:21:32.000000000 -0700
@@ -349,8 +349,19 @@
 {
 	if (dirlen < 0) {
 		char *cpy = strdup(dir);
+#ifndef __OS2__ // 06 Mar 09 SHL use is_abs_path...
 		if (*cpy != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (!is_abs_path(cpy)) {
+			if (drive_spec_width(cpy))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), cpy, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+	        }
+#endif
 		if (path_is_daemon_excluded(cpy, 0))
 			goto chdir_error;
 		dir = cpy;
@@ -364,8 +375,19 @@
 				dirlen = strlen(dir);
 		} else if (pathname == dir)
 			return 1;
+#ifndef __OS2__ // 06 Mar 09 SHL use is_abs_path...
 		if (dir && *dir != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (dir && !is_abs_path(dir)) {
+			if (drive_spec_width(dir))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+		}
+#endif
 	}
 
 	pathname = dir;
@@ -378,8 +400,13 @@
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
 		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
-		if (dir != orig_dir)
-			change_dir(orig_dir, CD_NORMAL);
+		rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
+		if (dir != orig_dir) {
+			if (!change_dir(orig_dir, CD_NORMAL)) {
+				if (verbose > 1)
+					rprintf(FLOG, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+		}
 		pathname = NULL;
 		pathname_len = 0;
 		return 0;
@@ -1329,6 +1356,8 @@
 {
 	struct file_struct *file;
 
+	// rprintf(FINFO, "* [%s] send_file_name fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+
 	file = make_file(fname, flist, stp, flags, filter_level);
 	if (!file)
 		return NULL;
@@ -1971,6 +2000,7 @@
 	int len, dirlen;
 	STRUCT_STAT st;
 	char *p, *dir;
+	static char* the_root = "/";
 	struct file_list *flist;
 	struct timeval start_tv, end_tv;
 	int64 start_write;
@@ -2014,6 +2044,7 @@
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
 			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
 				full_fname(argv[0]));
+			rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), argv[0], __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 		use_ff_fd = 1;
@@ -2033,17 +2064,22 @@
 			if (argc-- == 0)
 				break;
 			strlcpy(fbuf, *argv++, MAXPATHLEN);
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 			if (sanitize_paths)
 				sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Feb 09 SHL debug xattrs
+
 		len = strlen(fbuf);
 		if (relative_paths) {
 			/* We clean up fbuf below. */
 			name_type = NORMAL_NAME;
 		} else if (!len || fbuf[len - 1] == '/') {
-			if (len == 2 && fbuf[0] == '.') {
-				/* Turn "./" into just "." rather than "./." */
+			// Empty path or trailing /
+			// 06 Mar 09 SHL
+			if (len == 2 + drive_spec_width(fbuf) && fbuf[drive_spec_width(fbuf)] == '.') {
+				/* Turn trailing "./" into just "." rather than "./." */
 				fbuf[--len] = '\0';
 			} else {
 				if (len + 1 >= MAXPATHLEN)
@@ -2054,6 +2090,7 @@
 			name_type = DOTDIR_NAME;
 		} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
 		    && (len == 2 || fbuf[len-3] == '/')) {
+			// Got ..  or trailing /..
 			if (len + 2 >= MAXPATHLEN)
 				overflow_exit("send_file_list");
 			fbuf[len++] = '/';
@@ -2072,18 +2109,39 @@
 			if (p) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 06 Mar 09 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else
 					dir = fbuf;
-				len -= p - fbuf + 1;
-				fn = p + 1;
+				fn = p + 1;		// Point at filename part
+				len -= fn - fbuf;	//  fn length
+				// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			} else
 				fn = fbuf;
 		} else {
 			if ((p = strstr(fbuf, "/./")) != NULL) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 06 Mar 09 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else {
 					dir = fbuf;
 					clean_fname(dir, 0);
@@ -2105,6 +2163,8 @@
 			}
 			len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
 					    | CFN_DROP_TRAILING_DOT_DIR);
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+			// 06 Mar 09 SHL fixme?
 			if (len == 1) {
 				if (fn[0] == '/') {
 					fn = "/.";
@@ -2137,6 +2197,8 @@
 			name_type = DOTDIR_NAME;
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list dir %s fn %s len %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug xattrs
+
 		dirlen = dir ? strlen(dir) : 0;
 		if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
 			if (!change_pathname(NULL, dir, -dirlen))
@@ -2146,9 +2208,16 @@
 		} else if (!change_pathname(NULL, lastdir, lastdir_len))
 			continue;
 
+		// 06 Mar 09 SHL
+		if (dir && dir != the_root && dir != fbuf)
+			free(dir);	// We allocated it
+
 		if (fn != fbuf)
 			memmove(fbuf, fn, len + 1);
 
+		// rprintf(FINFO, "* [%s] send_file_list fn %s %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s len %d %s(%u)\n", who_am_i(), fbuf, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+
 		if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
@@ -2169,12 +2238,14 @@
 		}
 
 		if (inc_recurse && relative_paths && *fbuf) {
+			// 06 Mar 09 SHL fixme
 			if ((p = strchr(fbuf+1, '/')) != NULL) {
 				if (p - fbuf == 1 && *fbuf == '.') {
 					if ((fn = strchr(p+1, '/')) != NULL)
 						p = fn;
 				} else
 					fn = p;
+			        // rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 				send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
 				if (fn == p)
 					continue;
@@ -2182,6 +2253,7 @@
 		} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
 			/* Send the implied directories at the start of the
 			 * source spec, so we get their permissions right. */
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
 		}
 
@@ -2190,6 +2262,7 @@
 
 		if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
 			struct file_struct *file;
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			file = send_file_name(f, flist, fbuf, &st,
 					      FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
 					      NO_FILTERS);
@@ -2205,9 +2278,11 @@
 				}
 			} else
 				send_if_directory(f, flist, file, fbuf, len, flags);
-		} else
+		} else {
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
 	}
+	}
 
 	gettimeofday(&end_tv, NULL);
 	stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/generator.c ./generator.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/generator.c	2009-12-23 11:36:26.000000000 -0800
+++ ./generator.c	2010-04-10 16:04:18.000000000 -0700
@@ -98,6 +98,10 @@
 extern int backup_suffix_len;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+// 14 Oct 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 int ignore_perishable = 0;
 int non_perishable_cnt = 0;
@@ -272,6 +276,7 @@
 	}
 
 	p = fname + dlen;
+	// 16 Feb 09 SHL fixme slash?
 	if (dlen != 1 || *fname != '/')
 		*p++ = '/';
 	remainder = MAXPATHLEN - (p - fname);
@@ -590,7 +595,7 @@
 	} else
 #endif
 	if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
-		return 0;
+		return 0;		// Changed
 
 	if (preserve_perms) {
 		if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
@@ -622,7 +627,7 @@
 	}
 #endif
 
-	return 1;
+	return 1;			// No change
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -646,19 +651,28 @@
 		} else if (keep_time
 		 ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
 		 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
-		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s file->modtime %u sxp->st.st_mtime %u %s(%u)\n", who_am_i(), fnamecmp, file->modtime, sxp->st.st_mtime, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme times
+			if (verbose > 1)
+				rprintf(FINFO, "[%s] %s time differs file->modtime %u sxp->st.st_mtime %u\n", who_am_i(), fnamecmp, file->modtime, sxp->st.st_mtime);
 			iflags |= ITEM_REPORT_TIME;
+		}
+
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
 		} else
 #endif
 		if (preserve_perms) {
-			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) {
+				// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
 				iflags |= ITEM_REPORT_PERMS;
+			}
 		} else if (preserve_executability
-		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0))) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
 			iflags |= ITEM_REPORT_PERMS;
+		 }
 		if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 			iflags |= ITEM_REPORT_OWNER;
 		if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
@@ -1472,8 +1486,10 @@
 			}
 		}
 #ifdef SUPPORT_XATTRS
-		if (preserve_xattrs && statret == 1)
+		if (preserve_xattrs && statret == 1) {
+			rprintf(FINFO, "* [%s] receive_generator running copy_xattrs fnamecmpbuf %s fname %s %s(%u)\n", who_am_i(), fnamecmpbuf, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
 			copy_xattrs(fnamecmpbuf, fname);
+		}
 #endif
 		if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
 		    && verbose && code != FNONE && f_out != -1)
@@ -1492,6 +1508,17 @@
 			}
 			need_retouch_dir_perms = 1;
 		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If source directory not archived (i.e. not writable by group)
+		// may need to touch up after file operations complete
+		// see map_os2_attributes
+		if (!need_retouch_dir_perms && os2_perms &&
+		    ~file->mode & S_IWGRP) {
+			// rprintf(FINFO, "* [%s] recv_generator dir %s needs retouch mode %o %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 14 Oct 09 SHL fixme dir perms
+			need_retouch_dir_perms = 1;
+		}
+#endif
 #endif
 
 		if (real_ret != 0 && one_file_system)
@@ -1511,7 +1538,7 @@
 				change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
 		}
 		goto cleanup;
-	}
+	} // is_dir
 
 	/* If we're not preserving permissions, change the file-list's
 	 * mode based on the local permissions and some heuristics. */
@@ -2042,10 +2069,18 @@
 	} else
 		start = end = ndx;
 
+	// rprintf(FINFO, "* [%s] touch_up_dirs start %u end %u %s(%u)\n", who_am_i(), start, end,  __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
+
 	/* Fix any directory permissions that were modified during the
 	 * transfer and/or re-set any tweaked modified-time values. */
 	for (i = start; i <= end; i++, counter++) {
+		// 23 Mar 10 SHL overcome xattrs generated by libc chmod
+#ifdef __OS2__
+		int need_xattrs_set = 0;
+#endif
 		file = flist->files[i];
+		// fname = f_name(file, NULL); // 14 Oct 09 SHL debug dir perms
+		// rprintf(FINFO, "* [%s] touch_up_dirs dir %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 		if (!S_ISDIR(file->mode)
 		 || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))
 			continue;
@@ -2056,18 +2091,80 @@
 		}
 		/* Be sure not to retouch permissions with --fake-super. */
 		fix_dir_perms = !am_root && !(file->mode & S_IWUSR);
+#ifndef __OS2__
 		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
 		 || !(need_retouch_dir_times || fix_dir_perms))
 			continue;
+else // __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived on (i.e. writable by group)
+		// See map_os2_attributes
+		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
+		 || !(need_retouch_dir_times || fix_dir_perms
+		      || !os2_perms || (~file->mode & S_IWGRP)))
+			continue;
+#endif
 		fname = f_name(file, NULL);
-		if (fix_dir_perms)
+#ifdef __OS2__
+		// 14 Oct 09 SHL Need to set time before clearing archive bit
+		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);
+		}
+#endif
+		if (fix_dir_perms) {
 			do_chmod(fname, file->mode);
+#ifdef __OS2__
+			// 25 Mar 10 SHL fixme to be sure can update EAs after setting read-only
+			// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWUSR fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			need_xattrs_set = preserve_xattrs;
+#endif
+		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived off (i.e. not writable by group)
+		// See map_os2_attributes
+		// Other os/2 perms should already be OK
+		// There is no way to know for sure if directory was modified so we check
+		else if (os2_perms && ~file->mode & S_IWGRP) {
+			STRUCT_STAT st;
+			if (link_stat(fname, &st, 0) == 0 &&
+			    ((file->mode ^ st.st_mode) & S_IWGRP)) {
+				// rprintf(FINFO, "* [%s] touch_up_dirs chmod(%s, 0%o) %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
+				do_chmod(fname, file->mode);
+				// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+				// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWGRP(archive) fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+				need_xattrs_set = need_xattrs_set || preserve_xattrs;
+			}
+		}
+#endif
+#ifndef __OS2__
 		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);
 		}
+#endif
+#ifdef __OS2__
+		if (need_xattrs_set) {
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			stat_x sx;
+			// rprintf(FINFO, "* [%s] touch_up_dirs doing set_xattr for %s %s %s(%u)\n", who_am_i(), fname, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			if (verbose > 2)
+				rprintf(FINFO, "%s removing EAs generated by libc chmod %s\n", who_am_i(), fname);
+			memset(&sx, 0, sizeof(stat_x));
+			// Should not need to provide target item list to set_xattr
+			// link_stat(fname, &sx.st, 0);
+			// sx.xattr = new(item_list);
+			// *sxp.xattr = empty_xattr;
+			set_xattr(fname, file, fname, &sx);
+			// free_xattr(&sx);
+		}
+#endif
 		if (counter >= loopchk_limit) {
 			if (allowed_lull)
 				maybe_send_keepalive();
@@ -2075,7 +2172,7 @@
 				maybe_flush_socket(0);
 			counter = 0;
 		}
-	}
+	} // for
 }
 
 void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/getaddrinfo.c ./lib/getaddrinfo.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/getaddrinfo.c	2009-12-12 17:20:34.000000000 -0800
+++ ./lib/getaddrinfo.c	2010-03-25 15:21:32.000000000 -0700
@@ -403,12 +403,16 @@
 	int ret = -1;
 	char *p = NULL;
 
+	// rprintf(FINFO, "* [%s] gethostnameinfo NI_NUMERICHOST %u %s(%u)\n", who_am_i(), flags & NI_NUMERICHOST, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	if (!(flags & NI_NUMERICHOST)) {
+		// rprintf(FINFO, "* [%s] gethostnameinfo %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		struct hostent *hp = gethostbyaddr(
 				(void *)&((struct sockaddr_in *)sa)->sin_addr,
 				sizeof (struct in_addr),
 				sa->sa_family);
+		// rprintf(FINFO, "* [%s] gethostnameinfo hp %p %s(%u)\n", who_am_i(), hp, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		ret = check_hostent_err(hp);
+		// rprintf(FINFO, "* [%s] ret %d %s(%u)\n", who_am_i(), ret, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (ret == 0) {
 			/* Name looked up successfully. */
 			ret = snprintf(node, nodelen, "%s", hp->h_name);
@@ -424,6 +428,7 @@
 			return 0;
 		}
 
+		// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (flags & NI_NAMEREQD) {
 			/* If we require a name and didn't get one,
 			 * automatically fail. */
@@ -431,6 +436,7 @@
 		}
 		/* Otherwise just fall into the numeric host code... */
 	}
+	// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
 	ret = snprintf(node, nodelen, "%s", p);
 	if (ret < 0 || (size_t)ret >= nodelen) {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/sysxattrs.c ./lib/sysxattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/sysxattrs.c	2008-03-01 12:01:40.000000000 -0800
+++ ./lib/sysxattrs.c	2010-03-25 15:21:32.000000000 -0700
@@ -126,6 +126,336 @@
 	return len;
 }
 
+#elif defined(__OS2__)
+
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+
+static void map_os2_apiret(APIRET rc)
+{
+	switch (rc) {
+	case ERROR_SHARING_VIOLATION:
+		errno = EACCES;
+		break;
+	case 0:
+		// Should not have been called - try to do no harm
+		break;
+	default:
+		// 31 Jul 09 SHL fixme to map better
+		// if (verbose > 2)
+		rprintf(FINFO, "[%s] can not map OS/2 error %lu to errno\n", who_am_i(), rc);	// 31 Jul 09 SHL
+		/* Ensure non-zero */
+		if (!errno)
+			errno = EINVAL;
+
+	}
+}
+
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+	return unisetxattr (path, 0, name, value, size, 0);
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	EAOP2       eaop2 = {0,0,0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+	pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;
+	do {
+		if (path) {
+			rc = DosQueryPathInfo(path, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryPathInfo(%s, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] %s requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), path, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		else {
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryFileInfo(%u, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] handle %d requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), file, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		if (rc)
+			break;
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0) {
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value) {
+			if ((size_t)rc > size) {
+				errno = ERANGE;
+				rc = -1;
+			}
+			else {
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+		free(pgea2list);
+	if (pgea2list)
+		free(pfea2list);
+
+	return rc;
+}
+
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat;
+	if (!path && !file) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (path) {
+		rc = DosQueryPathInfo(path, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryPathInfo(%s, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] %s reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), path, stat.cbList);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryFilInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] handle %d reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), file, stat.cbList);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	if (stat.cbList <= 4) {
+		// NO ea
+		return 0;
+	}
+	//YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
+	buf = (char *)_tmalloc(stat.cbList * 2);
+	// 19 Sep 09 SHL was trapping on large copies
+	if (!buf) {
+		rprintf(FERROR, "out of memory allocating %lu at %s(%u)\n", stat.cbList * 2, __FILE__, __LINE__);	// 19 Sep 09 SHL fixme gone debug
+		return -1;
+	}
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc) {
+		rprintf(FERROR, "[%s] unilistxattr DosEnumAttribute failed with error %u at %s(%u)\n", who_am_i(), rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		_tfree(buf);
+		map_os2_apiret(rc);	// 31 Jul 09 SHL moved here to ensure errno returned
+		return -1;
+	}
+	else if (verbose > 2) {
+		if (path)
+			rprintf(FINFO, "[%s] %s has %lu DosEnumAttribute items\n", who_am_i(), path, ulCount);	// 28 Jul 08 SHL
+		else
+			rprintf(FINFO, "[%s] handle %d has %lu DosEnumAttribute items\n", who_am_i(), file, ulCount);	// 28 Jul 08 SHL
+	}
+	if (ulCount > 0) {
+		for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset)) {
+			if (pfea->cbName > 0) {
+				gotsize += pfea->cbName + 1;
+				// Avoid overflow
+				if (p && (size_t)gotsize <= size) {
+					pfea->szName[pfea->cbName] = 0;
+					strcpy(p, pfea->szName);
+					p += strlen(p) + 1;
+				}
+			}
+			if (!pfea->oNextEntryOffset)
+				break;
+		}
+	}
+	_tfree(buf);
+	if ((size_t)gotsize > size) {
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	if (verbose > 2)
+		rprintf(FINFO, "[%s] returning %ld EA list bytes\n", who_am_i(), (unsigned long)gotsize);	// 28 Jul 08 SHL
+	return gotsize;
+}
+
+int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0,0,0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosFileInfo(%u, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0,0,0};
+	PFEA2LIST   pfea2list = NULL;
+	// char * p;			// 17 May 09 SHL  fixme
+
+	if ((!path && !file) || !name || (!value && size)) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0) {
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0) {
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(FEA2LIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value) {
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetFileInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	free(pfea2list);
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
 #else
 
 #error You need to create xattr compatibility functions.
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/sysxattrs.h ./lib/sysxattrs.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/sysxattrs.h	2007-04-07 10:22:24.000000000 -0700
+++ ./lib/sysxattrs.h	2010-03-25 15:21:32.000000000 -0700
@@ -19,6 +19,13 @@
 int sys_lremovexattr(const char *path, const char *name);
 ssize_t sys_llistxattr(const char *path, char *list, size_t size);
 
+#ifdef __OS2__
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size);
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size);
+int uniremovexattr (const char *path, int file, const char *name);
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags);
+#endif
+
 #else
 
 /* No xattrs available */
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/wildmatch.c ./lib/wildmatch.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/wildmatch.c	2007-05-21 22:58:58.000000000 -0700
+++ ./lib/wildmatch.c	2010-03-25 15:21:32.000000000 -0700
@@ -89,8 +89,14 @@
 	    p_ch = *++p;
 	    /* FALLTHROUGH */
 	  default:
+#ifndef __OS2__
 	    if (t_ch != p_ch)
 		return FALSE;
+#else
+	    // 18 Oct 09 SHL be case insensitive
+	    if (t_ch != p_ch && (t_ch ^ p_ch) != 0x20)
+		return FALSE;
+#endif
 	    continue;
 	  case '?':
 	    /* Match anything but '/'. */
@@ -150,8 +156,14 @@
 		    p_ch = *++p;
 		    if (!p_ch)
 			return ABORT_ALL;
+#ifndef __OS2__
 		    if (t_ch == p_ch)
 			matched = TRUE;
+#else
+		    // 18 Oct 09 SHL be case insensitive
+		    if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			matched = TRUE;
+#endif
 		} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
 		    p_ch = *++p;
 		    if (p_ch == '\\') {
@@ -159,6 +171,7 @@
 			if (!p_ch)
 			    return ABORT_ALL;
 		    }
+		    // 18 Oct 09 SHL [a-z] ranges remain case-sensitive for now
 		    if (t_ch <= p_ch && t_ch >= prev_ch)
 			matched = TRUE;
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
@@ -173,8 +186,14 @@
 			/* Didn't find ":]", so treat like a normal set. */
 			p = s - 2;
 			p_ch = '[';
+#ifndef __OS2__
 			if (t_ch == p_ch)
 			    matched = TRUE;
+#else
+			// 18 Oct 09 SHL be case insensitive
+			if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			    matched = TRUE;
+#endif
 			continue;
 		    }
 		    if (CC_EQ(s,i, "alnum")) {
@@ -218,6 +237,11 @@
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
 		} else if (t_ch == p_ch)
 		    matched = TRUE;
+#ifdef __OS2__
+		// 18 Oct 09 SHL be case insensitive
+		else if ((t_ch ^ p_ch) == 0x20)
+		    matched = TRUE;
+#endif
 	    } while (prev_ch = p_ch, (p_ch = *++p) != ']');
 	    if (matched == special || t_ch == '/')
 		return FALSE;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/ln ./ln
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/ln	2106-02-06 22:28:16.000000000 
+++ ./ln	2010-03-25 19:48:34.000000000 -0700
@@ -0,0 +1,3 @@
+# ln fake
+
+sh -c echo "$@"
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/loadparm.c ./loadparm.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/loadparm.c	2009-01-17 13:41:34.000000000 -0800
+++ ./loadparm.c	2010-03-25 15:21:32.000000000 -0700
@@ -654,10 +654,23 @@
 	    *(char *)dest_ptr = *(char *)src_ptr;
 	    break;
 
+#ifndef __OS2__
 	  case P_PATH:
 	  case P_STRING:
 	    string_set(dest_ptr,*(char **)src_ptr);
 	    break;
+#else
+	  case P_PATH:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    // 06 Mar 09 SHL Force unix slashes
+	    // 16 May 09 SHL Use normalize_dir_slashes
+	    normalize_dir_slashes(*(char **)dest_ptr);
+	    break;
+
+	  case P_STRING:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    break;
+#endif
 
 	  default:
 	    break;
@@ -726,7 +739,12 @@
        string_set(parm_ptr,parmvalue);
        if ((cp = *(char**)parm_ptr) != NULL) {
 	   int len = strlen(cp);
+#ifndef __OS2__
 	   while (len > 1 && cp[len-1] == '/') len--;
+#else
+	   int drive_letter_adj = *(cp + 1) == ':' && isalpha(*cp) ? 2 : 0;
+	   while (len > 1 + drive_letter_adj && cp[len-1] == '/') len--;
+#endif
 	   cp[len] = '\0';
        }
        break;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/log.c ./log.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/log.c	2009-01-17 13:41:34.000000000 -0800
+++ ./log.c	2010-03-25 15:21:32.000000000 -0700
@@ -371,6 +371,7 @@
 	va_list ap;
 	char buf[BIGPATHBUFLEN];
 	size_t len;
+	int e = errno;			// 27 Apr 09 SHL preserve errno
 
 	va_start(ap, format);
 	len = vsnprintf(buf, sizeof buf, format, ap);
@@ -403,6 +404,7 @@
 	}
 
 	rwrite(code, buf, len, 0);
+	errno = e;
 }
 
 /* This is like rprintf, but it also tries to print some
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/main.c ./main.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/main.c	2009-12-19 13:39:48.000000000 -0800
+++ ./main.c	2010-03-25 15:21:32.000000000 -0700
@@ -532,6 +532,8 @@
 			if (!change_dir(dest_path, CD_NORMAL)) {
 				rsyserr(FERROR, errno, "change_dir#1 %s failed",
 					full_fname(dest_path));
+				// 22 Jul 09 SHL was FLOG?  why?
+				rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 				exit_cleanup(RERR_FILESELECT);
 			}
 			return NULL;
@@ -592,6 +594,8 @@
 		if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
 			rsyserr(FERROR, errno, "change_dir#2 %s failed",
 				full_fname(dest_path));
+			// 22 Jul 09 SHL was FLOG?  why?
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 
@@ -612,6 +616,8 @@
 	if (!change_dir(dest_path, CD_NORMAL)) {
 		rsyserr(FERROR, errno, "change_dir#3 %s failed",
 			full_fname(dest_path));
+		// 22 Jul 09 SHL was FLOG?  why?
+		rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 		exit_cleanup(RERR_FILESELECT);
 	}
 	*cp = '/';
@@ -703,8 +709,9 @@
 
 	if (!relative_paths) {
 		if (!change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#3 %s failed",
+			rsyserr(FERROR, errno, "change_dir#4 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -875,8 +882,9 @@
 		argc--;
 		argv++;
 		if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#4 %s failed",
+			rsyserr(FERROR, errno, "change_dir#5 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -931,6 +939,7 @@
 			if (check_filter(elp, FLOG, dir, 1) < 0)
 				goto options_rejected;
 		}
+		// 25 Sep 09 SHL fixme slashes
 		if (partial_dir && *partial_dir == '/'
 		 && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
 		    options_rejected:
@@ -1089,7 +1098,7 @@
 
 	for (i = 0; argv[i]; i++) {
 		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
+			rprintf (FERROR, "out of memory at %s(%u)\n",
 				 __FILE__, __LINE__);
 			return RERR_MALLOC;
 		}
@@ -1120,6 +1129,14 @@
 	 * command line. */
 	if ((ret = copy_argv(argv)) != 0)
 		return ret;
+#ifdef __OS2__
+	{
+		int i;
+		for (i = 0; i < argc; i++) {
+			normalize_dir_slashes(argv[i]);
+		}
+	}
+#endif
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -1443,6 +1460,7 @@
 	 * (implemented by forking "pwd" and reading its output) doesn't
 	 * work when there are other child processes.  Also, on all systems
 	 * that implement getcwd that way "pwd" can't be found after chroot. */
+	// rprintf(FINFO, "* [%s] %s %s(%u)\n", who_am_i(), "(null)", __FILE__, __LINE__);	// 28 Jul 08 SHL debug chdir
 	change_dir(NULL, CD_NORMAL);
 
 	init_flist();
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/options.c ./options.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/options.c	2009-12-21 14:40:40.000000000 -0800
+++ ./options.c	2010-03-25 15:21:32.000000000 -0700
@@ -52,6 +52,10 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+// 13 Jun 09 SHL Added
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -116,7 +120,11 @@
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
+#ifndef __OS2__
 int modify_window = 0;
+#else
+int modify_window = 1;			// 28 Jul 09 SHL allow for 2 second resolution
+#endif
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
@@ -262,6 +270,10 @@
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
 	rprintf(f, "Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.\n");
 	rprintf(f, "Web site: http://rsync.samba.org/\n");
+#ifdef __OS2__ // 22 Jul 09 SHL
+	rprintf(f, "Built by Steven H. Levine " __DATE__ " " __TIME__ "\n");
+	rprintf(f, "Built with GCC " __VERSION__ "\n");
+#endif
 	rprintf(f, "Capabilities:\n");
 	rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
 		(int)(sizeof (OFF_T) * 8),
@@ -338,6 +350,9 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+#ifdef __OS2__
+  rprintf(F," -2, --os2-perms             preserve native OS/2 permissions\n");
+#endif
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
 #ifdef SUPPORT_ACLS
@@ -480,6 +495,10 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+#ifdef __OS2__
+  {"os2-perms",       '2', POPT_ARG_NONE,   0, '2', 0, 0 },
+  {"no-os2-perms",     0,  POPT_ARG_VAL,    &os2_perms, 0, 0, 0 },
+#endif
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
@@ -1033,6 +1052,10 @@
 		case OPT_EXCLUDE_FROM:
 		case OPT_INCLUDE_FROM:
 			arg = poptGetOptArg(pc);
+#ifdef __OS2__
+			// 18 Oct 09 SHL
+			normalize_dir_slashes((char *)arg);	// hack cough - override const
+#endif
 			if (sanitize_paths)
 				arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 			if (daemon_filter_list.head) {
@@ -1140,6 +1163,13 @@
 			}
 			break;
 
+// 14 Jun 09 SHL
+#ifdef __OS2__
+		case '2':
+			os2_perms = 1;
+			preserve_perms = 1;	// Implied
+			break;
+#endif
 		case OPT_WRITE_BATCH:
 			/* batch_name is already set */
 			write_batch = 1;
@@ -1475,6 +1505,7 @@
 			char *dir;
 			if (!*backup_dir)
 				goto options_rejected;
+			// 25 Sep 09 SHL fixme slashes
 			dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
 			clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
 			if (check_filter(elp, FLOG, dir, 1) < 0)
@@ -1783,6 +1814,12 @@
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
 		argstr[x++] = 'E';
+// 13 Jun 09 SHL
+#ifdef __OS2__
+	if (os2_perms)
+		argstr[x++] = '2';
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls)
 		argstr[x++] = 'A';
@@ -2103,6 +2140,10 @@
 			break;
 		}
 		if (*s == ':' || *s == '/') {
+#			ifdef __OS2__	// 29 Jun 09 SHL don't confuse drive letter with host spec
+			if (*s == ':' && s == str + 1 && drive_spec_width(s - 1) != 0)
+				continue;
+#			endif
 			if (!hostlen)
 				hostlen = s - host_start;
 			if (*s++ == '/') {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/params.c ./params.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/params.c	2007-11-22 09:51:20.000000000 -0800
+++ ./params.c	2010-03-25 15:21:32.000000000 -0700
@@ -168,6 +168,7 @@
   while( pos >= 0 && isSpace(line + pos) )
      pos--;
 
+  // 16 May 09 SHL fixme to not be confused by trailing \ in path
   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
   } /* Continuation */
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/proto.h ./proto.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/proto.h	2009-12-31 13:20:00.000000000 -0800
+++ ./proto.h	2010-03-25 17:16:04.000000000 -0700
@@ -378,6 +378,8 @@
 int flist_ndx_pop(flist_ndx_list *lp);
 void *expand_item_list(item_list *lp, size_t item_size,
 		       const char *desc, int incr);
+void normalize_dir_slashes(char *path);
+void assert_no_dir_slashes(char *path);
 void free_xattr(stat_x *sxp);
 int get_xattr(const char *fname, stat_x *sxp);
 int copy_xattrs(const char *source, const char *dest);
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/readme.os2 ./readme.os2
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/readme.os2	2106-02-06 22:28:16.000000000 
+++ ./readme.os2	2010-04-08 22:48:38.000000000 -0700
@@ -0,0 +1,87 @@
+Rsync v3.0.7 compiled with GCC 4.3.4 & kLibc v0.6.3
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+We (Paul and Steven) are using this as both client and server for backups
+
+Changes in this version:
+- Updated to v3.0.6
+- Incorporated a bunch of patches from Steven Levine
+- Move to GCC 4.3.4 as a compiler
+- --xattrs now works for remote servers
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 permissions
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+- Defaulted to %ETC% for rsyncd.conf
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+  Run make install
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Cheers,
+
+Paul Smedley
+Adelaide, Australia
+
+and
+
+Steven Levine
+Costa Mesa, California, USA
+
+09 April 2010
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/readme.shl ./readme.shl
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/readme.shl	2106-02-06 22:28:16.000000000 
+++ ./readme.shl	2010-04-13 11:07:14.000000000 -0700
@@ -0,0 +1,88 @@
+
+Rsync v3.0.7 compiled with GCC 3.3.5 & kLibc v0.6.3
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+These are Steven Levine's notes
+See readme.os2 for Paul Smedley's notes
+
+Changes in this version:
+
+- Updated to v3.0.7
+- Added logic to ensure directory xattrs get updated after mode changes
+- Started work on supporting standard tests
+- Migrated existing 3.0.6 patches
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 permissions
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke a some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+
+  Run make install
+
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Have fun,
+
+Steven Levine
+Costa Mesa, California, USA
+
+13 Apr 2010
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/receiver.c ./receiver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/receiver.c	2009-04-12 12:48:58.000000000 -0700
+++ ./receiver.c	2010-03-25 15:21:32.000000000 -0700
@@ -471,7 +471,7 @@
 				handle_delayed_updates(local_name);
 			send_msg(MSG_DONE, "", 0, 0);
 			continue;
-		}
+		} // NDX_DONE
 
 		if (ndx - cur_flist->ndx_start >= 0)
 			file = cur_flist->files[ndx - cur_flist->ndx_start];
@@ -809,8 +809,8 @@
 			if (inc_recurse)
 				send_msg_int(MSG_NO_SEND, ndx);
 			break;
-		}
-	}
+		} // switch
+	} // while
 	if (make_backups < 0)
 		make_backups = -make_backups;
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/rsync.c ./rsync.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/rsync.c	2009-12-19 13:39:48.000000000 -0800
+++ ./rsync.c	2010-03-25 15:21:32.000000000 -0700
@@ -385,6 +385,8 @@
 	mode_t new_mode = file->mode;
 	int inherit;
 
+	// rprintf(FINFO, "* [%s] set_file_attrs fname %s mode %o file %p sxp %p %s(%u)\n", who_am_i(), fname, file->mode, file, sxp, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	if (!sxp) {
 		if (dry_run)
 			return 1;
@@ -497,6 +499,7 @@
 
 #ifdef HAVE_CHMOD
 	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+		// rprintf(FINFO, "* [%s] set_file_attrs fname %s sxp->st.st_mode %o new_mode %o %s(%u)\n", who_am_i(), fname, sxp->st.st_mode, new_mode, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
@@ -554,8 +557,12 @@
 		    int overwriting_basis)
 {
 	int ret;
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
 	const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
+	if (partialptr && drive_spec_width(partialptr))
+		rprintf(FINFO, "* [%s] finish_transfer partialptr %s fname %s fnamecmp %s %s(%u)\n", who_am_i(), partialptr, fname, fnamecmp, __FILE__, __LINE__);	// 25 Sep 09 SHL debug slashes
+
 	if (inplace) {
 		if (verbose > 2)
 			rprintf(FINFO, "finishing %s\n", fname);
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/rsync.h ./rsync.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/rsync.h	2009-12-23 11:36:26.000000000 -0800
+++ ./rsync.h	2010-03-25 15:21:32.000000000 -0700
@@ -1145,3 +1145,12 @@
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+// 05 Mar 09 SHL support drive letters
+#ifndef __OS2__
+#define drive_spec_width(p) 0
+#define is_abs_path(p) (*(p) == '/')
+#else
+#define drive_spec_width(p) ((isalpha(*(p)) && *((p) + 1) == ':') ? 2 : 0)
+#define is_abs_path(p) (*((p) + drive_spec_width(p)) == '/')
+#endif
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/runtests.sh ./runtests.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/runtests.sh	2008-05-18 07:00:48.000000000 -0700
+++ ./runtests.sh	2010-03-25 19:57:14.000000000 -0700
@@ -239,8 +239,8 @@
     $setfacl_nodef "$scratchdir" || true
     chmod g-s "$scratchdir"
     case "$srcdir" in
-    /*) ln -s "$srcdir" "$scratchdir/src" ;;
-    *)  ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
+    /*) echo ln -s "$srcdir" "$scratchdir/src" ;;
+    *)  echo ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
     esac
     return 0
 }
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/sender.c ./sender.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/sender.c	2009-12-12 17:23:02.000000000 -0800
+++ ./sender.c	2010-03-25 15:21:32.000000000 -0700
@@ -366,7 +366,7 @@
 		send_msg_int(MSG_IO_ERROR, io_error);
 
 	if (verbose > 2)
-		rprintf(FINFO, "send files finished\n");
+		rprintf(FINFO, "send_files finished\n");	// 06 Mar 09 SHL
 
 	match_report();
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/syscall.c ./syscall.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/syscall.c	2009-01-17 13:41:34.000000000 -0800
+++ ./syscall.c	2010-03-25 15:21:32.000000000 -0700
@@ -28,6 +28,24 @@
 #ifdef HAVE_SYS_ATTR_H
 #include <sys/attr.h>
 #endif
+// 06 Mar 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define setmode
+#if defined HAVE_SETMODE && O_BINARY && __OS2__
+// From gcc io.h
+int setmode (int, int);
+// From gcc os2emx.h
+#endif
+#ifdef __OS2__ // 01 Aug 09 SHL
+// 01 Aug 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define _sopen
+int _sopen (__const__ char *, int, int, ...);	// hack cough
+#include "share.h"			// SH_DENYNO
+#endif
+
+#if defined __OS2__
+// 27 Apr 09 SHL Need definitions for FILE_...
+#define INCL_DOS
+// #include <os2.h>
+#include <os2emx.h>
+#endif
 
 extern int dry_run;
 extern int am_root;
@@ -35,6 +53,10 @@
 extern int list_only;
 extern int preserve_perms;
 extern int preserve_executability;
+// 13 Jun 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -138,12 +160,32 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+#ifdef __OS2__
+	int fd;
+#endif
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
 
+#ifndef __OS2__
 	return open(pathname, flags | O_BINARY, mode);
+#else
+	// 31 Jul 09 SHL if open fails, try shared open in case file already opened for write
+	fd = open(pathname, flags | O_BINARY, mode);
+	if (fd == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
+		fd = _sopen(pathname, flags | O_BINARY, SH_DENYNO, mode);
+		if (fd != -1)
+			rprintf(FINFO, "[%s] opened %s for shared write - file may change during sync\n", who_am_i(), pathname);
+		else if (verbose) {
+			int e = errno;
+			rsyserr(FINFO, errno, "do_open _sopen fallback failed for %s", pathname);
+			errno = e;
+		}
+
+	}
+	return fd;
+#endif
 }
 
 #ifdef HAVE_CHMOD
@@ -152,6 +194,9 @@
 	int code;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+
+	// rprintf(FINFO, "* [%s] do_chmod path %s requested mode %o %s(%u)\n", who_am_i(), path, mode, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	if (S_ISLNK(mode)) {
 #ifdef HAVE_LCHMOD
 		code = lchmod(path, mode & CHMOD_BITS);
@@ -164,10 +209,69 @@
 		attrList.commonattr = ATTR_CMN_ACCESSMASK;
 		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
 #else
-		code = 1;
+		code = 1;		// Can not set symlink
 #endif
 	} else
+#ifndef __OS2__
+		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+#else
+	{
+		ULONG attributes = 0;
+		if (os2_perms) {
+			// Unmap mode to recover native OS/2 attributes
+			// See map_os2_attributes
+			// If not readable by owner, hidden
+			if (~mode & S_IRUSR)
+				attributes |= FILE_HIDDEN;
+			// If readable by group, system
+			if (mode & S_IRGRP)
+				attributes |= FILE_SYSTEM;
+			// If writable by group, archived
+			if (mode & S_IWGRP)
+				attributes |= FILE_ARCHIVED;
+			// Reset group rw bits to match other rw bits - hack cough
+			if (mode & S_IROTH)
+				mode |= S_IRGRP;
+			else
+				mode &= ~S_IRGRP;
+			if (mode & S_IWOTH)
+				mode |= S_IWGRP;
+			else
+				mode &= ~S_IWGRP;
+		}
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+		if (!code && os2_perms) {
+			// Adjust native attributes not handled by chmod - system, hidden, archived
+			// Maybe libc will do this someday
+			// chmod already handles readonly
+			// Adjust attributes if any but archived set or if archived not set in requested attributes
+			FILESTATUS3 fs3;
+			APIRET apiret = DosQueryPathInfo((PCSZ)path,
+							 FIL_STANDARD,
+							 &fs3,
+							 sizeof(fs3));
+			// 26 Sep 09 SHL fixme perms - set code on failure - need map_apiret_errno()
+			if (apiret)
+				rprintf(FERROR, "[%s] DosQueryPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+			else {
+				ULONG m = attributes | (fs3.attrFile & ~(FILE_SYSTEM | FILE_HIDDEN | FILE_ARCHIVED));
+				if (m != fs3.attrFile) {
+					ULONG old_attrFile = fs3.attrFile;
+					fs3.attrFile = m;
+					apiret = DosSetPathInfo((PCSZ)path,
+								 FIL_STANDARD,
+								 &fs3, sizeof(fs3),
+								 0);
+					if (apiret)
+						rprintf(FERROR, "[%s] DosSetPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+					// 17 Sep 09 SHL os2_perms
+					else if (verbose > 1)
+						rprintf(FINFO, "[%s] changed %s attrFile from %lx to %lx (attributes %lx)\n", who_am_i(), path, old_attrFile, fs3.attrFile, attributes);	// 21 Jul 09 SHL
+				}
+			}
+		}
+	}
+#endif
 	if (code != 0 && (preserve_perms || preserve_executability))
 		return code;
 	return 0;
@@ -238,12 +342,55 @@
 #endif
 }
 
+#ifdef __OS2__
+
+/**
+ * Map native OS/2 attributes to something rsync can send
+ * See do_chmod for unmap logic
+ */
+
+static void map_os2_attributes(STRUCT_STAT *st)
+{
+	// If hidden, readable by none
+	if (st->st_attr & FILE_HIDDEN)
+		st->st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+	// If readonly, writable by none
+	if (st->st_attr & FILE_READONLY)
+		st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+
+	// Steal group bits for native attributes without obvious mappings - hack cough
+	// If system, readable by group
+	if (st->st_attr & FILE_SYSTEM)
+		st->st_mode |= S_IRGRP;
+	else
+		st->st_mode &= ~S_IRGRP;
+	// If archived, writable by group
+	if (st->st_attr & FILE_ARCHIVED)
+		st->st_mode |= S_IWGRP;
+	else
+		st->st_mode &= ~S_IWGRP;
+}
+
+#endif
+
 int do_stat(const char *fname, STRUCT_STAT *st)
 {
 #ifdef USE_STAT64_FUNCS
 	return stat64(fname, st);
 #else
+#ifndef __OS2__
 	return stat(fname, st);
+#else
+	int code;
+	code = stat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
@@ -253,7 +400,19 @@
 # ifdef USE_STAT64_FUNCS
 	return lstat64(fname, st);
 # else
+#ifndef __OS2__
 	return lstat(fname, st);
+#else
+	// 27 Apr 09 SHL map OS/2 permissions
+	int code = lstat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 # endif
 #else
 	return do_stat(fname, st);
@@ -265,7 +424,19 @@
 #ifdef USE_STAT64_FUNCS
 	return fstat64(fd, st);
 #else
+#ifndef __OS2__
 	return fstat(fd, st);
+#else
+	int code;
+	code = fstat(fd, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %u mode from %o to %o (st_attr %o)\n", who_am_i(), fd, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/t_stub.c ./t_stub.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/t_stub.c	2009-01-17 13:41:34.000000000 -0800
+++ ./t_stub.c	2010-03-25 17:22:00.000000000 -0700
@@ -32,6 +32,12 @@
 char *module_dir;
 struct filter_list_struct daemon_filter_list;
 
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
+int verbose = 0;
+
+
  void rprintf(UNUSED(enum logcode code), const char *format, ...)
 {
 	va_list ap;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/t_unsafe.c ./t_unsafe.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/t_unsafe.c	2009-01-17 13:41:34.000000000 -0800
+++ ./t_unsafe.c	2010-03-25 17:21:50.000000000 -0700
@@ -27,7 +27,6 @@
 int am_root = 0;
 int read_only = 0;
 int list_only = 0;
-int verbose = 0;
 int preserve_perms = 0;
 int preserve_executability = 0;
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/testsuite/rsync.fns ./testsuite/rsync.fns
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/testsuite/rsync.fns	2009-12-13 19:35:00.000000000 -0800
+++ ./testsuite/rsync.fns	2010-03-25 19:58:32.000000000 -0700
@@ -150,7 +150,7 @@
 
     echo $ECHO_N "This file has no trailing lf$ECHO_C" > "$fromdir/nolf"
     umask 0
-    ln -s nolf "$fromdir/nolf-symlink"
+    echo ln -s nolf "$fromdir/nolf-symlink"
     umask 022
 
     cat "$srcdir"/*.c > "$fromdir/text"
@@ -319,10 +319,10 @@
 build_symlinks() {
     mkdir "$fromdir"
     date >"$fromdir/referent"
-    ln -s referent "$fromdir/relative"
-    ln -s "$fromdir/referent" "$fromdir/absolute"
-    ln -s nonexistent "$fromdir/dangling"
-    ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
+    echo ln -s referent "$fromdir/relative"
+    echo ln -s "$fromdir/referent" "$fromdir/absolute"
+    echo ln -s nonexistent "$fromdir/dangling"
+    echo ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
 }
 
 test_fail() {
@@ -345,7 +345,7 @@
 }
 
 # Determine what shell command will appropriately test for links.
-ln -s foo "$scratchdir/testlink"
+echo ln -s foo "$scratchdir/testlink"
 for cmd in test /bin/test /usr/bin/test /usr/ucb/bin/test /usr/ucb/test
 do
     for switch in -h -L
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/util.c ./util.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/util.c	2009-03-03 08:57:42.000000000 -0800
+++ ./util.c	2010-03-25 15:21:32.000000000 -0700
@@ -23,6 +23,10 @@
 #include "rsync.h"
 #include "ifuncs.h"
 
+#ifdef __OS2__
+#include <os2emx.h>
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int module_id;
@@ -191,6 +195,10 @@
 	char *p;
 	int ret = 0;
 
+#ifdef __OS2__ // 06 Mar 09 SHL use drive_spec_width
+	fname += drive_spec_width(fname);		/* Bypass drive letter */
+#endif /* __OS2__ */
+
 	while (*fname == '/')
 		fname++;
 	while (strncmp(fname, "./", 2) == 0)
@@ -420,6 +428,8 @@
 {
 	int tries = 4;
 
+	// rprintf(FINFO, "* [%s] robust_rename %s->%s %s(%u)\n", who_am_i(), from, to, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	while (tries--) {
 		if (do_rename(from, to) == 0)
 			return 0;
@@ -444,6 +454,27 @@
 				return -2;
 			do_unlink(from);
 			return 1;
+#ifdef __OS2__ // 27 Apr 09 SHL
+		// libc rename semantics differs from linux
+		// clear readonly if this caused rename to fail
+		case EACCES:
+		{
+			STRUCT_STAT st;
+			int code;
+			if (verbose)
+				rprintf(FINFO, "[%s] robust_rename retrying %s after EACCES\n", who_am_i(), to);	// 22 Jul 09 SHL
+			code = do_stat(to, &st);
+			if (!code) {
+				// 27 Apr 09 SHL fixme to use st_mode when libc fixed
+				if (st.st_attr & FILE_READONLY) {
+					st.st_mode |= S_IWUSR;
+					code = do_chmod(to, st.st_mode);
+					if (!code)
+						break;	// Try again
+				}
+			}
+		}
+#endif
 		default:
 			return -1;
 		}
@@ -818,10 +849,18 @@
 {
 	char *limit = name - 1, *t = name, *f = name;
 	int anchored;
+#ifdef __OS2__
+	int drive_letter_adj;	// 0 if not, 2 if yes 15 Dec 08 SHL
+#endif
 
 	if (!name)
 		return 0;
 
+#ifdef __OS2__ // 06 Mar 09 SHL use drive_spec_width...
+	drive_letter_adj = drive_spec_width(name);
+	f += drive_letter_adj;			// Keep drive letter
+	t += drive_letter_adj;
+#endif /* __OS2__ */
 	if ((anchored = *f == '/') != 0) {
 		*t++ = *f++;
 #ifdef __CYGWIN__
@@ -869,10 +908,18 @@
 		while (*f && (*t++ = *f++) != '/') {}
 	}
 
+#ifndef __OS2__ // 06 Feb 09 SHL
 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 		t--;
 	if (t == name)
 		*t++ = '.';
+#else
+	if (t > name + anchored + drive_letter_adj && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
+		t--;
+	if (t == name + drive_letter_adj)
+		*t++ = '.';		// Ensure not empty
+#endif
+
 	*t = '\0';
 
 	return t - name;
@@ -906,14 +953,28 @@
 	char *start, *sanp;
 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 
+	// rprintf(FINFO, "* [%s] sanitize_path p %s %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 06 Feb 09 SHL
 	if (dest != p) {
 		int plen = strlen(p);
-		if (*p == '/') {
+		int drive_letter_adj = drive_spec_width(p);	// 0 if not, 2 if yes 15 Dec 08 SHL
+#ifndef __OS2__
+		if (*p == '/')
+#else // 06 Feb 09 SHL use is_abs_path...
+		if (!is_abs_path(p)) {
+			if (drive_letter_adj)
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 06 Feb 09 SHL
+		} else
+#endif
+		{
 			if (!rootdir)
 				rootdir = module_dir;
 			rlen = strlen(rootdir);
 			depth = 0;
+#ifndef __OS2__
 			p++;
+#else
+			p += drive_spec_width(p) + 1;
+#endif
 		}
 		if (dest) {
 			if (rlen + plen + 1 >= MAXPATHLEN)
@@ -922,8 +983,13 @@
 			out_of_memory("sanitize_path");
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
+#ifndef __OS2__
 			if (rlen > 1)
 				dest[rlen++] = '/';
+#else
+			if (rlen > 1 + drive_letter_adj)
+				dest[rlen++] = '/';
+#endif
 		}
 	}
 
@@ -967,6 +1033,20 @@
 		}
 		/* copy one component through next slash */
 		while (*p && (*sanp++ = *p++) != '/') {}
+#if 0 // 16 May 09 SHL fixme to be gone
+#ifndef __OS2__
+		while (*p && (*sanp++ = *p++) != '/') {}
+#else
+		while(*p) {
+			char c = *p++;
+			if (c == '\\')
+				c = '/';
+			*sanp++ = c;
+			if (c == '/')
+				break;
+		}
+#endif
+#endif
 	}
 	if (sanp == dest) {
 		/* ended up with nothing, so put in "." component */
@@ -974,16 +1054,23 @@
 	}
 	*sanp = '\0';
 
+	// rprintf(FINFO, "* [%s] sanitize_path dest %s %s(%u)\n", who_am_i(), dest, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
+
+	// 16 May 09 SHL  fixme to be gone
+	assert_no_dir_slashes(dest);
+
 	return dest;
 }
 
 /* Like chdir(), but it keeps track of the current directory (in the
  * global "curr_dir"), and ensures that the path size doesn't overflow.
- * Also cleans the path using the clean_fname() function. */
+ * Also cleans the path using the clean_fname() function.
+ * Returns 1 of change OK.  Otherwise 0 */
 int change_dir(const char *dir, int set_path_only)
 {
 	static int initialised;
 	unsigned int len;
+	// rprintf(FINFO, "* [%s] change_dir dir %s %s(%u)\n", who_am_i(), dir ? dir : "(null)", __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
 
 	if (!initialised) {
 		initialised = 1;
@@ -992,6 +1079,7 @@
 			exit_cleanup(RERR_FILESELECT);
 		}
 		curr_dir_len = strlen(curr_dir);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__);	// 06 Feb 09 SHL debug
 	}
 
 	if (!dir)	/* this call was probably just to initialize */
@@ -1001,23 +1089,49 @@
 	if (len == 1 && *dir == '.')
 		return 1;
 
-	if (*dir == '/') {
+	// 06 Mar 09 SHL use is_abs_path
+	if (is_abs_path(dir)) {
+		// Absolute path
 		if (len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifndef __OS2__ // 28 Jul 08 SHL
 		if (!set_path_only && chdir(dir))
 			return 0;
 		memcpy(curr_dir, dir, len + 1);
+#else
+		if (!set_path_only) {
+			if (chdir(dir)) {
+				rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL
+				return 0;
+			}
+			if (drive_spec_width(dir) && _chdrive(*dir)) {
+				rprintf(FERROR, "[%s] change_dir _chdrive failed for dir %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL
+				return 0;
+			}
+		}
+		memcpy(curr_dir, dir, len + 1);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
+#endif
 	} else {
+		// Relative path
 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifdef __OS2__
+		if (drive_spec_width(dir)) {
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			errno = EINVAL;
+			return -1;
+		}
+#endif
 		curr_dir[curr_dir_len] = '/';
 		memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
 
 		if (!set_path_only && chdir(curr_dir)) {
+			rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 			curr_dir[curr_dir_len] = '\0';
 			return 0;
 		}
@@ -1042,12 +1156,15 @@
 {
 	unsigned int len;
 
-	if (*path != '/') { /* Make path absolute. */
+	// 06 Mar 09 SHL use is_abs_path
+	if (!is_abs_path(path)) { /* Make path absolute. */
 		int len = strlen(path);
+		if (drive_spec_width(path))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 28 Jul 08 SHL
 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
-		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
+		memcpy(curr_dir + curr_dir_len + 1, path + drive_spec_width(path), len + 1);
 		if (!(path = strdup(curr_dir)))
 			out_of_memory("normalize_path");
 		curr_dir[curr_dir_len] = '\0';
@@ -1078,9 +1195,14 @@
 	if (result)
 		free(result);
 
-	if (*fn == '/')
+	// 06 Mar 09 SHL use is_abs_path
+	if (is_abs_path(fn))
 		p1 = p2 = "";
 	else {
+#ifdef __OS2__
+		if (drive_spec_width(fn))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 06 Feb 09 SHL
+#endif
 		p1 = curr_dir + module_dirlen;
 		for (p2 = p1; *p2 == '/'; p2++) {}
 		if (*p2)
@@ -1109,6 +1231,9 @@
 
 	if ((fn = strrchr(fname, '/')) != NULL) {
 		fn++;
+		// 25 Sep 09 SHL fixme slashes - handle drive letter if needed
+		if (partial_dir && drive_spec_width(partial_dir))
+			rprintf(FINFO, "* [%s] partial_dir_fname partial_dir %s fname %s %s(%u)\n", who_am_i(), partial_dir, fname, __FILE__, __LINE__);	// 25 Sep 09 SHL debug slashes
 		if (*partial_dir != '/') {
 			int len = fn - fname;
 			strncpy(t, fname, len); /* safe */
@@ -1140,6 +1265,7 @@
 
 	if (fname != partial_fname)
 		return 1;
+	// 25 Sep 09 SHL fixme slashes?
 	if (!create && *partial_dir == '/')
 		return 1;
 	if (!(fn = strrchr(partial_fname, '/')))
@@ -1690,3 +1816,24 @@
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+#ifdef __OS2__ // 16 May 09 SHL
+/**
+ * Convert OS/2 backslashes to unix forward slashes
+ */
+void normalize_dir_slashes(char *path)
+{
+	// 19 Oct 09 SHL rework for speed
+	if (path) {
+		char *p = path;
+		while((p = strchr(path, '\\')) != NULL)
+			*p++ = '/';
+	}
+}
+
+void assert_no_dir_slashes(char *path)
+{
+	if (path && strchr(path, '\\') != 0)
+		rprintf(FERROR, "[%s] unexpected backslash in path %s %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 06 Feb 09 SHL
+}
+#endif // __OS2__
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/xattrs.c ./xattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/xattrs.c	2009-08-14 07:04:24.000000000 -0700
+++ ./xattrs.c	2010-03-25 15:21:32.000000000 -0700
@@ -110,6 +110,8 @@
 {
 	const rsync_xa *xa1 = x1;
 	const rsync_xa *xa2 = x2;
+	// rprintf(FINFO, "* [%s] rsync_xal_compare_names xa1.name %s xa2.name %s %s(%u)\n", who_am_i(), xa1->name, xa2->name, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
+
 	return strcmp(xa1->name, xa2->name);
 }
 
@@ -141,7 +143,9 @@
 				fname, arg);
 			return -1;
 		}
+		/* Expand buffer - get size */
 		list_len = sys_llistxattr(fname, NULL, 0);
+		/* Should not occur */
 		if (list_len < 0) {
 			arg = 0;
 			goto got_error;
@@ -240,9 +244,11 @@
 			 || (am_root < 0
 			  && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
 			   || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
-			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
+			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) {
+				rprintf(FINFO, "* [%s] rsync_xal_get skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
 				continue;
 		}
+		}
 
 		datum_len = name_len; /* Pass extra size to get_xattr_data() */
 		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -283,10 +289,12 @@
 {
 	sxp->xattr = new(item_list);
 	*sxp->xattr = empty_xattr;
+	// rprintf(FINFO, "* [%s] get_xattr fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
 	if (rsync_xal_get(fname, sxp->xattr) < 0) {
 		free_xattr(sxp);
 		return -1;
 	}
+	// rprintf(FINFO, "* [%s] get_xattr count %d %s(%u)\n", who_am_i(), sxp->xattr ? sxp->xattr->count : -1, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
 	return 0;
 }
 
@@ -459,11 +467,13 @@
 	snd_rxa = lst->items;
 	snd_cnt = lst->count;
 
+	// rprintf(FINFO, "* [%s] xattr_diff fname %s rec_cnt %u snd_cnt %u find_all %u %s(%u)\n", who_am_i(), file->basename, rec_cnt, snd_cnt, find_all, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
+
 	/* 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) {
 		if (!find_all)
-			return 1;
+			return 1;	// Say different
 		xattrs_equal = 0;
 	}
 
@@ -485,7 +495,7 @@
 		}
 		if (!same) {
 			if (!find_all)
-				return 1;
+				return 1;	// Say different
 			xattrs_equal = 0;
 		}
 
@@ -502,6 +512,8 @@
 	if (rec_cnt)
 		xattrs_equal = 0;
 
+	// rprintf(FINFO, "* [%s] xattr_diff xattrs_equal %u %s(%u)\n", who_am_i(), xattrs_equal, __FILE__, __LINE__);	// 04 Oct 09 SHL debug xattrs
+
 	return !xattrs_equal;
 }
 
@@ -652,6 +664,8 @@
 		temp_xattr.count = 0;
 	}
 
+	// rprintf(FINFO, "* [%s] receive_xattr %s read count %u am_root %u %s(%u)\n", who_am_i(), file->basename, count, am_root, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
+
 	for (num = 1; num <= count; num++) {
 		char *ptr, *name;
 		rsync_xa *rxa;
@@ -698,12 +712,14 @@
 			memcpy(name, RSYNC_PREFIX, RPRE_LEN);
 		} else {
 			free(ptr);
+			rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
 			continue;
 		}
 #endif
 		/* No rsync.%FOO attributes are copied w/o 2 -X options. */
 		if (preserve_xattrs < 2 && name_len > RPRE_LEN
 		 && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
+			rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
 			free(ptr);
 			continue;
 		}
@@ -715,13 +731,17 @@
 		rxa->num = num;
 	}
 
-	if (need_sort && count > 1)
-		qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
+	// rprintf(FINFO, "* [%s] receive_xattr temp_xattr.items %p temp_xattr.count %u %s(%u)\n", who_am_i(), temp_xattr.items, temp_xattr.count, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
+
+	// 28 Jul 08 SHL sort number used not number malloced
+	if (need_sort && temp_xattr.count > 1)
+		qsort(temp_xattr.items, temp_xattr.count, sizeof (rsync_xa), rsync_xal_compare_names);
 
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
 
 	F_XATTR(file) = ndx;
+	// rprintf(FINFO, "* [%s] receive_xattr %s ndx %u count %d %s(%u)\n", who_am_i(), file->basename, ndx, rsync_xal_l.count, __FILE__, __LINE__);	// 28 Jul 08 SHL debug xattrs
 }
 
 /* Turn the xattr data in stat_x into cached xattr data, setting the index
@@ -770,6 +790,7 @@
 	size_t name_len;
 	int ret = 0;
 
+	// rprintf(FINFO, "* [%s] rsync_xal_set fname %s fnamecmp %s %s(%u)\n", who_am_i(), fname, fnamecmp, __FILE__, __LINE__);	// 23 Mar 10 SHL debug libc chmod xattrs
 	/* This puts the current name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(fname)) < 0)
 		return -1;

Steven Levine

2010-04-14 04:34

manager   ~0001534

The rsync-3.0.7-20100413-shl patch set supports rsync 3.0.7. The patch set adds logic to ensure that directory xattrs are corrected when libc chmod modifies them. Prior builds required a second rsync run to accomplish this.

Steven Levine

2010-08-16 13:29

manager  

rsync-3.0.7-20100413-shl.zip (300,665 bytes)

Steven Levine

2010-08-16 13:31

manager   ~0001710

rsync-3.0.7-20100413-shl.zip is an rsync binary built with the rsync-3.0.7-20100413-shl.diff patch set.

Steven Levine

2010-11-25 08:52

manager  

rsync-3.0.7-20101124-shl.diff (105,431 bytes)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/Makefile.in ./Makefile.in
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/Makefile.in	2009-12-12 17:22:42.000000000 -0800
+++ ./Makefile.in	2010-04-13 11:04:48.000000000 -0700
@@ -12,6 +12,7 @@
 CFLAGS=@CFLAGS@
 CPPFLAGS=@CPPFLAGS@
 EXEEXT=@EXEEXT@
+# 14 Jun 09 SHL fixme to do bldlevel strings
 LDFLAGS=@LDFLAGS@
 
 INSTALLCMD=@INSTALL@
@@ -42,7 +43,8 @@
 	popt/popthelp.o popt/poptparse.o
 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
 
-TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
+# 25 Mar 10 SHL
+TLS_OBJ = tls.o t_stub.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
@@ -68,6 +70,10 @@
 	-mkdir -p ${DESTDIR}${mandir}/man5
 	if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
 	if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
+	if test -f readme.os2; then ${INSTALLMAN} -m 644 readme.os2 ${DESTDIR}${prefix}; fi
+	if test -f readme.shl; then ${INSTALLMAN} -m 644 readme.shl ${DESTDIR}${prefix}; fi
+	if test -f rsync.map; then ${INSTALLMAN} -m 644 rsync.map ${DESTDIR}${prefix}; fi
+	if test -s "${DIFFFILE}"; then if test -f ${DIFFFILE}; then ${INSTALLMAN} -m 644 ${DIFFFILE} ${DESTDIR}${prefix}; fi; fi
 
 install-strip:
 	$(MAKE) INSTALL_STRIP='-s' install
@@ -107,11 +113,11 @@
 getfsdev$(EXEEXT): getfsdev.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
 
-TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
+TRIMSLASH_OBJ = trimslash.o t_stub.o syscall.o lib/compat.o lib/snprintf.o
 trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
-T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
+T_UNSAFE_OBJ = t_unsafe.o t_stub.o syscall.o util.o lib/compat.o lib/snprintf.o lib/wildmatch.o
 t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
 
@@ -189,9 +195,10 @@
 	yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
 	-$(srcdir)/tweak_manpage rsyncd.conf.5
 
+# 06 Feb 09 SHL clean maps
 clean: cleantests
 	rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
-		rounding rounding.h *.old
+		rounding rounding.h *.old rsync.map rounding.map
 
 cleantests:
 	rm -rf ./testtmp*
@@ -243,11 +250,13 @@
 wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
 
+# 25 Mar 10 SHL
+
 testsuite/chown-fake.test:
-	ln -s chown.test $(srcdir)/testsuite/chown-fake.test
+	echo ln -s chown.test $(srcdir)/testsuite/chown-fake.test
 
 testsuite/devices-fake.test:
-	ln -s devices.test $(srcdir)/testsuite/devices-fake.test
+	echo ln -s devices.test $(srcdir)/testsuite/devices-fake.test
 
 # This does *not* depend on building or installing: you can use it to
 # check a version installed from a binary or some other source tree,
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/access.c ./access.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/access.c	2009-01-17 13:41:34.000000000 -0800
+++ ./access.c	2010-03-25 15:21:32.000000000 -0700
@@ -100,7 +100,9 @@
 	hints.ai_flags = AI_NUMERICHOST;
 #endif
 
-	if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	// if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	if ((gai = getaddrinfo(addr, NULL, &hints, &resa)) != 0) {			// 27 Jul 08 SHL debug
+		// rprintf(FINFO, "* [%s] match_address gai %d %s(%u)\n", who_am_i(), gai, __FILE__, __LINE__);	// 28 Jul 08 SHL debug addrinfo
 		if (p)
 			*p = '/';
 		return 0;
@@ -110,8 +112,8 @@
 	if (p)
 		*p++ = '/';
 	if (gai != 0) {
-		rprintf(FLOG, "error matching address %s: %s\n",
-			tok, gai_strerror(gai));
+		rprintf(FLOG, "* error matching address %s: %s (%d)\n",
+			tok, gai_strerror(gai), gai);
 		freeaddrinfo(resa);
 		return 0;
 	}
@@ -222,7 +224,11 @@
 	if (host)
 		strlower(host);
 
+	// rprintf(FINFO, "* [%s] access_match %s (%s) %s(%u)\n", who_am_i(), host, addr, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
+
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+
+		// rprintf(FINFO, "* [%s] access_match tok %s %s(%u)\n", who_am_i(), tok, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
 		if (match_hostname(host, tok) || match_address(addr, tok)) {
 			free(list2);
 			return 1;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/authenticate.c ./authenticate.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/authenticate.c	2009-01-17 13:41:34.000000000 -0800
+++ ./authenticate.c	2010-03-25 15:21:32.000000000 -0700
@@ -96,7 +96,9 @@
 	if (do_stat(fname, &st) == -1) {
 		rsyserr(FLOG, errno, "stat(%s)", fname);
 		ok = 0;
-	} else if (lp_strict_modes(module)) {
+	}
+#ifndef __OS2__	 /* 29 Jun 09 SHL suppress unsupported mode checks */
+	else if (lp_strict_modes(module)) {
 		if ((st.st_mode & 06) != 0) {
 			rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
 			ok = 0;
@@ -105,6 +107,7 @@
 			ok = 0;
 		}
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		rprintf(FLOG, "continuing without secrets file\n");
 		close(fd);
@@ -173,13 +176,16 @@
 	if (do_stat(filename, &st) == -1) {
 		rsyserr(FWARNING, errno, "stat(%s)", filename);
 		ok = 0;
-	} else if ((st.st_mode & 06) != 0) {
+	}
+#ifndef __OS2__	 /* 12 Jun 08 SHL suppress unsupported mode checks */
+	else if ((st.st_mode & 06) != 0) {
 		rprintf(FWARNING, "password file must not be other-accessible\n");
 		ok = 0;
 	} else if (MY_UID() == 0 && st.st_uid != 0) {
 		rprintf(FWARNING, "password file must be owned by root when running as root\n");
 		ok = 0;
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		close(fd);
 		rprintf(FWARNING, "continuing without password file\n");
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/clientname.c ./clientname.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/clientname.c	2009-01-17 13:41:34.000000000 -0800
+++ ./clientname.c	2010-03-25 15:21:32.000000000 -0700
@@ -95,8 +95,10 @@
 	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
-	if (initialised)
+	if (initialised) {
+		// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		return name_buf;
+	}
 
 	strlcpy(name_buf, default_name, sizeof name_buf);
 	initialised = 1;
@@ -148,6 +150,8 @@
 			port_buf, sizeof port_buf) == 0)
 		check_name(fd, &ss, name_buf, sizeof name_buf);
 
+	// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
+
 	return name_buf;
 }
 
@@ -216,14 +220,17 @@
 	int name_err;
 
 	/* reverse lookup */
+	// rprintf(FINFO, "* [%s] lookup_name %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
 			       name_buf, name_buf_size,
 			       port_buf, port_buf_size,
 			       NI_NAMEREQD | NI_NUMERICSERV);
 	if (name_err != 0) {
 		strlcpy(name_buf, default_name, name_buf_size);
-		rprintf(FLOG, "name lookup failed for %s: %s\n",
-			client_addr(fd), gai_strerror(name_err));
+		// rprintf(FINFO, "name lookup failed for %s: %s\n",
+		//	client_addr(fd), gai_strerror(name_err));
+		rprintf(FLOG, "lookup_name failed for %s: %s (%d) at %s(%u) [%s]\n",	// 27 Jul 08 SHL debug
+			client_addr(fd), gai_strerror(name_err), name_err, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL
 		return name_err;
 	}
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/clientserver.c ./clientserver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/clientserver.c	2009-12-12 22:43:50.000000000 -0800
+++ ./clientserver.c	2010-11-24 13:44:46.000000000 -0800
@@ -426,6 +426,8 @@
 	iconv_opt = NULL;
 #endif
 
+	if (verbose)
+		rprintf(FINFO, "[%s] rsync_module addr:host is %s:%s\n", who_am_i(), addr, host);	// 2008-07-28 SHL
 	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
 		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
 			name, host, addr);
@@ -439,6 +441,14 @@
 		return -1;
 	}
 
+// 2010-09-17 SHL libc does not do well with chroot c:/ etc.
+#ifdef __OS2__
+	if (use_chroot) {
+		io_printf(f_out, "@ERROR: use chroot not supported\n");
+		return -1;
+	}
+#endif
+
 	if (am_daemon && am_server) {
 		rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",
 			name, host, addr);
@@ -479,6 +489,7 @@
 
 	am_root = (MY_UID() == 0);
 
+#ifndef __OS2__
 	if (am_root) {
 		p = lp_uid(i);
 		if (!name_to_uid(p, &uid)) {
@@ -501,6 +512,7 @@
 		}
 	}
 
+#endif
 	/* TODO: If we're not root, but the configuration requests
 	 * that we change to some uid other than the current one, then
 	 * log a warning. */
@@ -509,6 +521,9 @@
 	 * supplementary groups. */
 
 	module_dir = lp_path(i);
+
+	// fprintf(stderr, "* [%s] module_dir %s %s(%u)\n", who_am_i(), module_dir, __FILE__, __LINE__); // 2010-09-16 SHL debug
+
 	if (use_chroot) {
 		if ((p = strstr(module_dir, "/./")) != NULL) {
 			*p = '\0'; /* Temporary... */
@@ -533,6 +548,8 @@
 		full_module_path = module_dir = module_chdir;
 	}
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug path
+
 	if (module_dirlen == 1) {
 		module_dirlen = 0;
 		set_filter_dir("/", 1);
@@ -656,6 +673,8 @@
 	}
 #endif
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
 	if (use_chroot) {
 		/*
 		 * XXX: The 'use chroot' flag is a fairly reliable
@@ -677,8 +696,13 @@
 		module_chdir = module_dir;
 	}
 
-	if (!change_dir(module_chdir, CD_NORMAL))
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+		// rsyserr(FERROR, errno, "[%s] chdir %s failed at %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2008-12-15 SHL debug
+		// rprintf(FINFO, "* [%s] chdir module_chdir %s failed %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 		return path_failure(f_out, module_chdir, True);
+	}
 	if (module_dirlen || !use_chroot)
 		sanitize_paths = 1;
 
@@ -993,6 +1017,7 @@
 	close(fd);
 }
 
+#ifndef __OS2__
 /* Become a daemon, discarding the controlling terminal. */
 static void become_daemon(void)
 {
@@ -1026,6 +1051,7 @@
 		open("/dev/null", O_RDWR);
 	}
 }
+#endif // __OS2__
 
 int daemon_main(void)
 {
@@ -1048,10 +1074,14 @@
 		exit_cleanup(RERR_SYNTAX);
 	}
 
+#ifndef __OS2__
 	if (no_detach)
 		create_pid_file();
 	else
 		become_daemon();
+#else
+	create_pid_file();
+#endif
 
 	if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
 		rsync_port = RSYNC_PORT;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/compat.c ./compat.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/compat.c	2009-12-21 14:40:40.000000000 -0800
+++ ./compat.c	2010-03-25 15:21:32.000000000 -0700
@@ -200,11 +200,12 @@
 			exit_cleanup(RERR_PROTOCOL);
 		}
 		if (preserve_xattrs && !local_server) {
-			rprintf(FERROR,
-			    "--xattrs requires protocol 30 or higher"
+		  	preserve_xattrs = 0;	// 06 Feb 09 SHL force off for old servers
+			rprintf(FWARNING,
+			    "--xattrs requires protocol 30 or higher - option disabled"
 			    " (negotiated %d).\n",
 			    protocol_version);
-			exit_cleanup(RERR_PROTOCOL);
+			// exit_cleanup(RERR_PROTOCOL);	// 06 Feb 09 SHL
 		}
 	}
 
@@ -296,6 +297,7 @@
 	if (need_unsorted_flist && (!am_sender || inc_recurse))
 		unsort_ndx = ++file_extra_cnt;
 
+	// 16 Feb 09 SHL fixme slashes?
 	if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
 		int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
 		if (!am_sender || protocol_version >= 30)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/configure.sh ./configure.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/configure.sh	2009-12-31 13:15:44.000000000 -0800
+++ ./configure.sh	2010-03-25 15:21:32.000000000 -0700
@@ -69,6 +69,8 @@
   as_echo='sh -c $as_echo_body as_echo'
 fi
 
+# 18 Jun 09 SHL fixme to not be broken - 3.0.5 worked - maybe autoconf 2.6.3 broke it
+
 # The user is always right.
 if test "${PATH_SEPARATOR+set}" != set; then
   PATH_SEPARATOR=:
@@ -2088,6 +2090,7 @@
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
+  echo SHL $as_dir
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     $as_echo "PATH: $as_dir"
@@ -8333,6 +8336,15 @@
 	$as_echo "#define SUPPORT_XATTRS 1" >>confdefs.h
 
 	;;
+    *os2*)
+	{ echo "$as_me:$LINENO: result: Using OS/2 extattrs" >&5
+echo "${ECHO_T}Using OS/2 extattrs" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_XATTRS 1
+_ACEOF
+
+	;;
+
     *)
 	if test x"$enable_xattr_support" = x"yes"; then
 	    as_fn_error "Failed to find extended attribute support" "$LINENO" 5
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/exclude.c ./exclude.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/exclude.c	2009-12-30 12:25:32.000000000 -0800
+++ ./exclude.c	2010-09-30 18:53:38.000000000 -0700
@@ -298,7 +298,7 @@
 	unsigned int fn_len;
 
 	if (!parent_dirscan && *merge_file != '/') {
-		/* Return the name unchanged it doesn't have any slashes. */
+		/* Return the name unchanged if it doesn't have any slashes. */
 		if (len_ptr) {
 			const char *p = merge_file + *len_ptr;
 			while (--p > merge_file && *p != '/') {}
@@ -310,6 +310,7 @@
 			return (char *)merge_file;
 	}
 
+	// 16 Feb 09 SHL fixme slash
 	fn = *merge_file == '/' ? buf : tmpbuf;
 	if (sanitize_paths) {
 		const char *r = prefix_skip ? "/" : NULL;
@@ -351,6 +352,7 @@
 void set_filter_dir(const char *dir, unsigned int dirlen)
 {
 	unsigned int len;
+	// 16 Feb 09 SHL fixme slash?
 	if (*dir != '/') {
 		memcpy(dirbuf, curr_dir, curr_dir_len);
 		dirbuf[curr_dir_len] = '/';
@@ -548,6 +550,7 @@
 	int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
 	char *p, *pattern = ex->pattern;
 	const char *strings[16]; /* more than enough */
+	// 16 Feb 09 SHL fixme slash?
 	const char *name = fname + (*fname == '/');
 
 	if (!*name)
@@ -605,8 +608,15 @@
 		if (litmatch_array(pattern, strings, slash_handling))
 			return ret_match;
 	} else if (anchored_match) {
+#ifndef __OS2__
 		if (strcmp(name, pattern) == 0)
 			return ret_match;
+#else
+		// 18 Oct 09 SHL Case insensitive
+		if (stricmp(name, pattern) == 0)
+			return ret_match;
+#endif
+
 	} else {
 		int l1 = strlen(name);
 		int l2 = strlen(pattern);
@@ -988,6 +998,25 @@
 				cp = ".cvsignore";
 				pat_len = 10;
 			}
+#ifdef __OS2__
+			else {
+				// 2009-10-19 SHL normalize
+				// 30 Sep 10 SHL avoid writing to const memory
+				/* If we are passed paths from the filter they
+				   might have DOS slashes, convert to Unix slashes
+				   except for the 1st characters (fixme to doc why - I forgot)
+				   If we are processing a const string, it will already
+				   have Unix slashes so don't try to write to const memory
+				*/
+				char ch;
+				p = cp + pat_len;	// Must be non-const for gcc
+				ch = *p;		// Remember 1st character - fixme to say why
+				normalize_dir_slashes((char *)cp);	// Hack cough - override const
+				if (*p != ch)
+					*(char*)p = ch;	// Ensure leading char not changed - fixme to say why
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len, cp, strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
+			}
+#endif
 			len = pat_len;
 			if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
 				const char *name = cp + len;
@@ -998,6 +1027,8 @@
 				len = pat_len;
 			}
 			if (new_mflags & MATCHFLG_PERDIR_MERGE) {
+				// 19 Oct 09 SHL fixme to complain if have drive letter?
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 				if (parent_dirscan) {
 					if (!(p = parse_merge_name(cp, &len,
 								module_dirlen)))
@@ -1014,6 +1045,7 @@
 			}
 		}
 
+		// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 		add_rule(listp, cp, pat_len, new_mflags, xflags);
 
 		if (new_mflags & MATCHFLG_CVS_IGNORE
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/flist.c ./flist.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/flist.c	2009-12-21 14:40:40.000000000 -0800
+++ ./flist.c	2010-11-09 15:09:34.000000000 -0800
@@ -349,8 +349,19 @@
 {
 	if (dirlen < 0) {
 		char *cpy = strdup(dir);
+#ifndef __OS2__ // 06 Mar 09 SHL use is_abs_path...
 		if (*cpy != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (!is_abs_path(cpy)) {
+			if (drive_spec_width(cpy))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), cpy, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+	        }
+#endif
 		if (path_is_daemon_excluded(cpy, 0))
 			goto chdir_error;
 		dir = cpy;
@@ -364,8 +375,19 @@
 				dirlen = strlen(dir);
 		} else if (pathname == dir)
 			return 1;
+#ifndef __OS2__ // 06 Mar 09 SHL use is_abs_path...
 		if (dir && *dir != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (dir && !is_abs_path(dir)) {
+			if (drive_spec_width(dir))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 06 Feb 09 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+		}
+#endif
 	}
 
 	pathname = dir;
@@ -378,8 +400,13 @@
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
 		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
-		if (dir != orig_dir)
-			change_dir(orig_dir, CD_NORMAL);
+		rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
+		if (dir != orig_dir) {
+			if (!change_dir(orig_dir, CD_NORMAL)) {
+				if (verbose > 1)
+					rprintf(FLOG, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 21 Jul 09 SHL
+			}
+		}
 		pathname = NULL;
 		pathname_len = 0;
 		return 0;
@@ -1329,6 +1356,8 @@
 {
 	struct file_struct *file;
 
+	// rprintf(FINFO, "* [%s] send_file_name fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+
 	file = make_file(fname, flist, stp, flags, filter_level);
 	if (!file)
 		return NULL;
@@ -1971,6 +2000,7 @@
 	int len, dirlen;
 	STRUCT_STAT st;
 	char *p, *dir;
+	static char* the_root = "/";
 	struct file_list *flist;
 	struct timeval start_tv, end_tv;
 	int64 start_write;
@@ -2014,6 +2044,7 @@
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
 			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
 				full_fname(argv[0]));
+			rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), argv[0], __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 		use_ff_fd = 1;
@@ -2033,19 +2064,25 @@
 			if (argc-- == 0)
 				break;
 			strlcpy(fbuf, *argv++, MAXPATHLEN);
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 16 Sep 10 SHL debug paths
 			if (sanitize_paths)
 				sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 16 Sep 10 SHL debug paths
+
 		len = strlen(fbuf);
 		if (relative_paths) {
 			/* We clean up fbuf below. */
 			name_type = NORMAL_NAME;
 		} else if (!len || fbuf[len - 1] == '/') {
-			if (len == 2 && fbuf[0] == '.') {
-				/* Turn "./" into just "." rather than "./." */
+			/* Empty path or trailing / */
+			// 2009-03-06 SHL
+			if (len == 2 + drive_spec_width(fbuf) && fbuf[drive_spec_width(fbuf)] == '.') {
+				/* Turn trailing "./" into just "." rather than "./." */
 				fbuf[--len] = '\0';
 			} else {
+				/* Turn trailing "xyz/" into "xyz/." */
 				if (len + 1 >= MAXPATHLEN)
 					overflow_exit("send_file_list");
 				fbuf[len++] = '.';
@@ -2054,6 +2091,7 @@
 			name_type = DOTDIR_NAME;
 		} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
 		    && (len == 2 || fbuf[len-3] == '/')) {
+			/* Got ..  or trailing /.. */
 			if (len + 2 >= MAXPATHLEN)
 				overflow_exit("send_file_list");
 			fbuf[len++] = '/';
@@ -2072,18 +2110,39 @@
 			if (p) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 06 Mar 09 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else
 					dir = fbuf;
-				len -= p - fbuf + 1;
-				fn = p + 1;
+				fn = p + 1;		// Point at filename part
+				len -= fn - fbuf;	//  fn length
+				// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			} else
 				fn = fbuf;
 		} else {
 			if ((p = strstr(fbuf, "/./")) != NULL) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 06 Mar 09 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else {
 					dir = fbuf;
 					clean_fname(dir, 0);
@@ -2105,6 +2164,8 @@
 			}
 			len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
 					    | CFN_DROP_TRAILING_DOT_DIR);
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+			// 06 Mar 09 SHL fixme?
 			if (len == 1) {
 				if (fn[0] == '/') {
 					fn = "/.";
@@ -2137,6 +2198,8 @@
 			name_type = DOTDIR_NAME;
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list dir %s fn %s len %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", fn, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug xattrs
+
 		dirlen = dir ? strlen(dir) : 0;
 		if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
 			if (!change_pathname(NULL, dir, -dirlen))
@@ -2146,9 +2209,16 @@
 		} else if (!change_pathname(NULL, lastdir, lastdir_len))
 			continue;
 
+		// 06 Mar 09 SHL
+		if (dir && dir != the_root && dir != fbuf)
+			free(dir);	// We allocated it
+
 		if (fn != fbuf)
 			memmove(fbuf, fn, len + 1);
 
+		// rprintf(FINFO, "* [%s] send_file_list fn %s %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s len %d %s(%u)\n", who_am_i(), fbuf, len, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
+
 		if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
@@ -2169,12 +2239,14 @@
 		}
 
 		if (inc_recurse && relative_paths && *fbuf) {
+			// 06 Mar 09 SHL fixme
 			if ((p = strchr(fbuf+1, '/')) != NULL) {
 				if (p - fbuf == 1 && *fbuf == '.') {
 					if ((fn = strchr(p+1, '/')) != NULL)
 						p = fn;
 				} else
 					fn = p;
+				// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 				send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
 				if (fn == p)
 					continue;
@@ -2182,6 +2254,7 @@
 		} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
 			/* Send the implied directories at the start of the
 			 * source spec, so we get their permissions right. */
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
 		}
 
@@ -2190,6 +2263,7 @@
 
 		if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
 			struct file_struct *file;
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			file = send_file_name(f, flist, fbuf, &st,
 					      FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
 					      NO_FILTERS);
@@ -2205,9 +2279,11 @@
 				}
 			} else
 				send_if_directory(f, flist, file, fbuf, len, flags);
-		} else
+		} else {
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 06 Mar 09 SHL debug
 			send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
 	}
+	} /* while */
 
 	gettimeofday(&end_tv, NULL);
 	stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/generator.c ./generator.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/generator.c	2009-12-23 11:36:26.000000000 -0800
+++ ./generator.c	2010-09-17 10:34:52.000000000 -0700
@@ -98,6 +98,10 @@
 extern int backup_suffix_len;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+// 14 Oct 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 int ignore_perishable = 0;
 int non_perishable_cnt = 0;
@@ -272,6 +276,7 @@
 	}
 
 	p = fname + dlen;
+	// 16 Feb 09 SHL fixme slash?
 	if (dlen != 1 || *fname != '/')
 		*p++ = '/';
 	remainder = MAXPATHLEN - (p - fname);
@@ -590,7 +595,7 @@
 	} else
 #endif
 	if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0)
-		return 0;
+		return 0;		// Changed
 
 	if (preserve_perms) {
 		if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
@@ -622,7 +627,7 @@
 	}
 #endif
 
-	return 1;
+	return 1;			// No change
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -646,19 +651,30 @@
 		} else if (keep_time
 		 ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
 		 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
-		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s file->modtime %u sxp->st.st_mtime %u %s(%u)\n", who_am_i(), fnamecmp, file->modtime, sxp->st.st_mtime, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme times
+			if (verbose > 1)
+				rprintf(FINFO, "%s times differ sender %u receiver %u\n", fnamecmp, file->modtime, sxp->st.st_mtime);
 			iflags |= ITEM_REPORT_TIME;
+		}
+
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
 		} else
 #endif
 		if (preserve_perms) {
-			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) {
+				// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
+				if (verbose > 1)
+					rprintf(FINFO, "%s perms differ sender %o receiver %o\n", fnamecmp, file->mode, sxp->st.st_mode);
 				iflags |= ITEM_REPORT_PERMS;
+			}
 		} else if (preserve_executability
-		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0))) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
 			iflags |= ITEM_REPORT_PERMS;
+		 }
 		if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 			iflags |= ITEM_REPORT_OWNER;
 		if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
@@ -1472,8 +1488,10 @@
 			}
 		}
 #ifdef SUPPORT_XATTRS
-		if (preserve_xattrs && statret == 1)
+		if (preserve_xattrs && statret == 1) {
+			// rprintf(FINFO, "* [%s] receive_generator running copy_xattrs fnamecmpbuf %s fname %s %s(%u)\n", who_am_i(), fnamecmpbuf, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
 			copy_xattrs(fnamecmpbuf, fname);
+		}
 #endif
 		if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
 		    && verbose && code != FNONE && f_out != -1)
@@ -1492,6 +1510,17 @@
 			}
 			need_retouch_dir_perms = 1;
 		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If source directory not archived (i.e. not writable by group)
+		// may need to touch up after file operations complete
+		// see map_os2_attributes
+		if (!need_retouch_dir_perms && os2_perms &&
+		    ~file->mode & S_IWGRP) {
+			// rprintf(FINFO, "* [%s] recv_generator dir %s needs retouch mode %o %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 14 Oct 09 SHL fixme dir perms
+			need_retouch_dir_perms = 1;
+		}
+#endif
 #endif
 
 		if (real_ret != 0 && one_file_system)
@@ -1511,7 +1540,7 @@
 				change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
 		}
 		goto cleanup;
-	}
+	} // is_dir
 
 	/* If we're not preserving permissions, change the file-list's
 	 * mode based on the local permissions and some heuristics. */
@@ -2042,10 +2071,18 @@
 	} else
 		start = end = ndx;
 
+	// rprintf(FINFO, "* [%s] touch_up_dirs start %u end %u %s(%u)\n", who_am_i(), start, end,  __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
+
 	/* Fix any directory permissions that were modified during the
 	 * transfer and/or re-set any tweaked modified-time values. */
 	for (i = start; i <= end; i++, counter++) {
+		// 23 Mar 10 SHL overcome xattrs generated by libc chmod
+#ifdef __OS2__
+		int need_xattrs_set = 0;
+#endif
 		file = flist->files[i];
+		// fname = f_name(file, NULL); // 14 Oct 09 SHL debug dir perms
+		// rprintf(FINFO, "* [%s] touch_up_dirs dir %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 		if (!S_ISDIR(file->mode)
 		 || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))
 			continue;
@@ -2056,18 +2093,80 @@
 		}
 		/* Be sure not to retouch permissions with --fake-super. */
 		fix_dir_perms = !am_root && !(file->mode & S_IWUSR);
+#ifndef __OS2__
 		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
 		 || !(need_retouch_dir_times || fix_dir_perms))
 			continue;
+else // __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived on (i.e. writable by group)
+		// See map_os2_attributes
+		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
+		 || !(need_retouch_dir_times || fix_dir_perms
+		      || !os2_perms || (~file->mode & S_IWGRP)))
+			continue;
+#endif
 		fname = f_name(file, NULL);
-		if (fix_dir_perms)
+#ifdef __OS2__
+		// 14 Oct 09 SHL Need to set time before clearing archive bit
+		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);
+		}
+#endif
+		if (fix_dir_perms) {
+			do_chmod(fname, file->mode);
+#ifdef __OS2__
+			// 25 Mar 10 SHL fixme to be sure can update EAs after setting read-only
+			// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWUSR fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			need_xattrs_set = preserve_xattrs;
+#endif
+		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived off (i.e. not writable by group)
+		// See map_os2_attributes
+		// Other os/2 perms should already be OK
+		// There is no way to know for sure if directory was modified so we check
+		else if (os2_perms && ~file->mode & S_IWGRP) {
+			STRUCT_STAT st;
+			if (link_stat(fname, &st, 0) == 0 &&
+			    ((file->mode ^ st.st_mode) & S_IWGRP)) {
+				// rprintf(FINFO, "* [%s] touch_up_dirs chmod(%s, 0%o) %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 			do_chmod(fname, file->mode);
+				// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+				// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWGRP(archive) fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+				need_xattrs_set = need_xattrs_set || preserve_xattrs;
+			}
+		}
+#endif
+#ifndef __OS2__
 		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);
 		}
+#endif
+#ifdef __OS2__
+		if (need_xattrs_set) {
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			stat_x sx;
+			// rprintf(FINFO, "* [%s] touch_up_dirs doing set_xattr for %s %s %s(%u)\n", who_am_i(), fname, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			if (verbose > 2)
+				rprintf(FINFO, "%s removing EAs generated by libc chmod %s\n", who_am_i(), fname);
+			memset(&sx, 0, sizeof(stat_x));
+			// Should not need to provide target item list to set_xattr
+			// link_stat(fname, &sx.st, 0);
+			// sx.xattr = new(item_list);
+			// *sxp.xattr = empty_xattr;
+			set_xattr(fname, file, fname, &sx);
+			// free_xattr(&sx);
+		}
+#endif
 		if (counter >= loopchk_limit) {
 			if (allowed_lull)
 				maybe_send_keepalive();
@@ -2075,7 +2174,7 @@
 				maybe_flush_socket(0);
 			counter = 0;
 		}
-	}
+	} // for
 }
 
 void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/getaddrinfo.c ./lib/getaddrinfo.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/getaddrinfo.c	2009-12-12 17:20:34.000000000 -0800
+++ ./lib/getaddrinfo.c	2010-03-25 15:21:32.000000000 -0700
@@ -403,12 +403,16 @@
 	int ret = -1;
 	char *p = NULL;
 
+	// rprintf(FINFO, "* [%s] gethostnameinfo NI_NUMERICHOST %u %s(%u)\n", who_am_i(), flags & NI_NUMERICHOST, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	if (!(flags & NI_NUMERICHOST)) {
+		// rprintf(FINFO, "* [%s] gethostnameinfo %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		struct hostent *hp = gethostbyaddr(
 				(void *)&((struct sockaddr_in *)sa)->sin_addr,
 				sizeof (struct in_addr),
 				sa->sa_family);
+		// rprintf(FINFO, "* [%s] gethostnameinfo hp %p %s(%u)\n", who_am_i(), hp, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		ret = check_hostent_err(hp);
+		// rprintf(FINFO, "* [%s] ret %d %s(%u)\n", who_am_i(), ret, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (ret == 0) {
 			/* Name looked up successfully. */
 			ret = snprintf(node, nodelen, "%s", hp->h_name);
@@ -424,6 +428,7 @@
 			return 0;
 		}
 
+		// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (flags & NI_NAMEREQD) {
 			/* If we require a name and didn't get one,
 			 * automatically fail. */
@@ -431,6 +436,7 @@
 		}
 		/* Otherwise just fall into the numeric host code... */
 	}
+	// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
 	ret = snprintf(node, nodelen, "%s", p);
 	if (ret < 0 || (size_t)ret >= nodelen) {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/sysxattrs.c ./lib/sysxattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/sysxattrs.c	2008-03-01 12:01:40.000000000 -0800
+++ ./lib/sysxattrs.c	2010-03-25 15:21:32.000000000 -0700
@@ -126,6 +126,336 @@
 	return len;
 }
 
+#elif defined(__OS2__)
+
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+
+static void map_os2_apiret(APIRET rc)
+{
+	switch (rc) {
+	case ERROR_SHARING_VIOLATION:
+		errno = EACCES;
+		break;
+	case 0:
+		// Should not have been called - try to do no harm
+		break;
+	default:
+		// 31 Jul 09 SHL fixme to map better
+		// if (verbose > 2)
+		rprintf(FINFO, "[%s] can not map OS/2 error %lu to errno\n", who_am_i(), rc);	// 31 Jul 09 SHL
+		/* Ensure non-zero */
+		if (!errno)
+			errno = EINVAL;
+
+	}
+}
+
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+	return unisetxattr (path, 0, name, value, size, 0);
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	EAOP2       eaop2 = {0,0,0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+	pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;
+	do {
+		if (path) {
+			rc = DosQueryPathInfo(path, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryPathInfo(%s, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] %s requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), path, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		else {
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryFileInfo(%u, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] handle %d requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), file, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		if (rc)
+			break;
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0) {
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value) {
+			if ((size_t)rc > size) {
+				errno = ERANGE;
+				rc = -1;
+			}
+			else {
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+		free(pgea2list);
+	if (pgea2list)
+		free(pfea2list);
+
+	return rc;
+}
+
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat;
+	if (!path && !file) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (path) {
+		rc = DosQueryPathInfo(path, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryPathInfo(%s, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] %s reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), path, stat.cbList);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryFilInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] handle %d reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), file, stat.cbList);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	if (stat.cbList <= 4) {
+		// NO ea
+		return 0;
+	}
+	//YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
+	buf = (char *)_tmalloc(stat.cbList * 2);
+	// 19 Sep 09 SHL was trapping on large copies
+	if (!buf) {
+		rprintf(FERROR, "out of memory allocating %lu at %s(%u)\n", stat.cbList * 2, __FILE__, __LINE__);	// 19 Sep 09 SHL fixme gone debug
+		return -1;
+	}
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc) {
+		rprintf(FERROR, "[%s] unilistxattr DosEnumAttribute failed with error %u at %s(%u)\n", who_am_i(), rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		_tfree(buf);
+		map_os2_apiret(rc);	// 31 Jul 09 SHL moved here to ensure errno returned
+		return -1;
+	}
+	else if (verbose > 2) {
+		if (path)
+			rprintf(FINFO, "[%s] %s has %lu DosEnumAttribute items\n", who_am_i(), path, ulCount);	// 28 Jul 08 SHL
+		else
+			rprintf(FINFO, "[%s] handle %d has %lu DosEnumAttribute items\n", who_am_i(), file, ulCount);	// 28 Jul 08 SHL
+	}
+	if (ulCount > 0) {
+		for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset)) {
+			if (pfea->cbName > 0) {
+				gotsize += pfea->cbName + 1;
+				// Avoid overflow
+				if (p && (size_t)gotsize <= size) {
+					pfea->szName[pfea->cbName] = 0;
+					strcpy(p, pfea->szName);
+					p += strlen(p) + 1;
+				}
+			}
+			if (!pfea->oNextEntryOffset)
+				break;
+		}
+	}
+	_tfree(buf);
+	if ((size_t)gotsize > size) {
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	if (verbose > 2)
+		rprintf(FINFO, "[%s] returning %ld EA list bytes\n", who_am_i(), (unsigned long)gotsize);	// 28 Jul 08 SHL
+	return gotsize;
+}
+
+int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0,0,0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosFileInfo(%u, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0,0,0};
+	PFEA2LIST   pfea2list = NULL;
+	// char * p;			// 17 May 09 SHL  fixme
+
+	if ((!path && !file) || !name || (!value && size)) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0) {
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0) {
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(FEA2LIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value) {
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetFileInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	free(pfea2list);
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
 #else
 
 #error You need to create xattr compatibility functions.
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/sysxattrs.h ./lib/sysxattrs.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/sysxattrs.h	2007-04-07 10:22:24.000000000 -0700
+++ ./lib/sysxattrs.h	2010-03-25 15:21:32.000000000 -0700
@@ -19,6 +19,13 @@
 int sys_lremovexattr(const char *path, const char *name);
 ssize_t sys_llistxattr(const char *path, char *list, size_t size);
 
+#ifdef __OS2__
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size);
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size);
+int uniremovexattr (const char *path, int file, const char *name);
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags);
+#endif
+
 #else
 
 /* No xattrs available */
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/wildmatch.c ./lib/wildmatch.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/lib/wildmatch.c	2007-05-21 22:58:58.000000000 -0700
+++ ./lib/wildmatch.c	2010-03-25 15:21:32.000000000 -0700
@@ -89,8 +89,14 @@
 	    p_ch = *++p;
 	    /* FALLTHROUGH */
 	  default:
+#ifndef __OS2__
 	    if (t_ch != p_ch)
 		return FALSE;
+#else
+	    // 18 Oct 09 SHL be case insensitive
+	    if (t_ch != p_ch && (t_ch ^ p_ch) != 0x20)
+		return FALSE;
+#endif
 	    continue;
 	  case '?':
 	    /* Match anything but '/'. */
@@ -150,8 +156,14 @@
 		    p_ch = *++p;
 		    if (!p_ch)
 			return ABORT_ALL;
+#ifndef __OS2__
 		    if (t_ch == p_ch)
 			matched = TRUE;
+#else
+		    // 18 Oct 09 SHL be case insensitive
+		    if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			matched = TRUE;
+#endif
 		} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
 		    p_ch = *++p;
 		    if (p_ch == '\\') {
@@ -159,6 +171,7 @@
 			if (!p_ch)
 			    return ABORT_ALL;
 		    }
+		    // 18 Oct 09 SHL [a-z] ranges remain case-sensitive for now
 		    if (t_ch <= p_ch && t_ch >= prev_ch)
 			matched = TRUE;
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
@@ -173,8 +186,14 @@
 			/* Didn't find ":]", so treat like a normal set. */
 			p = s - 2;
 			p_ch = '[';
+#ifndef __OS2__
 			if (t_ch == p_ch)
 			    matched = TRUE;
+#else
+			// 18 Oct 09 SHL be case insensitive
+			if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			    matched = TRUE;
+#endif
 			continue;
 		    }
 		    if (CC_EQ(s,i, "alnum")) {
@@ -218,6 +237,11 @@
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
 		} else if (t_ch == p_ch)
 		    matched = TRUE;
+#ifdef __OS2__
+		// 18 Oct 09 SHL be case insensitive
+		else if ((t_ch ^ p_ch) == 0x20)
+		    matched = TRUE;
+#endif
 	    } while (prev_ch = p_ch, (p_ch = *++p) != ']');
 	    if (matched == special || t_ch == '/')
 		return FALSE;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/ln ./ln
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/ln	2106-02-06 22:28:16.000000000 
+++ ./ln	2010-03-25 19:48:34.000000000 -0700
@@ -0,0 +1,3 @@
+# ln fake
+
+sh -c echo "$@"
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/loadparm.c ./loadparm.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/loadparm.c	2009-01-17 13:41:34.000000000 -0800
+++ ./loadparm.c	2010-11-24 13:10:54.000000000 -0800
@@ -212,7 +212,7 @@
  /* read_only; */		True,
  /* strict_modes; */		True,
  /* transfer_logging; */	False,
- /* use_chroot; */		True,
+ /* use_chroot; */		False,	// 2010-09-17 SHL libc chroot not quite right
  /* write_only; */		False,
 };
 
@@ -654,10 +654,23 @@
 	    *(char *)dest_ptr = *(char *)src_ptr;
 	    break;
 
+#ifndef __OS2__
 	  case P_PATH:
 	  case P_STRING:
 	    string_set(dest_ptr,*(char **)src_ptr);
 	    break;
+#else
+	  case P_PATH:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    // 2009-03-06 SHL Force unix slashes
+	    // 2009-05-16 SHL Use normalize_dir_slashes
+	    normalize_dir_slashes(*(char **)dest_ptr);
+	    break;
+
+	  case P_STRING:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    break;
+#endif
 
 	  default:
 	    break;
@@ -725,8 +738,14 @@
      case P_PATH:
        string_set(parm_ptr,parmvalue);
        if ((cp = *(char**)parm_ptr) != NULL) {
+	   // Chop trailing slashes unless root
 	   int len = strlen(cp);
+#ifndef __OS2__
 	   while (len > 1 && cp[len-1] == '/') len--;
+#else
+	   // 2010-11-24 SHL Use drive_spec_width
+	   while (len > drive_spec_width(cp) + 1 && cp[len-1] == '/') len--;
+#endif
 	   cp[len] = '\0';
        }
        break;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/log.c ./log.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/log.c	2009-01-17 13:41:34.000000000 -0800
+++ ./log.c	2010-03-25 15:21:32.000000000 -0700
@@ -371,6 +371,7 @@
 	va_list ap;
 	char buf[BIGPATHBUFLEN];
 	size_t len;
+	int e = errno;			// 27 Apr 09 SHL preserve errno
 
 	va_start(ap, format);
 	len = vsnprintf(buf, sizeof buf, format, ap);
@@ -403,6 +404,7 @@
 	}
 
 	rwrite(code, buf, len, 0);
+	errno = e;
 }
 
 /* This is like rprintf, but it also tries to print some
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/main.c ./main.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/main.c	2009-12-19 13:39:48.000000000 -0800
+++ ./main.c	2010-10-30 10:50:42.000000000 -0700
@@ -271,10 +271,23 @@
 
 	if (verbose || do_stats) {
 		rprintf(FCLIENT, "\n");
+#ifndef __OS2__
 		rprintf(FINFO,
 			"sent %s bytes  received %s bytes  %s bytes/sec\n",
 			human_num(total_written), human_num(total_read),
 			human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
+#else
+		{
+			// 2010-10-30 SHL show elapsed time
+			time_t t = endtime - starttime + 1;	// Always round up
+			rprintf(FINFO,
+				"sent %s bytes  received %s bytes  %s bytes/sec  elapsed %02u:%02u:%02u\n",
+				human_num(total_written),
+				human_num(total_read),
+				human_dnum((total_written + total_read)/(0.5 + t), 2),
+				t / 3600, (t / 60) % 60, t % 60);
+		}
+#endif
 		rprintf(FINFO, "total size is %s  speedup is %.2f%s\n",
 			human_num(stats.total_size),
 			(double)stats.total_size / (total_written+total_read),
@@ -532,6 +545,8 @@
 			if (!change_dir(dest_path, CD_NORMAL)) {
 				rsyserr(FERROR, errno, "change_dir#1 %s failed",
 					full_fname(dest_path));
+				// 22 Jul 09 SHL was FLOG?  why?
+				rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 				exit_cleanup(RERR_FILESELECT);
 			}
 			return NULL;
@@ -592,6 +607,8 @@
 		if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
 			rsyserr(FERROR, errno, "change_dir#2 %s failed",
 				full_fname(dest_path));
+			// 22 Jul 09 SHL was FLOG?  why?
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 
@@ -612,6 +629,8 @@
 	if (!change_dir(dest_path, CD_NORMAL)) {
 		rsyserr(FERROR, errno, "change_dir#3 %s failed",
 			full_fname(dest_path));
+		// 22 Jul 09 SHL was FLOG?  why?
+		rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 		exit_cleanup(RERR_FILESELECT);
 	}
 	*cp = '/';
@@ -703,8 +722,9 @@
 
 	if (!relative_paths) {
 		if (!change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#3 %s failed",
+			rsyserr(FERROR, errno, "change_dir#4 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -875,8 +895,9 @@
 		argc--;
 		argv++;
 		if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#4 %s failed",
+			rsyserr(FERROR, errno, "change_dir#5 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -931,6 +952,7 @@
 			if (check_filter(elp, FLOG, dir, 1) < 0)
 				goto options_rejected;
 		}
+		// 25 Sep 09 SHL fixme slashes
 		if (partial_dir && *partial_dir == '/'
 		 && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
 		    options_rejected:
@@ -1089,7 +1111,7 @@
 
 	for (i = 0; argv[i]; i++) {
 		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
+			rprintf (FERROR, "out of memory at %s(%u)\n",
 				 __FILE__, __LINE__);
 			return RERR_MALLOC;
 		}
@@ -1120,6 +1142,14 @@
 	 * command line. */
 	if ((ret = copy_argv(argv)) != 0)
 		return ret;
+#ifdef __OS2__
+	{
+		int i;
+		for (i = 0; i < argc; i++) {
+			normalize_dir_slashes(argv[i]);
+		}
+	}
+#endif
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -1443,6 +1473,7 @@
 	 * (implemented by forking "pwd" and reading its output) doesn't
 	 * work when there are other child processes.  Also, on all systems
 	 * that implement getcwd that way "pwd" can't be found after chroot. */
+	// rprintf(FINFO, "* [%s] %s %s(%u)\n", who_am_i(), "(null)", __FILE__, __LINE__);	// 28 Jul 08 SHL debug chdir
 	change_dir(NULL, CD_NORMAL);
 
 	init_flist();
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/options.c ./options.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/options.c	2009-12-21 14:40:40.000000000 -0800
+++ ./options.c	2010-03-25 15:21:32.000000000 -0700
@@ -52,6 +52,10 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+// 13 Jun 09 SHL Added
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -116,7 +120,11 @@
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
+#ifndef __OS2__
 int modify_window = 0;
+#else
+int modify_window = 1;			// 28 Jul 09 SHL allow for 2 second resolution
+#endif
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
@@ -262,6 +270,10 @@
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
 	rprintf(f, "Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.\n");
 	rprintf(f, "Web site: http://rsync.samba.org/\n");
+#ifdef __OS2__ // 22 Jul 09 SHL
+	rprintf(f, "Built by Steven H. Levine " __DATE__ " " __TIME__ "\n");
+	rprintf(f, "Built with GCC " __VERSION__ "\n");
+#endif
 	rprintf(f, "Capabilities:\n");
 	rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
 		(int)(sizeof (OFF_T) * 8),
@@ -338,6 +350,9 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+#ifdef __OS2__
+  rprintf(F," -2, --os2-perms             preserve native OS/2 permissions\n");
+#endif
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
 #ifdef SUPPORT_ACLS
@@ -480,6 +495,10 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+#ifdef __OS2__
+  {"os2-perms",       '2', POPT_ARG_NONE,   0, '2', 0, 0 },
+  {"no-os2-perms",     0,  POPT_ARG_VAL,    &os2_perms, 0, 0, 0 },
+#endif
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
@@ -1033,6 +1052,10 @@
 		case OPT_EXCLUDE_FROM:
 		case OPT_INCLUDE_FROM:
 			arg = poptGetOptArg(pc);
+#ifdef __OS2__
+			// 18 Oct 09 SHL
+			normalize_dir_slashes((char *)arg);	// hack cough - override const
+#endif
 			if (sanitize_paths)
 				arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 			if (daemon_filter_list.head) {
@@ -1140,6 +1163,13 @@
 			}
 			break;
 
+// 14 Jun 09 SHL
+#ifdef __OS2__
+		case '2':
+			os2_perms = 1;
+			preserve_perms = 1;	// Implied
+			break;
+#endif
 		case OPT_WRITE_BATCH:
 			/* batch_name is already set */
 			write_batch = 1;
@@ -1475,6 +1505,7 @@
 			char *dir;
 			if (!*backup_dir)
 				goto options_rejected;
+			// 25 Sep 09 SHL fixme slashes
 			dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
 			clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
 			if (check_filter(elp, FLOG, dir, 1) < 0)
@@ -1783,6 +1814,12 @@
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
 		argstr[x++] = 'E';
+// 13 Jun 09 SHL
+#ifdef __OS2__
+	if (os2_perms)
+		argstr[x++] = '2';
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls)
 		argstr[x++] = 'A';
@@ -2103,6 +2140,10 @@
 			break;
 		}
 		if (*s == ':' || *s == '/') {
+#			ifdef __OS2__	// 29 Jun 09 SHL don't confuse drive letter with host spec
+			if (*s == ':' && s == str + 1 && drive_spec_width(s - 1) != 0)
+				continue;
+#			endif
 			if (!hostlen)
 				hostlen = s - host_start;
 			if (*s++ == '/') {
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/params.c ./params.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/params.c	2007-11-22 09:51:20.000000000 -0800
+++ ./params.c	2010-11-24 13:39:02.000000000 -0800
@@ -166,9 +166,24 @@
   {
   pos--;
   while( pos >= 0 && isSpace(line + pos) )
-     pos--;
+     pos--;				// Find last non-whitespace
 
+#ifndef __OS2__
   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
+#else
+  // 2010-11-24 SHL handle path specs like c:\ special to avoid
+  // losing \ before it can be mapped to /
+  // Assume parsing value so name and value nul separated
+  if ( pos >= 0) {
+    if (line[pos] != '\\')
+      pos = -1;				// Not continued
+    else if (pos >= 3) {
+      if (*(line + pos - 3) == 0 && drive_spec_width(line + pos - 2) > 0)
+        pos = -1;			// Not continued
+    }
+  }
+  return pos;
+#endif
   } /* Continuation */
 
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/proto.h ./proto.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/proto.h	2009-12-31 13:20:00.000000000 -0800
+++ ./proto.h	2010-03-25 17:16:04.000000000 -0700
@@ -378,6 +378,8 @@
 int flist_ndx_pop(flist_ndx_list *lp);
 void *expand_item_list(item_list *lp, size_t item_size,
 		       const char *desc, int incr);
+void normalize_dir_slashes(char *path);
+void assert_no_dir_slashes(char *path);
 void free_xattr(stat_x *sxp);
 int get_xattr(const char *fname, stat_x *sxp);
 int copy_xattrs(const char *source, const char *dest);
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/readme.os2 ./readme.os2
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/readme.os2	2106-02-06 22:28:16.000000000 
+++ ./readme.os2	2010-04-08 22:48:38.000000000 -0700
@@ -0,0 +1,87 @@
+Rsync v3.0.7 compiled with GCC 4.3.4 & kLibc v0.6.3
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+We (Paul and Steven) are using this as both client and server for backups
+
+Changes in this version:
+- Updated to v3.0.6
+- Incorporated a bunch of patches from Steven Levine
+- Move to GCC 4.3.4 as a compiler
+- --xattrs now works for remote servers
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 permissions
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+- Defaulted to %ETC% for rsyncd.conf
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+  Run make install
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Cheers,
+
+Paul Smedley
+Adelaide, Australia
+
+and
+
+Steven Levine
+Costa Mesa, California, USA
+
+09 April 2010
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/readme.shl ./readme.shl
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/readme.shl	2106-02-06 22:28:16.000000000 
+++ ./readme.shl	2010-11-24 13:40:04.000000000 -0800
@@ -0,0 +1,101 @@
+
+Rsync v3.0.7 compiled with GCC 3.3.5 & kLibc v0.6.3 by Steven H. Levine
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+These are Steven Levine's notes
+See readme.os2 for Paul Smedley's notes
+
+Changes in this version (newest first):
+
+- rsync conf now accepts root paths like c:\
+- --stats shows elapsed time
+- Filter pattern matches are now case-insensitive
+- Added logic to ensure directory xattrs updated after libc chmod changes xattrs
+- Started work on supporting testsuite
+- Updated to rsync v3.0.7 sources
+- Migrated existing 3.0.6 patches
+
+Binary builds are available at
+
+  http://mantis.smedley.info/view.php?id=366
+
+Known issues
+
+- Newly created directories do not always get correct libc extended attributes
+  Next rsync run will set the libc extended attributes to the correct values
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 readonly permissions along
+  with the system, hidden and archive file/directory attributes
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke a some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+
+  Run make install
+
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Have fun,
+
+Steven Levine
+Costa Mesa, California, USA
+
+2010-11-24 SHL
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/receiver.c ./receiver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/receiver.c	2009-04-12 12:48:58.000000000 -0700
+++ ./receiver.c	2010-03-25 15:21:32.000000000 -0700
@@ -471,7 +471,7 @@
 				handle_delayed_updates(local_name);
 			send_msg(MSG_DONE, "", 0, 0);
 			continue;
-		}
+		} // NDX_DONE
 
 		if (ndx - cur_flist->ndx_start >= 0)
 			file = cur_flist->files[ndx - cur_flist->ndx_start];
@@ -809,8 +809,8 @@
 			if (inc_recurse)
 				send_msg_int(MSG_NO_SEND, ndx);
 			break;
-		}
-	}
+		} // switch
+	} // while
 	if (make_backups < 0)
 		make_backups = -make_backups;
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/rsync.c ./rsync.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/rsync.c	2009-12-19 13:39:48.000000000 -0800
+++ ./rsync.c	2010-09-17 11:20:10.000000000 -0700
@@ -385,6 +385,8 @@
 	mode_t new_mode = file->mode;
 	int inherit;
 
+	// rprintf(FINFO, "* [%s] set_file_attrs fname %s mode %o file %p sxp %p %s(%u)\n", who_am_i(), fname, file->mode, file, sxp, __FILE__, __LINE__); // 27 Apr 09 SHL debug perms
+
 	if (!sxp) {
 		if (dry_run)
 			return 1;
@@ -497,6 +499,7 @@
 
 #ifdef HAVE_CHMOD
 	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+		// rprintf(FINFO, "* [%s] set_file_attrs fname %s sxp->st.st_mode %o new_mode %o %s(%u)\n", who_am_i(), fname, sxp->st.st_mode, new_mode, __FILE__, __LINE__); // 27 Apr 09 SHL debug perms
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
@@ -554,8 +557,13 @@
 		    int overwriting_basis)
 {
 	int ret;
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
 	const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
+	if (partialptr && drive_spec_width(partialptr))
+		rprintf(FINFO, "* [%s] finish_transfer partialptr %s fname %s fnamecmp %s %s(%u)\n", who_am_i(), partialptr, fname, fnamecmp, __FILE__, __LINE__); // 25 Sep 09 SHL debug slashes
+
 	if (inplace) {
 		if (verbose > 2)
 			rprintf(FINFO, "finishing %s\n", fname);
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/rsync.h ./rsync.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/rsync.h	2009-12-23 11:36:26.000000000 -0800
+++ ./rsync.h	2010-03-25 15:21:32.000000000 -0700
@@ -1145,3 +1145,12 @@
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+// 05 Mar 09 SHL support drive letters
+#ifndef __OS2__
+#define drive_spec_width(p) 0
+#define is_abs_path(p) (*(p) == '/')
+#else
+#define drive_spec_width(p) ((isalpha(*(p)) && *((p) + 1) == ':') ? 2 : 0)
+#define is_abs_path(p) (*((p) + drive_spec_width(p)) == '/')
+#endif
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/runtests.sh ./runtests.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/runtests.sh	2008-05-18 07:00:48.000000000 -0700
+++ ./runtests.sh	2010-03-25 19:57:14.000000000 -0700
@@ -239,8 +239,8 @@
     $setfacl_nodef "$scratchdir" || true
     chmod g-s "$scratchdir"
     case "$srcdir" in
-    /*) ln -s "$srcdir" "$scratchdir/src" ;;
-    *)  ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
+    /*) echo ln -s "$srcdir" "$scratchdir/src" ;;
+    *)  echo ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
     esac
     return 0
 }
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/sender.c ./sender.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/sender.c	2009-12-12 17:23:02.000000000 -0800
+++ ./sender.c	2010-03-25 15:21:32.000000000 -0700
@@ -366,7 +366,7 @@
 		send_msg_int(MSG_IO_ERROR, io_error);
 
 	if (verbose > 2)
-		rprintf(FINFO, "send files finished\n");
+		rprintf(FINFO, "send_files finished\n");	// 06 Mar 09 SHL
 
 	match_report();
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/syscall.c ./syscall.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/syscall.c	2009-01-17 13:41:34.000000000 -0800
+++ ./syscall.c	2010-03-25 15:21:32.000000000 -0700
@@ -28,6 +28,24 @@
 #ifdef HAVE_SYS_ATTR_H
 #include <sys/attr.h>
 #endif
+// 06 Mar 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define setmode
+#if defined HAVE_SETMODE && O_BINARY && __OS2__
+// From gcc io.h
+int setmode (int, int);
+// From gcc os2emx.h
+#endif
+#ifdef __OS2__ // 01 Aug 09 SHL
+// 01 Aug 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define _sopen
+int _sopen (__const__ char *, int, int, ...);	// hack cough
+#include "share.h"			// SH_DENYNO
+#endif
+
+#if defined __OS2__
+// 27 Apr 09 SHL Need definitions for FILE_...
+#define INCL_DOS
+// #include <os2.h>
+#include <os2emx.h>
+#endif
 
 extern int dry_run;
 extern int am_root;
@@ -35,6 +53,10 @@
 extern int list_only;
 extern int preserve_perms;
 extern int preserve_executability;
+// 13 Jun 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -138,12 +160,32 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+#ifdef __OS2__
+	int fd;
+#endif
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
 
+#ifndef __OS2__
 	return open(pathname, flags | O_BINARY, mode);
+#else
+	// 31 Jul 09 SHL if open fails, try shared open in case file already opened for write
+	fd = open(pathname, flags | O_BINARY, mode);
+	if (fd == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
+		fd = _sopen(pathname, flags | O_BINARY, SH_DENYNO, mode);
+		if (fd != -1)
+			rprintf(FINFO, "[%s] opened %s for shared write - file may change during sync\n", who_am_i(), pathname);
+		else if (verbose) {
+			int e = errno;
+			rsyserr(FINFO, errno, "do_open _sopen fallback failed for %s", pathname);
+			errno = e;
+		}
+
+	}
+	return fd;
+#endif
 }
 
 #ifdef HAVE_CHMOD
@@ -152,6 +194,9 @@
 	int code;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+
+	// rprintf(FINFO, "* [%s] do_chmod path %s requested mode %o %s(%u)\n", who_am_i(), path, mode, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 	if (S_ISLNK(mode)) {
 #ifdef HAVE_LCHMOD
 		code = lchmod(path, mode & CHMOD_BITS);
@@ -164,10 +209,69 @@
 		attrList.commonattr = ATTR_CMN_ACCESSMASK;
 		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
 #else
-		code = 1;
+		code = 1;		// Can not set symlink
 #endif
 	} else
+#ifndef __OS2__
+		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+#else
+	{
+		ULONG attributes = 0;
+		if (os2_perms) {
+			// Unmap mode to recover native OS/2 attributes
+			// See map_os2_attributes
+			// If not readable by owner, hidden
+			if (~mode & S_IRUSR)
+				attributes |= FILE_HIDDEN;
+			// If readable by group, system
+			if (mode & S_IRGRP)
+				attributes |= FILE_SYSTEM;
+			// If writable by group, archived
+			if (mode & S_IWGRP)
+				attributes |= FILE_ARCHIVED;
+			// Reset group rw bits to match other rw bits - hack cough
+			if (mode & S_IROTH)
+				mode |= S_IRGRP;
+			else
+				mode &= ~S_IRGRP;
+			if (mode & S_IWOTH)
+				mode |= S_IWGRP;
+			else
+				mode &= ~S_IWGRP;
+		}
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+		if (!code && os2_perms) {
+			// Adjust native attributes not handled by chmod - system, hidden, archived
+			// Maybe libc will do this someday
+			// chmod already handles readonly
+			// Adjust attributes if any but archived set or if archived not set in requested attributes
+			FILESTATUS3 fs3;
+			APIRET apiret = DosQueryPathInfo((PCSZ)path,
+							 FIL_STANDARD,
+							 &fs3,
+							 sizeof(fs3));
+			// 26 Sep 09 SHL fixme perms - set code on failure - need map_apiret_errno()
+			if (apiret)
+				rprintf(FERROR, "[%s] DosQueryPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+			else {
+				ULONG m = attributes | (fs3.attrFile & ~(FILE_SYSTEM | FILE_HIDDEN | FILE_ARCHIVED));
+				if (m != fs3.attrFile) {
+					ULONG old_attrFile = fs3.attrFile;
+					fs3.attrFile = m;
+					apiret = DosSetPathInfo((PCSZ)path,
+								 FIL_STANDARD,
+								 &fs3, sizeof(fs3),
+								 0);
+					if (apiret)
+						rprintf(FERROR, "[%s] DosSetPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+					// 17 Sep 09 SHL os2_perms
+					else if (verbose > 1)
+						rprintf(FINFO, "[%s] changed %s attrFile from %lx to %lx (attributes %lx)\n", who_am_i(), path, old_attrFile, fs3.attrFile, attributes);	// 21 Jul 09 SHL
+				}
+			}
+		}
+	}
+#endif
 	if (code != 0 && (preserve_perms || preserve_executability))
 		return code;
 	return 0;
@@ -238,12 +342,55 @@
 #endif
 }
 
+#ifdef __OS2__
+
+/**
+ * Map native OS/2 attributes to something rsync can send
+ * See do_chmod for unmap logic
+ */
+
+static void map_os2_attributes(STRUCT_STAT *st)
+{
+	// If hidden, readable by none
+	if (st->st_attr & FILE_HIDDEN)
+		st->st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+	// If readonly, writable by none
+	if (st->st_attr & FILE_READONLY)
+		st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+
+	// Steal group bits for native attributes without obvious mappings - hack cough
+	// If system, readable by group
+	if (st->st_attr & FILE_SYSTEM)
+		st->st_mode |= S_IRGRP;
+	else
+		st->st_mode &= ~S_IRGRP;
+	// If archived, writable by group
+	if (st->st_attr & FILE_ARCHIVED)
+		st->st_mode |= S_IWGRP;
+	else
+		st->st_mode &= ~S_IWGRP;
+}
+
+#endif
+
 int do_stat(const char *fname, STRUCT_STAT *st)
 {
 #ifdef USE_STAT64_FUNCS
 	return stat64(fname, st);
 #else
+#ifndef __OS2__
 	return stat(fname, st);
+#else
+	int code;
+	code = stat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
@@ -253,7 +400,19 @@
 # ifdef USE_STAT64_FUNCS
 	return lstat64(fname, st);
 # else
+#ifndef __OS2__
 	return lstat(fname, st);
+#else
+	// 27 Apr 09 SHL map OS/2 permissions
+	int code = lstat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 # endif
 #else
 	return do_stat(fname, st);
@@ -265,7 +424,19 @@
 #ifdef USE_STAT64_FUNCS
 	return fstat64(fd, st);
 #else
+#ifndef __OS2__
 	return fstat(fd, st);
+#else
+	int code;
+	code = fstat(fd, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %u mode from %o to %o (st_attr %o)\n", who_am_i(), fd, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/t_stub.c ./t_stub.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/t_stub.c	2009-01-17 13:41:34.000000000 -0800
+++ ./t_stub.c	2010-03-25 17:22:00.000000000 -0700
@@ -32,6 +32,12 @@
 char *module_dir;
 struct filter_list_struct daemon_filter_list;
 
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
+int verbose = 0;
+
+
  void rprintf(UNUSED(enum logcode code), const char *format, ...)
 {
 	va_list ap;
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/t_unsafe.c ./t_unsafe.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/t_unsafe.c	2009-01-17 13:41:34.000000000 -0800
+++ ./t_unsafe.c	2010-03-25 17:21:50.000000000 -0700
@@ -27,7 +27,6 @@
 int am_root = 0;
 int read_only = 0;
 int list_only = 0;
-int verbose = 0;
 int preserve_perms = 0;
 int preserve_executability = 0;
 
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/testsuite/rsync.fns ./testsuite/rsync.fns
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/testsuite/rsync.fns	2009-12-13 19:35:00.000000000 -0800
+++ ./testsuite/rsync.fns	2010-03-25 19:58:32.000000000 -0700
@@ -150,7 +150,7 @@
 
     echo $ECHO_N "This file has no trailing lf$ECHO_C" > "$fromdir/nolf"
     umask 0
-    ln -s nolf "$fromdir/nolf-symlink"
+    echo ln -s nolf "$fromdir/nolf-symlink"
     umask 022
 
     cat "$srcdir"/*.c > "$fromdir/text"
@@ -319,10 +319,10 @@
 build_symlinks() {
     mkdir "$fromdir"
     date >"$fromdir/referent"
-    ln -s referent "$fromdir/relative"
-    ln -s "$fromdir/referent" "$fromdir/absolute"
-    ln -s nonexistent "$fromdir/dangling"
-    ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
+    echo ln -s referent "$fromdir/relative"
+    echo ln -s "$fromdir/referent" "$fromdir/absolute"
+    echo ln -s nonexistent "$fromdir/dangling"
+    echo ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
 }
 
 test_fail() {
@@ -345,7 +345,7 @@
 }
 
 # Determine what shell command will appropriately test for links.
-ln -s foo "$scratchdir/testlink"
+echo ln -s foo "$scratchdir/testlink"
 for cmd in test /bin/test /usr/bin/test /usr/ucb/bin/test /usr/ucb/test
 do
     for switch in -h -L
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/util.c ./util.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/util.c	2009-03-03 08:57:42.000000000 -0800
+++ ./util.c	2010-11-24 13:45:56.000000000 -0800
@@ -23,6 +23,10 @@
 #include "rsync.h"
 #include "ifuncs.h"
 
+#ifdef __OS2__
+#include <os2emx.h>
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int module_id;
@@ -191,6 +195,10 @@
 	char *p;
 	int ret = 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width
+	fname += drive_spec_width(fname);		/* Bypass drive letter */
+#endif /* __OS2__ */
+
 	while (*fname == '/')
 		fname++;
 	while (strncmp(fname, "./", 2) == 0)
@@ -420,6 +428,8 @@
 {
 	int tries = 4;
 
+	// rprintf(FINFO, "* [%s] robust_rename %s->%s %s(%u)\n", who_am_i(), from, to, __FILE__, __LINE__); // 2009-04-27 SHL debug perms
+
 	while (tries--) {
 		if (do_rename(from, to) == 0)
 			return 0;
@@ -444,6 +454,27 @@
 				return -2;
 			do_unlink(from);
 			return 1;
+#ifdef __OS2__ // 2009-04-27 SHL
+		// libc rename semantics differs from linux
+		// clear readonly if this caused rename to fail
+		case EACCES:
+		{
+			STRUCT_STAT st;
+			int code;
+			if (verbose)
+				rprintf(FINFO, "[%s] robust_rename retrying %s after EACCES\n", who_am_i(), to);	// 2009-07-22 SHL
+			code = do_stat(to, &st);
+			if (!code) {
+				// 2009-04-27 SHL fixme to use st_mode when libc fixed
+				if (st.st_attr & FILE_READONLY) {
+					st.st_mode |= S_IWUSR;
+					code = do_chmod(to, st.st_mode);
+					if (!code)
+						break;	// Try again
+				}
+			}
+		}
+#endif
 		default:
 			return -1;
 		}
@@ -818,10 +849,18 @@
 {
 	char *limit = name - 1, *t = name, *f = name;
 	int anchored;
+#ifdef __OS2__
+	int drive_letter_adj;	// 0 if not, 2 if yes 2008-12-15 SHL
+#endif
 
 	if (!name)
 		return 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width...
+	drive_letter_adj = drive_spec_width(name);
+	f += drive_letter_adj;			// Keep drive letter
+	t += drive_letter_adj;
+#endif /* __OS2__ */
 	if ((anchored = *f == '/') != 0) {
 		*t++ = *f++;
 #ifdef __CYGWIN__
@@ -869,10 +908,18 @@
 		while (*f && (*t++ = *f++) != '/') {}
 	}
 
+#ifndef __OS2__ // 2009-02-06 SHL
 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 		t--;
 	if (t == name)
 		*t++ = '.';
+#else
+	if (t > name + anchored + drive_letter_adj && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
+		t--;
+	if (t == name + drive_letter_adj)
+		*t++ = '.';		// Ensure not empty
+#endif
+
 	*t = '\0';
 
 	return t - name;
@@ -906,14 +953,28 @@
 	char *start, *sanp;
 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 
+	// rprintf(FINFO, "* [%s] sanitize_path p %s %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
 	if (dest != p) {
 		int plen = strlen(p);
-		if (*p == '/') {
+		int drive_letter_adj = drive_spec_width(p);	// 0 if not, 2 if yes 2008-12-15 SHL
+#ifndef __OS2__
+		if (*p == '/')
+#else // 2009-02-06 SHL use is_abs_path...
+		if (!is_abs_path(p)) {
+			if (drive_letter_adj)
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
+		} else
+#endif
+		{
 			if (!rootdir)
 				rootdir = module_dir;
 			rlen = strlen(rootdir);
 			depth = 0;
+#ifndef __OS2__
 			p++;
+#else
+			p += drive_spec_width(p) + 1;
+#endif
 		}
 		if (dest) {
 			if (rlen + plen + 1 >= MAXPATHLEN)
@@ -922,8 +983,13 @@
 			out_of_memory("sanitize_path");
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
+#ifndef __OS2__
 			if (rlen > 1)
 				dest[rlen++] = '/';
+#else
+			if (rlen > 1 + drive_letter_adj)
+				dest[rlen++] = '/';
+#endif
 		}
 	}
 
@@ -967,6 +1033,20 @@
 		}
 		/* copy one component through next slash */
 		while (*p && (*sanp++ = *p++) != '/') {}
+#if 0 // 2009-05-16 SHL fixme to be gone
+#ifndef __OS2__
+		while (*p && (*sanp++ = *p++) != '/') {}
+#else
+		while(*p) {
+			char c = *p++;
+			if (c == '\\')
+				c = '/';
+			*sanp++ = c;
+			if (c == '/')
+				break;
+		}
+#endif
+#endif
 	}
 	if (sanp == dest) {
 		/* ended up with nothing, so put in "." component */
@@ -974,16 +1054,23 @@
 	}
 	*sanp = '\0';
 
+	// rprintf(FINFO, "* [%s] sanitize_path dest %s %s(%u)\n", who_am_i(), dest, __FILE__, __LINE__); // 2009-02-06 SHL debug
+
+	// 2009-05-16 SHL  fixme to be gone
+	assert_no_dir_slashes(dest);
+
 	return dest;
 }
 
 /* Like chdir(), but it keeps track of the current directory (in the
  * global "curr_dir"), and ensures that the path size doesn't overflow.
- * Also cleans the path using the clean_fname() function. */
+ * Also cleans the path using the clean_fname() function.
+ * Returns 1 of change OK.  Otherwise 0 */
 int change_dir(const char *dir, int set_path_only)
 {
 	static int initialised;
 	unsigned int len;
+	// rprintf(FINFO, "* [%s] change_dir dir %s initialised %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", initialised, __FILE__, __LINE__); // 2009-04-27 SHL debug perms
 
 	if (!initialised) {
 		initialised = 1;
@@ -992,6 +1079,7 @@
 			exit_cleanup(RERR_FILESELECT);
 		}
 		curr_dir_len = strlen(curr_dir);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 	}
 
 	if (!dir)	/* this call was probably just to initialize */
@@ -1001,23 +1089,49 @@
 	if (len == 1 && *dir == '.')
 		return 1;
 
-	if (*dir == '/') {
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(dir)) {
+		// Absolute path
 		if (len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifndef __OS2__ // 2008-07-28 SHL
 		if (!set_path_only && chdir(dir))
 			return 0;
 		memcpy(curr_dir, dir, len + 1);
+#else
+		if (!set_path_only) {
+			if (chdir(dir)) {
+				rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+			if (drive_spec_width(dir) && _chdrive(*dir)) {
+				rprintf(FERROR, "[%s] change_dir _chdrive failed for dir %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+		}
+		memcpy(curr_dir, dir, len + 1);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
+#endif
 	} else {
+		// Relative path
 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifdef __OS2__
+		if (drive_spec_width(dir)) {
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			errno = EINVAL;
+			return -1;
+		}
+#endif
 		curr_dir[curr_dir_len] = '/';
 		memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
 
 		if (!set_path_only && chdir(curr_dir)) {
+			rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
 			curr_dir[curr_dir_len] = '\0';
 			return 0;
 		}
@@ -1042,12 +1156,15 @@
 {
 	unsigned int len;
 
-	if (*path != '/') { /* Make path absolute. */
+	// 2009-03-06 SHL use is_abs_path
+	if (!is_abs_path(path)) { /* Make path absolute. */
 		int len = strlen(path);
+		if (drive_spec_width(path))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2008-07-28 SHL
 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
-		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
+		memcpy(curr_dir + curr_dir_len + 1, path + drive_spec_width(path), len + 1);
 		if (!(path = strdup(curr_dir)))
 			out_of_memory("normalize_path");
 		curr_dir[curr_dir_len] = '\0';
@@ -1056,7 +1173,9 @@
 			out_of_memory("normalize_path");
 	}
 
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 	len = clean_fname(path, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 
 	if (len_ptr)
 		*len_ptr = len;
@@ -1078,9 +1197,14 @@
 	if (result)
 		free(result);
 
-	if (*fn == '/')
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(fn))
 		p1 = p2 = "";
 	else {
+#ifdef __OS2__
+		if (drive_spec_width(fn))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-02-06 SHL
+#endif
 		p1 = curr_dir + module_dirlen;
 		for (p2 = p1; *p2 == '/'; p2++) {}
 		if (*p2)
@@ -1109,6 +1233,9 @@
 
 	if ((fn = strrchr(fname, '/')) != NULL) {
 		fn++;
+		// 2009-09-25 SHL fixme slashes - handle drive letter if needed
+		if (partial_dir && drive_spec_width(partial_dir))
+			rprintf(FINFO, "* [%s] partial_dir_fname partial_dir %s fname %s %s(%u)\n", who_am_i(), partial_dir, fname, __FILE__, __LINE__); // 2009-09-25 SHL debug slashes
 		if (*partial_dir != '/') {
 			int len = fn - fname;
 			strncpy(t, fname, len); /* safe */
@@ -1140,6 +1267,7 @@
 
 	if (fname != partial_fname)
 		return 1;
+	// 2009-09-25 SHL fixme slashes?
 	if (!create && *partial_dir == '/')
 		return 1;
 	if (!(fn = strrchr(partial_fname, '/')))
@@ -1690,3 +1818,24 @@
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+#ifdef __OS2__ // 2009-05-16 SHL
+/**
+ * Convert OS/2 backslashes to unix forward slashes
+ */
+void normalize_dir_slashes(char *path)
+{
+	// 2010-11-24 SHL rework for more speed
+	if (path) {
+		char *p = path;
+		while((p = strchr(p, '\\')) != NULL)
+			*p++ = '/';
+	}
+}
+
+void assert_no_dir_slashes(char *path)
+{
+	if (path && strchr(path, '\\') != 0)
+		rprintf(FERROR, "[%s] unexpected backslash in path %s %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2009-02-06 SHL
+}
+#endif // __OS2__
diff -r -u -w -N -x'0_*' -x'*_shl' -x'*_shl.*' -x'*.diff' -x'*-20[01][0-9][01][0-9]*' -x'*-20[01][0-9]-[01][0-9]*' -xctags.tag -x'*.o' -x'*.map' -x'*.exe' -x'config.*' -x'*.sym' -xdummy -xMakefile -xshconfig -xrounding.h -x'0_*/*' -x'0~_*' -x.saved -x'*~' -x'*#' -xtest.log -x'*.old' I:/sla_dev2_browse/rsync/rsync-3.0.7/xattrs.c ./xattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.7/xattrs.c	2009-08-14 07:04:24.000000000 -0700
+++ ./xattrs.c	2010-09-17 11:20:40.000000000 -0700
@@ -110,6 +110,8 @@
 {
 	const rsync_xa *xa1 = x1;
 	const rsync_xa *xa2 = x2;
+	// rprintf(FINFO, "* [%s] rsync_xal_compare_names xa1.name %s xa2.name %s %s(%u)\n", who_am_i(), xa1->name, xa2->name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
 	return strcmp(xa1->name, xa2->name);
 }
 
@@ -141,7 +143,9 @@
 				fname, arg);
 			return -1;
 		}
+		/* Expand buffer - get size */
 		list_len = sys_llistxattr(fname, NULL, 0);
+		/* Should not occur */
 		if (list_len < 0) {
 			arg = 0;
 			goto got_error;
@@ -240,9 +244,11 @@
 			 || (am_root < 0
 			  && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
 			   || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
-			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
+			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) {
+				// rprintf(FINFO, "* [%s] rsync_xal_get skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 				continue;
 		}
+		}
 
 		datum_len = name_len; /* Pass extra size to get_xattr_data() */
 		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -283,10 +289,12 @@
 {
 	sxp->xattr = new(item_list);
 	*sxp->xattr = empty_xattr;
+	// rprintf(FINFO, "* [%s] get_xattr fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 	if (rsync_xal_get(fname, sxp->xattr) < 0) {
 		free_xattr(sxp);
 		return -1;
 	}
+	// rprintf(FINFO, "* [%s] get_xattr count %d %s(%u)\n", who_am_i(), sxp->xattr ? sxp->xattr->count : -1, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 	return 0;
 }
 
@@ -459,11 +467,13 @@
 	snd_rxa = lst->items;
 	snd_cnt = lst->count;
 
+	// rprintf(FINFO, "* [%s] xattr_diff fname %s rec_cnt %u snd_cnt %u find_all %u %s(%u)\n", who_am_i(), file->basename, rec_cnt, snd_cnt, find_all, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
+
 	/* 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) {
 		if (!find_all)
-			return 1;
+			return 1;	// Say different
 		xattrs_equal = 0;
 	}
 
@@ -485,7 +495,7 @@
 		}
 		if (!same) {
 			if (!find_all)
-				return 1;
+				return 1;	// Say different
 			xattrs_equal = 0;
 		}
 
@@ -502,6 +512,8 @@
 	if (rec_cnt)
 		xattrs_equal = 0;
 
+	// rprintf(FINFO, "* [%s] xattr_diff xattrs_equal %u %s(%u)\n", who_am_i(), xattrs_equal, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
+
 	return !xattrs_equal;
 }
 
@@ -652,6 +664,8 @@
 		temp_xattr.count = 0;
 	}
 
+	// rprintf(FINFO, "* [%s] receive_xattr %s read count %u am_root %u %s(%u)\n", who_am_i(), file->basename, count, am_root, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
 	for (num = 1; num <= count; num++) {
 		char *ptr, *name;
 		rsync_xa *rxa;
@@ -698,12 +712,14 @@
 			memcpy(name, RSYNC_PREFIX, RPRE_LEN);
 		} else {
 			free(ptr);
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 			continue;
 		}
 #endif
 		/* No rsync.%FOO attributes are copied w/o 2 -X options. */
 		if (preserve_xattrs < 2 && name_len > RPRE_LEN
 		 && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 			free(ptr);
 			continue;
 		}
@@ -715,13 +731,17 @@
 		rxa->num = num;
 	}
 
-	if (need_sort && count > 1)
-		qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
+	// rprintf(FINFO, "* [%s] receive_xattr temp_xattr.items %p temp_xattr.count %u %s(%u)\n", who_am_i(), temp_xattr.items, temp_xattr.count, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
+	// 28 Jul 08 SHL sort number used not number malloced
+	if (need_sort && temp_xattr.count > 1)
+		qsort(temp_xattr.items, temp_xattr.count, sizeof (rsync_xa), rsync_xal_compare_names);
 
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
 
 	F_XATTR(file) = ndx;
+	// rprintf(FINFO, "* [%s] receive_xattr %s ndx %u count %d %s(%u)\n", who_am_i(), file->basename, ndx, rsync_xal_l.count, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 }
 
 /* Turn the xattr data in stat_x into cached xattr data, setting the index
@@ -770,6 +790,7 @@
 	size_t name_len;
 	int ret = 0;
 
+	// rprintf(FINFO, "* [%s] rsync_xal_set fname %s fnamecmp %s %s(%u)\n", who_am_i(), fname, fnamecmp, __FILE__, __LINE__); // 23 Mar 10 SHL debug libc chmod xattrs
 	/* This puts the current name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(fname)) < 0)
 		return -1;

Steven Levine

2010-11-25 08:52

manager  

rsync-3.0.7-20101124-shl.zip (302,849 bytes)

Steven Levine

2010-11-25 08:54

manager   ~0001769

rsync-3.0.7-20101124-shl.zip is an rsync binary built with the rsync-3.0.7-20101124-shl.diff patch set.

It adjusts the config file parser to accept paths of the form c:\.

It also adds elapsed time to the --stats output.

Steven Levine

2011-04-26 14:44

manager  

rsync-3.0.8-20110425-shl.zip (329,391 bytes)

Steven Levine

2011-04-26 14:44

manager  

rsync-3.0.8-20110425-shl.diff (112,670 bytes)
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/Makefile.in ./Makefile.in
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/Makefile.in	2011-03-26 10:01:36.000000000 -0700
+++ ./Makefile.in	2011-04-25 22:06:26.000000000 -0700
@@ -12,6 +12,7 @@
 CFLAGS=@CFLAGS@
 CPPFLAGS=@CPPFLAGS@
 EXEEXT=@EXEEXT@
+# 14 Jun 09 SHL fixme to do bldlevel strings
 LDFLAGS=@LDFLAGS@
 
 INSTALLCMD=@INSTALL@
@@ -42,7 +43,8 @@
 	popt/popthelp.o popt/poptparse.o
 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
 
-TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
+# 25 Mar 10 SHL
+TLS_OBJ = tls.o t_stub.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
@@ -68,6 +70,11 @@
 	-mkdir -p ${DESTDIR}${mandir}/man5
 	if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
 	if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
+	if test -f readme.os2; then ${INSTALLMAN} -m 644 readme.os2 ${DESTDIR}${prefix}; fi
+	if test -f readme.shl; then ${INSTALLMAN} -m 644 readme.shl ${DESTDIR}${prefix}; fi
+	if test -f rsync.map; then ${INSTALLMAN} -m 644 rsync.map ${DESTDIR}${prefix}; fi
+	if test -f rsync.sym; then ${INSTALLMAN} -m 644 rsync.sym ${DESTDIR}${prefix}; fi
+	if test -s "${DIFFFILE}"; then if test -f ${DIFFFILE}; then ${INSTALLMAN} -m 644 ${DIFFFILE} ${DESTDIR}${prefix}; fi; fi
 
 install-strip:
 	$(MAKE) INSTALL_STRIP='-s' install
@@ -107,11 +114,11 @@
 getfsdev$(EXEEXT): getfsdev.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
 
-TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
+TRIMSLASH_OBJ = trimslash.o t_stub.o syscall.o lib/compat.o lib/snprintf.o
 trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
-T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
+T_UNSAFE_OBJ = t_unsafe.o t_stub.o syscall.o util.o lib/compat.o lib/snprintf.o lib/wildmatch.o
 t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
 
@@ -189,9 +196,10 @@
 	yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
 	-$(srcdir)/tweak_manpage rsyncd.conf.5
 
+# 06 Feb 09 SHL clean maps
 clean: cleantests
 	rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
-		rounding rounding.h *.old
+		rounding rounding.h *.old rsync.map rounding.map
 
 cleantests:
 	rm -rf ./testtmp*
@@ -243,11 +251,13 @@
 wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
 
+# 25 Mar 10 SHL
+
 testsuite/chown-fake.test:
-	ln -s chown.test $(srcdir)/testsuite/chown-fake.test
+	echo ln -s chown.test $(srcdir)/testsuite/chown-fake.test
 
 testsuite/devices-fake.test:
-	ln -s devices.test $(srcdir)/testsuite/devices-fake.test
+	echo ln -s devices.test $(srcdir)/testsuite/devices-fake.test
 
 testsuite/xattrs-hlink.test:
 	ln -s xattrs.test $(srcdir)/testsuite/xattrs-hlink.test
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/access.c ./access.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/access.c	2009-01-17 13:41:34.000000000 -0800
+++ ./access.c	2011-04-18 22:11:36.000000000 -0700
@@ -100,7 +100,9 @@
 	hints.ai_flags = AI_NUMERICHOST;
 #endif
 
-	if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	// if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	if ((gai = getaddrinfo(addr, NULL, &hints, &resa)) != 0) {			// 27 Jul 08 SHL debug
+		// rprintf(FINFO, "* [%s] match_address gai %d %s(%u)\n", who_am_i(), gai, __FILE__, __LINE__);	// 28 Jul 08 SHL debug addrinfo
 		if (p)
 			*p = '/';
 		return 0;
@@ -110,8 +112,8 @@
 	if (p)
 		*p++ = '/';
 	if (gai != 0) {
-		rprintf(FLOG, "error matching address %s: %s\n",
-			tok, gai_strerror(gai));
+		rprintf(FLOG, "* error matching address %s: %s (%d)\n",
+			tok, gai_strerror(gai), gai);
 		freeaddrinfo(resa);
 		return 0;
 	}
@@ -222,7 +224,11 @@
 	if (host)
 		strlower(host);
 
+	// rprintf(FINFO, "* [%s] access_match %s (%s) %s(%u)\n", who_am_i(), host, addr, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
+
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+
+		// rprintf(FINFO, "* [%s] access_match tok %s %s(%u)\n", who_am_i(), tok, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
 		if (match_hostname(host, tok) || match_address(addr, tok)) {
 			free(list2);
 			return 1;
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/authenticate.c ./authenticate.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/authenticate.c	2009-01-17 13:41:34.000000000 -0800
+++ ./authenticate.c	2011-04-18 22:11:36.000000000 -0700
@@ -96,7 +96,9 @@
 	if (do_stat(fname, &st) == -1) {
 		rsyserr(FLOG, errno, "stat(%s)", fname);
 		ok = 0;
-	} else if (lp_strict_modes(module)) {
+	}
+#ifndef __OS2__	 /* 29 Jun 09 SHL suppress unsupported mode checks */
+	else if (lp_strict_modes(module)) {
 		if ((st.st_mode & 06) != 0) {
 			rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
 			ok = 0;
@@ -105,6 +107,7 @@
 			ok = 0;
 		}
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		rprintf(FLOG, "continuing without secrets file\n");
 		close(fd);
@@ -173,13 +176,16 @@
 	if (do_stat(filename, &st) == -1) {
 		rsyserr(FWARNING, errno, "stat(%s)", filename);
 		ok = 0;
-	} else if ((st.st_mode & 06) != 0) {
+	}
+#ifndef __OS2__	 /* 12 Jun 08 SHL suppress unsupported mode checks */
+	else if ((st.st_mode & 06) != 0) {
 		rprintf(FWARNING, "password file must not be other-accessible\n");
 		ok = 0;
 	} else if (MY_UID() == 0 && st.st_uid != 0) {
 		rprintf(FWARNING, "password file must be owned by root when running as root\n");
 		ok = 0;
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		close(fd);
 		rprintf(FWARNING, "continuing without password file\n");
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/clientname.c ./clientname.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/clientname.c	2009-01-17 13:41:34.000000000 -0800
+++ ./clientname.c	2011-04-18 22:11:36.000000000 -0700
@@ -95,8 +95,10 @@
 	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
-	if (initialised)
+	if (initialised) {
+		// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		return name_buf;
+	}
 
 	strlcpy(name_buf, default_name, sizeof name_buf);
 	initialised = 1;
@@ -148,6 +150,8 @@
 			port_buf, sizeof port_buf) == 0)
 		check_name(fd, &ss, name_buf, sizeof name_buf);
 
+	// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
+
 	return name_buf;
 }
 
@@ -216,14 +220,17 @@
 	int name_err;
 
 	/* reverse lookup */
+	// rprintf(FINFO, "* [%s] lookup_name %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
 			       name_buf, name_buf_size,
 			       port_buf, port_buf_size,
 			       NI_NAMEREQD | NI_NUMERICSERV);
 	if (name_err != 0) {
 		strlcpy(name_buf, default_name, name_buf_size);
-		rprintf(FLOG, "name lookup failed for %s: %s\n",
-			client_addr(fd), gai_strerror(name_err));
+		// rprintf(FINFO, "name lookup failed for %s: %s\n",
+		//	client_addr(fd), gai_strerror(name_err));
+		rprintf(FLOG, "lookup_name failed for %s: %s (%d) at %s(%u) [%s]\n",	// 27 Jul 08 SHL debug
+			client_addr(fd), gai_strerror(name_err), name_err, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL
 		return name_err;
 	}
 
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/clientserver.c ./clientserver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/clientserver.c	2010-12-23 22:08:34.000000000 -0800
+++ ./clientserver.c	2011-04-18 22:11:36.000000000 -0700
@@ -429,6 +429,8 @@
 	iconv_opt = NULL;
 #endif
 
+	if (verbose)
+		rprintf(FINFO, "[%s] rsync_module addr:host is %s:%s\n", who_am_i(), addr, host);	// 2008-07-28 SHL
 	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
 		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
 			name, host, addr);
@@ -442,6 +444,14 @@
 		return -1;
 	}
 
+// 2010-09-17 SHL libc does not do well with chroot c:/ etc.
+#ifdef __OS2__
+	if (use_chroot) {
+		io_printf(f_out, "@ERROR: use chroot not supported\n");
+		return -1;
+	}
+#endif
+
 	if (am_daemon && am_server) {
 		rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",
 			name, host, addr);
@@ -482,6 +492,7 @@
 
 	am_root = (MY_UID() == 0);
 
+#ifndef __OS2__
 	if (am_root) {
 		p = lp_uid(i);
 		if (!name_to_uid(p, &uid)) {
@@ -504,6 +515,7 @@
 		}
 	}
 
+#endif
 	/* TODO: If we're not root, but the configuration requests
 	 * that we change to some uid other than the current one, then
 	 * log a warning. */
@@ -512,6 +524,9 @@
 	 * supplementary groups. */
 
 	module_dir = lp_path(i);
+ 
+ 	// fprintf(stderr, "* [%s] module_dir %s %s(%u)\n", who_am_i(), module_dir, __FILE__, __LINE__); // 2010-09-16 SHL debug
+ 
 	if (*module_dir == '\0') {
 		rprintf(FLOG, "No path specified for module %s\n", name);
 		io_printf(f_out, "@ERROR: no path setting.\n");
@@ -541,6 +556,8 @@
 		full_module_path = module_dir = module_chdir;
 	}
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug path
+
 	if (module_dirlen == 1) {
 		module_dirlen = 0;
 		set_filter_dir("/", 1);
@@ -664,6 +681,8 @@
 	}
 #endif
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
 	if (use_chroot) {
 		/*
 		 * XXX: The 'use chroot' flag is a fairly reliable
@@ -685,8 +704,13 @@
 		module_chdir = module_dir;
 	}
 
-	if (!change_dir(module_chdir, CD_NORMAL))
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+		// rsyserr(FERROR, errno, "[%s] chdir %s failed at %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2008-12-15 SHL debug
+		// rprintf(FINFO, "* [%s] chdir module_chdir %s failed %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 		return path_failure(f_out, module_chdir, True);
+	}
 	if (module_dirlen || !use_chroot)
 		sanitize_paths = 1;
 
@@ -1001,6 +1025,7 @@
 	close(fd);
 }
 
+#ifndef __OS2__
 /* Become a daemon, discarding the controlling terminal. */
 static void become_daemon(void)
 {
@@ -1034,6 +1059,7 @@
 		open("/dev/null", O_RDWR);
 	}
 }
+#endif // __OS2__
 
 int daemon_main(void)
 {
@@ -1056,10 +1082,14 @@
 		exit_cleanup(RERR_SYNTAX);
 	}
 
+#ifndef __OS2__
 	if (no_detach)
 		create_pid_file();
 	else
 		become_daemon();
+#else
+	create_pid_file();
+#endif
 
 	if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
 		rsync_port = RSYNC_PORT;
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/compat.c ./compat.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/compat.c	2011-02-21 11:32:48.000000000 -0800
+++ ./compat.c	2011-04-18 22:11:36.000000000 -0700
@@ -201,11 +201,12 @@
 			exit_cleanup(RERR_PROTOCOL);
 		}
 		if (preserve_xattrs && !local_server) {
-			rprintf(FERROR,
-			    "--xattrs requires protocol 30 or higher"
+		  	preserve_xattrs = 0;	// 06 Feb 09 SHL force off for old servers
+			rprintf(FWARNING,
+			    "--xattrs requires protocol 30 or higher - option disabled"
 			    " (negotiated %d).\n",
 			    protocol_version);
-			exit_cleanup(RERR_PROTOCOL);
+			// exit_cleanup(RERR_PROTOCOL);	// 06 Feb 09 SHL
 		}
 	}
 
@@ -296,6 +297,7 @@
 	if (need_unsorted_flist && (!am_sender || inc_recurse))
 		unsort_ndx = ++file_extra_cnt;
 
+	// 16 Feb 09 SHL fixme slashes?
 	if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
 		int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
 		if (!am_sender || protocol_version >= 30)
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/configure.sh ./configure.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/configure.sh	2011-03-26 14:37:50.000000000 -0700
+++ ./configure.sh	2011-04-18 22:11:36.000000000 -0700
@@ -71,6 +71,8 @@
   as_echo='sh -c $as_echo_body as_echo'
 fi
 
+# 18 Jun 09 SHL fixme to not be broken - 3.0.5 worked - maybe autoconf 2.6.3 broke it
+
 # The user is always right.
 if test "${PATH_SEPARATOR+set}" != set; then
   PATH_SEPARATOR=:
@@ -8414,6 +8416,15 @@
 	$as_echo "#define SUPPORT_XATTRS 1" >>confdefs.h
 
 	;;
+    *os2*)
+	{ echo "$as_me:$LINENO: result: Using OS/2 extattrs" >&5
+echo "${ECHO_T}Using OS/2 extattrs" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_XATTRS 1
+_ACEOF
+
+	;;
+
     *)
 	if test x"$enable_xattr_support" = x"yes"; then
 	    as_fn_error $? "Failed to find extended attribute support" "$LINENO" 5
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/exclude.c ./exclude.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/exclude.c	2011-02-20 23:48:18.000000000 -0800
+++ ./exclude.c	2011-04-18 22:11:36.000000000 -0700
@@ -298,7 +298,7 @@
 	unsigned int fn_len;
 
 	if (!parent_dirscan && *merge_file != '/') {
-		/* Return the name unchanged it doesn't have any slashes. */
+		/* Return the name unchanged if it doesn't have any slashes. */
 		if (len_ptr) {
 			const char *p = merge_file + *len_ptr;
 			while (--p > merge_file && *p != '/') {}
@@ -310,6 +310,7 @@
 			return (char *)merge_file;
 	}
 
+	// 16 Feb 09 SHL fixme slash
 	fn = *merge_file == '/' ? buf : tmpbuf;
 	if (sanitize_paths) {
 		const char *r = prefix_skip ? "/" : NULL;
@@ -351,6 +352,7 @@
 void set_filter_dir(const char *dir, unsigned int dirlen)
 {
 	unsigned int len;
+	// 16 Feb 09 SHL fixme slash?
 	if (*dir != '/') {
 		memcpy(dirbuf, curr_dir, curr_dir_len);
 		dirbuf[curr_dir_len] = '/';
@@ -548,6 +550,7 @@
 	int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
 	char *p, *pattern = ex->pattern;
 	const char *strings[16]; /* more than enough */
+	// 16 Feb 09 SHL fixme slash?
 	const char *name = fname + (*fname == '/');
 
 	if (!*name)
@@ -605,8 +608,15 @@
 		if (litmatch_array(pattern, strings, slash_handling))
 			return ret_match;
 	} else if (anchored_match) {
+#ifndef __OS2__
 		if (strcmp(name, pattern) == 0)
 			return ret_match;
+#else
+		// 18 Oct 09 SHL Case insensitive
+		if (stricmp(name, pattern) == 0)
+			return ret_match;
+#endif
+
 	} else {
 		int l1 = strlen(name);
 		int l2 = strlen(pattern);
@@ -988,6 +998,25 @@
 				cp = ".cvsignore";
 				pat_len = 10;
 			}
+#ifdef __OS2__
+			else {
+				// 2009-10-19 SHL normalize
+				// 30 Sep 10 SHL avoid writing to const memory
+				/* If we are passed paths from the filter they
+				   might have DOS slashes, convert to Unix slashes
+				   except for the 1st characters (fixme to doc why - I forgot)
+				   If we are processing a const string, it will already
+				   have Unix slashes so don't try to write to const memory
+				*/
+				char ch;
+				p = cp + pat_len;	// Must be non-const for gcc
+				ch = *p;		// Remember 1st character - fixme to say why
+				normalize_dir_slashes((char *)cp);	// Hack cough - override const
+				if (*p != ch)
+					*(char*)p = ch;	// Ensure leading char not changed - fixme to say why
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len, cp, strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
+			}
+#endif
 			len = pat_len;
 			if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
 				const char *name = cp + len;
@@ -998,6 +1027,8 @@
 				len = pat_len;
 			}
 			if (new_mflags & MATCHFLG_PERDIR_MERGE) {
+				// 19 Oct 09 SHL fixme to complain if have drive letter?
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 				if (parent_dirscan) {
 					if (!(p = parse_merge_name(cp, &len,
 								module_dirlen)))
@@ -1014,6 +1045,7 @@
 			}
 		}
 
+		// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 		add_rule(listp, cp, pat_len, new_mflags, xflags);
 
 		if (new_mflags & MATCHFLG_CVS_IGNORE
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/flist.c ./flist.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/flist.c	2011-02-21 10:20:58.000000000 -0800
+++ ./flist.c	2011-04-18 22:11:36.000000000 -0700
@@ -347,8 +347,19 @@
 {
 	if (dirlen < 0) {
 		char *cpy = strdup(dir);
+#ifndef __OS2__ // 2009-03-06 SHL use is_abs_path...
 		if (*cpy != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (!is_abs_path(cpy)) {
+			if (drive_spec_width(cpy))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), cpy, __FILE__, __LINE__);	// 2009-02-06 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+	        }
+#endif
 		if (path_is_daemon_excluded(cpy, 0))
 			goto chdir_error;
 		dir = cpy;
@@ -362,8 +373,19 @@
 				dirlen = strlen(dir);
 		} else if (pathname == dir)
 			return 1;
+#ifndef __OS2__ // 2009-03-06 SHL use is_abs_path...
 		if (dir && *dir != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (dir && !is_abs_path(dir)) {
+			if (drive_spec_width(dir))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+		}
+#endif
 	}
 
 	pathname = dir;
@@ -376,8 +398,13 @@
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
 		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
-		if (dir != orig_dir)
-			change_dir(orig_dir, CD_NORMAL);
+		rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-07-21 SHL
+		if (dir != orig_dir) {
+			if (!change_dir(orig_dir, CD_NORMAL)) {
+				if (verbose > 1)
+					rprintf(FLOG, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+		}
 		pathname = NULL;
 		pathname_len = 0;
 		return 0;
@@ -1330,6 +1357,8 @@
 {
 	struct file_struct *file;
 
+	// rprintf(FINFO, "* [%s] send_file_name fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+
 	file = make_file(fname, flist, stp, flags, filter_level);
 	if (!file)
 		return NULL;
@@ -1975,6 +2004,7 @@
 	int len, dirlen;
 	STRUCT_STAT st;
 	char *p, *dir;
+	static char* the_root = "/";
 	struct file_list *flist;
 	struct timeval start_tv, end_tv;
 	int64 start_write;
@@ -2018,6 +2048,7 @@
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
 			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
 				full_fname(argv[0]));
+			rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), argv[0], __FILE__, __LINE__);	// 2009-07-21 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 		use_ff_fd = 1;
@@ -2037,19 +2068,25 @@
 			if (argc-- == 0)
 				break;
 			strlcpy(fbuf, *argv++, MAXPATHLEN);
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2010-09-16 SHL debug paths
 			if (sanitize_paths)
 				sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2010-09-16 SHL debug paths
+
 		len = strlen(fbuf);
 		if (relative_paths) {
 			/* We clean up fbuf below. */
 			name_type = NORMAL_NAME;
 		} else if (!len || fbuf[len - 1] == '/') {
-			if (len == 2 && fbuf[0] == '.') {
-				/* Turn "./" into just "." rather than "./." */
+			/* Empty path or trailing / */
+			// 2009-03-06 SHL Support drive letters
+			if (len == 2 + drive_spec_width(fbuf) && fbuf[drive_spec_width(fbuf)] == '.') {
+				/* Turn trailing "./" into just "." rather than "./." */
 				fbuf[--len] = '\0';
 			} else {
+				/* Turn trailing "xyz/" into "xyz/." */
 				if (len + 1 >= MAXPATHLEN)
 					overflow_exit("send_file_list");
 				fbuf[len++] = '.';
@@ -2058,6 +2095,7 @@
 			name_type = DOTDIR_NAME;
 		} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
 		    && (len == 2 || fbuf[len-3] == '/')) {
+			/* Got ..  or trailing /.. */
 			if (len + 2 >= MAXPATHLEN)
 				overflow_exit("send_file_list");
 			fbuf[len++] = '/';
@@ -2076,18 +2114,40 @@
 			if (p) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 2009-03-06 SHL Preserve drive letter in directory name
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else
 					dir = fbuf;
-				len -= p - fbuf + 1;
-				fn = p + 1;
+				fn = p + 1;		// Point at filename part
+				len -= fn - fbuf;	//  fn length
+				// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			} else
 				fn = fbuf;
 		} else {
+			// relative-paths
 			if ((p = strstr(fbuf, "/./")) != NULL) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 2009-03-06 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else {
 					dir = fbuf;
 					clean_fname(dir, 0);
@@ -2101,6 +2161,10 @@
 				fn = fbuf;
 			/* A leading ./ can be used in relative mode to affect
 			 * the dest dir without its name being in the path. */
+#ifdef __OS2__
+			// 2010-11-30 SHL Point after drive letter
+			fn += drive_spec_width(fn);
+#endif
 			if (*fn == '.' && fn[1] == '/' && !implied_dot_dir) {
 				send_file_name(f, flist, ".", NULL,
 				    (flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR,
@@ -2109,6 +2173,7 @@
 			}
 			len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
 					    | CFN_DROP_TRAILING_DOT_DIR);
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug relative-paths
 			if (len == 1) {
 				if (fn[0] == '/') {
 					fn = "/.";
@@ -2133,7 +2198,8 @@
 					exit_cleanup(RERR_SYNTAX);
 				}
 			}
-		}
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug relative-paths
+		} // relative-paths
 
 		if (!*fn) {
 			len = 1;
@@ -2141,6 +2207,8 @@
 			name_type = DOTDIR_NAME;
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list dir %s fn %s len %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug xattrs
+
 		dirlen = dir ? strlen(dir) : 0;
 		if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
 			if (!change_pathname(NULL, dir, -dirlen))
@@ -2150,9 +2218,16 @@
 		} else if (!change_pathname(NULL, lastdir, lastdir_len))
 			continue;
 
+		// 2009-03-06 SHL
+		if (dir && dir != the_root && dir != fbuf)
+			free(dir);	// We allocated it
+
 		if (fn != fbuf)
 			memmove(fbuf, fn, len + 1);
 
+		// rprintf(FINFO, "* [%s] send_file_list fn %s %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s len %d %s(%u)\n", who_am_i(), fbuf, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+
 		if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
@@ -2173,12 +2248,14 @@
 		}
 
 		if (inc_recurse && relative_paths && *fbuf) {
+			// 2009-03-06 SHL fixme
 			if ((p = strchr(fbuf+1, '/')) != NULL) {
 				if (p - fbuf == 1 && *fbuf == '.') {
 					if ((fn = strchr(p+1, '/')) != NULL)
 						p = fn;
 				} else
 					fn = p;
+				// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 				send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
 				if (fn == p)
 					continue;
@@ -2186,6 +2263,7 @@
 		} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
 			/* Send the implied directories at the start of the
 			 * source spec, so we get their permissions right. */
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
 		}
 
@@ -2194,6 +2272,7 @@
 
 		if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
 			struct file_struct *file;
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			file = send_file_name(f, flist, fbuf, &st,
 					      FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
 					      NO_FILTERS);
@@ -2209,9 +2288,11 @@
 				}
 			} else
 				send_if_directory(f, flist, file, fbuf, len, flags);
-		} else
+		} else {
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
 	}
+	} /* while */
 
 	gettimeofday(&end_tv, NULL);
 	stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000
@@ -2401,6 +2482,9 @@
 							struct file_struct *,
 							dir_flist->malloced);
 				dir_flist_malloced = dir_flist->malloced;
+				// 2010-11-30 SHL check out of memory
+				if (dir_flist->sorted == NULL)
+					out_of_memory("recv_file_list");
 			}
 			memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart,
 			       (dir_flist->used - dstart) * sizeof (struct file_struct*));
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/generator.c ./generator.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/generator.c	2011-03-26 10:17:14.000000000 -0700
+++ ./generator.c	2011-04-18 22:11:36.000000000 -0700
@@ -96,6 +96,10 @@
 extern int backup_suffix_len;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+// 14 Oct 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 int ignore_perishable = 0;
 int non_perishable_cnt = 0;
@@ -263,6 +267,7 @@
 	}
 
 	p = fname + dlen;
+	// 16 Feb 09 SHL fixme slash?
 	if (dlen != 1 || *fname != '/')
 		*p++ = '/';
 	remainder = MAXPATHLEN - (p - fname);
@@ -659,7 +664,7 @@
 #endif
 	}
 
-	return 1;
+	return 1;			// No change
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -680,19 +685,30 @@
 		} else if (keep_time
 		 ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
 		 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
-		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s file->modtime %u sxp->st.st_mtime %u %s(%u)\n", who_am_i(), fnamecmp, file->modtime, sxp->st.st_mtime, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme times
+			if (verbose > 1)
+				rprintf(FINFO, "%s times differ sender %u receiver %u\n", fnamecmp, file->modtime, sxp->st.st_mtime);
 			iflags |= ITEM_REPORT_TIME;
+		}
+
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
 		} else
 #endif
 		if (preserve_perms) {
-			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) {
+				// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
+				if (verbose > 1)
+					rprintf(FINFO, "%s perms differ sender %o receiver %o\n", fnamecmp, file->mode, sxp->st.st_mode);
 				iflags |= ITEM_REPORT_PERMS;
+			}
 		} else if (preserve_executability
-		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0))) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode %o file->mode %o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
 			iflags |= ITEM_REPORT_PERMS;
+		 }
 		if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 			iflags |= ITEM_REPORT_OWNER;
 		if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
@@ -1539,8 +1555,10 @@
 #endif
 
 #ifdef SUPPORT_XATTRS
-		if (preserve_xattrs && statret == 1)
+		if (preserve_xattrs && statret == 1) {
+			// rprintf(FINFO, "* [%s] receive_generator running copy_xattrs fnamecmpbuf %s fname %s %s(%u)\n", who_am_i(), fnamecmpbuf, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
 			copy_xattrs(fnamecmpbuf, fname);
+		}
 #endif
 		if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
 		    && verbose && code != FNONE && f_out != -1)
@@ -1640,6 +1658,17 @@
 			cur_flist->in_progress++;
 			goto cleanup;
 		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If source directory not archived (i.e. not writable by group)
+		// may need to touch up after file operations complete
+		// see map_os2_attributes
+		if (!need_retouch_dir_perms && os2_perms &&
+		    ~file->mode & S_IWGRP) {
+			// rprintf(FINFO, "* [%s] recv_generator dir %s needs retouch mode %o %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 14 Oct 09 SHL fixme dir perms
+			need_retouch_dir_perms = 1;
+		}
+#endif
 #endif
 		if (do_symlink(sl, fname) != 0) {
 			rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed",
@@ -1664,7 +1693,7 @@
 		}
 #endif
 		goto cleanup;
-	}
+	} // is_dir
 
 	if ((am_root && preserve_devices && IS_DEVICE(file->mode))
 	 || (preserve_specials && IS_SPECIAL(file->mode))) {
@@ -2096,10 +2125,18 @@
 	} else
 		start = end = ndx;
 
+	// rprintf(FINFO, "* [%s] touch_up_dirs start %u end %u %s(%u)\n", who_am_i(), start, end,  __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
+
 	/* Fix any directory permissions that were modified during the
 	 * transfer and/or re-set any tweaked modified-time values. */
 	for (i = start; i <= end; i++, counter++) {
+		// 23 Mar 10 SHL overcome xattrs generated by libc chmod
+#ifdef __OS2__
+		int need_xattrs_set = 0;
+#endif
 		file = flist->files[i];
+		// fname = f_name(file, NULL); // 14 Oct 09 SHL debug dir perms
+		// rprintf(FINFO, "* [%s] touch_up_dirs dir %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 		if (!S_ISDIR(file->mode)
 		 || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))
 			continue;
@@ -2110,18 +2147,80 @@
 		}
 		/* Be sure not to retouch permissions with --fake-super. */
 		fix_dir_perms = !am_root && !(file->mode & S_IWUSR);
+#ifndef __OS2__
 		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
 		 || !(need_retouch_dir_times || fix_dir_perms))
 			continue;
+else // __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived on (i.e. writable by group)
+		// See map_os2_attributes
+		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
+		 || !(need_retouch_dir_times || fix_dir_perms
+		      || !os2_perms || (~file->mode & S_IWGRP)))
+			continue;
+#endif
 		fname = f_name(file, NULL);
-		if (fix_dir_perms)
+#ifdef __OS2__
+		// 14 Oct 09 SHL Need to set time before clearing archive bit
+		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);
+		}
+#endif
+		if (fix_dir_perms) {
+			do_chmod(fname, file->mode);
+#ifdef __OS2__
+			// 25 Mar 10 SHL fixme to be sure can update EAs after setting read-only
+			// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWUSR fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			need_xattrs_set = preserve_xattrs;
+#endif
+		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived off (i.e. not writable by group)
+		// See map_os2_attributes
+		// Other os/2 perms should already be OK
+		// There is no way to know for sure if directory was modified so we check
+		else if (os2_perms && ~file->mode & S_IWGRP) {
+			STRUCT_STAT st;
+			if (link_stat(fname, &st, 0) == 0 &&
+			    ((file->mode ^ st.st_mode) & S_IWGRP)) {
+				// rprintf(FINFO, "* [%s] touch_up_dirs chmod(%s, 0%o) %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 			do_chmod(fname, file->mode);
+				// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+				// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWGRP(archive) fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+				need_xattrs_set = need_xattrs_set || preserve_xattrs;
+			}
+		}
+#endif
+#ifndef __OS2__
 		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);
 		}
+#endif
+#ifdef __OS2__
+		if (need_xattrs_set) {
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			stat_x sx;
+			// rprintf(FINFO, "* [%s] touch_up_dirs doing set_xattr for %s %s %s(%u)\n", who_am_i(), fname, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			if (verbose > 2)
+				rprintf(FINFO, "%s removing EAs generated by libc chmod %s\n", who_am_i(), fname);
+			memset(&sx, 0, sizeof(stat_x));
+			// Should not need to provide target item list to set_xattr
+			// link_stat(fname, &sx.st, 0);
+			// sx.xattr = new(item_list);
+			// *sxp.xattr = empty_xattr;
+			set_xattr(fname, file, fname, &sx);
+			// free_xattr(&sx);
+		}
+#endif
 		if (counter >= loopchk_limit) {
 			if (allowed_lull)
 				maybe_send_keepalive();
@@ -2129,7 +2228,7 @@
 				maybe_flush_socket(0);
 			counter = 0;
 		}
-	}
+	} // for
 }
 
 void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/getaddrinfo.c ./lib/getaddrinfo.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/getaddrinfo.c	2009-12-12 17:20:34.000000000 -0800
+++ ./lib/getaddrinfo.c	2011-04-18 22:11:36.000000000 -0700
@@ -403,12 +403,16 @@
 	int ret = -1;
 	char *p = NULL;
 
+	// rprintf(FINFO, "* [%s] gethostnameinfo NI_NUMERICHOST %u %s(%u)\n", who_am_i(), flags & NI_NUMERICHOST, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	if (!(flags & NI_NUMERICHOST)) {
+		// rprintf(FINFO, "* [%s] gethostnameinfo %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		struct hostent *hp = gethostbyaddr(
 				(void *)&((struct sockaddr_in *)sa)->sin_addr,
 				sizeof (struct in_addr),
 				sa->sa_family);
+		// rprintf(FINFO, "* [%s] gethostnameinfo hp %p %s(%u)\n", who_am_i(), hp, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		ret = check_hostent_err(hp);
+		// rprintf(FINFO, "* [%s] ret %d %s(%u)\n", who_am_i(), ret, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (ret == 0) {
 			/* Name looked up successfully. */
 			ret = snprintf(node, nodelen, "%s", hp->h_name);
@@ -424,6 +428,7 @@
 			return 0;
 		}
 
+		// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (flags & NI_NAMEREQD) {
 			/* If we require a name and didn't get one,
 			 * automatically fail. */
@@ -431,6 +436,7 @@
 		}
 		/* Otherwise just fall into the numeric host code... */
 	}
+	// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
 	ret = snprintf(node, nodelen, "%s", p);
 	if (ret < 0 || (size_t)ret >= nodelen) {
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/pool_alloc.c ./lib/pool_alloc.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/pool_alloc.c	2008-11-09 18:55:14.000000000 -0800
+++ ./lib/pool_alloc.c	2011-04-18 22:11:36.000000000 -0700
@@ -93,8 +93,10 @@
 	else if (pool->quantum > 1 && len % pool->quantum)
 		len += pool->quantum - len % pool->quantum;
 
-	if (len > pool->size)
+	if (len > pool->size) {
+	        rprintf(FERROR, "* [%s] pool_alloc len %u > pool->size %u %s(%u)\n", who_am_i(), len, pool->size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		goto bomb_out;
+	}
 
 	if (!pool->extents || len > pool->extents->free) {
 		void	*start;
@@ -111,16 +113,20 @@
 		if (pool->flags & POOL_APPEND)
 			asize += sizeof (struct pool_extent);
 
-		if (!(start = new_array(char, asize)))
+		if (!(start = new_array(char, asize))) {
+			rprintf(FERROR, "* [%s] new_array asize %u failed %s(%u)\n", who_am_i(), asize, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 			goto bomb_out;
+		}
 
 		if (pool->flags & POOL_CLEAR)
 			memset(start, 0, free);
 
 		if (pool->flags & POOL_APPEND)
 			ext = PTR_ADD(start, free);
-		else if (!(ext = new(struct pool_extent)))
+		else if (!(ext = new(struct pool_extent))) {
+			rprintf(FERROR, "* [%s] new pool_extent failed %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 			goto bomb_out;
+		}
 		if (pool->flags & POOL_QALIGN && pool->quantum > 1
 		    && (skew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
 			bound  += skew;
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.c ./lib/sysxattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.c	2008-03-01 12:01:40.000000000 -0800
+++ ./lib/sysxattrs.c	2011-04-18 22:11:36.000000000 -0700
@@ -126,6 +126,361 @@
 	return len;
 }
 
+#elif defined(__OS2__)
+
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+
+static void map_os2_apiret(APIRET rc)
+{
+	switch (rc) {
+	case ERROR_SHARING_VIOLATION:
+		errno = EACCES;
+		break;
+	case 0:
+		// Should not have been called - try to do no harm
+		break;
+	default:
+		// 2009-07-31 SHL fixme to map better
+		// if (verbose > 2)
+		rprintf(FINFO, "[%s] can not map OS/2 error %lu to errno\n", who_am_i(), rc);	// 31 Jul 09 SHL
+		/* Ensure non-zero */
+		if (!errno)
+			errno = EINVAL;
+
+	}
+}
+
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+	return unisetxattr (path, 0, name, value, size, 0);
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+static char *out_of_mem_msg = "out of memory allocating %lu at %s(%u)\n";
+
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	size_t reqsize;
+	EAOP2       eaop2 = {0,0,0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+	reqsize = sizeof(GEA2LIST) + namelen + 1;
+	pgea2list = (PGEA2LIST)calloc(reqsize, 1);
+	// 2010-11-30 SHL
+	if (pgea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	reqsize = sizeof(FEA2LIST) + 0x10000;
+	pfea2list = (PFEA2LIST)calloc(reqsize, 1);
+	// 2010-11-30 SHL
+	if (pfea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;
+	do {
+		if (path) {
+			rc = DosQueryPathInfo(path, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryPathInfo(%s, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] %s requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), path, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		else {
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryFileInfo(%u, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] handle %d requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), file, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		if (rc)
+			break;
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0) {
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value) {
+			if ((size_t)rc > size) {
+				errno = ERANGE;
+				rc = -1;
+			}
+			else {
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+		free(pgea2list);
+	if (pgea2list)
+		free(pfea2list);
+
+	return rc;
+}
+
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	size_t reqsize;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat;
+	if (!path && !file) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (path) {
+		rc = DosQueryPathInfo(path, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryPathInfo(%s, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] %s reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), path, stat.cbList);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryFilInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] handle %d reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), file, stat.cbList);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	if (stat.cbList <= 4) {
+		// NO ea
+		return 0;
+	}
+	//YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
+	reqsize = stat.cbList * 2;
+	buf = (char *)_tmalloc(reqsize);
+	// 2009-09-19 SHL was trapping on large copies
+	if (!buf) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);	// 2009-09-19 SHL
+		return -1;
+	}
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc) {
+		rprintf(FERROR, "[%s] unilistxattr DosEnumAttribute failed with error %u at %s(%u)\n", who_am_i(), rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		_tfree(buf);
+		map_os2_apiret(rc);	// 31 Jul 09 SHL moved here to ensure errno returned
+		return -1;
+	}
+	else if (verbose > 2) {
+		if (path)
+			rprintf(FINFO, "[%s] %s has %lu DosEnumAttribute items\n", who_am_i(), path, ulCount);	// 28 Jul 08 SHL
+		else
+			rprintf(FINFO, "[%s] handle %d has %lu DosEnumAttribute items\n", who_am_i(), file, ulCount);	// 28 Jul 08 SHL
+	}
+	if (ulCount > 0) {
+		for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset)) {
+			if (pfea->cbName > 0) {
+				gotsize += pfea->cbName + 1;
+				// Avoid overflow
+				if (p && (size_t)gotsize <= size) {
+					pfea->szName[pfea->cbName] = 0;
+					strcpy(p, pfea->szName);
+					p += strlen(p) + 1;
+				}
+			}
+			if (!pfea->oNextEntryOffset)
+				break;
+		}
+	}
+	_tfree(buf);
+	if ((size_t)gotsize > size) {
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	if (verbose > 2)
+		rprintf(FINFO, "[%s] returning %ld EA list bytes\n", who_am_i(), (unsigned long)gotsize);	// 28 Jul 08 SHL
+	return gotsize;
+}
+
+int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0,0,0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosFileInfo(%u, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0,0,0};
+	PFEA2LIST   pfea2list = NULL;
+	// char * p;			// 17 May 09 SHL  fixme
+
+	if ((!path && !file) || !name || (!value && size)) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0) {
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0) {
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(FEA2LIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	// 2010-11-30 SHL
+	if (pfea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, totalsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value) {
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetFileInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	free(pfea2list);
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
 #else
 
 #error You need to create xattr compatibility functions.
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.h ./lib/sysxattrs.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.h	2007-04-07 10:22:24.000000000 -0700
+++ ./lib/sysxattrs.h	2011-04-18 22:11:36.000000000 -0700
@@ -19,6 +19,13 @@
 int sys_lremovexattr(const char *path, const char *name);
 ssize_t sys_llistxattr(const char *path, char *list, size_t size);
 
+#ifdef __OS2__
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size);
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size);
+int uniremovexattr (const char *path, int file, const char *name);
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags);
+#endif
+
 #else
 
 /* No xattrs available */
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/wildmatch.c ./lib/wildmatch.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/wildmatch.c	2007-05-21 22:58:58.000000000 -0700
+++ ./lib/wildmatch.c	2011-04-18 22:11:36.000000000 -0700
@@ -89,8 +89,14 @@
 	    p_ch = *++p;
 	    /* FALLTHROUGH */
 	  default:
+#ifndef __OS2__
 	    if (t_ch != p_ch)
 		return FALSE;
+#else
+	    // 18 Oct 09 SHL be case insensitive
+	    if (t_ch != p_ch && (t_ch ^ p_ch) != 0x20)
+		return FALSE;
+#endif
 	    continue;
 	  case '?':
 	    /* Match anything but '/'. */
@@ -150,8 +156,14 @@
 		    p_ch = *++p;
 		    if (!p_ch)
 			return ABORT_ALL;
+#ifndef __OS2__
 		    if (t_ch == p_ch)
 			matched = TRUE;
+#else
+		    // 18 Oct 09 SHL be case insensitive
+		    if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			matched = TRUE;
+#endif
 		} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
 		    p_ch = *++p;
 		    if (p_ch == '\\') {
@@ -159,6 +171,7 @@
 			if (!p_ch)
 			    return ABORT_ALL;
 		    }
+		    // 18 Oct 09 SHL [a-z] ranges remain case-sensitive for now
 		    if (t_ch <= p_ch && t_ch >= prev_ch)
 			matched = TRUE;
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
@@ -173,8 +186,14 @@
 			/* Didn't find ":]", so treat like a normal set. */
 			p = s - 2;
 			p_ch = '[';
+#ifndef __OS2__
 			if (t_ch == p_ch)
 			    matched = TRUE;
+#else
+			// 18 Oct 09 SHL be case insensitive
+			if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			    matched = TRUE;
+#endif
 			continue;
 		    }
 		    if (CC_EQ(s,i, "alnum")) {
@@ -218,6 +237,11 @@
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
 		} else if (t_ch == p_ch)
 		    matched = TRUE;
+#ifdef __OS2__
+		// 18 Oct 09 SHL be case insensitive
+		else if ((t_ch ^ p_ch) == 0x20)
+		    matched = TRUE;
+#endif
 	    } while (prev_ch = p_ch, (p_ch = *++p) != ']');
 	    if (matched == special || t_ch == '/')
 		return FALSE;
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/loadparm.c ./loadparm.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/loadparm.c	2009-01-17 13:41:34.000000000 -0800
+++ ./loadparm.c	2011-04-18 22:11:36.000000000 -0700
@@ -212,7 +212,7 @@
  /* read_only; */		True,
  /* strict_modes; */		True,
  /* transfer_logging; */	False,
- /* use_chroot; */		True,
+ /* use_chroot; */		False,	// 2010-09-17 SHL libc chroot not quite right
  /* write_only; */		False,
 };
 
@@ -654,10 +654,23 @@
 	    *(char *)dest_ptr = *(char *)src_ptr;
 	    break;
 
+#ifndef __OS2__
 	  case P_PATH:
 	  case P_STRING:
 	    string_set(dest_ptr,*(char **)src_ptr);
 	    break;
+#else
+	  case P_PATH:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    // 2009-03-06 SHL Force unix slashes
+	    // 2009-05-16 SHL Use normalize_dir_slashes
+	    normalize_dir_slashes(*(char **)dest_ptr);
+	    break;
+
+	  case P_STRING:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    break;
+#endif
 
 	  default:
 	    break;
@@ -725,8 +738,14 @@
      case P_PATH:
        string_set(parm_ptr,parmvalue);
        if ((cp = *(char**)parm_ptr) != NULL) {
+	   // Chop trailing slashes unless root
 	   int len = strlen(cp);
+#ifndef __OS2__
 	   while (len > 1 && cp[len-1] == '/') len--;
+#else
+	   // 2010-11-24 SHL Use drive_spec_width
+	   while (len > drive_spec_width(cp) + 1 && cp[len-1] == '/') len--;
+#endif
 	   cp[len] = '\0';
        }
        break;
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/log.c ./log.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/log.c	2011-01-29 19:25:52.000000000 -0800
+++ ./log.c	2011-04-18 22:11:36.000000000 -0700
@@ -369,6 +369,7 @@
 	va_list ap;
 	char buf[BIGPATHBUFLEN];
 	size_t len;
+	int e = errno;			// 27 Apr 09 SHL preserve errno
 
 	va_start(ap, format);
 	len = vsnprintf(buf, sizeof buf, format, ap);
@@ -401,6 +402,7 @@
 	}
 
 	rwrite(code, buf, len, 0);
+	errno = e;
 }
 
 /* This is like rprintf, but it also tries to print some
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/main.c ./main.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/main.c	2011-02-22 08:21:08.000000000 -0800
+++ ./main.c	2011-04-18 22:11:36.000000000 -0700
@@ -27,6 +27,10 @@
 #include <locale.h>
 #endif
 
+#ifdef __OS2__
+#include <umalloc.h>			// Need for _heap_walk
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int list_only;
@@ -272,10 +276,23 @@
 
 	if (verbose || do_stats) {
 		rprintf(FCLIENT, "\n");
+#ifndef __OS2__
 		rprintf(FINFO,
 			"sent %s bytes  received %s bytes  %s bytes/sec\n",
 			human_num(total_written), human_num(total_read),
 			human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
+#else
+		{
+			// 2010-10-30 SHL show elapsed time
+			time_t t = endtime - starttime + 1;	// Always round up
+			rprintf(FINFO,
+				"sent %s bytes  received %s bytes  %s bytes/sec  elapsed %02u:%02u:%02u\n",
+				human_num(total_written),
+				human_num(total_read),
+				human_dnum((total_written + total_read)/(0.5 + t), 2),
+				t / 3600, (t / 60) % 60, t % 60);
+		}
+#endif
 		rprintf(FINFO, "total size is %s  speedup is %.2f%s\n",
 			human_num(stats.total_size),
 			(double)stats.total_size / (total_written+total_read),
@@ -287,6 +304,92 @@
 }
 
 
+#ifdef __OS2__				// 2010-12-25 SHL
+#ifdef HAVE_MALLINFO
+#error HAVE_MALLINFO unexpected
+#endif
+
+// See \EMX\doc\emxlib.doc
+
+struct mallinfo {
+  int arena;
+  int ordblks;
+  int smblks;
+  int hblks;
+  int hblkhd;
+  int usmblks;
+  int fsmblks;
+  int uordblks;
+  int fordblks;
+  int keepcost;
+};
+
+static struct mallinfo os2_mallinfo;
+
+
+// 2010-12-25 SHL push requires 4.5
+// #pragma GCC diagnostic push
+// 2010-12-25 SHL diagnosic requires 4.4.x
+// #pragma GCC diagnostic ignored "-Wunused-parameter"
+
+// 2010-12-25 SHL unused-parameter warnings expected with 3.3.5
+
+static int os2_mallinfo_callback(const void *block, size_t size, int flag,
+				 int status, const char *fname, size_t lineno)
+{
+	int err = 0;
+	switch (status) {
+	case _HEAPOK:
+	{
+		switch (flag) {
+		case _USEDENTRY:
+			os2_mallinfo.uordblks += size;
+			break;
+		case _FREEENTRY:
+			os2_mallinfo.fordblks += size;
+			break;
+	        default:
+			err = 99;
+		} // flag
+	}
+	break;
+	case _HEAPBADBEGIN:
+	case _HEAPBADEND:
+	case _HEAPBADNODE:
+	case _HEAPEMPTY:
+		// Let _heap_walk set return code
+		break;
+	default:
+		err = 99;
+	} // status
+	return err;
+}
+
+// 2010-12-25 SHL pop requires 4.5.x
+// #pragma GCC diagnostic pop
+// 2010-12-25 SHL diagnosic requires 4.4.x
+// #pragma GCC diagnostic warning "-Wunused-parameter"
+
+struct mallinfo mallinfo(void)
+{
+	int err;
+	memset(&os2_mallinfo, 0, sizeof(os2_mallinfo));
+	err = _heap_walk(os2_mallinfo_callback);
+
+	if (err) {
+		// fixme to report
+	}
+
+	os2_mallinfo.arena = os2_mallinfo.uordblks + os2_mallinfo.ordblks;
+
+	return os2_mallinfo;
+}
+
+#define HAVE_MALLINFO
+
+#endif // __OS2__
+
+
 /**
  * If our C library can get malloc statistics, then show them to FINFO
  **/
@@ -324,6 +427,9 @@
 	rprintf(FINFO, "  keepcost:  %10ld   (bytes in releasable chunk)\n",
 		(long)mi.keepcost);
 #endif /* HAVE_MALLINFO */
+
+#ifdef __OS2__				// 2010-12-25 SHL
+#endif // __OS2__
 }
 
 
@@ -541,6 +647,8 @@
 			if (!change_dir(dest_path, CD_NORMAL)) {
 				rsyserr(FERROR, errno, "change_dir#1 %s failed",
 					full_fname(dest_path));
+				// 22 Jul 09 SHL was FLOG?  why?
+				rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 				exit_cleanup(RERR_FILESELECT);
 			}
 			filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
@@ -602,6 +710,8 @@
 		if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
 			rsyserr(FERROR, errno, "change_dir#2 %s failed",
 				full_fname(dest_path));
+			// 22 Jul 09 SHL was FLOG?  why?
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 
@@ -622,6 +732,8 @@
 	if (!change_dir(dest_path, CD_NORMAL)) {
 		rsyserr(FERROR, errno, "change_dir#3 %s failed",
 			full_fname(dest_path));
+		// 22 Jul 09 SHL was FLOG?  why?
+		rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 		exit_cleanup(RERR_FILESELECT);
 	}
 	*cp = '/';
@@ -713,8 +825,9 @@
 
 	if (!relative_paths) {
 		if (!change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#3 %s failed",
+			rsyserr(FERROR, errno, "change_dir#4 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -885,8 +998,9 @@
 		argc--;
 		argv++;
 		if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#4 %s failed",
+			rsyserr(FERROR, errno, "change_dir#5 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -941,6 +1055,7 @@
 			if (check_filter(elp, FLOG, dir, 1) < 0)
 				goto options_rejected;
 		}
+		// 25 Sep 09 SHL fixme slashes
 		if (partial_dir && *partial_dir == '/'
 		 && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
 		    options_rejected:
@@ -1099,7 +1214,7 @@
 
 	for (i = 0; argv[i]; i++) {
 		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
+			rprintf (FERROR, "out of memory at %s(%u)\n",
 				 __FILE__, __LINE__);
 			return RERR_MALLOC;
 		}
@@ -1130,6 +1245,14 @@
 	 * command line. */
 	if ((ret = copy_argv(argv)) != 0)
 		return ret;
+#ifdef __OS2__
+	{
+		int i;
+		for (i = 0; i < argc; i++) {
+			normalize_dir_slashes(argv[i]);
+		}
+	}
+#endif
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -1453,6 +1576,7 @@
 	 * (implemented by forking "pwd" and reading its output) doesn't
 	 * work when there are other child processes.  Also, on all systems
 	 * that implement getcwd that way "pwd" can't be found after chroot. */
+	// rprintf(FINFO, "* [%s] %s %s(%u)\n", who_am_i(), "(null)", __FILE__, __LINE__);	// 28 Jul 08 SHL debug chdir
 	change_dir(NULL, CD_NORMAL);
 
 	init_flist();
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/options.c ./options.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/options.c	2011-02-21 11:32:48.000000000 -0800
+++ ./options.c	2011-04-18 22:11:36.000000000 -0700
@@ -52,6 +52,10 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+// 13 Jun 09 SHL Added
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -115,7 +119,11 @@
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
+#ifndef __OS2__
 int modify_window = 0;
+#else
+int modify_window = 1;			// 28 Jul 09 SHL allow for 2 second resolution
+#endif
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
@@ -261,6 +269,13 @@
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
 	rprintf(f, "Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.\n");
 	rprintf(f, "Web site: http://rsync.samba.org/\n");
+#ifdef __OS2__ // 2009-07-22 SHL
+	rprintf(f, "Built by Steven H. Levine " __DATE__ " " __TIME__ "\n");
+#if 0 // 2010-12-15 SHL Enable if building for Mensys with flist size limited - see util.c MALLOC_MAX
+	rprintf(f, "Built with MALLOC_MAX set to 200MiBytes\n");
+#endif // Mensys MALLOC_MAX
+	rprintf(f, "Built with GCC " __VERSION__ "\n");
+#endif
 	rprintf(f, "Capabilities:\n");
 	rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
 		(int)(sizeof (OFF_T) * 8),
@@ -337,6 +352,9 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+#ifdef __OS2__
+  rprintf(F," -2, --os2-perms             preserve native OS/2 permissions\n");
+#endif
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
 #ifdef SUPPORT_ACLS
@@ -479,6 +497,10 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+#ifdef __OS2__
+  {"os2-perms",       '2', POPT_ARG_NONE,   0, '2', 0, 0 },
+  {"no-os2-perms",     0,  POPT_ARG_VAL,    &os2_perms, 0, 0, 0 },
+#endif
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
@@ -1032,6 +1054,10 @@
 		case OPT_EXCLUDE_FROM:
 		case OPT_INCLUDE_FROM:
 			arg = poptGetOptArg(pc);
+#ifdef __OS2__
+			// 18 Oct 09 SHL
+			normalize_dir_slashes((char *)arg);	// hack cough - override const
+#endif
 			if (sanitize_paths)
 				arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 			if (daemon_filter_list.head) {
@@ -1139,6 +1165,13 @@
 			}
 			break;
 
+// 14 Jun 09 SHL
+#ifdef __OS2__
+		case '2':
+			os2_perms = 1;
+			preserve_perms = 1;	// Implied
+			break;
+#endif
 		case OPT_WRITE_BATCH:
 			/* batch_name is already set */
 			write_batch = 1;
@@ -1474,6 +1507,7 @@
 			char *dir;
 			if (!*backup_dir)
 				goto options_rejected;
+			// 25 Sep 09 SHL fixme slashes
 			dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
 			clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
 			if (check_filter(elp, FLOG, dir, 1) < 0)
@@ -1788,6 +1822,12 @@
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
 		argstr[x++] = 'E';
+// 13 Jun 09 SHL
+#ifdef __OS2__
+	if (os2_perms)
+		argstr[x++] = '2';
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls)
 		argstr[x++] = 'A';
@@ -2108,6 +2148,10 @@
 			break;
 		}
 		if (*s == ':' || *s == '/') {
+#			ifdef __OS2__	// 29 Jun 09 SHL don't confuse drive letter with host spec
+			if (*s == ':' && s == str + 1 && drive_spec_width(s - 1) != 0)
+				continue;
+#			endif
 			if (!hostlen)
 				hostlen = s - host_start;
 			if (*s++ == '/') {
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/params.c ./params.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/params.c	2007-11-22 09:51:20.000000000 -0800
+++ ./params.c	2011-04-18 22:11:36.000000000 -0700
@@ -166,9 +166,24 @@
   {
   pos--;
   while( pos >= 0 && isSpace(line + pos) )
-     pos--;
+     pos--;				// Find last non-whitespace
 
+#ifndef __OS2__
   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
+#else
+  // 2010-11-24 SHL handle path specs like c:\ special to avoid
+  // losing \ before it can be mapped to /
+  // Assume parsing value so name and value nul separated
+  if ( pos >= 0) {
+    if (line[pos] != '\\')
+      pos = -1;				// Not continued
+    else if (pos >= 3) {
+      if (*(line + pos - 3) == 0 && drive_spec_width(line + pos - 2) > 0)
+        pos = -1;			// Not continued
+    }
+  }
+  return pos;
+#endif
   } /* Continuation */
 
 
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.os2 ./readme.os2
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.os2	2106-02-06 22:28:16.000000000 
+++ ./readme.os2	2011-04-18 22:11:36.000000000 -0700
@@ -0,0 +1,87 @@
+Rsync v3.0.7 compiled with GCC 4.3.4 & kLibc v0.6.3
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+We (Paul and Steven) are using this as both client and server for backups
+
+Changes in this version:
+- Updated to v3.0.6
+- Incorporated a bunch of patches from Steven Levine
+- Move to GCC 4.3.4 as a compiler
+- --xattrs now works for remote servers
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 permissions
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+- Defaulted to %ETC% for rsyncd.conf
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+  Run make install
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Cheers,
+
+Paul Smedley
+Adelaide, Australia
+
+and
+
+Steven Levine
+Costa Mesa, California, USA
+
+09 April 2010
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.shl ./readme.shl
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.shl	2106-02-06 22:28:16.000000000 
+++ ./readme.shl	2011-04-25 22:07:22.000000000 -0700
@@ -0,0 +1,109 @@
+
+Rsync v3.0.8 compiled with GCC 4.5.2 & kLibc v0.6.3 by Steven H. Levine
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+Requires gcc452.dll available from http://download.smedley.info/gcc452.zip
+
+These are Steven Levine's notes
+See readme.os2 for Paul Smedley's notes
+
+Changes in this version (newest first):
+
+- Updated to rsync v3.0.8 sources
+- Now building with gcc 4.5.2 - requires gcc452.dll
+- --stats -vv now shows memory statistics
+- --relative now works with drive letters
+- added some more alloc failure checks
+- rsync conf now accepts root paths like c:\
+- --stats shows elapsed time
+- Filter pattern matches are now case-insensitive
+- Added logic to ensure directory xattrs updated after libc chmod changes xattrs
+- Started work on supporting testsuite
+- Updated to rsync v3.0.7 sources
+- Migrated existing 3.0.6 patches
+
+Binary builds are available at
+
+  http://mantis.smedley.info/view.php?id=366
+
+Known issues
+
+- Newly created directories do not always get correct libc extended attributes
+  Next rsync run will set the libc extended attributes to the correct values
+
+- --links probably not fully compatible with --os2perms
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 readonly permissions along
+  with the system, hidden and archive file/directory attributes
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke a some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+
+  Run make install
+
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Have fun,
+
+Steven Levine
+Costa Mesa, California, USA
+
+2011-04-18 SHL
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/receiver.c ./receiver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/receiver.c	2011-03-26 10:01:36.000000000 -0700
+++ ./receiver.c	2011-04-18 22:11:40.000000000 -0700
@@ -491,7 +491,7 @@
 				handle_delayed_updates(local_name);
 			send_msg(MSG_DONE, "", 0, 0);
 			continue;
-		}
+		} // NDX_DONE
 
 		if (ndx - cur_flist->ndx_start >= 0)
 			file = cur_flist->files[ndx - cur_flist->ndx_start];
@@ -830,8 +830,8 @@
 			if (inc_recurse)
 				send_msg_int(MSG_NO_SEND, ndx);
 			break;
-		}
-	}
+		} // switch
+	} // while
 	if (make_backups < 0)
 		make_backups = -make_backups;
 
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.c ./rsync.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.c	2011-02-22 10:48:12.000000000 -0800
+++ ./rsync.c	2011-04-18 22:11:40.000000000 -0700
@@ -383,6 +383,8 @@
 	mode_t new_mode = file->mode;
 	int inherit;
 
+	// rprintf(FINFO, "* [%s] set_file_attrs fname %s mode %o file %p sxp %p %s(%u)\n", who_am_i(), fname, file->mode, file, sxp, __FILE__, __LINE__); // 27 Apr 09 SHL debug perms
+
 	if (!sxp) {
 		if (dry_run)
 			return 1;
@@ -503,6 +505,7 @@
 
 #ifdef HAVE_CHMOD
 	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+		// rprintf(FINFO, "* [%s] set_file_attrs fname %s sxp->st.st_mode %o new_mode %o %s(%u)\n", who_am_i(), fname, sxp->st.st_mode, new_mode, __FILE__, __LINE__); // 27 Apr 09 SHL debug perms
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
@@ -560,8 +563,13 @@
 		    int overwriting_basis)
 {
 	int ret;
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
 	const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
+	if (partialptr && drive_spec_width(partialptr))
+		rprintf(FINFO, "* [%s] finish_transfer partialptr %s fname %s fnamecmp %s %s(%u)\n", who_am_i(), partialptr, fname, fnamecmp, __FILE__, __LINE__); // 25 Sep 09 SHL debug slashes
+
 	if (inplace) {
 		if (verbose > 2)
 			rprintf(FINFO, "finishing %s\n", fname);
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.h ./rsync.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.h	2011-02-21 11:32:50.000000000 -0800
+++ ./rsync.h	2011-04-18 22:11:40.000000000 -0700
@@ -1168,3 +1168,12 @@
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+// 05 Mar 09 SHL support drive letters
+#ifndef __OS2__
+#define drive_spec_width(p) 0
+#define is_abs_path(p) (*(p) == '/')
+#else
+#define drive_spec_width(p) ((isalpha(*(p)) && *((p) + 1) == ':') ? 2 : 0)
+#define is_abs_path(p) (*((p) + drive_spec_width(p)) == '/')
+#endif
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/runtests.sh ./runtests.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/runtests.sh	2008-05-18 07:00:48.000000000 -0700
+++ ./runtests.sh	2011-04-18 22:11:40.000000000 -0700
@@ -239,8 +239,8 @@
     $setfacl_nodef "$scratchdir" || true
     chmod g-s "$scratchdir"
     case "$srcdir" in
-    /*) ln -s "$srcdir" "$scratchdir/src" ;;
-    *)  ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
+    /*) echo ln -s "$srcdir" "$scratchdir/src" ;;
+    *)  echo ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
     esac
     return 0
 }
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/sender.c ./sender.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/sender.c	2009-12-12 17:23:02.000000000 -0800
+++ ./sender.c	2011-04-18 22:11:40.000000000 -0700
@@ -366,7 +366,7 @@
 		send_msg_int(MSG_IO_ERROR, io_error);
 
 	if (verbose > 2)
-		rprintf(FINFO, "send files finished\n");
+		rprintf(FINFO, "send_files finished\n");	// 06 Mar 09 SHL
 
 	match_report();
 
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/shconfig ./shconfig
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/shconfig	2106-02-06 22:28:16.000000000 
+++ ./shconfig	2011-04-18 22:14:16.000000000 -0700
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+# config.sh.in 
+
+# This file is processed by config.status to produce config.status,
+# containing autoconf-determined values needed by the test scripts.
+
+ECHO_T=""
+ECHO_N="-n"
+ECHO_C=""
+
+export ECHO_T ECHO_N ECHO_C
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/syscall.c ./syscall.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/syscall.c	2011-02-21 11:32:50.000000000 -0800
+++ ./syscall.c	2011-04-18 22:11:40.000000000 -0700
@@ -28,6 +28,24 @@
 #ifdef HAVE_SYS_ATTR_H
 #include <sys/attr.h>
 #endif
+// 06 Mar 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define setmode
+#if defined HAVE_SETMODE && O_BINARY && __OS2__
+// From gcc io.h
+int setmode (int, int);
+// From gcc os2emx.h
+#endif
+#ifdef __OS2__ // 01 Aug 09 SHL
+// 01 Aug 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define _sopen
+int _sopen (__const__ char *, int, int, ...);	// hack cough
+#include "share.h"			// SH_DENYNO
+#endif
+
+#if defined __OS2__
+// 27 Apr 09 SHL Need definitions for FILE_...
+#define INCL_DOS
+// #include <os2.h>
+#include <os2emx.h>
+#endif
 
 extern int dry_run;
 extern int am_root;
@@ -35,6 +53,10 @@
 extern int list_only;
 extern int preserve_perms;
 extern int preserve_executability;
+// 13 Jun 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -138,12 +160,32 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+#ifdef __OS2__
+	int fd;
+#endif
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
 
+#ifndef __OS2__
 	return open(pathname, flags | O_BINARY, mode);
+#else
+	// 31 Jul 09 SHL if open fails, try shared open in case file already opened for write
+	fd = open(pathname, flags | O_BINARY, mode);
+	if (fd == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
+		fd = _sopen(pathname, flags | O_BINARY, SH_DENYNO, mode);
+		if (fd != -1)
+			rprintf(FINFO, "[%s] opened %s for shared write - file may change during sync\n", who_am_i(), pathname);
+		else if (verbose) {
+			int e = errno;
+			rsyserr(FINFO, errno, "do_open _sopen fallback failed for %s", pathname);
+			errno = e;
+		}
+
+	}
+	return fd;
+#endif
 }
 
 #ifdef HAVE_CHMOD
@@ -152,6 +194,9 @@
 	int code;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+
+	// rprintf(FINFO, "* [%s] do_chmod path %s requested mode %o %s(%u)\n", who_am_i(), path, mode, __FILE__, __LINE__);	// 27 Apr 09 SHL debug perms
+
 #ifdef HAVE_LCHMOD
 	code = lchmod(path, mode & CHMOD_BITS);
 #else
@@ -165,10 +210,69 @@
 		attrList.commonattr = ATTR_CMN_ACCESSMASK;
 		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
 # else
-		code = 1;
+		code = 1;		// Can not set symlink
 # endif
 	} else
+#ifndef __OS2__
+		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+#else
+	{
+		ULONG attributes = 0;
+		if (os2_perms) {
+			// Unmap mode to recover native OS/2 attributes
+			// See map_os2_attributes
+			// If not readable by owner, hidden
+			if (~mode & S_IRUSR)
+				attributes |= FILE_HIDDEN;
+			// If readable by group, system
+			if (mode & S_IRGRP)
+				attributes |= FILE_SYSTEM;
+			// If writable by group, archived
+			if (mode & S_IWGRP)
+				attributes |= FILE_ARCHIVED;
+			// Reset group rw bits to match other rw bits - hack cough
+			if (mode & S_IROTH)
+				mode |= S_IRGRP;
+			else
+				mode &= ~S_IRGRP;
+			if (mode & S_IWOTH)
+				mode |= S_IWGRP;
+			else
+				mode &= ~S_IWGRP;
+		}
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+		if (!code && os2_perms) {
+			// Adjust native attributes not handled by chmod - system, hidden, archived
+			// Maybe libc will do this someday
+			// chmod already handles readonly
+			// Adjust attributes if any but archived set or if archived not set in requested attributes
+			FILESTATUS3 fs3;
+			APIRET apiret = DosQueryPathInfo((PCSZ)path,
+							 FIL_STANDARD,
+							 &fs3,
+							 sizeof(fs3));
+			// 26 Sep 09 SHL fixme perms - set code on failure - need map_apiret_errno()
+			if (apiret)
+				rprintf(FERROR, "[%s] DosQueryPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+			else {
+				ULONG m = attributes | (fs3.attrFile & ~(FILE_SYSTEM | FILE_HIDDEN | FILE_ARCHIVED));
+				if (m != fs3.attrFile) {
+					ULONG old_attrFile = fs3.attrFile;
+					fs3.attrFile = m;
+					apiret = DosSetPathInfo((PCSZ)path,
+								 FIL_STANDARD,
+								 &fs3, sizeof(fs3),
+								 0);
+					if (apiret)
+						rprintf(FERROR, "[%s] DosSetPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+					// 17 Sep 09 SHL os2_perms
+					else if (verbose > 1)
+						rprintf(FINFO, "[%s] changed %s attrFile from %lx to %lx (attributes %lx)\n", who_am_i(), path, old_attrFile, fs3.attrFile, attributes);	// 21 Jul 09 SHL
+				}
+			}
+		}
+	}
+#endif /* __OS2__ */
 #endif /* !HAVE_LCHMOD */
 	if (code != 0 && (preserve_perms || preserve_executability))
 		return code;
@@ -256,12 +360,55 @@
 #endif
 }
 
+#ifdef __OS2__
+
+/**
+ * Map native OS/2 attributes to something rsync can send
+ * See do_chmod for unmap logic
+ */
+
+static void map_os2_attributes(STRUCT_STAT *st)
+{
+	// If hidden, readable by none
+	if (st->st_attr & FILE_HIDDEN)
+		st->st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+	// If readonly, writable by none
+	if (st->st_attr & FILE_READONLY)
+		st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+
+	// Steal group bits for native attributes without obvious mappings - hack cough
+	// If system, readable by group
+	if (st->st_attr & FILE_SYSTEM)
+		st->st_mode |= S_IRGRP;
+	else
+		st->st_mode &= ~S_IRGRP;
+	// If archived, writable by group
+	if (st->st_attr & FILE_ARCHIVED)
+		st->st_mode |= S_IWGRP;
+	else
+		st->st_mode &= ~S_IWGRP;
+}
+
+#endif
+
 int do_stat(const char *fname, STRUCT_STAT *st)
 {
 #ifdef USE_STAT64_FUNCS
 	return stat64(fname, st);
 #else
+#ifndef __OS2__
 	return stat(fname, st);
+#else
+	int code;
+	code = stat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
@@ -271,7 +418,19 @@
 # ifdef USE_STAT64_FUNCS
 	return lstat64(fname, st);
 # else
+#ifndef __OS2__
 	return lstat(fname, st);
+#else
+	// 27 Apr 09 SHL map OS/2 permissions
+	int code = lstat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from %o to %o (st_attr %o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 # endif
 #else
 	return do_stat(fname, st);
@@ -283,7 +442,19 @@
 #ifdef USE_STAT64_FUNCS
 	return fstat64(fd, st);
 #else
+#ifndef __OS2__
 	return fstat(fd, st);
+#else
+	int code;
+	code = fstat(fd, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %u mode from %o to %o (st_attr %o)\n", who_am_i(), fd, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/t_stub.c ./t_stub.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/t_stub.c	2011-02-21 11:32:48.000000000 -0800
+++ ./t_stub.c	2011-04-18 22:11:40.000000000 -0700
@@ -33,6 +33,12 @@
 char *module_dir;
 struct filter_list_struct daemon_filter_list;
 
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
+int verbose = 0;
+
+
  void rprintf(UNUSED(enum logcode code), const char *format, ...)
 {
 	va_list ap;
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/t_unsafe.c ./t_unsafe.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/t_unsafe.c	2009-01-17 13:41:34.000000000 -0800
+++ ./t_unsafe.c	2011-04-18 22:11:40.000000000 -0700
@@ -27,7 +27,6 @@
 int am_root = 0;
 int read_only = 0;
 int list_only = 0;
-int verbose = 0;
 int preserve_perms = 0;
 int preserve_executability = 0;
 
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/testsuite/rsync.fns ./testsuite/rsync.fns
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/testsuite/rsync.fns	2011-03-13 20:48:54.000000000 -0700
+++ ./testsuite/rsync.fns	2011-04-18 22:11:40.000000000 -0700
@@ -151,7 +151,7 @@
 
     echo $ECHO_N "This file has no trailing lf$ECHO_C" > "$fromdir/nolf"
     umask 0
-    ln -s nolf "$fromdir/nolf-symlink"
+    echo ln -s nolf "$fromdir/nolf-symlink"
     umask 022
 
     cat "$srcdir"/*.c > "$fromdir/text"
@@ -321,10 +321,10 @@
 build_symlinks() {
     mkdir "$fromdir"
     date >"$fromdir/referent"
-    ln -s referent "$fromdir/relative"
-    ln -s "$fromdir/referent" "$fromdir/absolute"
-    ln -s nonexistent "$fromdir/dangling"
-    ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
+    echo ln -s referent "$fromdir/relative"
+    echo ln -s "$fromdir/referent" "$fromdir/absolute"
+    echo ln -s nonexistent "$fromdir/dangling"
+    echo ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
 }
 
 test_fail() {
@@ -347,7 +347,7 @@
 }
 
 # Determine what shell command will appropriately test for links.
-ln -s foo "$scratchdir/testlink"
+echo ln -s foo "$scratchdir/testlink"
 for cmd in test /bin/test /usr/bin/test /usr/ucb/bin/test /usr/ucb/test
 do
     for switch in -h -L
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/util.c ./util.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/util.c	2011-03-17 11:25:12.000000000 -0700
+++ ./util.c	2011-04-18 22:11:40.000000000 -0700
@@ -23,6 +23,10 @@
 #include "rsync.h"
 #include "ifuncs.h"
 
+#ifdef __OS2__
+#include <os2emx.h>
+#endif
+
 extern int verbose;
 extern int module_id;
 extern int modify_window;
@@ -201,6 +205,10 @@
 	char *p;
 	int ret = 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width
+	fname += drive_spec_width(fname);		/* Bypass drive letter */
+#endif /* __OS2__ */
+
 	while (*fname == '/')
 		fname++;
 	while (strncmp(fname, "./", 2) == 0)
@@ -430,6 +438,8 @@
 {
 	int tries = 4;
 
+	// rprintf(FINFO, "* [%s] robust_rename %s->%s %s(%u)\n", who_am_i(), from, to, __FILE__, __LINE__); // 2009-04-27 SHL debug perms
+
 	while (tries--) {
 		if (do_rename(from, to) == 0)
 			return 0;
@@ -454,6 +464,27 @@
 				return -2;
 			do_unlink(from);
 			return 1;
+#ifdef __OS2__ // 2009-04-27 SHL
+		// libc rename semantics differs from linux
+		// clear readonly if this caused rename to fail
+		case EACCES:
+		{
+			STRUCT_STAT st;
+			int code;
+			if (verbose)
+				rprintf(FINFO, "[%s] robust_rename retrying %s after EACCES\n", who_am_i(), to);	// 2009-07-22 SHL
+			code = do_stat(to, &st);
+			if (!code) {
+				// 2009-04-27 SHL fixme to use st_mode when libc fixed
+				if (st.st_attr & FILE_READONLY) {
+					st.st_mode |= S_IWUSR;
+					code = do_chmod(to, st.st_mode);
+					if (!code)
+						break;	// Try again
+				}
+			}
+		}
+#endif
 		default:
 			return -1;
 		}
@@ -828,10 +859,18 @@
 {
 	char *limit = name - 1, *t = name, *f = name;
 	int anchored;
+#ifdef __OS2__
+	int drive_letter_adj;	// 0 if not, 2 if yes 2008-12-15 SHL
+#endif
 
 	if (!name)
 		return 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width...
+	drive_letter_adj = drive_spec_width(name);
+	f += drive_letter_adj;			// Keep drive letter
+	t += drive_letter_adj;
+#endif /* __OS2__ */
 	if ((anchored = *f == '/') != 0) {
 		*t++ = *f++;
 #ifdef __CYGWIN__
@@ -879,10 +918,18 @@
 		while (*f && (*t++ = *f++) != '/') {}
 	}
 
+#ifndef __OS2__ // 2009-02-06 SHL
 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 		t--;
 	if (t == name)
 		*t++ = '.';
+#else
+	if (t > name + anchored + drive_letter_adj && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
+		t--;
+	if (t == name + drive_letter_adj)
+		*t++ = '.';		// Ensure not empty
+#endif
+
 	*t = '\0';
 
 	return t - name;
@@ -916,14 +963,28 @@
 	char *start, *sanp;
 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 
+	// rprintf(FINFO, "* [%s] sanitize_path p %s %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
 	if (dest != p) {
 		int plen = strlen(p);
-		if (*p == '/') {
+		int drive_letter_adj = drive_spec_width(p);	// 0 if not, 2 if yes 2008-12-15 SHL
+#ifndef __OS2__
+		if (*p == '/')
+#else // 2009-02-06 SHL use is_abs_path...
+		if (!is_abs_path(p)) {
+			if (drive_letter_adj)
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
+		} else
+#endif
+		{
 			if (!rootdir)
 				rootdir = module_dir;
 			rlen = strlen(rootdir);
 			depth = 0;
+#ifndef __OS2__
 			p++;
+#else
+			p += drive_spec_width(p) + 1;
+#endif
 		}
 		if (dest) {
 			if (rlen + plen + 1 >= MAXPATHLEN)
@@ -932,8 +993,13 @@
 			out_of_memory("sanitize_path");
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
+#ifndef __OS2__
 			if (rlen > 1)
 				dest[rlen++] = '/';
+#else
+			if (rlen > 1 + drive_letter_adj)
+				dest[rlen++] = '/';
+#endif
 		}
 	}
 
@@ -977,6 +1043,20 @@
 		}
 		/* copy one component through next slash */
 		while (*p && (*sanp++ = *p++) != '/') {}
+#if 0 // 2009-05-16 SHL fixme to be gone
+#ifndef __OS2__
+		while (*p && (*sanp++ = *p++) != '/') {}
+#else
+		while(*p) {
+			char c = *p++;
+			if (c == '\\')
+				c = '/';
+			*sanp++ = c;
+			if (c == '/')
+				break;
+		}
+#endif
+#endif
 	}
 	if (sanp == dest) {
 		/* ended up with nothing, so put in "." component */
@@ -984,16 +1064,23 @@
 	}
 	*sanp = '\0';
 
+	// rprintf(FINFO, "* [%s] sanitize_path dest %s %s(%u)\n", who_am_i(), dest, __FILE__, __LINE__); // 2009-02-06 SHL debug
+
+	// 2009-05-16 SHL  fixme to be gone
+	assert_no_dir_slashes(dest);
+
 	return dest;
 }
 
 /* Like chdir(), but it keeps track of the current directory (in the
  * global "curr_dir"), and ensures that the path size doesn't overflow.
- * Also cleans the path using the clean_fname() function. */
+ * Also cleans the path using the clean_fname() function.
+ * Returns 1 of change OK.  Otherwise 0 */
 int change_dir(const char *dir, int set_path_only)
 {
 	static int initialised;
 	unsigned int len;
+	// rprintf(FINFO, "* [%s] change_dir dir %s initialised %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", initialised, __FILE__, __LINE__); // 2009-04-27 SHL debug perms
 
 	if (!initialised) {
 		initialised = 1;
@@ -1002,6 +1089,7 @@
 			exit_cleanup(RERR_FILESELECT);
 		}
 		curr_dir_len = strlen(curr_dir);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 	}
 
 	if (!dir)	/* this call was probably just to initialize */
@@ -1011,23 +1099,49 @@
 	if (len == 1 && *dir == '.')
 		return 1;
 
-	if (*dir == '/') {
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(dir)) {
+		// Absolute path
 		if (len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifndef __OS2__ // 2008-07-28 SHL
 		if (!set_path_only && chdir(dir))
 			return 0;
 		memcpy(curr_dir, dir, len + 1);
+#else
+		if (!set_path_only) {
+			if (chdir(dir)) {
+				rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+			if (drive_spec_width(dir) && _chdrive(*dir)) {
+				rprintf(FERROR, "[%s] change_dir _chdrive failed for dir %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+		}
+		memcpy(curr_dir, dir, len + 1);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
+#endif
 	} else {
+		// Relative path
 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifdef __OS2__
+		if (drive_spec_width(dir)) {
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			errno = EINVAL;
+			return -1;
+		}
+#endif
 		curr_dir[curr_dir_len] = '/';
 		memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
 
 		if (!set_path_only && chdir(curr_dir)) {
+			rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
 			curr_dir[curr_dir_len] = '\0';
 			return 0;
 		}
@@ -1052,12 +1166,15 @@
 {
 	unsigned int len;
 
-	if (*path != '/') { /* Make path absolute. */
+	// 2009-03-06 SHL use is_abs_path
+	if (!is_abs_path(path)) { /* Make path absolute. */
 		int len = strlen(path);
+		if (drive_spec_width(path))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2008-07-28 SHL
 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
-		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
+		memcpy(curr_dir + curr_dir_len + 1, path + drive_spec_width(path), len + 1);
 		if (!(path = strdup(curr_dir)))
 			out_of_memory("normalize_path");
 		curr_dir[curr_dir_len] = '\0';
@@ -1066,7 +1183,9 @@
 			out_of_memory("normalize_path");
 	}
 
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 	len = clean_fname(path, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 
 	if (len_ptr)
 		*len_ptr = len;
@@ -1088,9 +1207,14 @@
 	if (result)
 		free(result);
 
-	if (*fn == '/')
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(fn))
 		p1 = p2 = "";
 	else {
+#ifdef __OS2__
+		if (drive_spec_width(fn))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-02-06 SHL
+#endif
 		p1 = curr_dir + module_dirlen;
 		for (p2 = p1; *p2 == '/'; p2++) {}
 		if (*p2)
@@ -1119,6 +1243,9 @@
 
 	if ((fn = strrchr(fname, '/')) != NULL) {
 		fn++;
+		// 2009-09-25 SHL fixme slashes - handle drive letter if needed
+		if (partial_dir && drive_spec_width(partial_dir))
+			rprintf(FINFO, "* [%s] partial_dir_fname partial_dir %s fname %s %s(%u)\n", who_am_i(), partial_dir, fname, __FILE__, __LINE__); // 2009-09-25 SHL debug slashes
 		if (*partial_dir != '/') {
 			int len = fn - fname;
 			strncpy(t, fname, len); /* safe */
@@ -1150,6 +1277,7 @@
 
 	if (fname != partial_fname)
 		return 1;
+	// 2009-09-25 SHL fixme slashes?
 	if (!create && *partial_dir == '/')
 		return 1;
 	if (!(fn = strrchr(partial_fname, '/')))
@@ -1420,19 +1548,29 @@
 }
 #endif
 
-#define MALLOC_MAX 0x40000000
+
+#if 0 // 2010-12-15 SHL Enable if building for Mensys with flist size limited - see util.c MALLOC_MAX
+#define MALLOC_MAX (200 * 1024 * 1024)	// MiBytes - Mensys, lower limit is NORMAL_EXTENT (256KiBytes)
+#else
+#define MALLOC_MAX 0x40000000		// 1GiByte
+#endif
+
 
 void *_new_array(unsigned long num, unsigned int size, int use_calloc)
 {
-	if (num >= MALLOC_MAX/size)
+	if (num >= MALLOC_MAX/size) {
+	        rprintf(FERROR, "* [%s] _new_array num %lu size %u failed %s(%u)\n", who_am_i(), num, size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		return NULL;
+	}
 	return use_calloc ? calloc(num, size) : malloc(num * size);
 }
 
 void *_realloc_array(void *ptr, unsigned int size, size_t num)
 {
-	if (num >= MALLOC_MAX/size)
+	if (num >= MALLOC_MAX/size) {
+	        rprintf(FERROR, "* [%s] _realloc_array num %lu size %u failed %s(%u)\n", who_am_i(), (unsigned long)num, size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		return NULL;
+	}
 	if (!ptr)
 		return malloc(size * num);
 	return realloc(ptr, size * num);
@@ -1700,3 +1838,24 @@
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+#ifdef __OS2__ // 2009-05-16 SHL
+/**
+ * Convert OS/2 backslashes to unix forward slashes
+ */
+void normalize_dir_slashes(char *path)
+{
+	// 2010-11-24 SHL rework for more speed
+	if (path) {
+		char *p = path;
+		while((p = strchr(p, '\\')) != NULL)
+			*p++ = '/';
+	}
+}
+
+void assert_no_dir_slashes(char *path)
+{
+	if (path && strchr(path, '\\') != 0)
+		rprintf(FERROR, "[%s] unexpected backslash in path %s %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2009-02-06 SHL
+}
+#endif // __OS2__
diff -r -u -w -N -xdummy -xln -xproto.h -xrounding.h -x.saved -x'[0-9][-_]*' -x'~[0-9][[-_]*' -x'config.*' -xctags.tag -xMakefile -x'SHL*' -x'*-20[01][0-9][01][0-9]*' -x'*.a' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.old' -x'*.orig' -x'*.Po' -x'*_shl' -x'*_shl.*' -x'*.sym' -x'*~' -x'*#' I:/sla_dev2_browse/rsync/rsync-3.0.8/xattrs.c ./xattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/xattrs.c	2011-02-21 11:32:50.000000000 -0800
+++ ./xattrs.c	2011-04-18 22:11:40.000000000 -0700
@@ -113,6 +113,8 @@
 {
 	const rsync_xa *xa1 = x1;
 	const rsync_xa *xa2 = x2;
+	// rprintf(FINFO, "* [%s] rsync_xal_compare_names xa1.name %s xa2.name %s %s(%u)\n", who_am_i(), xa1->name, xa2->name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
 	return strcmp(xa1->name, xa2->name);
 }
 
@@ -144,7 +146,9 @@
 				full_fname(fname), arg);
 			return -1;
 		}
+		/* Expand buffer - get size */
 		list_len = sys_llistxattr(fname, NULL, 0);
+		/* Should not occur */
 		if (list_len < 0) {
 			arg = 0;
 			goto got_error;
@@ -243,9 +247,11 @@
 			 || (am_root < 0
 			  && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
 			   || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
-			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
+			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) {
+				// rprintf(FINFO, "* [%s] rsync_xal_get skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 				continue;
 		}
+		}
 
 		datum_len = name_len; /* Pass extra size to get_xattr_data() */
 		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -306,10 +312,12 @@
 			return 0;
 	}
 
+	// rprintf(FINFO, "* [%s] get_xattr fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 	if (rsync_xal_get(fname, sxp->xattr) < 0) {
 		free_xattr(sxp);
 		return -1;
 	}
+	// rprintf(FINFO, "* [%s] get_xattr count %d %s(%u)\n", who_am_i(), sxp->xattr ? sxp->xattr->count : -1, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 	return 0;
 }
 
@@ -482,11 +490,13 @@
 	snd_rxa = lst->items;
 	snd_cnt = lst->count;
 
+	// rprintf(FINFO, "* [%s] xattr_diff fname %s rec_cnt %u snd_cnt %u find_all %u %s(%u)\n", who_am_i(), file->basename, rec_cnt, snd_cnt, find_all, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
+
 	/* 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) {
 		if (!find_all)
-			return 1;
+			return 1;	// Say different
 		xattrs_equal = 0;
 	}
 
@@ -508,7 +518,7 @@
 		}
 		if (!same) {
 			if (!find_all)
-				return 1;
+				return 1;	// Say different
 			xattrs_equal = 0;
 		}
 
@@ -525,6 +535,8 @@
 	if (rec_cnt)
 		xattrs_equal = 0;
 
+	// rprintf(FINFO, "* [%s] xattr_diff xattrs_equal %u %s(%u)\n", who_am_i(), xattrs_equal, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
+
 	return !xattrs_equal;
 }
 
@@ -675,6 +687,8 @@
 		temp_xattr.count = 0;
 	}
 
+	// rprintf(FINFO, "* [%s] receive_xattr %s read count %u am_root %u %s(%u)\n", who_am_i(), file->basename, count, am_root, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
 	for (num = 1; num <= count; num++) {
 		char *ptr, *name;
 		rsync_xa *rxa;
@@ -721,12 +735,14 @@
 			memcpy(name, RSYNC_PREFIX, RPRE_LEN);
 		} else {
 			free(ptr);
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 			continue;
 		}
 #endif
 		/* No rsync.%FOO attributes are copied w/o 2 -X options. */
 		if (preserve_xattrs < 2 && name_len > RPRE_LEN
 		 && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 			free(ptr);
 			continue;
 		}
@@ -738,13 +754,17 @@
 		rxa->num = num;
 	}
 
-	if (need_sort && count > 1)
-		qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
+	// rprintf(FINFO, "* [%s] receive_xattr temp_xattr.items %p temp_xattr.count %u %s(%u)\n", who_am_i(), temp_xattr.items, temp_xattr.count, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
+	// 28 Jul 08 SHL sort number used not number malloced
+	if (need_sort && temp_xattr.count > 1)
+		qsort(temp_xattr.items, temp_xattr.count, sizeof (rsync_xa), rsync_xal_compare_names);
 
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
 
 	F_XATTR(file) = ndx;
+	// rprintf(FINFO, "* [%s] receive_xattr %s ndx %u count %d %s(%u)\n", who_am_i(), file->basename, ndx, rsync_xal_l.count, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 }
 
 /* Turn the xattr data in stat_x into cached xattr data, setting the index
@@ -793,6 +813,7 @@
 	size_t name_len;
 	int ret = 0;
 
+	// rprintf(FINFO, "* [%s] rsync_xal_set fname %s fnamecmp %s %s(%u)\n", who_am_i(), fname, fnamecmp, __FILE__, __LINE__); // 23 Mar 10 SHL debug libc chmod xattrs
 	/* This puts the current name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(fname)) < 0)
 		return -1;

Steven Levine

2011-04-26 14:47

manager   ~0001912

rsync-3.0.8-20110425-shl.zip is an rsync binary built with the rsync-3.0.8-20110425-shl.diff patch set.

This build is
 - Updated to rsync v3.0.8 sources
 - Now building with gcc 4.5.2 - requires gcc452.dll

Steven Levine

2011-07-03 03:32

manager  

rsync-3.0.8-20110702-shl.diff (113,065 bytes)
Generated by diffux -N -xproto.h -xrounding.h on 07-02-11 10:59:01
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/Makefile.in ../rsync-3.0.8/Makefile.in
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/Makefile.in	2011-03-26 10:01:36.000000000 -0700
+++ ../rsync-3.0.8/Makefile.in	2011-04-25 22:06:26.000000000 -0700
@@ -12,6 +12,7 @@
 CFLAGS=@CFLAGS@
 CPPFLAGS=@CPPFLAGS@
 EXEEXT=@EXEEXT@
+# 14 Jun 09 SHL fixme to do bldlevel strings
 LDFLAGS=@LDFLAGS@
 
 INSTALLCMD=@INSTALL@
@@ -42,7 +43,8 @@
 	popt/popthelp.o popt/poptparse.o
 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
 
-TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
+# 25 Mar 10 SHL
+TLS_OBJ = tls.o t_stub.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
@@ -68,6 +70,11 @@
 	-mkdir -p ${DESTDIR}${mandir}/man5
 	if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
 	if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
+	if test -f readme.os2; then ${INSTALLMAN} -m 644 readme.os2 ${DESTDIR}${prefix}; fi
+	if test -f readme.shl; then ${INSTALLMAN} -m 644 readme.shl ${DESTDIR}${prefix}; fi
+	if test -f rsync.map; then ${INSTALLMAN} -m 644 rsync.map ${DESTDIR}${prefix}; fi
+	if test -f rsync.sym; then ${INSTALLMAN} -m 644 rsync.sym ${DESTDIR}${prefix}; fi
+	if test -s "${DIFFFILE}"; then if test -f ${DIFFFILE}; then ${INSTALLMAN} -m 644 ${DIFFFILE} ${DESTDIR}${prefix}; fi; fi
 
 install-strip:
 	$(MAKE) INSTALL_STRIP='-s' install
@@ -107,11 +114,11 @@
 getfsdev$(EXEEXT): getfsdev.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
 
-TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
+TRIMSLASH_OBJ = trimslash.o t_stub.o syscall.o lib/compat.o lib/snprintf.o
 trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
-T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
+T_UNSAFE_OBJ = t_unsafe.o t_stub.o syscall.o util.o lib/compat.o lib/snprintf.o lib/wildmatch.o
 t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
 
@@ -189,9 +196,10 @@
 	yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
 	-$(srcdir)/tweak_manpage rsyncd.conf.5
 
+# 06 Feb 09 SHL clean maps
 clean: cleantests
 	rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
-		rounding rounding.h *.old
+		rounding rounding.h *.old rsync.map rounding.map
 
 cleantests:
 	rm -rf ./testtmp*
@@ -243,11 +251,13 @@
 wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
 
+# 25 Mar 10 SHL
+
 testsuite/chown-fake.test:
-	ln -s chown.test $(srcdir)/testsuite/chown-fake.test
+	echo ln -s chown.test $(srcdir)/testsuite/chown-fake.test
 
 testsuite/devices-fake.test:
-	ln -s devices.test $(srcdir)/testsuite/devices-fake.test
+	echo ln -s devices.test $(srcdir)/testsuite/devices-fake.test
 
 testsuite/xattrs-hlink.test:
 	ln -s xattrs.test $(srcdir)/testsuite/xattrs-hlink.test
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/access.c ../rsync-3.0.8/access.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/access.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/access.c	2011-04-18 22:11:36.000000000 -0700
@@ -100,7 +100,9 @@
 	hints.ai_flags = AI_NUMERICHOST;
 #endif
 
-	if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	// if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	if ((gai = getaddrinfo(addr, NULL, &hints, &resa)) != 0) {			// 27 Jul 08 SHL debug
+		// rprintf(FINFO, "* [%s] match_address gai %d %s(%u)\n", who_am_i(), gai, __FILE__, __LINE__);	// 28 Jul 08 SHL debug addrinfo
 		if (p)
 			*p = '/';
 		return 0;
@@ -110,8 +112,8 @@
 	if (p)
 		*p++ = '/';
 	if (gai != 0) {
-		rprintf(FLOG, "error matching address %s: %s\n",
-			tok, gai_strerror(gai));
+		rprintf(FLOG, "* error matching address %s: %s (%d)\n",
+			tok, gai_strerror(gai), gai);
 		freeaddrinfo(resa);
 		return 0;
 	}
@@ -222,7 +224,11 @@
 	if (host)
 		strlower(host);
 
+	// rprintf(FINFO, "* [%s] access_match %s (%s) %s(%u)\n", who_am_i(), host, addr, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
+
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+
+		// rprintf(FINFO, "* [%s] access_match tok %s %s(%u)\n", who_am_i(), tok, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
 		if (match_hostname(host, tok) || match_address(addr, tok)) {
 			free(list2);
 			return 1;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/authenticate.c ../rsync-3.0.8/authenticate.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/authenticate.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/authenticate.c	2011-04-18 22:11:36.000000000 -0700
@@ -96,7 +96,9 @@
 	if (do_stat(fname, &st) == -1) {
 		rsyserr(FLOG, errno, "stat(%s)", fname);
 		ok = 0;
-	} else if (lp_strict_modes(module)) {
+	}
+#ifndef __OS2__	 /* 29 Jun 09 SHL suppress unsupported mode checks */
+	else if (lp_strict_modes(module)) {
 		if ((st.st_mode & 06) != 0) {
 			rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
 			ok = 0;
@@ -105,6 +107,7 @@
 			ok = 0;
 		}
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		rprintf(FLOG, "continuing without secrets file\n");
 		close(fd);
@@ -173,13 +176,16 @@
 	if (do_stat(filename, &st) == -1) {
 		rsyserr(FWARNING, errno, "stat(%s)", filename);
 		ok = 0;
-	} else if ((st.st_mode & 06) != 0) {
+	}
+#ifndef __OS2__	 /* 12 Jun 08 SHL suppress unsupported mode checks */
+	else if ((st.st_mode & 06) != 0) {
 		rprintf(FWARNING, "password file must not be other-accessible\n");
 		ok = 0;
 	} else if (MY_UID() == 0 && st.st_uid != 0) {
 		rprintf(FWARNING, "password file must be owned by root when running as root\n");
 		ok = 0;
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		close(fd);
 		rprintf(FWARNING, "continuing without password file\n");
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/clientname.c ../rsync-3.0.8/clientname.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/clientname.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/clientname.c	2011-04-18 22:11:36.000000000 -0700
@@ -95,8 +95,10 @@
 	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
-	if (initialised)
+	if (initialised) {
+		// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		return name_buf;
+	}
 
 	strlcpy(name_buf, default_name, sizeof name_buf);
 	initialised = 1;
@@ -148,6 +150,8 @@
 			port_buf, sizeof port_buf) == 0)
 		check_name(fd, &ss, name_buf, sizeof name_buf);
 
+	// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
+
 	return name_buf;
 }
 
@@ -216,14 +220,17 @@
 	int name_err;
 
 	/* reverse lookup */
+	// rprintf(FINFO, "* [%s] lookup_name %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
 			       name_buf, name_buf_size,
 			       port_buf, port_buf_size,
 			       NI_NAMEREQD | NI_NUMERICSERV);
 	if (name_err != 0) {
 		strlcpy(name_buf, default_name, name_buf_size);
-		rprintf(FLOG, "name lookup failed for %s: %s\n",
-			client_addr(fd), gai_strerror(name_err));
+		// rprintf(FINFO, "name lookup failed for %s: %s\n",
+		//	client_addr(fd), gai_strerror(name_err));
+		rprintf(FLOG, "lookup_name failed for %s: %s (%d) at %s(%u) [%s]\n",	// 27 Jul 08 SHL debug
+			client_addr(fd), gai_strerror(name_err), name_err, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL
 		return name_err;
 	}
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/clientserver.c ../rsync-3.0.8/clientserver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/clientserver.c	2010-12-23 22:08:34.000000000 -0800
+++ ../rsync-3.0.8/clientserver.c	2011-04-18 22:11:36.000000000 -0700
@@ -429,6 +429,8 @@
 	iconv_opt = NULL;
 #endif
 
+	if (verbose)
+		rprintf(FINFO, "[%s] rsync_module addr:host is %s:%s\n", who_am_i(), addr, host);	// 2008-07-28 SHL
 	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
 		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
 			name, host, addr);
@@ -442,6 +444,14 @@
 		return -1;
 	}
 
+// 2010-09-17 SHL libc does not do well with chroot c:/ etc.
+#ifdef __OS2__
+	if (use_chroot) {
+		io_printf(f_out, "@ERROR: use chroot not supported\n");
+		return -1;
+	}
+#endif
+
 	if (am_daemon && am_server) {
 		rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",
 			name, host, addr);
@@ -482,6 +492,7 @@
 
 	am_root = (MY_UID() == 0);
 
+#ifndef __OS2__
 	if (am_root) {
 		p = lp_uid(i);
 		if (!name_to_uid(p, &uid)) {
@@ -504,6 +515,7 @@
 		}
 	}
 
+#endif
 	/* TODO: If we're not root, but the configuration requests
 	 * that we change to some uid other than the current one, then
 	 * log a warning. */
@@ -512,6 +524,9 @@
 	 * supplementary groups. */
 
 	module_dir = lp_path(i);
+ 
+ 	// fprintf(stderr, "* [%s] module_dir %s %s(%u)\n", who_am_i(), module_dir, __FILE__, __LINE__); // 2010-09-16 SHL debug
+ 
 	if (*module_dir == '\0') {
 		rprintf(FLOG, "No path specified for module %s\n", name);
 		io_printf(f_out, "@ERROR: no path setting.\n");
@@ -541,6 +556,8 @@
 		full_module_path = module_dir = module_chdir;
 	}
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug path
+
 	if (module_dirlen == 1) {
 		module_dirlen = 0;
 		set_filter_dir("/", 1);
@@ -664,6 +681,8 @@
 	}
 #endif
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
 	if (use_chroot) {
 		/*
 		 * XXX: The 'use chroot' flag is a fairly reliable
@@ -685,8 +704,13 @@
 		module_chdir = module_dir;
 	}
 
-	if (!change_dir(module_chdir, CD_NORMAL))
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+		// rsyserr(FERROR, errno, "[%s] chdir %s failed at %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2008-12-15 SHL debug
+		// rprintf(FINFO, "* [%s] chdir module_chdir %s failed %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 		return path_failure(f_out, module_chdir, True);
+	}
 	if (module_dirlen || !use_chroot)
 		sanitize_paths = 1;
 
@@ -1001,6 +1025,7 @@
 	close(fd);
 }
 
+#ifndef __OS2__
 /* Become a daemon, discarding the controlling terminal. */
 static void become_daemon(void)
 {
@@ -1034,6 +1059,7 @@
 		open("/dev/null", O_RDWR);
 	}
 }
+#endif // __OS2__
 
 int daemon_main(void)
 {
@@ -1056,10 +1082,14 @@
 		exit_cleanup(RERR_SYNTAX);
 	}
 
+#ifndef __OS2__
 	if (no_detach)
 		create_pid_file();
 	else
 		become_daemon();
+#else
+	create_pid_file();
+#endif
 
 	if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
 		rsync_port = RSYNC_PORT;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/compat.c ../rsync-3.0.8/compat.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/compat.c	2011-02-21 11:32:48.000000000 -0800
+++ ../rsync-3.0.8/compat.c	2011-04-18 22:11:36.000000000 -0700
@@ -201,11 +201,12 @@
 			exit_cleanup(RERR_PROTOCOL);
 		}
 		if (preserve_xattrs && !local_server) {
-			rprintf(FERROR,
-			    "--xattrs requires protocol 30 or higher"
+		  	preserve_xattrs = 0;	// 06 Feb 09 SHL force off for old servers
+			rprintf(FWARNING,
+			    "--xattrs requires protocol 30 or higher - option disabled"
 			    " (negotiated %d).\n",
 			    protocol_version);
-			exit_cleanup(RERR_PROTOCOL);
+			// exit_cleanup(RERR_PROTOCOL);	// 06 Feb 09 SHL
 		}
 	}
 
@@ -296,6 +297,7 @@
 	if (need_unsorted_flist && (!am_sender || inc_recurse))
 		unsort_ndx = ++file_extra_cnt;
 
+	// 16 Feb 09 SHL fixme slashes?
 	if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
 		int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
 		if (!am_sender || protocol_version >= 30)
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/configure.sh ../rsync-3.0.8/configure.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/configure.sh	2011-03-26 14:37:50.000000000 -0700
+++ ../rsync-3.0.8/configure.sh	2011-04-18 22:11:36.000000000 -0700
@@ -71,6 +71,8 @@
   as_echo='sh -c $as_echo_body as_echo'
 fi
 
+# 18 Jun 09 SHL fixme to not be broken - 3.0.5 worked - maybe autoconf 2.6.3 broke it
+
 # The user is always right.
 if test "${PATH_SEPARATOR+set}" != set; then
   PATH_SEPARATOR=:
@@ -8414,6 +8416,15 @@
 	$as_echo "#define SUPPORT_XATTRS 1" >>confdefs.h
 
 	;;
+    *os2*)
+	{ echo "$as_me:$LINENO: result: Using OS/2 extattrs" >&5
+echo "${ECHO_T}Using OS/2 extattrs" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_XATTRS 1
+_ACEOF
+
+	;;
+
     *)
 	if test x"$enable_xattr_support" = x"yes"; then
 	    as_fn_error $? "Failed to find extended attribute support" "$LINENO" 5
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/exclude.c ../rsync-3.0.8/exclude.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/exclude.c	2011-02-20 23:48:18.000000000 -0800
+++ ../rsync-3.0.8/exclude.c	2011-04-18 22:11:36.000000000 -0700
@@ -298,7 +298,7 @@
 	unsigned int fn_len;
 
 	if (!parent_dirscan && *merge_file != '/') {
-		/* Return the name unchanged it doesn't have any slashes. */
+		/* Return the name unchanged if it doesn't have any slashes. */
 		if (len_ptr) {
 			const char *p = merge_file + *len_ptr;
 			while (--p > merge_file && *p != '/') {}
@@ -310,6 +310,7 @@
 			return (char *)merge_file;
 	}
 
+	// 16 Feb 09 SHL fixme slash
 	fn = *merge_file == '/' ? buf : tmpbuf;
 	if (sanitize_paths) {
 		const char *r = prefix_skip ? "/" : NULL;
@@ -351,6 +352,7 @@
 void set_filter_dir(const char *dir, unsigned int dirlen)
 {
 	unsigned int len;
+	// 16 Feb 09 SHL fixme slash?
 	if (*dir != '/') {
 		memcpy(dirbuf, curr_dir, curr_dir_len);
 		dirbuf[curr_dir_len] = '/';
@@ -548,6 +550,7 @@
 	int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
 	char *p, *pattern = ex->pattern;
 	const char *strings[16]; /* more than enough */
+	// 16 Feb 09 SHL fixme slash?
 	const char *name = fname + (*fname == '/');
 
 	if (!*name)
@@ -605,8 +608,15 @@
 		if (litmatch_array(pattern, strings, slash_handling))
 			return ret_match;
 	} else if (anchored_match) {
+#ifndef __OS2__
 		if (strcmp(name, pattern) == 0)
 			return ret_match;
+#else
+		// 18 Oct 09 SHL Case insensitive
+		if (stricmp(name, pattern) == 0)
+			return ret_match;
+#endif
+
 	} else {
 		int l1 = strlen(name);
 		int l2 = strlen(pattern);
@@ -988,6 +998,25 @@
 				cp = ".cvsignore";
 				pat_len = 10;
 			}
+#ifdef __OS2__
+			else {
+				// 2009-10-19 SHL normalize
+				// 30 Sep 10 SHL avoid writing to const memory
+				/* If we are passed paths from the filter they
+				   might have DOS slashes, convert to Unix slashes
+				   except for the 1st characters (fixme to doc why - I forgot)
+				   If we are processing a const string, it will already
+				   have Unix slashes so don't try to write to const memory
+				*/
+				char ch;
+				p = cp + pat_len;	// Must be non-const for gcc
+				ch = *p;		// Remember 1st character - fixme to say why
+				normalize_dir_slashes((char *)cp);	// Hack cough - override const
+				if (*p != ch)
+					*(char*)p = ch;	// Ensure leading char not changed - fixme to say why
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len, cp, strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
+			}
+#endif
 			len = pat_len;
 			if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
 				const char *name = cp + len;
@@ -998,6 +1027,8 @@
 				len = pat_len;
 			}
 			if (new_mflags & MATCHFLG_PERDIR_MERGE) {
+				// 19 Oct 09 SHL fixme to complain if have drive letter?
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 				if (parent_dirscan) {
 					if (!(p = parse_merge_name(cp, &len,
 								module_dirlen)))
@@ -1014,6 +1045,7 @@
 			}
 		}
 
+		// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 		add_rule(listp, cp, pat_len, new_mflags, xflags);
 
 		if (new_mflags & MATCHFLG_CVS_IGNORE
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/flist.c ../rsync-3.0.8/flist.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/flist.c	2011-02-21 10:20:58.000000000 -0800
+++ ../rsync-3.0.8/flist.c	2011-04-18 22:11:36.000000000 -0700
@@ -347,8 +347,19 @@
 {
 	if (dirlen < 0) {
 		char *cpy = strdup(dir);
+#ifndef __OS2__ // 2009-03-06 SHL use is_abs_path...
 		if (*cpy != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (!is_abs_path(cpy)) {
+			if (drive_spec_width(cpy))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), cpy, __FILE__, __LINE__);	// 2009-02-06 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+	        }
+#endif
 		if (path_is_daemon_excluded(cpy, 0))
 			goto chdir_error;
 		dir = cpy;
@@ -362,8 +373,19 @@
 				dirlen = strlen(dir);
 		} else if (pathname == dir)
 			return 1;
+#ifndef __OS2__ // 2009-03-06 SHL use is_abs_path...
 		if (dir && *dir != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (dir && !is_abs_path(dir)) {
+			if (drive_spec_width(dir))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+		}
+#endif
 	}
 
 	pathname = dir;
@@ -376,8 +398,13 @@
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
 		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
-		if (dir != orig_dir)
-			change_dir(orig_dir, CD_NORMAL);
+		rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-07-21 SHL
+		if (dir != orig_dir) {
+			if (!change_dir(orig_dir, CD_NORMAL)) {
+				if (verbose > 1)
+					rprintf(FLOG, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+		}
 		pathname = NULL;
 		pathname_len = 0;
 		return 0;
@@ -1330,6 +1357,8 @@
 {
 	struct file_struct *file;
 
+	// rprintf(FINFO, "* [%s] send_file_name fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+
 	file = make_file(fname, flist, stp, flags, filter_level);
 	if (!file)
 		return NULL;
@@ -1975,6 +2004,7 @@
 	int len, dirlen;
 	STRUCT_STAT st;
 	char *p, *dir;
+	static char* the_root = "/";
 	struct file_list *flist;
 	struct timeval start_tv, end_tv;
 	int64 start_write;
@@ -2018,6 +2048,7 @@
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
 			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
 				full_fname(argv[0]));
+			rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), argv[0], __FILE__, __LINE__);	// 2009-07-21 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 		use_ff_fd = 1;
@@ -2037,19 +2068,25 @@
 			if (argc-- == 0)
 				break;
 			strlcpy(fbuf, *argv++, MAXPATHLEN);
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2010-09-16 SHL debug paths
 			if (sanitize_paths)
 				sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2010-09-16 SHL debug paths
+
 		len = strlen(fbuf);
 		if (relative_paths) {
 			/* We clean up fbuf below. */
 			name_type = NORMAL_NAME;
 		} else if (!len || fbuf[len - 1] == '/') {
-			if (len == 2 && fbuf[0] == '.') {
-				/* Turn "./" into just "." rather than "./." */
+			/* Empty path or trailing / */
+			// 2009-03-06 SHL Support drive letters
+			if (len == 2 + drive_spec_width(fbuf) && fbuf[drive_spec_width(fbuf)] == '.') {
+				/* Turn trailing "./" into just "." rather than "./." */
 				fbuf[--len] = '\0';
 			} else {
+				/* Turn trailing "xyz/" into "xyz/." */
 				if (len + 1 >= MAXPATHLEN)
 					overflow_exit("send_file_list");
 				fbuf[len++] = '.';
@@ -2058,6 +2095,7 @@
 			name_type = DOTDIR_NAME;
 		} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
 		    && (len == 2 || fbuf[len-3] == '/')) {
+			/* Got ..  or trailing /.. */
 			if (len + 2 >= MAXPATHLEN)
 				overflow_exit("send_file_list");
 			fbuf[len++] = '/';
@@ -2076,18 +2114,40 @@
 			if (p) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 2009-03-06 SHL Preserve drive letter in directory name
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else
 					dir = fbuf;
-				len -= p - fbuf + 1;
-				fn = p + 1;
+				fn = p + 1;		// Point at filename part
+				len -= fn - fbuf;	//  fn length
+				// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			} else
 				fn = fbuf;
 		} else {
+			// relative-paths
 			if ((p = strstr(fbuf, "/./")) != NULL) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 2009-03-06 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else {
 					dir = fbuf;
 					clean_fname(dir, 0);
@@ -2101,6 +2161,10 @@
 				fn = fbuf;
 			/* A leading ./ can be used in relative mode to affect
 			 * the dest dir without its name being in the path. */
+#ifdef __OS2__
+			// 2010-11-30 SHL Point after drive letter
+			fn += drive_spec_width(fn);
+#endif
 			if (*fn == '.' && fn[1] == '/' && !implied_dot_dir) {
 				send_file_name(f, flist, ".", NULL,
 				    (flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR,
@@ -2109,6 +2173,7 @@
 			}
 			len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
 					    | CFN_DROP_TRAILING_DOT_DIR);
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug relative-paths
 			if (len == 1) {
 				if (fn[0] == '/') {
 					fn = "/.";
@@ -2133,7 +2198,8 @@
 					exit_cleanup(RERR_SYNTAX);
 				}
 			}
-		}
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug relative-paths
+		} // relative-paths
 
 		if (!*fn) {
 			len = 1;
@@ -2141,6 +2207,8 @@
 			name_type = DOTDIR_NAME;
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list dir %s fn %s len %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug xattrs
+
 		dirlen = dir ? strlen(dir) : 0;
 		if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
 			if (!change_pathname(NULL, dir, -dirlen))
@@ -2150,9 +2218,16 @@
 		} else if (!change_pathname(NULL, lastdir, lastdir_len))
 			continue;
 
+		// 2009-03-06 SHL
+		if (dir && dir != the_root && dir != fbuf)
+			free(dir);	// We allocated it
+
 		if (fn != fbuf)
 			memmove(fbuf, fn, len + 1);
 
+		// rprintf(FINFO, "* [%s] send_file_list fn %s %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s len %d %s(%u)\n", who_am_i(), fbuf, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+
 		if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
@@ -2173,12 +2248,14 @@
 		}
 
 		if (inc_recurse && relative_paths && *fbuf) {
+			// 2009-03-06 SHL fixme
 			if ((p = strchr(fbuf+1, '/')) != NULL) {
 				if (p - fbuf == 1 && *fbuf == '.') {
 					if ((fn = strchr(p+1, '/')) != NULL)
 						p = fn;
 				} else
 					fn = p;
+				// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 				send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
 				if (fn == p)
 					continue;
@@ -2186,6 +2263,7 @@
 		} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
 			/* Send the implied directories at the start of the
 			 * source spec, so we get their permissions right. */
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
 		}
 
@@ -2194,6 +2272,7 @@
 
 		if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
 			struct file_struct *file;
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			file = send_file_name(f, flist, fbuf, &st,
 					      FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
 					      NO_FILTERS);
@@ -2209,9 +2288,11 @@
 				}
 			} else
 				send_if_directory(f, flist, file, fbuf, len, flags);
-		} else
+		} else {
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
 	}
+	} /* while */
 
 	gettimeofday(&end_tv, NULL);
 	stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000
@@ -2401,6 +2482,9 @@
 							struct file_struct *,
 							dir_flist->malloced);
 				dir_flist_malloced = dir_flist->malloced;
+				// 2010-11-30 SHL check out of memory
+				if (dir_flist->sorted == NULL)
+					out_of_memory("recv_file_list");
 			}
 			memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart,
 			       (dir_flist->used - dstart) * sizeof (struct file_struct*));
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/generator.c ../rsync-3.0.8/generator.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/generator.c	2011-03-26 10:17:14.000000000 -0700
+++ ../rsync-3.0.8/generator.c	2011-05-25 17:18:46.000000000 -0700
@@ -96,6 +96,10 @@
 extern int backup_suffix_len;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+// 14 Oct 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 int ignore_perishable = 0;
 int non_perishable_cnt = 0;
@@ -263,6 +267,7 @@
 	}
 
 	p = fname + dlen;
+	// 16 Feb 09 SHL fixme slash?
 	if (dlen != 1 || *fname != '/')
 		*p++ = '/';
 	remainder = MAXPATHLEN - (p - fname);
@@ -659,7 +664,7 @@
 #endif
 	}
 
-	return 1;
+	return 1;			// No change
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -680,19 +685,30 @@
 		} else if (keep_time
 		 ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
 		 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
-		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s file->modtime %u sxp->st.st_mtime %u %s(%u)\n", who_am_i(), fnamecmp, file->modtime, sxp->st.st_mtime, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme times
+			if (verbose > 1)
+				rprintf(FINFO, "%s times differ sender %u receiver %u\n", fnamecmp, file->modtime, sxp->st.st_mtime);
 			iflags |= ITEM_REPORT_TIME;
+		}
+
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
 		} else
 #endif
 		if (preserve_perms) {
-			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) {
+				// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode 0%o file->mode 0%o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
+				if (verbose > 1)
+					rprintf(FINFO, "%s perms differ sender %o receiver %o\n", fnamecmp, file->mode, sxp->st.st_mode);
 				iflags |= ITEM_REPORT_PERMS;
+			}
 		} else if (preserve_executability
-		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0))) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode 0%o file->mode 0%o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
 			iflags |= ITEM_REPORT_PERMS;
+		 }
 		if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 			iflags |= ITEM_REPORT_OWNER;
 		if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
@@ -1539,8 +1555,10 @@
 #endif
 
 #ifdef SUPPORT_XATTRS
-		if (preserve_xattrs && statret == 1)
+		if (preserve_xattrs && statret == 1) {
+			// rprintf(FINFO, "* [%s] receive_generator running copy_xattrs fnamecmpbuf %s fname %s %s(%u)\n", who_am_i(), fnamecmpbuf, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
 			copy_xattrs(fnamecmpbuf, fname);
+		}
 #endif
 		if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
 		    && verbose && code != FNONE && f_out != -1)
@@ -1640,6 +1658,17 @@
 			cur_flist->in_progress++;
 			goto cleanup;
 		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If source directory not archived (i.e. not writable by group)
+		// may need to touch up after file operations complete
+		// see map_os2_attributes
+		if (!need_retouch_dir_perms && os2_perms &&
+		    ~file->mode & S_IWGRP) {
+			// rprintf(FINFO, "* [%s] recv_generator dir %s needs retouch mode 0%o %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 14 Oct 09 SHL fixme dir perms
+			need_retouch_dir_perms = 1;
+		}
+#endif
 #endif
 		if (do_symlink(sl, fname) != 0) {
 			rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed",
@@ -1664,7 +1693,7 @@
 		}
 #endif
 		goto cleanup;
-	}
+	} // is_dir
 
 	if ((am_root && preserve_devices && IS_DEVICE(file->mode))
 	 || (preserve_specials && IS_SPECIAL(file->mode))) {
@@ -2096,10 +2125,18 @@
 	} else
 		start = end = ndx;
 
+	// rprintf(FINFO, "* [%s] touch_up_dirs start %u end %u %s(%u)\n", who_am_i(), start, end,  __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
+
 	/* Fix any directory permissions that were modified during the
 	 * transfer and/or re-set any tweaked modified-time values. */
 	for (i = start; i <= end; i++, counter++) {
+		// 23 Mar 10 SHL overcome xattrs generated by libc chmod
+#ifdef __OS2__
+		int need_xattrs_set = 0;
+#endif
 		file = flist->files[i];
+		// fname = f_name(file, NULL); // 14 Oct 09 SHL debug dir perms
+		// rprintf(FINFO, "* [%s] touch_up_dirs dir %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 		if (!S_ISDIR(file->mode)
 		 || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))
 			continue;
@@ -2110,18 +2147,80 @@
 		}
 		/* Be sure not to retouch permissions with --fake-super. */
 		fix_dir_perms = !am_root && !(file->mode & S_IWUSR);
+#ifndef __OS2__
 		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
 		 || !(need_retouch_dir_times || fix_dir_perms))
 			continue;
+else // __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived on (i.e. writable by group)
+		// See map_os2_attributes
+		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
+		 || !(need_retouch_dir_times || fix_dir_perms
+		      || !os2_perms || (~file->mode & S_IWGRP)))
+			continue;
+#endif
 		fname = f_name(file, NULL);
-		if (fix_dir_perms)
+#ifdef __OS2__
+		// 14 Oct 09 SHL Need to set time before clearing archive bit
+		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);
+		}
+#endif
+		if (fix_dir_perms) {
+			do_chmod(fname, file->mode);
+#ifdef __OS2__
+			// 25 Mar 10 SHL fixme to be sure can update EAs after setting read-only
+			// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWUSR fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			need_xattrs_set = preserve_xattrs;
+#endif
+		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived off (i.e. not writable by group)
+		// See map_os2_attributes
+		// Other os/2 perms should already be OK
+		// There is no way to know for sure if directory was modified so we check
+		else if (os2_perms && ~file->mode & S_IWGRP) {
+			STRUCT_STAT st;
+			if (link_stat(fname, &st, 0) == 0 &&
+			    ((file->mode ^ st.st_mode) & S_IWGRP)) {
+				// rprintf(FINFO, "* [%s] touch_up_dirs chmod(%s, 0%o) %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 			do_chmod(fname, file->mode);
+				// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+				// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWGRP(archive) fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+				need_xattrs_set = need_xattrs_set || preserve_xattrs;
+			}
+		}
+#endif
+#ifndef __OS2__
 		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);
 		}
+#endif
+#ifdef __OS2__
+		if (need_xattrs_set) {
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			stat_x sx;
+			// rprintf(FINFO, "* [%s] touch_up_dirs doing set_xattr for %s %s %s(%u)\n", who_am_i(), fname, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			if (verbose > 2)
+				rprintf(FINFO, "%s removing EAs generated by libc chmod %s\n", who_am_i(), fname);
+			memset(&sx, 0, sizeof(stat_x));
+			// Should not need to provide target item list to set_xattr
+			// link_stat(fname, &sx.st, 0);
+			// sx.xattr = new(item_list);
+			// *sxp.xattr = empty_xattr;
+			set_xattr(fname, file, fname, &sx);
+			// free_xattr(&sx);
+		}
+#endif
 		if (counter >= loopchk_limit) {
 			if (allowed_lull)
 				maybe_send_keepalive();
@@ -2129,7 +2228,7 @@
 				maybe_flush_socket(0);
 			counter = 0;
 		}
-	}
+	} // for
 }
 
 void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/getaddrinfo.c ../rsync-3.0.8/lib/getaddrinfo.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/getaddrinfo.c	2009-12-12 17:20:34.000000000 -0800
+++ ../rsync-3.0.8/lib/getaddrinfo.c	2011-04-18 22:11:36.000000000 -0700
@@ -403,12 +403,16 @@
 	int ret = -1;
 	char *p = NULL;
 
+	// rprintf(FINFO, "* [%s] gethostnameinfo NI_NUMERICHOST %u %s(%u)\n", who_am_i(), flags & NI_NUMERICHOST, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	if (!(flags & NI_NUMERICHOST)) {
+		// rprintf(FINFO, "* [%s] gethostnameinfo %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		struct hostent *hp = gethostbyaddr(
 				(void *)&((struct sockaddr_in *)sa)->sin_addr,
 				sizeof (struct in_addr),
 				sa->sa_family);
+		// rprintf(FINFO, "* [%s] gethostnameinfo hp %p %s(%u)\n", who_am_i(), hp, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		ret = check_hostent_err(hp);
+		// rprintf(FINFO, "* [%s] ret %d %s(%u)\n", who_am_i(), ret, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (ret == 0) {
 			/* Name looked up successfully. */
 			ret = snprintf(node, nodelen, "%s", hp->h_name);
@@ -424,6 +428,7 @@
 			return 0;
 		}
 
+		// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (flags & NI_NAMEREQD) {
 			/* If we require a name and didn't get one,
 			 * automatically fail. */
@@ -431,6 +436,7 @@
 		}
 		/* Otherwise just fall into the numeric host code... */
 	}
+	// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
 	ret = snprintf(node, nodelen, "%s", p);
 	if (ret < 0 || (size_t)ret >= nodelen) {
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/pool_alloc.c ../rsync-3.0.8/lib/pool_alloc.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/pool_alloc.c	2008-11-09 18:55:14.000000000 -0800
+++ ../rsync-3.0.8/lib/pool_alloc.c	2011-04-18 22:11:36.000000000 -0700
@@ -93,8 +93,10 @@
 	else if (pool->quantum > 1 && len % pool->quantum)
 		len += pool->quantum - len % pool->quantum;
 
-	if (len > pool->size)
+	if (len > pool->size) {
+	        rprintf(FERROR, "* [%s] pool_alloc len %u > pool->size %u %s(%u)\n", who_am_i(), len, pool->size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		goto bomb_out;
+	}
 
 	if (!pool->extents || len > pool->extents->free) {
 		void	*start;
@@ -111,16 +113,20 @@
 		if (pool->flags & POOL_APPEND)
 			asize += sizeof (struct pool_extent);
 
-		if (!(start = new_array(char, asize)))
+		if (!(start = new_array(char, asize))) {
+			rprintf(FERROR, "* [%s] new_array asize %u failed %s(%u)\n", who_am_i(), asize, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 			goto bomb_out;
+		}
 
 		if (pool->flags & POOL_CLEAR)
 			memset(start, 0, free);
 
 		if (pool->flags & POOL_APPEND)
 			ext = PTR_ADD(start, free);
-		else if (!(ext = new(struct pool_extent)))
+		else if (!(ext = new(struct pool_extent))) {
+			rprintf(FERROR, "* [%s] new pool_extent failed %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 			goto bomb_out;
+		}
 		if (pool->flags & POOL_QALIGN && pool->quantum > 1
 		    && (skew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
 			bound  += skew;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.c ../rsync-3.0.8/lib/sysxattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.c	2008-03-01 12:01:40.000000000 -0800
+++ ../rsync-3.0.8/lib/sysxattrs.c	2011-04-18 22:11:36.000000000 -0700
@@ -126,6 +126,361 @@
 	return len;
 }
 
+#elif defined(__OS2__)
+
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+
+static void map_os2_apiret(APIRET rc)
+{
+	switch (rc) {
+	case ERROR_SHARING_VIOLATION:
+		errno = EACCES;
+		break;
+	case 0:
+		// Should not have been called - try to do no harm
+		break;
+	default:
+		// 2009-07-31 SHL fixme to map better
+		// if (verbose > 2)
+		rprintf(FINFO, "[%s] can not map OS/2 error %lu to errno\n", who_am_i(), rc);	// 31 Jul 09 SHL
+		/* Ensure non-zero */
+		if (!errno)
+			errno = EINVAL;
+
+	}
+}
+
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+	return unisetxattr (path, 0, name, value, size, 0);
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+static char *out_of_mem_msg = "out of memory allocating %lu at %s(%u)\n";
+
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	size_t reqsize;
+	EAOP2       eaop2 = {0,0,0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+	reqsize = sizeof(GEA2LIST) + namelen + 1;
+	pgea2list = (PGEA2LIST)calloc(reqsize, 1);
+	// 2010-11-30 SHL
+	if (pgea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	reqsize = sizeof(FEA2LIST) + 0x10000;
+	pfea2list = (PFEA2LIST)calloc(reqsize, 1);
+	// 2010-11-30 SHL
+	if (pfea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;
+	do {
+		if (path) {
+			rc = DosQueryPathInfo(path, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryPathInfo(%s, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] %s requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), path, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		else {
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryFileInfo(%u, FIL_QUERYEASFROMLIST) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] handle %d requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), file, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		if (rc)
+			break;
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0) {
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value) {
+			if ((size_t)rc > size) {
+				errno = ERANGE;
+				rc = -1;
+			}
+			else {
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+		free(pgea2list);
+	if (pgea2list)
+		free(pfea2list);
+
+	return rc;
+}
+
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	size_t reqsize;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat;
+	if (!path && !file) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (path) {
+		rc = DosQueryPathInfo(path, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryPathInfo(%s, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] %s reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), path, stat.cbList);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryFilInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] handle %d reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), file, stat.cbList);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	if (stat.cbList <= 4) {
+		// NO ea
+		return 0;
+	}
+	//YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
+	reqsize = stat.cbList * 2;
+	buf = (char *)_tmalloc(reqsize);
+	// 2009-09-19 SHL was trapping on large copies
+	if (!buf) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);	// 2009-09-19 SHL
+		return -1;
+	}
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc) {
+		rprintf(FERROR, "[%s] unilistxattr DosEnumAttribute failed with error %u at %s(%u)\n", who_am_i(), rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		_tfree(buf);
+		map_os2_apiret(rc);	// 31 Jul 09 SHL moved here to ensure errno returned
+		return -1;
+	}
+	else if (verbose > 2) {
+		if (path)
+			rprintf(FINFO, "[%s] %s has %lu DosEnumAttribute items\n", who_am_i(), path, ulCount);	// 28 Jul 08 SHL
+		else
+			rprintf(FINFO, "[%s] handle %d has %lu DosEnumAttribute items\n", who_am_i(), file, ulCount);	// 28 Jul 08 SHL
+	}
+	if (ulCount > 0) {
+		for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset)) {
+			if (pfea->cbName > 0) {
+				gotsize += pfea->cbName + 1;
+				// Avoid overflow
+				if (p && (size_t)gotsize <= size) {
+					pfea->szName[pfea->cbName] = 0;
+					strcpy(p, pfea->szName);
+					p += strlen(p) + 1;
+				}
+			}
+			if (!pfea->oNextEntryOffset)
+				break;
+		}
+	}
+	_tfree(buf);
+	if ((size_t)gotsize > size) {
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	if (verbose > 2)
+		rprintf(FINFO, "[%s] returning %ld EA list bytes\n", who_am_i(), (unsigned long)gotsize);	// 28 Jul 08 SHL
+	return gotsize;
+}
+
+int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0,0,0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosFileInfo(%u, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0,0,0};
+	PFEA2LIST   pfea2list = NULL;
+	// char * p;			// 17 May 09 SHL  fixme
+
+	if ((!path && !file) || !name || (!value && size)) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0) {
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0) {
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(FEA2LIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	// 2010-11-30 SHL
+	if (pfea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, totalsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value) {
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetFileInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	free(pfea2list);
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
 #else
 
 #error You need to create xattr compatibility functions.
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.h ../rsync-3.0.8/lib/sysxattrs.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.h	2007-04-07 10:22:24.000000000 -0700
+++ ../rsync-3.0.8/lib/sysxattrs.h	2011-04-18 22:11:36.000000000 -0700
@@ -19,6 +19,13 @@
 int sys_lremovexattr(const char *path, const char *name);
 ssize_t sys_llistxattr(const char *path, char *list, size_t size);
 
+#ifdef __OS2__
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size);
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size);
+int uniremovexattr (const char *path, int file, const char *name);
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags);
+#endif
+
 #else
 
 /* No xattrs available */
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/wildmatch.c ../rsync-3.0.8/lib/wildmatch.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/wildmatch.c	2007-05-21 22:58:58.000000000 -0700
+++ ../rsync-3.0.8/lib/wildmatch.c	2011-04-18 22:11:36.000000000 -0700
@@ -89,8 +89,14 @@
 	    p_ch = *++p;
 	    /* FALLTHROUGH */
 	  default:
+#ifndef __OS2__
 	    if (t_ch != p_ch)
 		return FALSE;
+#else
+	    // 18 Oct 09 SHL be case insensitive
+	    if (t_ch != p_ch && (t_ch ^ p_ch) != 0x20)
+		return FALSE;
+#endif
 	    continue;
 	  case '?':
 	    /* Match anything but '/'. */
@@ -150,8 +156,14 @@
 		    p_ch = *++p;
 		    if (!p_ch)
 			return ABORT_ALL;
+#ifndef __OS2__
 		    if (t_ch == p_ch)
 			matched = TRUE;
+#else
+		    // 18 Oct 09 SHL be case insensitive
+		    if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			matched = TRUE;
+#endif
 		} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
 		    p_ch = *++p;
 		    if (p_ch == '\\') {
@@ -159,6 +171,7 @@
 			if (!p_ch)
 			    return ABORT_ALL;
 		    }
+		    // 18 Oct 09 SHL [a-z] ranges remain case-sensitive for now
 		    if (t_ch <= p_ch && t_ch >= prev_ch)
 			matched = TRUE;
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
@@ -173,8 +186,14 @@
 			/* Didn't find ":]", so treat like a normal set. */
 			p = s - 2;
 			p_ch = '[';
+#ifndef __OS2__
 			if (t_ch == p_ch)
 			    matched = TRUE;
+#else
+			// 18 Oct 09 SHL be case insensitive
+			if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			    matched = TRUE;
+#endif
 			continue;
 		    }
 		    if (CC_EQ(s,i, "alnum")) {
@@ -218,6 +237,11 @@
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
 		} else if (t_ch == p_ch)
 		    matched = TRUE;
+#ifdef __OS2__
+		// 18 Oct 09 SHL be case insensitive
+		else if ((t_ch ^ p_ch) == 0x20)
+		    matched = TRUE;
+#endif
 	    } while (prev_ch = p_ch, (p_ch = *++p) != ']');
 	    if (matched == special || t_ch == '/')
 		return FALSE;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/loadparm.c ../rsync-3.0.8/loadparm.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/loadparm.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/loadparm.c	2011-04-18 22:11:36.000000000 -0700
@@ -212,7 +212,7 @@
  /* read_only; */		True,
  /* strict_modes; */		True,
  /* transfer_logging; */	False,
- /* use_chroot; */		True,
+ /* use_chroot; */		False,	// 2010-09-17 SHL libc chroot not quite right
  /* write_only; */		False,
 };
 
@@ -654,10 +654,23 @@
 	    *(char *)dest_ptr = *(char *)src_ptr;
 	    break;
 
+#ifndef __OS2__
 	  case P_PATH:
 	  case P_STRING:
 	    string_set(dest_ptr,*(char **)src_ptr);
 	    break;
+#else
+	  case P_PATH:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    // 2009-03-06 SHL Force unix slashes
+	    // 2009-05-16 SHL Use normalize_dir_slashes
+	    normalize_dir_slashes(*(char **)dest_ptr);
+	    break;
+
+	  case P_STRING:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    break;
+#endif
 
 	  default:
 	    break;
@@ -725,8 +738,14 @@
      case P_PATH:
        string_set(parm_ptr,parmvalue);
        if ((cp = *(char**)parm_ptr) != NULL) {
+	   // Chop trailing slashes unless root
 	   int len = strlen(cp);
+#ifndef __OS2__
 	   while (len > 1 && cp[len-1] == '/') len--;
+#else
+	   // 2010-11-24 SHL Use drive_spec_width
+	   while (len > drive_spec_width(cp) + 1 && cp[len-1] == '/') len--;
+#endif
 	   cp[len] = '\0';
        }
        break;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/log.c ../rsync-3.0.8/log.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/log.c	2011-01-29 19:25:52.000000000 -0800
+++ ../rsync-3.0.8/log.c	2011-04-18 22:11:36.000000000 -0700
@@ -369,6 +369,7 @@
 	va_list ap;
 	char buf[BIGPATHBUFLEN];
 	size_t len;
+	int e = errno;			// 27 Apr 09 SHL preserve errno
 
 	va_start(ap, format);
 	len = vsnprintf(buf, sizeof buf, format, ap);
@@ -401,6 +402,7 @@
 	}
 
 	rwrite(code, buf, len, 0);
+	errno = e;
 }
 
 /* This is like rprintf, but it also tries to print some
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/main.c ../rsync-3.0.8/main.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/main.c	2011-02-22 08:21:08.000000000 -0800
+++ ../rsync-3.0.8/main.c	2011-04-18 22:11:36.000000000 -0700
@@ -27,6 +27,10 @@
 #include <locale.h>
 #endif
 
+#ifdef __OS2__
+#include <umalloc.h>			// Need for _heap_walk
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int list_only;
@@ -272,10 +276,23 @@
 
 	if (verbose || do_stats) {
 		rprintf(FCLIENT, "\n");
+#ifndef __OS2__
 		rprintf(FINFO,
 			"sent %s bytes  received %s bytes  %s bytes/sec\n",
 			human_num(total_written), human_num(total_read),
 			human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
+#else
+		{
+			// 2010-10-30 SHL show elapsed time
+			time_t t = endtime - starttime + 1;	// Always round up
+			rprintf(FINFO,
+				"sent %s bytes  received %s bytes  %s bytes/sec  elapsed %02u:%02u:%02u\n",
+				human_num(total_written),
+				human_num(total_read),
+				human_dnum((total_written + total_read)/(0.5 + t), 2),
+				t / 3600, (t / 60) % 60, t % 60);
+		}
+#endif
 		rprintf(FINFO, "total size is %s  speedup is %.2f%s\n",
 			human_num(stats.total_size),
 			(double)stats.total_size / (total_written+total_read),
@@ -287,6 +304,92 @@
 }
 
 
+#ifdef __OS2__				// 2010-12-25 SHL
+#ifdef HAVE_MALLINFO
+#error HAVE_MALLINFO unexpected
+#endif
+
+// See \EMX\doc\emxlib.doc
+
+struct mallinfo {
+  int arena;
+  int ordblks;
+  int smblks;
+  int hblks;
+  int hblkhd;
+  int usmblks;
+  int fsmblks;
+  int uordblks;
+  int fordblks;
+  int keepcost;
+};
+
+static struct mallinfo os2_mallinfo;
+
+
+// 2010-12-25 SHL push requires 4.5
+// #pragma GCC diagnostic push
+// 2010-12-25 SHL diagnosic requires 4.4.x
+// #pragma GCC diagnostic ignored "-Wunused-parameter"
+
+// 2010-12-25 SHL unused-parameter warnings expected with 3.3.5
+
+static int os2_mallinfo_callback(const void *block, size_t size, int flag,
+				 int status, const char *fname, size_t lineno)
+{
+	int err = 0;
+	switch (status) {
+	case _HEAPOK:
+	{
+		switch (flag) {
+		case _USEDENTRY:
+			os2_mallinfo.uordblks += size;
+			break;
+		case _FREEENTRY:
+			os2_mallinfo.fordblks += size;
+			break;
+	        default:
+			err = 99;
+		} // flag
+	}
+	break;
+	case _HEAPBADBEGIN:
+	case _HEAPBADEND:
+	case _HEAPBADNODE:
+	case _HEAPEMPTY:
+		// Let _heap_walk set return code
+		break;
+	default:
+		err = 99;
+	} // status
+	return err;
+}
+
+// 2010-12-25 SHL pop requires 4.5.x
+// #pragma GCC diagnostic pop
+// 2010-12-25 SHL diagnosic requires 4.4.x
+// #pragma GCC diagnostic warning "-Wunused-parameter"
+
+struct mallinfo mallinfo(void)
+{
+	int err;
+	memset(&os2_mallinfo, 0, sizeof(os2_mallinfo));
+	err = _heap_walk(os2_mallinfo_callback);
+
+	if (err) {
+		// fixme to report
+	}
+
+	os2_mallinfo.arena = os2_mallinfo.uordblks + os2_mallinfo.ordblks;
+
+	return os2_mallinfo;
+}
+
+#define HAVE_MALLINFO
+
+#endif // __OS2__
+
+
 /**
  * If our C library can get malloc statistics, then show them to FINFO
  **/
@@ -324,6 +427,9 @@
 	rprintf(FINFO, "  keepcost:  %10ld   (bytes in releasable chunk)\n",
 		(long)mi.keepcost);
 #endif /* HAVE_MALLINFO */
+
+#ifdef __OS2__				// 2010-12-25 SHL
+#endif // __OS2__
 }
 
 
@@ -541,6 +647,8 @@
 			if (!change_dir(dest_path, CD_NORMAL)) {
 				rsyserr(FERROR, errno, "change_dir#1 %s failed",
 					full_fname(dest_path));
+				// 22 Jul 09 SHL was FLOG?  why?
+				rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 				exit_cleanup(RERR_FILESELECT);
 			}
 			filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
@@ -602,6 +710,8 @@
 		if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
 			rsyserr(FERROR, errno, "change_dir#2 %s failed",
 				full_fname(dest_path));
+			// 22 Jul 09 SHL was FLOG?  why?
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 
@@ -622,6 +732,8 @@
 	if (!change_dir(dest_path, CD_NORMAL)) {
 		rsyserr(FERROR, errno, "change_dir#3 %s failed",
 			full_fname(dest_path));
+		// 22 Jul 09 SHL was FLOG?  why?
+		rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 		exit_cleanup(RERR_FILESELECT);
 	}
 	*cp = '/';
@@ -713,8 +825,9 @@
 
 	if (!relative_paths) {
 		if (!change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#3 %s failed",
+			rsyserr(FERROR, errno, "change_dir#4 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -885,8 +998,9 @@
 		argc--;
 		argv++;
 		if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#4 %s failed",
+			rsyserr(FERROR, errno, "change_dir#5 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -941,6 +1055,7 @@
 			if (check_filter(elp, FLOG, dir, 1) < 0)
 				goto options_rejected;
 		}
+		// 25 Sep 09 SHL fixme slashes
 		if (partial_dir && *partial_dir == '/'
 		 && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
 		    options_rejected:
@@ -1099,7 +1214,7 @@
 
 	for (i = 0; argv[i]; i++) {
 		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
+			rprintf (FERROR, "out of memory at %s(%u)\n",
 				 __FILE__, __LINE__);
 			return RERR_MALLOC;
 		}
@@ -1130,6 +1245,14 @@
 	 * command line. */
 	if ((ret = copy_argv(argv)) != 0)
 		return ret;
+#ifdef __OS2__
+	{
+		int i;
+		for (i = 0; i < argc; i++) {
+			normalize_dir_slashes(argv[i]);
+		}
+	}
+#endif
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -1453,6 +1576,7 @@
 	 * (implemented by forking "pwd" and reading its output) doesn't
 	 * work when there are other child processes.  Also, on all systems
 	 * that implement getcwd that way "pwd" can't be found after chroot. */
+	// rprintf(FINFO, "* [%s] %s %s(%u)\n", who_am_i(), "(null)", __FILE__, __LINE__);	// 28 Jul 08 SHL debug chdir
 	change_dir(NULL, CD_NORMAL);
 
 	init_flist();
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/options.c ../rsync-3.0.8/options.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/options.c	2011-02-21 11:32:48.000000000 -0800
+++ ../rsync-3.0.8/options.c	2011-04-18 22:11:36.000000000 -0700
@@ -52,6 +52,10 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+// 13 Jun 09 SHL Added
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -115,7 +119,11 @@
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
+#ifndef __OS2__
 int modify_window = 0;
+#else
+int modify_window = 1;			// 28 Jul 09 SHL allow for 2 second resolution
+#endif
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
@@ -261,6 +269,13 @@
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
 	rprintf(f, "Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.\n");
 	rprintf(f, "Web site: http://rsync.samba.org/\n");
+#ifdef __OS2__ // 2009-07-22 SHL
+	rprintf(f, "Built by Steven H. Levine " __DATE__ " " __TIME__ "\n");
+#if 0 // 2010-12-15 SHL Enable if building for Mensys with flist size limited - see util.c MALLOC_MAX
+	rprintf(f, "Built with MALLOC_MAX set to 200MiBytes\n");
+#endif // Mensys MALLOC_MAX
+	rprintf(f, "Built with GCC " __VERSION__ "\n");
+#endif
 	rprintf(f, "Capabilities:\n");
 	rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
 		(int)(sizeof (OFF_T) * 8),
@@ -337,6 +352,9 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+#ifdef __OS2__
+  rprintf(F," -2, --os2-perms             preserve native OS/2 permissions\n");
+#endif
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
 #ifdef SUPPORT_ACLS
@@ -479,6 +497,10 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+#ifdef __OS2__
+  {"os2-perms",       '2', POPT_ARG_NONE,   0, '2', 0, 0 },
+  {"no-os2-perms",     0,  POPT_ARG_VAL,    &os2_perms, 0, 0, 0 },
+#endif
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
@@ -1032,6 +1054,10 @@
 		case OPT_EXCLUDE_FROM:
 		case OPT_INCLUDE_FROM:
 			arg = poptGetOptArg(pc);
+#ifdef __OS2__
+			// 18 Oct 09 SHL
+			normalize_dir_slashes((char *)arg);	// hack cough - override const
+#endif
 			if (sanitize_paths)
 				arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 			if (daemon_filter_list.head) {
@@ -1139,6 +1165,13 @@
 			}
 			break;
 
+// 14 Jun 09 SHL
+#ifdef __OS2__
+		case '2':
+			os2_perms = 1;
+			preserve_perms = 1;	// Implied
+			break;
+#endif
 		case OPT_WRITE_BATCH:
 			/* batch_name is already set */
 			write_batch = 1;
@@ -1474,6 +1507,7 @@
 			char *dir;
 			if (!*backup_dir)
 				goto options_rejected;
+			// 25 Sep 09 SHL fixme slashes
 			dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
 			clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
 			if (check_filter(elp, FLOG, dir, 1) < 0)
@@ -1788,6 +1822,12 @@
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
 		argstr[x++] = 'E';
+// 13 Jun 09 SHL
+#ifdef __OS2__
+	if (os2_perms)
+		argstr[x++] = '2';
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls)
 		argstr[x++] = 'A';
@@ -2108,6 +2148,10 @@
 			break;
 		}
 		if (*s == ':' || *s == '/') {
+#			ifdef __OS2__	// 29 Jun 09 SHL don't confuse drive letter with host spec
+			if (*s == ':' && s == str + 1 && drive_spec_width(s - 1) != 0)
+				continue;
+#			endif
 			if (!hostlen)
 				hostlen = s - host_start;
 			if (*s++ == '/') {
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/params.c ../rsync-3.0.8/params.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/params.c	2007-11-22 09:51:20.000000000 -0800
+++ ../rsync-3.0.8/params.c	2011-04-18 22:11:36.000000000 -0700
@@ -166,9 +166,24 @@
   {
   pos--;
   while( pos >= 0 && isSpace(line + pos) )
-     pos--;
+     pos--;				// Find last non-whitespace
 
+#ifndef __OS2__
   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
+#else
+  // 2010-11-24 SHL handle path specs like c:\ special to avoid
+  // losing \ before it can be mapped to /
+  // Assume parsing value so name and value nul separated
+  if ( pos >= 0) {
+    if (line[pos] != '\\')
+      pos = -1;				// Not continued
+    else if (pos >= 3) {
+      if (*(line + pos - 3) == 0 && drive_spec_width(line + pos - 2) > 0)
+        pos = -1;			// Not continued
+    }
+  }
+  return pos;
+#endif
   } /* Continuation */
 
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.os2 ../rsync-3.0.8/readme.os2
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.os2	2106-02-06 22:28:16.000000000 
+++ ../rsync-3.0.8/readme.os2	2011-04-18 22:11:36.000000000 -0700
@@ -0,0 +1,87 @@
+Rsync v3.0.7 compiled with GCC 4.3.4 & kLibc v0.6.3
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+We (Paul and Steven) are using this as both client and server for backups
+
+Changes in this version:
+- Updated to v3.0.6
+- Incorporated a bunch of patches from Steven Levine
+- Move to GCC 4.3.4 as a compiler
+- --xattrs now works for remote servers
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 permissions
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+- Defaulted to %ETC% for rsyncd.conf
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+  Run make install
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Cheers,
+
+Paul Smedley
+Adelaide, Australia
+
+and
+
+Steven Levine
+Costa Mesa, California, USA
+
+09 April 2010
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.shl ../rsync-3.0.8/readme.shl
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.shl	2106-02-06 22:28:16.000000000 
+++ ../rsync-3.0.8/readme.shl	2011-05-23 13:33:36.000000000 -0700
@@ -0,0 +1,109 @@
+
+Rsync v3.0.8 compiled with GCC 4.5.2 & kLibc v0.6.3 by Steven H. Levine
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+Requires gcc452.dll available from http://download.smedley.info/gcc452.zip
+
+These are Steven Levine's notes
+See readme.os2 for Paul Smedley's notes
+
+Changes in this version (newest first):
+
+- Updated to rsync v3.0.8 sources
+- Now building with gcc 4.5.2 - requires gcc452.dll
+- --stats -vv now shows memory statistics
+- --relative now works with drive letters
+- added some more alloc failure checks
+- rsync conf now accepts root paths like c:\
+- --stats shows elapsed time
+- Filter pattern matches are now case-insensitive
+- Added logic to ensure directory xattrs updated after libc chmod changes xattrs
+- Started work on supporting testsuite
+- Updated to rsync v3.0.7 sources
+- Migrated existing 3.0.6 patches
+
+Binary builds are available at
+
+  http://mantis.smedley.info/view.php?id=366
+
+Known issues
+
+- Newly created directories do not always get correct libc extended attributes
+  Next rsync run will set the libc extended attributes to the correct values
+
+- --links probably not fully compatible with --os2_perms
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 readonly permissions along
+  with the system, hidden and archive file/directory attributes
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke a some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+
+  Run make install
+
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Have fun,
+
+Steven Levine
+Costa Mesa, California, USA
+
+2011-04-18 SHL
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/receiver.c ../rsync-3.0.8/receiver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/receiver.c	2011-03-26 10:01:36.000000000 -0700
+++ ../rsync-3.0.8/receiver.c	2011-04-18 22:11:40.000000000 -0700
@@ -491,7 +491,7 @@
 				handle_delayed_updates(local_name);
 			send_msg(MSG_DONE, "", 0, 0);
 			continue;
-		}
+		} // NDX_DONE
 
 		if (ndx - cur_flist->ndx_start >= 0)
 			file = cur_flist->files[ndx - cur_flist->ndx_start];
@@ -830,8 +830,8 @@
 			if (inc_recurse)
 				send_msg_int(MSG_NO_SEND, ndx);
 			break;
-		}
-	}
+		} // switch
+	} // while
 	if (make_backups < 0)
 		make_backups = -make_backups;
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.c ../rsync-3.0.8/rsync.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.c	2011-02-22 10:48:12.000000000 -0800
+++ ../rsync-3.0.8/rsync.c	2011-07-02 10:58:18.000000000 -0700
@@ -383,6 +383,8 @@
 	mode_t new_mode = file->mode;
 	int inherit;
 
+	// rprintf(FINFO, "* [%s] set_file_attrs fname %s mode 0%o file %p sxp %p %s(%u)\n", who_am_i(), fname, file->mode, file, sxp, __FILE__, __LINE__); // 23 May 11 SHL debug os2_perms
+
 	if (!sxp) {
 		if (dry_run)
 			return 1;
@@ -503,6 +505,7 @@
 
 #ifdef HAVE_CHMOD
 	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+		// rprintf(FINFO, "* [%s] set_file_attrs fname %s sxp->st.st_mode 0%o new_mode 0%o %s(%u)\n", who_am_i(), fname, sxp->st.st_mode, new_mode, __FILE__, __LINE__); // 27 Apr 09 SHL debug perms
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
@@ -560,8 +563,13 @@
 		    int overwriting_basis)
 {
 	int ret;
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
 	const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
+	if (partialptr && drive_spec_width(partialptr))
+		rprintf(FINFO, "* [%s] finish_transfer partialptr %s fname %s fnamecmp %s %s(%u)\n", who_am_i(), partialptr, fname, fnamecmp, __FILE__, __LINE__); // 25 Sep 09 SHL debug slashes
+
 	if (inplace) {
 		if (verbose > 2)
 			rprintf(FINFO, "finishing %s\n", fname);
@@ -585,6 +593,7 @@
 		rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
 	ret = robust_rename(fnametmp, fname, temp_copy_name,
 			    file->mode & INITACCESSPERMS);
+
 	if (ret < 0) {
 		rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
 			ret == -2 ? "copy" : "rename",
@@ -597,6 +606,7 @@
 	}
 	if (ret == 0) {
 		/* The file was moved into place (not copied), so it's done. */
+		// rprintf(FINFO, "* [%s] finish_transfer robust_rename moved file %s(%u)\n", who_am_i(), __FILE__, __LINE__); // 2011-05-23 SHL debug os2_perms
 		return 1;
 	}
 	/* The file was copied, so tweak the perms of the copied file.  If it
@@ -604,6 +614,8 @@
 	fnametmp = temp_copy_name ? temp_copy_name : fname;
 
   do_set_file_attrs:
+	// rprintf(FINFO, "* [%s] finish_transfer before set_file_attrs %s %s(%u)\n", who_am_i(), fnametmp, __FILE__, __LINE__); // 2011-05-23 SHL debug os2_perms
+
 	set_file_attrs(fnametmp, file, NULL, fnamecmp,
 		       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.h ../rsync-3.0.8/rsync.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.h	2011-02-21 11:32:50.000000000 -0800
+++ ../rsync-3.0.8/rsync.h	2011-04-18 22:11:40.000000000 -0700
@@ -1168,3 +1168,12 @@
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+// 05 Mar 09 SHL support drive letters
+#ifndef __OS2__
+#define drive_spec_width(p) 0
+#define is_abs_path(p) (*(p) == '/')
+#else
+#define drive_spec_width(p) ((isalpha(*(p)) && *((p) + 1) == ':') ? 2 : 0)
+#define is_abs_path(p) (*((p) + drive_spec_width(p)) == '/')
+#endif
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/runtests.sh ../rsync-3.0.8/runtests.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/runtests.sh	2008-05-18 07:00:48.000000000 -0700
+++ ../rsync-3.0.8/runtests.sh	2011-04-18 22:11:40.000000000 -0700
@@ -239,8 +239,8 @@
     $setfacl_nodef "$scratchdir" || true
     chmod g-s "$scratchdir"
     case "$srcdir" in
-    /*) ln -s "$srcdir" "$scratchdir/src" ;;
-    *)  ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
+    /*) echo ln -s "$srcdir" "$scratchdir/src" ;;
+    *)  echo ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
     esac
     return 0
 }
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/sender.c ../rsync-3.0.8/sender.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/sender.c	2009-12-12 17:23:02.000000000 -0800
+++ ../rsync-3.0.8/sender.c	2011-04-18 22:11:40.000000000 -0700
@@ -366,7 +366,7 @@
 		send_msg_int(MSG_IO_ERROR, io_error);
 
 	if (verbose > 2)
-		rprintf(FINFO, "send files finished\n");
+		rprintf(FINFO, "send_files finished\n");	// 06 Mar 09 SHL
 
 	match_report();
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/syscall.c ../rsync-3.0.8/syscall.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/syscall.c	2011-02-21 11:32:50.000000000 -0800
+++ ../rsync-3.0.8/syscall.c	2011-05-25 17:38:54.000000000 -0700
@@ -28,6 +28,24 @@
 #ifdef HAVE_SYS_ATTR_H
 #include <sys/attr.h>
 #endif
+// 06 Mar 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define setmode
+#if defined HAVE_SETMODE && O_BINARY && __OS2__
+// From gcc io.h
+int setmode (int, int);
+// From gcc os2emx.h
+#endif
+#ifdef __OS2__ // 01 Aug 09 SHL
+// 01 Aug 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define _sopen
+int _sopen (__const__ char *, int, int, ...);	// hack cough
+#include "share.h"			// SH_DENYNO
+#endif
+
+#if defined __OS2__
+// 27 Apr 09 SHL Need definitions for FILE_...
+#define INCL_DOS
+// #include <os2.h>
+#include <os2emx.h>
+#endif
 
 extern int dry_run;
 extern int am_root;
@@ -35,6 +53,10 @@
 extern int list_only;
 extern int preserve_perms;
 extern int preserve_executability;
+// 13 Jun 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -138,12 +160,32 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+#ifdef __OS2__
+	int fd;
+#endif
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
 
+#ifndef __OS2__
 	return open(pathname, flags | O_BINARY, mode);
+#else
+	// 31 Jul 09 SHL if open fails, try shared open in case file already opened for write
+	fd = open(pathname, flags | O_BINARY, mode);
+	if (fd == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
+		fd = _sopen(pathname, flags | O_BINARY, SH_DENYNO, mode);
+		if (fd != -1)
+			rprintf(FINFO, "[%s] opened %s for shared write - file may change during sync\n", who_am_i(), pathname);
+		else if (verbose) {
+			int e = errno;
+			rsyserr(FINFO, errno, "do_open _sopen fallback failed for %s", pathname);
+			errno = e;
+		}
+
+	}
+	return fd;
+#endif
 }
 
 #ifdef HAVE_CHMOD
@@ -152,9 +194,75 @@
 	int code;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+
 #ifdef HAVE_LCHMOD
+#ifndef __OS2__
 	code = lchmod(path, mode & CHMOD_BITS);
 #else
+	{
+		// rprintf(FINFO, "* [%s] do_chmod path %s requested mode 0%o %s(%u)\n", who_am_i(), path, mode, __FILE__, __LINE__);	// 23 May 11 SHL debug os2_perms
+
+		ULONG attributes = 0;
+		if (os2_perms) {
+			mode_t old_mode = mode;	// 2011-05-23 SHL os2_perms debug
+			// Unmap mode to recover native OS/2 attributes
+			// See map_os2_attributes
+			// If not readable by owner, hidden
+			if (~mode & S_IRUSR)
+				attributes |= FILE_HIDDEN;
+			// If readable by group, system
+			if (mode & S_IRGRP)
+				attributes |= FILE_SYSTEM;
+			// If writable by group, archived
+			if (mode & S_IWGRP)
+				attributes |= FILE_ARCHIVED;
+			// Reset group rw bits to match other rw bits - hack cough
+			if (mode & S_IROTH)
+				mode |= S_IRGRP;
+			else
+				mode &= ~S_IRGRP;
+			if (mode & S_IWOTH)
+				mode |= S_IWGRP;
+			else
+				mode &= ~S_IWGRP;
+			// rprintf(FINFO, "* [%s] unmapped %s mode from 0%lo to 0%lo (attributes 0x%lx)\n", who_am_i(), path, (unsigned long)old_mode, (unsigned long)mode, attributes);	// 2011-05-23 SHL os2_perms debug
+		}
+		code = lchmod(path, mode & CHMOD_BITS);
+		if (!code && os2_perms) {
+			// Adjust native attributes not handled by chmod - system, hidden, archived
+			// Maybe libc will do this someday
+			// chmod already handles readonly
+			// Adjust attributes if any but archived set or if archived not set in requested attributes
+			FILESTATUS3 fs3;
+			APIRET apiret = DosQueryPathInfo((PCSZ)path,
+							 FIL_STANDARD,
+							 &fs3,
+							 sizeof(fs3));
+			// 26 Sep 09 SHL fixme perms - set code on failure - need map_apiret_errno()
+			if (apiret)
+				rprintf(FERROR, "[%s] DosQueryPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+			else {
+				ULONG m = attributes | (fs3.attrFile & ~(FILE_SYSTEM | FILE_HIDDEN | FILE_ARCHIVED));
+				if (m != fs3.attrFile) {
+					ULONG old_attrFile = fs3.attrFile;
+					fs3.attrFile = m;
+					apiret = DosSetPathInfo((PCSZ)path,
+								 FIL_STANDARD,
+								 &fs3, sizeof(fs3),
+								 0);
+					if (apiret)
+						rprintf(FERROR, "[%s] DosSetPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+					else if (verbose > 1)
+						rprintf(FINFO, "[%s] changed %s attrFile from 0x%lx to 0x%lx (attributes 0x%lx)\n", who_am_i(), path, old_attrFile, fs3.attrFile, attributes);	// 21 Jul 09 SHL
+				}
+			}
+		}
+	}
+#endif /* __OS2__ */
+#else  // !HAVE_LCHMOD
+#ifdef __OS2__
+#error __OS2__ patch requires LCHMOD defined
+#endif /* __OS2__ */
 	if (S_ISLNK(mode)) {
 # if defined HAVE_SETATTRLIST
 		struct attrlist attrList;
@@ -165,8 +273,8 @@
 		attrList.commonattr = ATTR_CMN_ACCESSMASK;
 		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
 # else
-		code = 1;
-# endif
+		code = 1;		// Can not set symlink
+# endif // HAVE_SETATTRLIST
 	} else
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
 #endif /* !HAVE_LCHMOD */
@@ -256,12 +364,55 @@
 #endif
 }
 
+#ifdef __OS2__
+
+/**
+ * Map native OS/2 attributes to something rsync can send
+ * See do_chmod for unmap logic
+ */
+
+static void map_os2_attributes(STRUCT_STAT *st)
+{
+	// If hidden, readable by none
+	if (st->st_attr & FILE_HIDDEN)
+		st->st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+	// If readonly, writable by none
+	if (st->st_attr & FILE_READONLY)
+		st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+
+	// Steal group bits for native attributes without obvious mappings - hack cough
+	// If system, readable by group
+	if (st->st_attr & FILE_SYSTEM)
+		st->st_mode |= S_IRGRP;
+	else
+		st->st_mode &= ~S_IRGRP;
+	// If archived, writable by group
+	if (st->st_attr & FILE_ARCHIVED)
+		st->st_mode |= S_IWGRP;
+	else
+		st->st_mode &= ~S_IWGRP;
+}
+
+#endif
+
 int do_stat(const char *fname, STRUCT_STAT *st)
 {
 #ifdef USE_STAT64_FUNCS
 	return stat64(fname, st);
 #else
+#ifndef __OS2__
 	return stat(fname, st);
+#else
+	int code;
+	code = stat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from 0%o to 0%o (st_attr 0%o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
@@ -271,7 +422,19 @@
 # ifdef USE_STAT64_FUNCS
 	return lstat64(fname, st);
 # else
+#ifndef __OS2__
 	return lstat(fname, st);
+#else
+	// 27 Apr 09 SHL map OS/2 permissions
+	int code = lstat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from 0%o to 0%o (st_attr 0%o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 # endif
 #else
 	return do_stat(fname, st);
@@ -283,7 +446,19 @@
 #ifdef USE_STAT64_FUNCS
 	return fstat64(fd, st);
 #else
+#ifndef __OS2__
 	return fstat(fd, st);
+#else
+	int code;
+	code = fstat(fd, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %u mode from 0%o to 0%o (st_attr 0%o)\n", who_am_i(), fd, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/t_stub.c ../rsync-3.0.8/t_stub.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/t_stub.c	2011-02-21 11:32:48.000000000 -0800
+++ ../rsync-3.0.8/t_stub.c	2011-04-18 22:11:40.000000000 -0700
@@ -33,6 +33,12 @@
 char *module_dir;
 struct filter_list_struct daemon_filter_list;
 
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
+int verbose = 0;
+
+
  void rprintf(UNUSED(enum logcode code), const char *format, ...)
 {
 	va_list ap;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/t_unsafe.c ../rsync-3.0.8/t_unsafe.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/t_unsafe.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/t_unsafe.c	2011-04-18 22:11:40.000000000 -0700
@@ -27,7 +27,6 @@
 int am_root = 0;
 int read_only = 0;
 int list_only = 0;
-int verbose = 0;
 int preserve_perms = 0;
 int preserve_executability = 0;
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/testsuite/rsync.fns ../rsync-3.0.8/testsuite/rsync.fns
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/testsuite/rsync.fns	2011-03-13 20:48:54.000000000 -0700
+++ ../rsync-3.0.8/testsuite/rsync.fns	2011-04-18 22:11:40.000000000 -0700
@@ -151,7 +151,7 @@
 
     echo $ECHO_N "This file has no trailing lf$ECHO_C" > "$fromdir/nolf"
     umask 0
-    ln -s nolf "$fromdir/nolf-symlink"
+    echo ln -s nolf "$fromdir/nolf-symlink"
     umask 022
 
     cat "$srcdir"/*.c > "$fromdir/text"
@@ -321,10 +321,10 @@
 build_symlinks() {
     mkdir "$fromdir"
     date >"$fromdir/referent"
-    ln -s referent "$fromdir/relative"
-    ln -s "$fromdir/referent" "$fromdir/absolute"
-    ln -s nonexistent "$fromdir/dangling"
-    ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
+    echo ln -s referent "$fromdir/relative"
+    echo ln -s "$fromdir/referent" "$fromdir/absolute"
+    echo ln -s nonexistent "$fromdir/dangling"
+    echo ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
 }
 
 test_fail() {
@@ -347,7 +347,7 @@
 }
 
 # Determine what shell command will appropriately test for links.
-ln -s foo "$scratchdir/testlink"
+echo ln -s foo "$scratchdir/testlink"
 for cmd in test /bin/test /usr/bin/test /usr/ucb/bin/test /usr/ucb/test
 do
     for switch in -h -L
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/util.c ../rsync-3.0.8/util.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/util.c	2011-03-17 11:25:12.000000000 -0700
+++ ../rsync-3.0.8/util.c	2011-05-25 16:59:24.000000000 -0700
@@ -23,6 +23,10 @@
 #include "rsync.h"
 #include "ifuncs.h"
 
+#ifdef __OS2__
+#include <os2emx.h>
+#endif
+
 extern int verbose;
 extern int module_id;
 extern int modify_window;
@@ -201,6 +205,10 @@
 	char *p;
 	int ret = 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width
+	fname += drive_spec_width(fname);		/* Bypass drive letter */
+#endif /* __OS2__ */
+
 	while (*fname == '/')
 		fname++;
 	while (strncmp(fname, "./", 2) == 0)
@@ -430,6 +438,8 @@
 {
 	int tries = 4;
 
+	// rprintf(FINFO, "* [%s] robust_rename %s->%s %s(%u)\n", who_am_i(), from, to, __FILE__, __LINE__); // 2009-04-27 SHL debug os2_perms
+
 	while (tries--) {
 		if (do_rename(from, to) == 0)
 			return 0;
@@ -454,6 +464,27 @@
 				return -2;
 			do_unlink(from);
 			return 1;
+#ifdef __OS2__ // 2009-04-27 SHL
+		// libc rename semantics differs from linux
+		// clear readonly if this caused rename to fail
+		case EACCES:
+		{
+			STRUCT_STAT st;
+			int code;
+			if (verbose)
+				rprintf(FINFO, "[%s] robust_rename retrying %s after EACCES\n", who_am_i(), to);	// 2009-07-22 SHL
+			code = do_stat(to, &st);
+			if (!code) {
+				// 2009-04-27 SHL fixme to use st_mode when libc fixed
+				if (st.st_attr & FILE_READONLY) {
+					st.st_mode |= S_IWUSR;
+					code = do_chmod(to, st.st_mode);
+					if (!code)
+						break;	// Try again
+				}
+			}
+		}
+#endif
 		default:
 			return -1;
 		}
@@ -828,10 +859,18 @@
 {
 	char *limit = name - 1, *t = name, *f = name;
 	int anchored;
+#ifdef __OS2__
+	int drive_letter_adj;	// 0 if not, 2 if yes 2008-12-15 SHL
+#endif
 
 	if (!name)
 		return 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width...
+	drive_letter_adj = drive_spec_width(name);
+	f += drive_letter_adj;			// Keep drive letter
+	t += drive_letter_adj;
+#endif /* __OS2__ */
 	if ((anchored = *f == '/') != 0) {
 		*t++ = *f++;
 #ifdef __CYGWIN__
@@ -879,10 +918,18 @@
 		while (*f && (*t++ = *f++) != '/') {}
 	}
 
+#ifndef __OS2__ // 2009-02-06 SHL
 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 		t--;
 	if (t == name)
 		*t++ = '.';
+#else
+	if (t > name + anchored + drive_letter_adj && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
+		t--;
+	if (t == name + drive_letter_adj)
+		*t++ = '.';		// Ensure not empty
+#endif
+
 	*t = '\0';
 
 	return t - name;
@@ -916,14 +963,28 @@
 	char *start, *sanp;
 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 
+	// rprintf(FINFO, "* [%s] sanitize_path p %s %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
 	if (dest != p) {
 		int plen = strlen(p);
-		if (*p == '/') {
+		int drive_letter_adj = drive_spec_width(p);	// 0 if not, 2 if yes 2008-12-15 SHL
+#ifndef __OS2__
+		if (*p == '/')
+#else // 2009-02-06 SHL use is_abs_path...
+		if (!is_abs_path(p)) {
+			if (drive_letter_adj)
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
+		} else
+#endif
+		{
 			if (!rootdir)
 				rootdir = module_dir;
 			rlen = strlen(rootdir);
 			depth = 0;
+#ifndef __OS2__
 			p++;
+#else
+			p += drive_spec_width(p) + 1;
+#endif
 		}
 		if (dest) {
 			if (rlen + plen + 1 >= MAXPATHLEN)
@@ -932,8 +993,13 @@
 			out_of_memory("sanitize_path");
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
+#ifndef __OS2__
 			if (rlen > 1)
 				dest[rlen++] = '/';
+#else
+			if (rlen > 1 + drive_letter_adj)
+				dest[rlen++] = '/';
+#endif
 		}
 	}
 
@@ -977,6 +1043,20 @@
 		}
 		/* copy one component through next slash */
 		while (*p && (*sanp++ = *p++) != '/') {}
+#if 0 // 2009-05-16 SHL fixme to be gone
+#ifndef __OS2__
+		while (*p && (*sanp++ = *p++) != '/') {}
+#else
+		while(*p) {
+			char c = *p++;
+			if (c == '\\')
+				c = '/';
+			*sanp++ = c;
+			if (c == '/')
+				break;
+		}
+#endif
+#endif
 	}
 	if (sanp == dest) {
 		/* ended up with nothing, so put in "." component */
@@ -984,16 +1064,23 @@
 	}
 	*sanp = '\0';
 
+	// rprintf(FINFO, "* [%s] sanitize_path dest %s %s(%u)\n", who_am_i(), dest, __FILE__, __LINE__); // 2009-02-06 SHL debug
+
+	// 2009-05-16 SHL  fixme to be gone
+	assert_no_dir_slashes(dest);
+
 	return dest;
 }
 
 /* Like chdir(), but it keeps track of the current directory (in the
  * global "curr_dir"), and ensures that the path size doesn't overflow.
- * Also cleans the path using the clean_fname() function. */
+ * Also cleans the path using the clean_fname() function.
+ * Returns 1 of change OK.  Otherwise 0 */
 int change_dir(const char *dir, int set_path_only)
 {
 	static int initialised;
 	unsigned int len;
+	// rprintf(FINFO, "* [%s] change_dir dir %s initialised %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", initialised, __FILE__, __LINE__); // 2009-04-27 SHL debug perms
 
 	if (!initialised) {
 		initialised = 1;
@@ -1002,6 +1089,7 @@
 			exit_cleanup(RERR_FILESELECT);
 		}
 		curr_dir_len = strlen(curr_dir);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 	}
 
 	if (!dir)	/* this call was probably just to initialize */
@@ -1011,23 +1099,49 @@
 	if (len == 1 && *dir == '.')
 		return 1;
 
-	if (*dir == '/') {
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(dir)) {
+		// Absolute path
 		if (len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifndef __OS2__ // 2008-07-28 SHL
 		if (!set_path_only && chdir(dir))
 			return 0;
 		memcpy(curr_dir, dir, len + 1);
+#else
+		if (!set_path_only) {
+			if (chdir(dir)) {
+				rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+			if (drive_spec_width(dir) && _chdrive(*dir)) {
+				rprintf(FERROR, "[%s] change_dir _chdrive failed for dir %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+		}
+		memcpy(curr_dir, dir, len + 1);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
+#endif
 	} else {
+		// Relative path
 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifdef __OS2__
+		if (drive_spec_width(dir)) {
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			errno = EINVAL;
+			return -1;
+		}
+#endif
 		curr_dir[curr_dir_len] = '/';
 		memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
 
 		if (!set_path_only && chdir(curr_dir)) {
+			rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
 			curr_dir[curr_dir_len] = '\0';
 			return 0;
 		}
@@ -1052,12 +1166,15 @@
 {
 	unsigned int len;
 
-	if (*path != '/') { /* Make path absolute. */
+	// 2009-03-06 SHL use is_abs_path
+	if (!is_abs_path(path)) { /* Make path absolute. */
 		int len = strlen(path);
+		if (drive_spec_width(path))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2008-07-28 SHL
 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
-		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
+		memcpy(curr_dir + curr_dir_len + 1, path + drive_spec_width(path), len + 1);
 		if (!(path = strdup(curr_dir)))
 			out_of_memory("normalize_path");
 		curr_dir[curr_dir_len] = '\0';
@@ -1066,7 +1183,9 @@
 			out_of_memory("normalize_path");
 	}
 
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 	len = clean_fname(path, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 
 	if (len_ptr)
 		*len_ptr = len;
@@ -1088,9 +1207,14 @@
 	if (result)
 		free(result);
 
-	if (*fn == '/')
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(fn))
 		p1 = p2 = "";
 	else {
+#ifdef __OS2__
+		if (drive_spec_width(fn))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-02-06 SHL
+#endif
 		p1 = curr_dir + module_dirlen;
 		for (p2 = p1; *p2 == '/'; p2++) {}
 		if (*p2)
@@ -1119,6 +1243,9 @@
 
 	if ((fn = strrchr(fname, '/')) != NULL) {
 		fn++;
+		// 2009-09-25 SHL fixme slashes - handle drive letter if needed
+		if (partial_dir && drive_spec_width(partial_dir))
+			rprintf(FINFO, "* [%s] partial_dir_fname partial_dir %s fname %s %s(%u)\n", who_am_i(), partial_dir, fname, __FILE__, __LINE__); // 2009-09-25 SHL debug slashes
 		if (*partial_dir != '/') {
 			int len = fn - fname;
 			strncpy(t, fname, len); /* safe */
@@ -1150,6 +1277,7 @@
 
 	if (fname != partial_fname)
 		return 1;
+	// 2009-09-25 SHL fixme slashes?
 	if (!create && *partial_dir == '/')
 		return 1;
 	if (!(fn = strrchr(partial_fname, '/')))
@@ -1420,19 +1548,29 @@
 }
 #endif
 
-#define MALLOC_MAX 0x40000000
+
+#if 0 // 2010-12-15 SHL Enable if building for Mensys with flist size limited - see util.c MALLOC_MAX
+#define MALLOC_MAX (200 * 1024 * 1024)	// MiBytes - Mensys, lower limit is NORMAL_EXTENT (256KiBytes)
+#else
+#define MALLOC_MAX 0x40000000		// 1GiByte
+#endif
+
 
 void *_new_array(unsigned long num, unsigned int size, int use_calloc)
 {
-	if (num >= MALLOC_MAX/size)
+	if (num >= MALLOC_MAX/size) {
+	        rprintf(FERROR, "* [%s] _new_array num %lu size %u failed %s(%u)\n", who_am_i(), num, size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		return NULL;
+	}
 	return use_calloc ? calloc(num, size) : malloc(num * size);
 }
 
 void *_realloc_array(void *ptr, unsigned int size, size_t num)
 {
-	if (num >= MALLOC_MAX/size)
+	if (num >= MALLOC_MAX/size) {
+	        rprintf(FERROR, "* [%s] _realloc_array num %lu size %u failed %s(%u)\n", who_am_i(), (unsigned long)num, size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		return NULL;
+	}
 	if (!ptr)
 		return malloc(size * num);
 	return realloc(ptr, size * num);
@@ -1700,3 +1838,24 @@
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+#ifdef __OS2__ // 2009-05-16 SHL
+/**
+ * Convert OS/2 backslashes to unix forward slashes
+ */
+void normalize_dir_slashes(char *path)
+{
+	// 2010-11-24 SHL rework for more speed
+	if (path) {
+		char *p = path;
+		while((p = strchr(p, '\\')) != NULL)
+			*p++ = '/';
+	}
+}
+
+void assert_no_dir_slashes(char *path)
+{
+	if (path && strchr(path, '\\') != 0)
+		rprintf(FERROR, "[%s] unexpected backslash in path %s %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2009-02-06 SHL
+}
+#endif // __OS2__
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/xattrs.c ../rsync-3.0.8/xattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/xattrs.c	2011-02-21 11:32:50.000000000 -0800
+++ ../rsync-3.0.8/xattrs.c	2011-04-18 22:11:40.000000000 -0700
@@ -113,6 +113,8 @@
 {
 	const rsync_xa *xa1 = x1;
 	const rsync_xa *xa2 = x2;
+	// rprintf(FINFO, "* [%s] rsync_xal_compare_names xa1.name %s xa2.name %s %s(%u)\n", who_am_i(), xa1->name, xa2->name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
 	return strcmp(xa1->name, xa2->name);
 }
 
@@ -144,7 +146,9 @@
 				full_fname(fname), arg);
 			return -1;
 		}
+		/* Expand buffer - get size */
 		list_len = sys_llistxattr(fname, NULL, 0);
+		/* Should not occur */
 		if (list_len < 0) {
 			arg = 0;
 			goto got_error;
@@ -243,9 +247,11 @@
 			 || (am_root < 0
 			  && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
 			   || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
-			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
+			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) {
+				// rprintf(FINFO, "* [%s] rsync_xal_get skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 				continue;
 		}
+		}
 
 		datum_len = name_len; /* Pass extra size to get_xattr_data() */
 		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -306,10 +312,12 @@
 			return 0;
 	}
 
+	// rprintf(FINFO, "* [%s] get_xattr fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 	if (rsync_xal_get(fname, sxp->xattr) < 0) {
 		free_xattr(sxp);
 		return -1;
 	}
+	// rprintf(FINFO, "* [%s] get_xattr count %d %s(%u)\n", who_am_i(), sxp->xattr ? sxp->xattr->count : -1, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 	return 0;
 }
 
@@ -482,11 +490,13 @@
 	snd_rxa = lst->items;
 	snd_cnt = lst->count;
 
+	// rprintf(FINFO, "* [%s] xattr_diff fname %s rec_cnt %u snd_cnt %u find_all %u %s(%u)\n", who_am_i(), file->basename, rec_cnt, snd_cnt, find_all, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
+
 	/* 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) {
 		if (!find_all)
-			return 1;
+			return 1;	// Say different
 		xattrs_equal = 0;
 	}
 
@@ -508,7 +518,7 @@
 		}
 		if (!same) {
 			if (!find_all)
-				return 1;
+				return 1;	// Say different
 			xattrs_equal = 0;
 		}
 
@@ -525,6 +535,8 @@
 	if (rec_cnt)
 		xattrs_equal = 0;
 
+	// rprintf(FINFO, "* [%s] xattr_diff xattrs_equal %u %s(%u)\n", who_am_i(), xattrs_equal, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
+
 	return !xattrs_equal;
 }
 
@@ -675,6 +687,8 @@
 		temp_xattr.count = 0;
 	}
 
+	// rprintf(FINFO, "* [%s] receive_xattr %s read count %u am_root %u %s(%u)\n", who_am_i(), file->basename, count, am_root, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
 	for (num = 1; num <= count; num++) {
 		char *ptr, *name;
 		rsync_xa *rxa;
@@ -721,12 +735,14 @@
 			memcpy(name, RSYNC_PREFIX, RPRE_LEN);
 		} else {
 			free(ptr);
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 			continue;
 		}
 #endif
 		/* No rsync.%FOO attributes are copied w/o 2 -X options. */
 		if (preserve_xattrs < 2 && name_len > RPRE_LEN
 		 && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 			free(ptr);
 			continue;
 		}
@@ -738,13 +754,17 @@
 		rxa->num = num;
 	}
 
-	if (need_sort && count > 1)
-		qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
+	// rprintf(FINFO, "* [%s] receive_xattr temp_xattr.items %p temp_xattr.count %u %s(%u)\n", who_am_i(), temp_xattr.items, temp_xattr.count, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
+	// 28 Jul 08 SHL sort number used not number malloced
+	if (need_sort && temp_xattr.count > 1)
+		qsort(temp_xattr.items, temp_xattr.count, sizeof (rsync_xa), rsync_xal_compare_names);
 
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
 
 	F_XATTR(file) = ndx;
+	// rprintf(FINFO, "* [%s] receive_xattr %s ndx %u count %d %s(%u)\n", who_am_i(), file->basename, ndx, rsync_xal_l.count, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 }
 
 /* Turn the xattr data in stat_x into cached xattr data, setting the index
@@ -793,6 +813,7 @@
 	size_t name_len;
 	int ret = 0;
 
+	// rprintf(FINFO, "* [%s] rsync_xal_set fname %s fnamecmp %s %s(%u)\n", who_am_i(), fname, fnamecmp, __FILE__, __LINE__); // 23 Mar 10 SHL debug libc chmod xattrs
 	/* This puts the current name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(fname)) < 0)
 		return -1;

Steven Levine

2011-07-03 03:38

manager   ~0001933

rsync-3.0.8-20110702-shl.zip is an rsync binary built with the rsync-3.0.8-20110702-shl.diff patch set.

This build is based on the rsync v3.0.8 sources and built with with gcc 4.5.2 so it requires gcc452.dll.

There are minimal changes compared to the rsync-3.0.8-20110425-shl. The changes are mostly clean of internal debugging code.

Steven Levine

2011-07-03 03:43

manager  

rsync-3.0.8-20110702-shl.zip (330,152 bytes)

Steven Levine

2011-12-31 16:00

manager  

rsync-3.0.8-20111230-shl.zip (330,900 bytes)

Steven Levine

2011-12-31 16:01

manager  

rsync-3.0.8-20111230-shl.diff (113,106 bytes)
Generated by diffux -N -xproto.h -xrounding.h on 12-30-11 21:18:20
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/Makefile.in ../rsync-3.0.8/Makefile.in
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/Makefile.in	2011-03-26 10:01:36.000000000 -0700
+++ ../rsync-3.0.8/Makefile.in	2011-04-25 22:06:26.000000000 -0700
@@ -12,6 +12,7 @@
 CFLAGS=@CFLAGS@
 CPPFLAGS=@CPPFLAGS@
 EXEEXT=@EXEEXT@
+# 14 Jun 09 SHL fixme to do bldlevel strings
 LDFLAGS=@LDFLAGS@
 
 INSTALLCMD=@INSTALL@
@@ -42,7 +43,8 @@
 	popt/popthelp.o popt/poptparse.o
 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
 
-TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
+# 25 Mar 10 SHL
+TLS_OBJ = tls.o t_stub.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
@@ -68,6 +70,11 @@
 	-mkdir -p ${DESTDIR}${mandir}/man5
 	if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
 	if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
+	if test -f readme.os2; then ${INSTALLMAN} -m 644 readme.os2 ${DESTDIR}${prefix}; fi
+	if test -f readme.shl; then ${INSTALLMAN} -m 644 readme.shl ${DESTDIR}${prefix}; fi
+	if test -f rsync.map; then ${INSTALLMAN} -m 644 rsync.map ${DESTDIR}${prefix}; fi
+	if test -f rsync.sym; then ${INSTALLMAN} -m 644 rsync.sym ${DESTDIR}${prefix}; fi
+	if test -s "${DIFFFILE}"; then if test -f ${DIFFFILE}; then ${INSTALLMAN} -m 644 ${DIFFFILE} ${DESTDIR}${prefix}; fi; fi
 
 install-strip:
 	$(MAKE) INSTALL_STRIP='-s' install
@@ -107,11 +114,11 @@
 getfsdev$(EXEEXT): getfsdev.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
 
-TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
+TRIMSLASH_OBJ = trimslash.o t_stub.o syscall.o lib/compat.o lib/snprintf.o
 trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
-T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
+T_UNSAFE_OBJ = t_unsafe.o t_stub.o syscall.o util.o lib/compat.o lib/snprintf.o lib/wildmatch.o
 t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
 
@@ -189,9 +196,10 @@
 	yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
 	-$(srcdir)/tweak_manpage rsyncd.conf.5
 
+# 06 Feb 09 SHL clean maps
 clean: cleantests
 	rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
-		rounding rounding.h *.old
+		rounding rounding.h *.old rsync.map rounding.map
 
 cleantests:
 	rm -rf ./testtmp*
@@ -243,11 +251,13 @@
 wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
 
+# 25 Mar 10 SHL
+
 testsuite/chown-fake.test:
-	ln -s chown.test $(srcdir)/testsuite/chown-fake.test
+	echo ln -s chown.test $(srcdir)/testsuite/chown-fake.test
 
 testsuite/devices-fake.test:
-	ln -s devices.test $(srcdir)/testsuite/devices-fake.test
+	echo ln -s devices.test $(srcdir)/testsuite/devices-fake.test
 
 testsuite/xattrs-hlink.test:
 	ln -s xattrs.test $(srcdir)/testsuite/xattrs-hlink.test
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/access.c ../rsync-3.0.8/access.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/access.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/access.c	2011-04-18 22:11:36.000000000 -0700
@@ -100,7 +100,9 @@
 	hints.ai_flags = AI_NUMERICHOST;
 #endif
 
-	if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	// if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	if ((gai = getaddrinfo(addr, NULL, &hints, &resa)) != 0) {			// 27 Jul 08 SHL debug
+		// rprintf(FINFO, "* [%s] match_address gai %d %s(%u)\n", who_am_i(), gai, __FILE__, __LINE__);	// 28 Jul 08 SHL debug addrinfo
 		if (p)
 			*p = '/';
 		return 0;
@@ -110,8 +112,8 @@
 	if (p)
 		*p++ = '/';
 	if (gai != 0) {
-		rprintf(FLOG, "error matching address %s: %s\n",
-			tok, gai_strerror(gai));
+		rprintf(FLOG, "* error matching address %s: %s (%d)\n",
+			tok, gai_strerror(gai), gai);
 		freeaddrinfo(resa);
 		return 0;
 	}
@@ -222,7 +224,11 @@
 	if (host)
 		strlower(host);
 
+	// rprintf(FINFO, "* [%s] access_match %s (%s) %s(%u)\n", who_am_i(), host, addr, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
+
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+
+		// rprintf(FINFO, "* [%s] access_match tok %s %s(%u)\n", who_am_i(), tok, __FILE__, __LINE__);	// 28 Jul 08 SHL debug access
 		if (match_hostname(host, tok) || match_address(addr, tok)) {
 			free(list2);
 			return 1;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/authenticate.c ../rsync-3.0.8/authenticate.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/authenticate.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/authenticate.c	2011-04-18 22:11:36.000000000 -0700
@@ -96,7 +96,9 @@
 	if (do_stat(fname, &st) == -1) {
 		rsyserr(FLOG, errno, "stat(%s)", fname);
 		ok = 0;
-	} else if (lp_strict_modes(module)) {
+	}
+#ifndef __OS2__	 /* 29 Jun 09 SHL suppress unsupported mode checks */
+	else if (lp_strict_modes(module)) {
 		if ((st.st_mode & 06) != 0) {
 			rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
 			ok = 0;
@@ -105,6 +107,7 @@
 			ok = 0;
 		}
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		rprintf(FLOG, "continuing without secrets file\n");
 		close(fd);
@@ -173,13 +176,16 @@
 	if (do_stat(filename, &st) == -1) {
 		rsyserr(FWARNING, errno, "stat(%s)", filename);
 		ok = 0;
-	} else if ((st.st_mode & 06) != 0) {
+	}
+#ifndef __OS2__	 /* 12 Jun 08 SHL suppress unsupported mode checks */
+	else if ((st.st_mode & 06) != 0) {
 		rprintf(FWARNING, "password file must not be other-accessible\n");
 		ok = 0;
 	} else if (MY_UID() == 0 && st.st_uid != 0) {
 		rprintf(FWARNING, "password file must be owned by root when running as root\n");
 		ok = 0;
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		close(fd);
 		rprintf(FWARNING, "continuing without password file\n");
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/clientname.c ../rsync-3.0.8/clientname.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/clientname.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/clientname.c	2011-04-18 22:11:36.000000000 -0700
@@ -95,8 +95,10 @@
 	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
-	if (initialised)
+	if (initialised) {
+		// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		return name_buf;
+	}
 
 	strlcpy(name_buf, default_name, sizeof name_buf);
 	initialised = 1;
@@ -148,6 +150,8 @@
 			port_buf, sizeof port_buf) == 0)
 		check_name(fd, &ss, name_buf, sizeof name_buf);
 
+	// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
+
 	return name_buf;
 }
 
@@ -216,14 +220,17 @@
 	int name_err;
 
 	/* reverse lookup */
+	// rprintf(FINFO, "* [%s] lookup_name %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
 			       name_buf, name_buf_size,
 			       port_buf, port_buf_size,
 			       NI_NAMEREQD | NI_NUMERICSERV);
 	if (name_err != 0) {
 		strlcpy(name_buf, default_name, name_buf_size);
-		rprintf(FLOG, "name lookup failed for %s: %s\n",
-			client_addr(fd), gai_strerror(name_err));
+		// rprintf(FINFO, "name lookup failed for %s: %s\n",
+		//	client_addr(fd), gai_strerror(name_err));
+		rprintf(FLOG, "lookup_name failed for %s: %s (%d) at %s(%u) [%s]\n",	// 27 Jul 08 SHL debug
+			client_addr(fd), gai_strerror(name_err), name_err, __FILE__, __LINE__, who_am_i());	// 28 Jul 08 SHL
 		return name_err;
 	}
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/clientserver.c ../rsync-3.0.8/clientserver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/clientserver.c	2010-12-23 22:08:34.000000000 -0800
+++ ../rsync-3.0.8/clientserver.c	2011-04-18 22:11:36.000000000 -0700
@@ -429,6 +429,8 @@
 	iconv_opt = NULL;
 #endif
 
+	if (verbose)
+		rprintf(FINFO, "[%s] rsync_module addr:host is %s:%s\n", who_am_i(), addr, host);	// 2008-07-28 SHL
 	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
 		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
 			name, host, addr);
@@ -442,6 +444,14 @@
 		return -1;
 	}
 
+// 2010-09-17 SHL libc does not do well with chroot c:/ etc.
+#ifdef __OS2__
+	if (use_chroot) {
+		io_printf(f_out, "@ERROR: use chroot not supported\n");
+		return -1;
+	}
+#endif
+
 	if (am_daemon && am_server) {
 		rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",
 			name, host, addr);
@@ -482,6 +492,7 @@
 
 	am_root = (MY_UID() == 0);
 
+#ifndef __OS2__
 	if (am_root) {
 		p = lp_uid(i);
 		if (!name_to_uid(p, &uid)) {
@@ -504,6 +515,7 @@
 		}
 	}
 
+#endif
 	/* TODO: If we're not root, but the configuration requests
 	 * that we change to some uid other than the current one, then
 	 * log a warning. */
@@ -512,6 +524,9 @@
 	 * supplementary groups. */
 
 	module_dir = lp_path(i);
+ 
+ 	// fprintf(stderr, "* [%s] module_dir %s %s(%u)\n", who_am_i(), module_dir, __FILE__, __LINE__); // 2010-09-16 SHL debug
+ 
 	if (*module_dir == '\0') {
 		rprintf(FLOG, "No path specified for module %s\n", name);
 		io_printf(f_out, "@ERROR: no path setting.\n");
@@ -541,6 +556,8 @@
 		full_module_path = module_dir = module_chdir;
 	}
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug path
+
 	if (module_dirlen == 1) {
 		module_dirlen = 0;
 		set_filter_dir("/", 1);
@@ -664,6 +681,8 @@
 	}
 #endif
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
 	if (use_chroot) {
 		/*
 		 * XXX: The 'use chroot' flag is a fairly reliable
@@ -685,8 +704,13 @@
 		module_chdir = module_dir;
 	}
 
-	if (!change_dir(module_chdir, CD_NORMAL))
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+		// rsyserr(FERROR, errno, "[%s] chdir %s failed at %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2008-12-15 SHL debug
+		// rprintf(FINFO, "* [%s] chdir module_chdir %s failed %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 		return path_failure(f_out, module_chdir, True);
+	}
 	if (module_dirlen || !use_chroot)
 		sanitize_paths = 1;
 
@@ -1001,6 +1025,7 @@
 	close(fd);
 }
 
+#ifndef __OS2__
 /* Become a daemon, discarding the controlling terminal. */
 static void become_daemon(void)
 {
@@ -1034,6 +1059,7 @@
 		open("/dev/null", O_RDWR);
 	}
 }
+#endif // __OS2__
 
 int daemon_main(void)
 {
@@ -1056,10 +1082,14 @@
 		exit_cleanup(RERR_SYNTAX);
 	}
 
+#ifndef __OS2__
 	if (no_detach)
 		create_pid_file();
 	else
 		become_daemon();
+#else
+	create_pid_file();
+#endif
 
 	if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
 		rsync_port = RSYNC_PORT;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/compat.c ../rsync-3.0.8/compat.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/compat.c	2011-02-21 11:32:48.000000000 -0800
+++ ../rsync-3.0.8/compat.c	2011-04-18 22:11:36.000000000 -0700
@@ -201,11 +201,12 @@
 			exit_cleanup(RERR_PROTOCOL);
 		}
 		if (preserve_xattrs && !local_server) {
-			rprintf(FERROR,
-			    "--xattrs requires protocol 30 or higher"
+		  	preserve_xattrs = 0;	// 06 Feb 09 SHL force off for old servers
+			rprintf(FWARNING,
+			    "--xattrs requires protocol 30 or higher - option disabled"
 			    " (negotiated %d).\n",
 			    protocol_version);
-			exit_cleanup(RERR_PROTOCOL);
+			// exit_cleanup(RERR_PROTOCOL);	// 06 Feb 09 SHL
 		}
 	}
 
@@ -296,6 +297,7 @@
 	if (need_unsorted_flist && (!am_sender || inc_recurse))
 		unsort_ndx = ++file_extra_cnt;
 
+	// 16 Feb 09 SHL fixme slashes?
 	if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
 		int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
 		if (!am_sender || protocol_version >= 30)
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/configure.sh ../rsync-3.0.8/configure.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/configure.sh	2011-03-26 14:37:50.000000000 -0700
+++ ../rsync-3.0.8/configure.sh	2011-04-18 22:11:36.000000000 -0700
@@ -71,6 +71,8 @@
   as_echo='sh -c $as_echo_body as_echo'
 fi
 
+# 18 Jun 09 SHL fixme to not be broken - 3.0.5 worked - maybe autoconf 2.6.3 broke it
+
 # The user is always right.
 if test "${PATH_SEPARATOR+set}" != set; then
   PATH_SEPARATOR=:
@@ -8414,6 +8416,15 @@
 	$as_echo "#define SUPPORT_XATTRS 1" >>confdefs.h
 
 	;;
+    *os2*)
+	{ echo "$as_me:$LINENO: result: Using OS/2 extattrs" >&5
+echo "${ECHO_T}Using OS/2 extattrs" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_XATTRS 1
+_ACEOF
+
+	;;
+
     *)
 	if test x"$enable_xattr_support" = x"yes"; then
 	    as_fn_error $? "Failed to find extended attribute support" "$LINENO" 5
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/exclude.c ../rsync-3.0.8/exclude.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/exclude.c	2011-02-20 23:48:18.000000000 -0800
+++ ../rsync-3.0.8/exclude.c	2011-04-18 22:11:36.000000000 -0700
@@ -298,7 +298,7 @@
 	unsigned int fn_len;
 
 	if (!parent_dirscan && *merge_file != '/') {
-		/* Return the name unchanged it doesn't have any slashes. */
+		/* Return the name unchanged if it doesn't have any slashes. */
 		if (len_ptr) {
 			const char *p = merge_file + *len_ptr;
 			while (--p > merge_file && *p != '/') {}
@@ -310,6 +310,7 @@
 			return (char *)merge_file;
 	}
 
+	// 16 Feb 09 SHL fixme slash
 	fn = *merge_file == '/' ? buf : tmpbuf;
 	if (sanitize_paths) {
 		const char *r = prefix_skip ? "/" : NULL;
@@ -351,6 +352,7 @@
 void set_filter_dir(const char *dir, unsigned int dirlen)
 {
 	unsigned int len;
+	// 16 Feb 09 SHL fixme slash?
 	if (*dir != '/') {
 		memcpy(dirbuf, curr_dir, curr_dir_len);
 		dirbuf[curr_dir_len] = '/';
@@ -548,6 +550,7 @@
 	int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
 	char *p, *pattern = ex->pattern;
 	const char *strings[16]; /* more than enough */
+	// 16 Feb 09 SHL fixme slash?
 	const char *name = fname + (*fname == '/');
 
 	if (!*name)
@@ -605,8 +608,15 @@
 		if (litmatch_array(pattern, strings, slash_handling))
 			return ret_match;
 	} else if (anchored_match) {
+#ifndef __OS2__
 		if (strcmp(name, pattern) == 0)
 			return ret_match;
+#else
+		// 18 Oct 09 SHL Case insensitive
+		if (stricmp(name, pattern) == 0)
+			return ret_match;
+#endif
+
 	} else {
 		int l1 = strlen(name);
 		int l2 = strlen(pattern);
@@ -988,6 +998,25 @@
 				cp = ".cvsignore";
 				pat_len = 10;
 			}
+#ifdef __OS2__
+			else {
+				// 2009-10-19 SHL normalize
+				// 30 Sep 10 SHL avoid writing to const memory
+				/* If we are passed paths from the filter they
+				   might have DOS slashes, convert to Unix slashes
+				   except for the 1st characters (fixme to doc why - I forgot)
+				   If we are processing a const string, it will already
+				   have Unix slashes so don't try to write to const memory
+				*/
+				char ch;
+				p = cp + pat_len;	// Must be non-const for gcc
+				ch = *p;		// Remember 1st character - fixme to say why
+				normalize_dir_slashes((char *)cp);	// Hack cough - override const
+				if (*p != ch)
+					*(char*)p = ch;	// Ensure leading char not changed - fixme to say why
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len, cp, strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
+			}
+#endif
 			len = pat_len;
 			if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
 				const char *name = cp + len;
@@ -998,6 +1027,8 @@
 				len = pat_len;
 			}
 			if (new_mflags & MATCHFLG_PERDIR_MERGE) {
+				// 19 Oct 09 SHL fixme to complain if have drive letter?
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 				if (parent_dirscan) {
 					if (!(p = parse_merge_name(cp, &len,
 								module_dirlen)))
@@ -1014,6 +1045,7 @@
 			}
 		}
 
+		// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 19 Oct 09 SHL fixme filter files
 		add_rule(listp, cp, pat_len, new_mflags, xflags);
 
 		if (new_mflags & MATCHFLG_CVS_IGNORE
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/flist.c ../rsync-3.0.8/flist.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/flist.c	2011-02-21 10:20:58.000000000 -0800
+++ ../rsync-3.0.8/flist.c	2011-04-18 22:11:36.000000000 -0700
@@ -347,8 +347,19 @@
 {
 	if (dirlen < 0) {
 		char *cpy = strdup(dir);
+#ifndef __OS2__ // 2009-03-06 SHL use is_abs_path...
 		if (*cpy != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (!is_abs_path(cpy)) {
+			if (drive_spec_width(cpy))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), cpy, __FILE__, __LINE__);	// 2009-02-06 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+	        }
+#endif
 		if (path_is_daemon_excluded(cpy, 0))
 			goto chdir_error;
 		dir = cpy;
@@ -362,8 +373,19 @@
 				dirlen = strlen(dir);
 		} else if (pathname == dir)
 			return 1;
+#ifndef __OS2__ // 2009-03-06 SHL use is_abs_path...
 		if (dir && *dir != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (dir && !is_abs_path(dir)) {
+			if (drive_spec_width(dir))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+		}
+#endif
 	}
 
 	pathname = dir;
@@ -376,8 +398,13 @@
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
 		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
-		if (dir != orig_dir)
-			change_dir(orig_dir, CD_NORMAL);
+		rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-07-21 SHL
+		if (dir != orig_dir) {
+			if (!change_dir(orig_dir, CD_NORMAL)) {
+				if (verbose > 1)
+					rprintf(FLOG, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+		}
 		pathname = NULL;
 		pathname_len = 0;
 		return 0;
@@ -1330,6 +1357,8 @@
 {
 	struct file_struct *file;
 
+	// rprintf(FINFO, "* [%s] send_file_name fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+
 	file = make_file(fname, flist, stp, flags, filter_level);
 	if (!file)
 		return NULL;
@@ -1975,6 +2004,7 @@
 	int len, dirlen;
 	STRUCT_STAT st;
 	char *p, *dir;
+	static char* the_root = "/";
 	struct file_list *flist;
 	struct timeval start_tv, end_tv;
 	int64 start_write;
@@ -2018,6 +2048,7 @@
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
 			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
 				full_fname(argv[0]));
+			rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), argv[0], __FILE__, __LINE__);	// 2009-07-21 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 		use_ff_fd = 1;
@@ -2037,19 +2068,25 @@
 			if (argc-- == 0)
 				break;
 			strlcpy(fbuf, *argv++, MAXPATHLEN);
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2010-09-16 SHL debug paths
 			if (sanitize_paths)
 				sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2010-09-16 SHL debug paths
+
 		len = strlen(fbuf);
 		if (relative_paths) {
 			/* We clean up fbuf below. */
 			name_type = NORMAL_NAME;
 		} else if (!len || fbuf[len - 1] == '/') {
-			if (len == 2 && fbuf[0] == '.') {
-				/* Turn "./" into just "." rather than "./." */
+			/* Empty path or trailing / */
+			// 2009-03-06 SHL Support drive letters
+			if (len == 2 + drive_spec_width(fbuf) && fbuf[drive_spec_width(fbuf)] == '.') {
+				/* Turn trailing "./" into just "." rather than "./." */
 				fbuf[--len] = '\0';
 			} else {
+				/* Turn trailing "xyz/" into "xyz/." */
 				if (len + 1 >= MAXPATHLEN)
 					overflow_exit("send_file_list");
 				fbuf[len++] = '.';
@@ -2058,6 +2095,7 @@
 			name_type = DOTDIR_NAME;
 		} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
 		    && (len == 2 || fbuf[len-3] == '/')) {
+			/* Got ..  or trailing /.. */
 			if (len + 2 >= MAXPATHLEN)
 				overflow_exit("send_file_list");
 			fbuf[len++] = '/';
@@ -2076,18 +2114,40 @@
 			if (p) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 2009-03-06 SHL Preserve drive letter in directory name
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else
 					dir = fbuf;
-				len -= p - fbuf + 1;
-				fn = p + 1;
+				fn = p + 1;		// Point at filename part
+				len -= fn - fbuf;	//  fn length
+				// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			} else
 				fn = fbuf;
 		} else {
+			// relative-paths
 			if ((p = strstr(fbuf, "/./")) != NULL) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 2009-03-06 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else {
 					dir = fbuf;
 					clean_fname(dir, 0);
@@ -2101,6 +2161,10 @@
 				fn = fbuf;
 			/* A leading ./ can be used in relative mode to affect
 			 * the dest dir without its name being in the path. */
+#ifdef __OS2__
+			// 2010-11-30 SHL Point after drive letter
+			fn += drive_spec_width(fn);
+#endif
 			if (*fn == '.' && fn[1] == '/' && !implied_dot_dir) {
 				send_file_name(f, flist, ".", NULL,
 				    (flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR,
@@ -2109,6 +2173,7 @@
 			}
 			len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
 					    | CFN_DROP_TRAILING_DOT_DIR);
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug relative-paths
 			if (len == 1) {
 				if (fn[0] == '/') {
 					fn = "/.";
@@ -2133,7 +2198,8 @@
 					exit_cleanup(RERR_SYNTAX);
 				}
 			}
-		}
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug relative-paths
+		} // relative-paths
 
 		if (!*fn) {
 			len = 1;
@@ -2141,6 +2207,8 @@
 			name_type = DOTDIR_NAME;
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list dir %s fn %s len %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug xattrs
+
 		dirlen = dir ? strlen(dir) : 0;
 		if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
 			if (!change_pathname(NULL, dir, -dirlen))
@@ -2150,9 +2218,16 @@
 		} else if (!change_pathname(NULL, lastdir, lastdir_len))
 			continue;
 
+		// 2009-03-06 SHL
+		if (dir && dir != the_root && dir != fbuf)
+			free(dir);	// We allocated it
+
 		if (fn != fbuf)
 			memmove(fbuf, fn, len + 1);
 
+		// rprintf(FINFO, "* [%s] send_file_list fn %s %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s len %d %s(%u)\n", who_am_i(), fbuf, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+
 		if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
@@ -2173,12 +2248,14 @@
 		}
 
 		if (inc_recurse && relative_paths && *fbuf) {
+			// 2009-03-06 SHL fixme
 			if ((p = strchr(fbuf+1, '/')) != NULL) {
 				if (p - fbuf == 1 && *fbuf == '.') {
 					if ((fn = strchr(p+1, '/')) != NULL)
 						p = fn;
 				} else
 					fn = p;
+				// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 				send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
 				if (fn == p)
 					continue;
@@ -2186,6 +2263,7 @@
 		} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
 			/* Send the implied directories at the start of the
 			 * source spec, so we get their permissions right. */
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
 		}
 
@@ -2194,6 +2272,7 @@
 
 		if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
 			struct file_struct *file;
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			file = send_file_name(f, flist, fbuf, &st,
 					      FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
 					      NO_FILTERS);
@@ -2209,9 +2288,11 @@
 				}
 			} else
 				send_if_directory(f, flist, file, fbuf, len, flags);
-		} else
+		} else {
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
 	}
+	} /* while */
 
 	gettimeofday(&end_tv, NULL);
 	stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000
@@ -2401,6 +2482,9 @@
 							struct file_struct *,
 							dir_flist->malloced);
 				dir_flist_malloced = dir_flist->malloced;
+				// 2010-11-30 SHL check out of memory
+				if (dir_flist->sorted == NULL)
+					out_of_memory("recv_file_list");
 			}
 			memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart,
 			       (dir_flist->used - dstart) * sizeof (struct file_struct*));
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/generator.c ../rsync-3.0.8/generator.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/generator.c	2011-03-26 10:17:14.000000000 -0700
+++ ../rsync-3.0.8/generator.c	2011-05-25 17:18:46.000000000 -0700
@@ -96,6 +96,10 @@
 extern int backup_suffix_len;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+// 14 Oct 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 int ignore_perishable = 0;
 int non_perishable_cnt = 0;
@@ -263,6 +267,7 @@
 	}
 
 	p = fname + dlen;
+	// 16 Feb 09 SHL fixme slash?
 	if (dlen != 1 || *fname != '/')
 		*p++ = '/';
 	remainder = MAXPATHLEN - (p - fname);
@@ -659,7 +664,7 @@
 #endif
 	}
 
-	return 1;
+	return 1;			// No change
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -680,19 +685,30 @@
 		} else if (keep_time
 		 ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
 		 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
-		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s file->modtime %u sxp->st.st_mtime %u %s(%u)\n", who_am_i(), fnamecmp, file->modtime, sxp->st.st_mtime, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme times
+			if (verbose > 1)
+				rprintf(FINFO, "%s times differ sender %u receiver %u\n", fnamecmp, file->modtime, sxp->st.st_mtime);
 			iflags |= ITEM_REPORT_TIME;
+		}
+
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
 		} else
 #endif
 		if (preserve_perms) {
-			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) {
+				// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode 0%o file->mode 0%o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
+				if (verbose > 1)
+					rprintf(FINFO, "%s perms differ sender %o receiver %o\n", fnamecmp, file->mode, sxp->st.st_mode);
 				iflags |= ITEM_REPORT_PERMS;
+			}
 		} else if (preserve_executability
-		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0))) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode 0%o file->mode 0%o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 17 Sep 09 SHL fixme perms
 			iflags |= ITEM_REPORT_PERMS;
+		 }
 		if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 			iflags |= ITEM_REPORT_OWNER;
 		if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
@@ -1539,8 +1555,10 @@
 #endif
 
 #ifdef SUPPORT_XATTRS
-		if (preserve_xattrs && statret == 1)
+		if (preserve_xattrs && statret == 1) {
+			// rprintf(FINFO, "* [%s] receive_generator running copy_xattrs fnamecmpbuf %s fname %s %s(%u)\n", who_am_i(), fnamecmpbuf, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
 			copy_xattrs(fnamecmpbuf, fname);
+		}
 #endif
 		if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
 		    && verbose && code != FNONE && f_out != -1)
@@ -1640,6 +1658,17 @@
 			cur_flist->in_progress++;
 			goto cleanup;
 		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If source directory not archived (i.e. not writable by group)
+		// may need to touch up after file operations complete
+		// see map_os2_attributes
+		if (!need_retouch_dir_perms && os2_perms &&
+		    ~file->mode & S_IWGRP) {
+			// rprintf(FINFO, "* [%s] recv_generator dir %s needs retouch mode 0%o %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 14 Oct 09 SHL fixme dir perms
+			need_retouch_dir_perms = 1;
+		}
+#endif
 #endif
 		if (do_symlink(sl, fname) != 0) {
 			rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed",
@@ -1664,7 +1693,7 @@
 		}
 #endif
 		goto cleanup;
-	}
+	} // is_dir
 
 	if ((am_root && preserve_devices && IS_DEVICE(file->mode))
 	 || (preserve_specials && IS_SPECIAL(file->mode))) {
@@ -2096,10 +2125,18 @@
 	} else
 		start = end = ndx;
 
+	// rprintf(FINFO, "* [%s] touch_up_dirs start %u end %u %s(%u)\n", who_am_i(), start, end,  __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
+
 	/* Fix any directory permissions that were modified during the
 	 * transfer and/or re-set any tweaked modified-time values. */
 	for (i = start; i <= end; i++, counter++) {
+		// 23 Mar 10 SHL overcome xattrs generated by libc chmod
+#ifdef __OS2__
+		int need_xattrs_set = 0;
+#endif
 		file = flist->files[i];
+		// fname = f_name(file, NULL); // 14 Oct 09 SHL debug dir perms
+		// rprintf(FINFO, "* [%s] touch_up_dirs dir %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 		if (!S_ISDIR(file->mode)
 		 || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))
 			continue;
@@ -2110,18 +2147,80 @@
 		}
 		/* Be sure not to retouch permissions with --fake-super. */
 		fix_dir_perms = !am_root && !(file->mode & S_IWUSR);
+#ifndef __OS2__
 		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
 		 || !(need_retouch_dir_times || fix_dir_perms))
 			continue;
+else // __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived on (i.e. writable by group)
+		// See map_os2_attributes
+		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
+		 || !(need_retouch_dir_times || fix_dir_perms
+		      || !os2_perms || (~file->mode & S_IWGRP)))
+			continue;
+#endif
 		fname = f_name(file, NULL);
-		if (fix_dir_perms)
+#ifdef __OS2__
+		// 14 Oct 09 SHL Need to set time before clearing archive bit
+		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);
+		}
+#endif
+		if (fix_dir_perms) {
+			do_chmod(fname, file->mode);
+#ifdef __OS2__
+			// 25 Mar 10 SHL fixme to be sure can update EAs after setting read-only
+			// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWUSR fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			need_xattrs_set = preserve_xattrs;
+#endif
+		}
+#ifdef __OS2__
+		// 14 Oct 09 SHL
+		// If os/2 perms and want archived off (i.e. not writable by group)
+		// See map_os2_attributes
+		// Other os/2 perms should already be OK
+		// There is no way to know for sure if directory was modified so we check
+		else if (os2_perms && ~file->mode & S_IWGRP) {
+			STRUCT_STAT st;
+			if (link_stat(fname, &st, 0) == 0 &&
+			    ((file->mode ^ st.st_mode) & S_IWGRP)) {
+				// rprintf(FINFO, "* [%s] touch_up_dirs chmod(%s, 0%o) %s(%u)\n", who_am_i(), fname, file->mode, __FILE__, __LINE__); // 17 Sep 09 SHL fixme dir perms
 			do_chmod(fname, file->mode);
+				// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+				// rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set chmod ~S_IWGRP(archive) fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+				need_xattrs_set = need_xattrs_set || preserve_xattrs;
+			}
+		}
+#endif
+#ifndef __OS2__
 		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);
 		}
+#endif
+#ifdef __OS2__
+		if (need_xattrs_set) {
+			// 23 Mar 10 SHL overwrite xattrs generated by libc chmod
+			stat_x sx;
+			// rprintf(FINFO, "* [%s] touch_up_dirs doing set_xattr for %s %s %s(%u)\n", who_am_i(), fname, fname, __FILE__, __LINE__); // 23 Mar 10 SHL fixme libc chmod xattrs debug
+			if (verbose > 2)
+				rprintf(FINFO, "%s removing EAs generated by libc chmod %s\n", who_am_i(), fname);
+			memset(&sx, 0, sizeof(stat_x));
+			// Should not need to provide target item list to set_xattr
+			// link_stat(fname, &sx.st, 0);
+			// sx.xattr = new(item_list);
+			// *sxp.xattr = empty_xattr;
+			set_xattr(fname, file, fname, &sx);
+			// free_xattr(&sx);
+		}
+#endif
 		if (counter >= loopchk_limit) {
 			if (allowed_lull)
 				maybe_send_keepalive();
@@ -2129,7 +2228,7 @@
 				maybe_flush_socket(0);
 			counter = 0;
 		}
-	}
+	} // for
 }
 
 void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/getaddrinfo.c ../rsync-3.0.8/lib/getaddrinfo.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/getaddrinfo.c	2009-12-12 17:20:34.000000000 -0800
+++ ../rsync-3.0.8/lib/getaddrinfo.c	2011-04-18 22:11:36.000000000 -0700
@@ -403,12 +403,16 @@
 	int ret = -1;
 	char *p = NULL;
 
+	// rprintf(FINFO, "* [%s] gethostnameinfo NI_NUMERICHOST %u %s(%u)\n", who_am_i(), flags & NI_NUMERICHOST, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	if (!(flags & NI_NUMERICHOST)) {
+		// rprintf(FINFO, "* [%s] gethostnameinfo %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		struct hostent *hp = gethostbyaddr(
 				(void *)&((struct sockaddr_in *)sa)->sin_addr,
 				sizeof (struct in_addr),
 				sa->sa_family);
+		// rprintf(FINFO, "* [%s] gethostnameinfo hp %p %s(%u)\n", who_am_i(), hp, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		ret = check_hostent_err(hp);
+		// rprintf(FINFO, "* [%s] ret %d %s(%u)\n", who_am_i(), ret, __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (ret == 0) {
 			/* Name looked up successfully. */
 			ret = snprintf(node, nodelen, "%s", hp->h_name);
@@ -424,6 +428,7 @@
 			return 0;
 		}
 
+		// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 		if (flags & NI_NAMEREQD) {
 			/* If we require a name and didn't get one,
 			 * automatically fail. */
@@ -431,6 +436,7 @@
 		}
 		/* Otherwise just fall into the numeric host code... */
 	}
+	// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 28 Jul 08 SHL debug
 	p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
 	ret = snprintf(node, nodelen, "%s", p);
 	if (ret < 0 || (size_t)ret >= nodelen) {
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/pool_alloc.c ../rsync-3.0.8/lib/pool_alloc.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/pool_alloc.c	2008-11-09 18:55:14.000000000 -0800
+++ ../rsync-3.0.8/lib/pool_alloc.c	2011-04-18 22:11:36.000000000 -0700
@@ -93,8 +93,10 @@
 	else if (pool->quantum > 1 && len % pool->quantum)
 		len += pool->quantum - len % pool->quantum;
 
-	if (len > pool->size)
+	if (len > pool->size) {
+	        rprintf(FERROR, "* [%s] pool_alloc len %u > pool->size %u %s(%u)\n", who_am_i(), len, pool->size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		goto bomb_out;
+	}
 
 	if (!pool->extents || len > pool->extents->free) {
 		void	*start;
@@ -111,16 +113,20 @@
 		if (pool->flags & POOL_APPEND)
 			asize += sizeof (struct pool_extent);
 
-		if (!(start = new_array(char, asize)))
+		if (!(start = new_array(char, asize))) {
+			rprintf(FERROR, "* [%s] new_array asize %u failed %s(%u)\n", who_am_i(), asize, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 			goto bomb_out;
+		}
 
 		if (pool->flags & POOL_CLEAR)
 			memset(start, 0, free);
 
 		if (pool->flags & POOL_APPEND)
 			ext = PTR_ADD(start, free);
-		else if (!(ext = new(struct pool_extent)))
+		else if (!(ext = new(struct pool_extent))) {
+			rprintf(FERROR, "* [%s] new pool_extent failed %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 			goto bomb_out;
+		}
 		if (pool->flags & POOL_QALIGN && pool->quantum > 1
 		    && (skew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
 			bound  += skew;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.c ../rsync-3.0.8/lib/sysxattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.c	2008-03-01 12:01:40.000000000 -0800
+++ ../rsync-3.0.8/lib/sysxattrs.c	2011-12-30 21:06:12.000000000 -0800
@@ -126,6 +126,360 @@
 	return len;
 }
 
+#elif defined(__OS2__)
+
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+
+static void map_os2_apiret(APIRET rc)
+{
+	switch (rc) {
+	case ERROR_SHARING_VIOLATION:
+		errno = EACCES;
+		break;
+	case 0:
+		// Should not have been called - try to do no harm
+		break;
+	default:
+		// 2009-07-31 SHL fixme to map better
+		// if (verbose > 2)
+		rprintf(FINFO, "[%s] can not map OS/2 error %lu to errno\n", who_am_i(), rc);	// 31 Jul 09 SHL
+		/* Ensure non-zero */
+		if (!errno)
+			errno = EINVAL;
+
+	}
+}
+
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+	return unisetxattr (path, 0, name, value, size, 0);
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+static char *out_of_mem_msg = "out of memory allocating %lu at %s(%u)\n";
+
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	size_t reqsize;
+	EAOP2       eaop2 = {0,0,0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+	reqsize = sizeof(GEA2LIST) + namelen + 1;
+	pgea2list = (PGEA2LIST)calloc(reqsize, 1);
+	// 2010-11-30 SHL
+	if (pgea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	reqsize = sizeof(FEA2LIST) + 0x10000;
+	pfea2list = (PFEA2LIST)calloc(reqsize, 1);
+	// 2010-11-30 SHL
+	if (pfea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;
+	do {
+		if (path) {
+			rc = DosQueryPathInfo(path, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryPathInfo(%s, FIL_QUERYEASFROMLIST) for %s failed with error %u at %s(%u)\n", who_am_i(), path, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] %s requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), path, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		else {
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryFileInfo(%u, FIL_QUERYEASFROMLIST) for %s failed with error %u at %s(%u)\n", who_am_i(), file, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] handle %d requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), file, eaop2.fpFEA2List->cbList, name);	// 28 Jul 08 SHL
+		}
+		if (rc)
+			break;
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0) {
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value) {
+			if ((size_t)rc > size) {
+				errno = ERANGE;
+				rc = -1;
+			}
+			else {
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+		free(pgea2list);
+	if (pgea2list)
+		free(pfea2list);
+
+	return rc;
+}
+
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	size_t reqsize;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat;
+	if (!path && !file) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (path) {
+		rc = DosQueryPathInfo(path, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryPathInfo(%s, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] %s reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), path, stat.cbList);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryFilInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] handle %d reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), file, stat.cbList);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	if (stat.cbList <= 4) {
+		// NO ea
+		return 0;
+	}
+	//YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
+	reqsize = stat.cbList * 2;
+	buf = (char *)_tmalloc(reqsize);
+	// 2009-09-19 SHL was trapping on large copies
+	if (!buf) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);	// 2009-09-19 SHL
+		return -1;
+	}
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc) {
+		rprintf(FERROR, "[%s] unilistxattr DosEnumAttribute failed with error %u at %s(%u)\n", who_am_i(), rc, __FILE__, __LINE__);	// 28 Jul 08 SHL
+		_tfree(buf);
+		map_os2_apiret(rc);	// 31 Jul 09 SHL moved here to ensure errno returned
+		return -1;
+	}
+	else if (verbose > 2) {
+		if (path)
+			rprintf(FINFO, "[%s] %s has %lu DosEnumAttribute items\n", who_am_i(), path, ulCount);	// 28 Jul 08 SHL
+		else
+			rprintf(FINFO, "[%s] handle %d has %lu DosEnumAttribute items\n", who_am_i(), file, ulCount);	// 28 Jul 08 SHL
+	}
+	if (ulCount > 0) {
+		for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset)) {
+			if (pfea->cbName > 0) {
+				gotsize += pfea->cbName + 1;
+				// Avoid overflow
+				if (p && (size_t)gotsize <= size) {
+					pfea->szName[pfea->cbName] = 0;
+					strcpy(p, pfea->szName);
+					p += strlen(p) + 1;
+				}
+			}
+			if (!pfea->oNextEntryOffset)
+				break;
+		}
+	}
+	_tfree(buf);
+	if ((size_t)gotsize > size) {
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	if (verbose > 2)
+		rprintf(FINFO, "[%s] returning %ld EA list bytes\n", who_am_i(), (unsigned long)gotsize);	// 28 Jul 08 SHL
+	return gotsize;
+}
+
+int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0,0,0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) for %s failed with error %u at %s(%u)\n", who_am_i(), path, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosFileInfo(%u, FIL_QUERYEASIZE) for %s failed with error %u %s(%u)\n", who_am_i(), file, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0,0,0};
+	PFEA2LIST   pfea2list = NULL;
+
+	if ((!path && !file) || !name || (!value && size)) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0) {
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0) {
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(FEA2LIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	// 2010-11-30 SHL
+	if (pfea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, totalsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value) {
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo(path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) for %s failed with error %u at %s(%u)\n", who_am_i(), path, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for %s\n", who_am_i(), name, path);	// 28 Jul 08 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetFileInfo(%u, FIL_QUERYEASIZE) for %s failed with error %u at %s(%u)\n", who_am_i(), file, name, rc, __FILE__, __LINE__);	// 30 Dec 11 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for handle %d\n", who_am_i(), name, file);	// 28 Jul 08 SHL
+	}
+	free(pfea2list);
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
 #else
 
 #error You need to create xattr compatibility functions.
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.h ../rsync-3.0.8/lib/sysxattrs.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/sysxattrs.h	2007-04-07 10:22:24.000000000 -0700
+++ ../rsync-3.0.8/lib/sysxattrs.h	2011-04-18 22:11:36.000000000 -0700
@@ -19,6 +19,13 @@
 int sys_lremovexattr(const char *path, const char *name);
 ssize_t sys_llistxattr(const char *path, char *list, size_t size);
 
+#ifdef __OS2__
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size);
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size);
+int uniremovexattr (const char *path, int file, const char *name);
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags);
+#endif
+
 #else
 
 /* No xattrs available */
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/wildmatch.c ../rsync-3.0.8/lib/wildmatch.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/lib/wildmatch.c	2007-05-21 22:58:58.000000000 -0700
+++ ../rsync-3.0.8/lib/wildmatch.c	2011-04-18 22:11:36.000000000 -0700
@@ -89,8 +89,14 @@
 	    p_ch = *++p;
 	    /* FALLTHROUGH */
 	  default:
+#ifndef __OS2__
 	    if (t_ch != p_ch)
 		return FALSE;
+#else
+	    // 18 Oct 09 SHL be case insensitive
+	    if (t_ch != p_ch && (t_ch ^ p_ch) != 0x20)
+		return FALSE;
+#endif
 	    continue;
 	  case '?':
 	    /* Match anything but '/'. */
@@ -150,8 +156,14 @@
 		    p_ch = *++p;
 		    if (!p_ch)
 			return ABORT_ALL;
+#ifndef __OS2__
 		    if (t_ch == p_ch)
 			matched = TRUE;
+#else
+		    // 18 Oct 09 SHL be case insensitive
+		    if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			matched = TRUE;
+#endif
 		} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
 		    p_ch = *++p;
 		    if (p_ch == '\\') {
@@ -159,6 +171,7 @@
 			if (!p_ch)
 			    return ABORT_ALL;
 		    }
+		    // 18 Oct 09 SHL [a-z] ranges remain case-sensitive for now
 		    if (t_ch <= p_ch && t_ch >= prev_ch)
 			matched = TRUE;
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
@@ -173,8 +186,14 @@
 			/* Didn't find ":]", so treat like a normal set. */
 			p = s - 2;
 			p_ch = '[';
+#ifndef __OS2__
 			if (t_ch == p_ch)
 			    matched = TRUE;
+#else
+			// 18 Oct 09 SHL be case insensitive
+			if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			    matched = TRUE;
+#endif
 			continue;
 		    }
 		    if (CC_EQ(s,i, "alnum")) {
@@ -218,6 +237,11 @@
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
 		} else if (t_ch == p_ch)
 		    matched = TRUE;
+#ifdef __OS2__
+		// 18 Oct 09 SHL be case insensitive
+		else if ((t_ch ^ p_ch) == 0x20)
+		    matched = TRUE;
+#endif
 	    } while (prev_ch = p_ch, (p_ch = *++p) != ']');
 	    if (matched == special || t_ch == '/')
 		return FALSE;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/loadparm.c ../rsync-3.0.8/loadparm.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/loadparm.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/loadparm.c	2011-04-18 22:11:36.000000000 -0700
@@ -212,7 +212,7 @@
  /* read_only; */		True,
  /* strict_modes; */		True,
  /* transfer_logging; */	False,
- /* use_chroot; */		True,
+ /* use_chroot; */		False,	// 2010-09-17 SHL libc chroot not quite right
  /* write_only; */		False,
 };
 
@@ -654,10 +654,23 @@
 	    *(char *)dest_ptr = *(char *)src_ptr;
 	    break;
 
+#ifndef __OS2__
 	  case P_PATH:
 	  case P_STRING:
 	    string_set(dest_ptr,*(char **)src_ptr);
 	    break;
+#else
+	  case P_PATH:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    // 2009-03-06 SHL Force unix slashes
+	    // 2009-05-16 SHL Use normalize_dir_slashes
+	    normalize_dir_slashes(*(char **)dest_ptr);
+	    break;
+
+	  case P_STRING:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    break;
+#endif
 
 	  default:
 	    break;
@@ -725,8 +738,14 @@
      case P_PATH:
        string_set(parm_ptr,parmvalue);
        if ((cp = *(char**)parm_ptr) != NULL) {
+	   // Chop trailing slashes unless root
 	   int len = strlen(cp);
+#ifndef __OS2__
 	   while (len > 1 && cp[len-1] == '/') len--;
+#else
+	   // 2010-11-24 SHL Use drive_spec_width
+	   while (len > drive_spec_width(cp) + 1 && cp[len-1] == '/') len--;
+#endif
 	   cp[len] = '\0';
        }
        break;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/log.c ../rsync-3.0.8/log.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/log.c	2011-01-29 19:25:52.000000000 -0800
+++ ../rsync-3.0.8/log.c	2011-04-18 22:11:36.000000000 -0700
@@ -369,6 +369,7 @@
 	va_list ap;
 	char buf[BIGPATHBUFLEN];
 	size_t len;
+	int e = errno;			// 27 Apr 09 SHL preserve errno
 
 	va_start(ap, format);
 	len = vsnprintf(buf, sizeof buf, format, ap);
@@ -401,6 +402,7 @@
 	}
 
 	rwrite(code, buf, len, 0);
+	errno = e;
 }
 
 /* This is like rprintf, but it also tries to print some
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/main.c ../rsync-3.0.8/main.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/main.c	2011-02-22 08:21:08.000000000 -0800
+++ ../rsync-3.0.8/main.c	2011-04-18 22:11:36.000000000 -0700
@@ -27,6 +27,10 @@
 #include <locale.h>
 #endif
 
+#ifdef __OS2__
+#include <umalloc.h>			// Need for _heap_walk
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int list_only;
@@ -272,10 +276,23 @@
 
 	if (verbose || do_stats) {
 		rprintf(FCLIENT, "\n");
+#ifndef __OS2__
 		rprintf(FINFO,
 			"sent %s bytes  received %s bytes  %s bytes/sec\n",
 			human_num(total_written), human_num(total_read),
 			human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
+#else
+		{
+			// 2010-10-30 SHL show elapsed time
+			time_t t = endtime - starttime + 1;	// Always round up
+			rprintf(FINFO,
+				"sent %s bytes  received %s bytes  %s bytes/sec  elapsed %02u:%02u:%02u\n",
+				human_num(total_written),
+				human_num(total_read),
+				human_dnum((total_written + total_read)/(0.5 + t), 2),
+				t / 3600, (t / 60) % 60, t % 60);
+		}
+#endif
 		rprintf(FINFO, "total size is %s  speedup is %.2f%s\n",
 			human_num(stats.total_size),
 			(double)stats.total_size / (total_written+total_read),
@@ -287,6 +304,92 @@
 }
 
 
+#ifdef __OS2__				// 2010-12-25 SHL
+#ifdef HAVE_MALLINFO
+#error HAVE_MALLINFO unexpected
+#endif
+
+// See \EMX\doc\emxlib.doc
+
+struct mallinfo {
+  int arena;
+  int ordblks;
+  int smblks;
+  int hblks;
+  int hblkhd;
+  int usmblks;
+  int fsmblks;
+  int uordblks;
+  int fordblks;
+  int keepcost;
+};
+
+static struct mallinfo os2_mallinfo;
+
+
+// 2010-12-25 SHL push requires 4.5
+// #pragma GCC diagnostic push
+// 2010-12-25 SHL diagnosic requires 4.4.x
+// #pragma GCC diagnostic ignored "-Wunused-parameter"
+
+// 2010-12-25 SHL unused-parameter warnings expected with 3.3.5
+
+static int os2_mallinfo_callback(const void *block, size_t size, int flag,
+				 int status, const char *fname, size_t lineno)
+{
+	int err = 0;
+	switch (status) {
+	case _HEAPOK:
+	{
+		switch (flag) {
+		case _USEDENTRY:
+			os2_mallinfo.uordblks += size;
+			break;
+		case _FREEENTRY:
+			os2_mallinfo.fordblks += size;
+			break;
+	        default:
+			err = 99;
+		} // flag
+	}
+	break;
+	case _HEAPBADBEGIN:
+	case _HEAPBADEND:
+	case _HEAPBADNODE:
+	case _HEAPEMPTY:
+		// Let _heap_walk set return code
+		break;
+	default:
+		err = 99;
+	} // status
+	return err;
+}
+
+// 2010-12-25 SHL pop requires 4.5.x
+// #pragma GCC diagnostic pop
+// 2010-12-25 SHL diagnosic requires 4.4.x
+// #pragma GCC diagnostic warning "-Wunused-parameter"
+
+struct mallinfo mallinfo(void)
+{
+	int err;
+	memset(&os2_mallinfo, 0, sizeof(os2_mallinfo));
+	err = _heap_walk(os2_mallinfo_callback);
+
+	if (err) {
+		// fixme to report
+	}
+
+	os2_mallinfo.arena = os2_mallinfo.uordblks + os2_mallinfo.ordblks;
+
+	return os2_mallinfo;
+}
+
+#define HAVE_MALLINFO
+
+#endif // __OS2__
+
+
 /**
  * If our C library can get malloc statistics, then show them to FINFO
  **/
@@ -324,6 +427,9 @@
 	rprintf(FINFO, "  keepcost:  %10ld   (bytes in releasable chunk)\n",
 		(long)mi.keepcost);
 #endif /* HAVE_MALLINFO */
+
+#ifdef __OS2__				// 2010-12-25 SHL
+#endif // __OS2__
 }
 
 
@@ -541,6 +647,8 @@
 			if (!change_dir(dest_path, CD_NORMAL)) {
 				rsyserr(FERROR, errno, "change_dir#1 %s failed",
 					full_fname(dest_path));
+				// 22 Jul 09 SHL was FLOG?  why?
+				rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 				exit_cleanup(RERR_FILESELECT);
 			}
 			filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
@@ -602,6 +710,8 @@
 		if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
 			rsyserr(FERROR, errno, "change_dir#2 %s failed",
 				full_fname(dest_path));
+			// 22 Jul 09 SHL was FLOG?  why?
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 
@@ -622,6 +732,8 @@
 	if (!change_dir(dest_path, CD_NORMAL)) {
 		rsyserr(FERROR, errno, "change_dir#3 %s failed",
 			full_fname(dest_path));
+		// 22 Jul 09 SHL was FLOG?  why?
+		rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 21 Jul 09 SHL
 		exit_cleanup(RERR_FILESELECT);
 	}
 	*cp = '/';
@@ -713,8 +825,9 @@
 
 	if (!relative_paths) {
 		if (!change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#3 %s failed",
+			rsyserr(FERROR, errno, "change_dir#4 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -885,8 +998,9 @@
 		argc--;
 		argv++;
 		if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#4 %s failed",
+			rsyserr(FERROR, errno, "change_dir#5 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 21 Jul 09 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -941,6 +1055,7 @@
 			if (check_filter(elp, FLOG, dir, 1) < 0)
 				goto options_rejected;
 		}
+		// 25 Sep 09 SHL fixme slashes
 		if (partial_dir && *partial_dir == '/'
 		 && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
 		    options_rejected:
@@ -1099,7 +1214,7 @@
 
 	for (i = 0; argv[i]; i++) {
 		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
+			rprintf (FERROR, "out of memory at %s(%u)\n",
 				 __FILE__, __LINE__);
 			return RERR_MALLOC;
 		}
@@ -1130,6 +1245,14 @@
 	 * command line. */
 	if ((ret = copy_argv(argv)) != 0)
 		return ret;
+#ifdef __OS2__
+	{
+		int i;
+		for (i = 0; i < argc; i++) {
+			normalize_dir_slashes(argv[i]);
+		}
+	}
+#endif
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -1453,6 +1576,7 @@
 	 * (implemented by forking "pwd" and reading its output) doesn't
 	 * work when there are other child processes.  Also, on all systems
 	 * that implement getcwd that way "pwd" can't be found after chroot. */
+	// rprintf(FINFO, "* [%s] %s %s(%u)\n", who_am_i(), "(null)", __FILE__, __LINE__);	// 28 Jul 08 SHL debug chdir
 	change_dir(NULL, CD_NORMAL);
 
 	init_flist();
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/options.c ../rsync-3.0.8/options.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/options.c	2011-02-21 11:32:48.000000000 -0800
+++ ../rsync-3.0.8/options.c	2011-04-18 22:11:36.000000000 -0700
@@ -52,6 +52,10 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+// 13 Jun 09 SHL Added
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -115,7 +119,11 @@
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
+#ifndef __OS2__
 int modify_window = 0;
+#else
+int modify_window = 1;			// 28 Jul 09 SHL allow for 2 second resolution
+#endif
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
@@ -261,6 +269,13 @@
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
 	rprintf(f, "Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.\n");
 	rprintf(f, "Web site: http://rsync.samba.org/\n");
+#ifdef __OS2__ // 2009-07-22 SHL
+	rprintf(f, "Built by Steven H. Levine " __DATE__ " " __TIME__ "\n");
+#if 0 // 2010-12-15 SHL Enable if building for Mensys with flist size limited - see util.c MALLOC_MAX
+	rprintf(f, "Built with MALLOC_MAX set to 200MiBytes\n");
+#endif // Mensys MALLOC_MAX
+	rprintf(f, "Built with GCC " __VERSION__ "\n");
+#endif
 	rprintf(f, "Capabilities:\n");
 	rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
 		(int)(sizeof (OFF_T) * 8),
@@ -337,6 +352,9 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+#ifdef __OS2__
+  rprintf(F," -2, --os2-perms             preserve native OS/2 permissions\n");
+#endif
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
 #ifdef SUPPORT_ACLS
@@ -479,6 +497,10 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+#ifdef __OS2__
+  {"os2-perms",       '2', POPT_ARG_NONE,   0, '2', 0, 0 },
+  {"no-os2-perms",     0,  POPT_ARG_VAL,    &os2_perms, 0, 0, 0 },
+#endif
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
@@ -1032,6 +1054,10 @@
 		case OPT_EXCLUDE_FROM:
 		case OPT_INCLUDE_FROM:
 			arg = poptGetOptArg(pc);
+#ifdef __OS2__
+			// 18 Oct 09 SHL
+			normalize_dir_slashes((char *)arg);	// hack cough - override const
+#endif
 			if (sanitize_paths)
 				arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 			if (daemon_filter_list.head) {
@@ -1139,6 +1165,13 @@
 			}
 			break;
 
+// 14 Jun 09 SHL
+#ifdef __OS2__
+		case '2':
+			os2_perms = 1;
+			preserve_perms = 1;	// Implied
+			break;
+#endif
 		case OPT_WRITE_BATCH:
 			/* batch_name is already set */
 			write_batch = 1;
@@ -1474,6 +1507,7 @@
 			char *dir;
 			if (!*backup_dir)
 				goto options_rejected;
+			// 25 Sep 09 SHL fixme slashes
 			dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
 			clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
 			if (check_filter(elp, FLOG, dir, 1) < 0)
@@ -1788,6 +1822,12 @@
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
 		argstr[x++] = 'E';
+// 13 Jun 09 SHL
+#ifdef __OS2__
+	if (os2_perms)
+		argstr[x++] = '2';
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls)
 		argstr[x++] = 'A';
@@ -2108,6 +2148,10 @@
 			break;
 		}
 		if (*s == ':' || *s == '/') {
+#			ifdef __OS2__	// 29 Jun 09 SHL don't confuse drive letter with host spec
+			if (*s == ':' && s == str + 1 && drive_spec_width(s - 1) != 0)
+				continue;
+#			endif
 			if (!hostlen)
 				hostlen = s - host_start;
 			if (*s++ == '/') {
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/params.c ../rsync-3.0.8/params.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/params.c	2007-11-22 09:51:20.000000000 -0800
+++ ../rsync-3.0.8/params.c	2011-04-18 22:11:36.000000000 -0700
@@ -166,9 +166,24 @@
   {
   pos--;
   while( pos >= 0 && isSpace(line + pos) )
-     pos--;
+     pos--;				// Find last non-whitespace
 
+#ifndef __OS2__
   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
+#else
+  // 2010-11-24 SHL handle path specs like c:\ special to avoid
+  // losing \ before it can be mapped to /
+  // Assume parsing value so name and value nul separated
+  if ( pos >= 0) {
+    if (line[pos] != '\\')
+      pos = -1;				// Not continued
+    else if (pos >= 3) {
+      if (*(line + pos - 3) == 0 && drive_spec_width(line + pos - 2) > 0)
+        pos = -1;			// Not continued
+    }
+  }
+  return pos;
+#endif
   } /* Continuation */
 
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.os2 ../rsync-3.0.8/readme.os2
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.os2	2106-02-06 22:28:16.000000000 
+++ ../rsync-3.0.8/readme.os2	2011-04-18 22:11:36.000000000 -0700
@@ -0,0 +1,87 @@
+Rsync v3.0.7 compiled with GCC 4.3.4 & kLibc v0.6.3
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+
+We (Paul and Steven) are using this as both client and server for backups
+
+Changes in this version:
+- Updated to v3.0.6
+- Incorporated a bunch of patches from Steven Levine
+- Move to GCC 4.3.4 as a compiler
+- --xattrs now works for remote servers
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 permissions
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+- Defaulted to %ETC% for rsyncd.conf
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+  Run make install
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Cheers,
+
+Paul Smedley
+Adelaide, Australia
+
+and
+
+Steven Levine
+Costa Mesa, California, USA
+
+09 April 2010
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.shl ../rsync-3.0.8/readme.shl
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/readme.shl	2106-02-06 22:28:16.000000000 
+++ ../rsync-3.0.8/readme.shl	2011-05-23 13:33:36.000000000 -0700
@@ -0,0 +1,109 @@
+
+Rsync v3.0.8 compiled with GCC 4.5.2 & kLibc v0.6.3 by Steven H. Levine
+
+Requires libc063.dll available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
+Requires gcc452.dll available from http://download.smedley.info/gcc452.zip
+
+These are Steven Levine's notes
+See readme.os2 for Paul Smedley's notes
+
+Changes in this version (newest first):
+
+- Updated to rsync v3.0.8 sources
+- Now building with gcc 4.5.2 - requires gcc452.dll
+- --stats -vv now shows memory statistics
+- --relative now works with drive letters
+- added some more alloc failure checks
+- rsync conf now accepts root paths like c:\
+- --stats shows elapsed time
+- Filter pattern matches are now case-insensitive
+- Added logic to ensure directory xattrs updated after libc chmod changes xattrs
+- Started work on supporting testsuite
+- Updated to rsync v3.0.7 sources
+- Migrated existing 3.0.6 patches
+
+Binary builds are available at
+
+  http://mantis.smedley.info/view.php?id=366
+
+Known issues
+
+- Newly created directories do not always get correct libc extended attributes
+  Next rsync run will set the libc extended attributes to the correct values
+
+- --links probably not fully compatible with --os2_perms
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 readonly permissions along
+  with the system, hidden and archive file/directory attributes
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke a some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+
+  Run make install
+
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Have fun,
+
+Steven Levine
+Costa Mesa, California, USA
+
+2011-04-18 SHL
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/receiver.c ../rsync-3.0.8/receiver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/receiver.c	2011-03-26 10:01:36.000000000 -0700
+++ ../rsync-3.0.8/receiver.c	2011-04-18 22:11:40.000000000 -0700
@@ -491,7 +491,7 @@
 				handle_delayed_updates(local_name);
 			send_msg(MSG_DONE, "", 0, 0);
 			continue;
-		}
+		} // NDX_DONE
 
 		if (ndx - cur_flist->ndx_start >= 0)
 			file = cur_flist->files[ndx - cur_flist->ndx_start];
@@ -830,8 +830,8 @@
 			if (inc_recurse)
 				send_msg_int(MSG_NO_SEND, ndx);
 			break;
-		}
-	}
+		} // switch
+	} // while
 	if (make_backups < 0)
 		make_backups = -make_backups;
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.c ../rsync-3.0.8/rsync.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.c	2011-02-22 10:48:12.000000000 -0800
+++ ../rsync-3.0.8/rsync.c	2011-07-02 10:58:18.000000000 -0700
@@ -383,6 +383,8 @@
 	mode_t new_mode = file->mode;
 	int inherit;
 
+	// rprintf(FINFO, "* [%s] set_file_attrs fname %s mode 0%o file %p sxp %p %s(%u)\n", who_am_i(), fname, file->mode, file, sxp, __FILE__, __LINE__); // 23 May 11 SHL debug os2_perms
+
 	if (!sxp) {
 		if (dry_run)
 			return 1;
@@ -503,6 +505,7 @@
 
 #ifdef HAVE_CHMOD
 	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+		// rprintf(FINFO, "* [%s] set_file_attrs fname %s sxp->st.st_mode 0%o new_mode 0%o %s(%u)\n", who_am_i(), fname, sxp->st.st_mode, new_mode, __FILE__, __LINE__); // 27 Apr 09 SHL debug perms
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
@@ -560,8 +563,13 @@
 		    int overwriting_basis)
 {
 	int ret;
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
 	const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
+	// 16 Feb 09 SHL fixme slashes - can we have drive letter here?
+	if (partialptr && drive_spec_width(partialptr))
+		rprintf(FINFO, "* [%s] finish_transfer partialptr %s fname %s fnamecmp %s %s(%u)\n", who_am_i(), partialptr, fname, fnamecmp, __FILE__, __LINE__); // 25 Sep 09 SHL debug slashes
+
 	if (inplace) {
 		if (verbose > 2)
 			rprintf(FINFO, "finishing %s\n", fname);
@@ -585,6 +593,7 @@
 		rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
 	ret = robust_rename(fnametmp, fname, temp_copy_name,
 			    file->mode & INITACCESSPERMS);
+
 	if (ret < 0) {
 		rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
 			ret == -2 ? "copy" : "rename",
@@ -597,6 +606,7 @@
 	}
 	if (ret == 0) {
 		/* The file was moved into place (not copied), so it's done. */
+		// rprintf(FINFO, "* [%s] finish_transfer robust_rename moved file %s(%u)\n", who_am_i(), __FILE__, __LINE__); // 2011-05-23 SHL debug os2_perms
 		return 1;
 	}
 	/* The file was copied, so tweak the perms of the copied file.  If it
@@ -604,6 +614,8 @@
 	fnametmp = temp_copy_name ? temp_copy_name : fname;
 
   do_set_file_attrs:
+	// rprintf(FINFO, "* [%s] finish_transfer before set_file_attrs %s %s(%u)\n", who_am_i(), fnametmp, __FILE__, __LINE__); // 2011-05-23 SHL debug os2_perms
+
 	set_file_attrs(fnametmp, file, NULL, fnamecmp,
 		       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.h ../rsync-3.0.8/rsync.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/rsync.h	2011-02-21 11:32:50.000000000 -0800
+++ ../rsync-3.0.8/rsync.h	2011-04-18 22:11:40.000000000 -0700
@@ -1168,3 +1168,12 @@
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+// 05 Mar 09 SHL support drive letters
+#ifndef __OS2__
+#define drive_spec_width(p) 0
+#define is_abs_path(p) (*(p) == '/')
+#else
+#define drive_spec_width(p) ((isalpha(*(p)) && *((p) + 1) == ':') ? 2 : 0)
+#define is_abs_path(p) (*((p) + drive_spec_width(p)) == '/')
+#endif
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/runtests.sh ../rsync-3.0.8/runtests.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/runtests.sh	2008-05-18 07:00:48.000000000 -0700
+++ ../rsync-3.0.8/runtests.sh	2011-04-18 22:11:40.000000000 -0700
@@ -239,8 +239,8 @@
     $setfacl_nodef "$scratchdir" || true
     chmod g-s "$scratchdir"
     case "$srcdir" in
-    /*) ln -s "$srcdir" "$scratchdir/src" ;;
-    *)  ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
+    /*) echo ln -s "$srcdir" "$scratchdir/src" ;;
+    *)  echo ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
     esac
     return 0
 }
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/sender.c ../rsync-3.0.8/sender.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/sender.c	2009-12-12 17:23:02.000000000 -0800
+++ ../rsync-3.0.8/sender.c	2011-04-18 22:11:40.000000000 -0700
@@ -366,7 +366,7 @@
 		send_msg_int(MSG_IO_ERROR, io_error);
 
 	if (verbose > 2)
-		rprintf(FINFO, "send files finished\n");
+		rprintf(FINFO, "send_files finished\n");	// 06 Mar 09 SHL
 
 	match_report();
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/syscall.c ../rsync-3.0.8/syscall.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/syscall.c	2011-02-21 11:32:50.000000000 -0800
+++ ../rsync-3.0.8/syscall.c	2011-05-25 17:38:54.000000000 -0700
@@ -28,6 +28,24 @@
 #ifdef HAVE_SYS_ATTR_H
 #include <sys/attr.h>
 #endif
+// 06 Mar 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define setmode
+#if defined HAVE_SETMODE && O_BINARY && __OS2__
+// From gcc io.h
+int setmode (int, int);
+// From gcc os2emx.h
+#endif
+#ifdef __OS2__ // 01 Aug 09 SHL
+// 01 Aug 09 SHL libc io.h conflicts with rsync io.h - need to cheat to define _sopen
+int _sopen (__const__ char *, int, int, ...);	// hack cough
+#include "share.h"			// SH_DENYNO
+#endif
+
+#if defined __OS2__
+// 27 Apr 09 SHL Need definitions for FILE_...
+#define INCL_DOS
+// #include <os2.h>
+#include <os2emx.h>
+#endif
 
 extern int dry_run;
 extern int am_root;
@@ -35,6 +53,10 @@
 extern int list_only;
 extern int preserve_perms;
 extern int preserve_executability;
+// 13 Jun 09 SHL
+#ifdef __OS2__
+extern int os2_perms;
+#endif
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -138,12 +160,32 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+#ifdef __OS2__
+	int fd;
+#endif
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
 
+#ifndef __OS2__
 	return open(pathname, flags | O_BINARY, mode);
+#else
+	// 31 Jul 09 SHL if open fails, try shared open in case file already opened for write
+	fd = open(pathname, flags | O_BINARY, mode);
+	if (fd == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
+		fd = _sopen(pathname, flags | O_BINARY, SH_DENYNO, mode);
+		if (fd != -1)
+			rprintf(FINFO, "[%s] opened %s for shared write - file may change during sync\n", who_am_i(), pathname);
+		else if (verbose) {
+			int e = errno;
+			rsyserr(FINFO, errno, "do_open _sopen fallback failed for %s", pathname);
+			errno = e;
+		}
+
+	}
+	return fd;
+#endif
 }
 
 #ifdef HAVE_CHMOD
@@ -152,9 +194,75 @@
 	int code;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+
 #ifdef HAVE_LCHMOD
+#ifndef __OS2__
 	code = lchmod(path, mode & CHMOD_BITS);
 #else
+	{
+		// rprintf(FINFO, "* [%s] do_chmod path %s requested mode 0%o %s(%u)\n", who_am_i(), path, mode, __FILE__, __LINE__);	// 23 May 11 SHL debug os2_perms
+
+		ULONG attributes = 0;
+		if (os2_perms) {
+			mode_t old_mode = mode;	// 2011-05-23 SHL os2_perms debug
+			// Unmap mode to recover native OS/2 attributes
+			// See map_os2_attributes
+			// If not readable by owner, hidden
+			if (~mode & S_IRUSR)
+				attributes |= FILE_HIDDEN;
+			// If readable by group, system
+			if (mode & S_IRGRP)
+				attributes |= FILE_SYSTEM;
+			// If writable by group, archived
+			if (mode & S_IWGRP)
+				attributes |= FILE_ARCHIVED;
+			// Reset group rw bits to match other rw bits - hack cough
+			if (mode & S_IROTH)
+				mode |= S_IRGRP;
+			else
+				mode &= ~S_IRGRP;
+			if (mode & S_IWOTH)
+				mode |= S_IWGRP;
+			else
+				mode &= ~S_IWGRP;
+			// rprintf(FINFO, "* [%s] unmapped %s mode from 0%lo to 0%lo (attributes 0x%lx)\n", who_am_i(), path, (unsigned long)old_mode, (unsigned long)mode, attributes);	// 2011-05-23 SHL os2_perms debug
+		}
+		code = lchmod(path, mode & CHMOD_BITS);
+		if (!code && os2_perms) {
+			// Adjust native attributes not handled by chmod - system, hidden, archived
+			// Maybe libc will do this someday
+			// chmod already handles readonly
+			// Adjust attributes if any but archived set or if archived not set in requested attributes
+			FILESTATUS3 fs3;
+			APIRET apiret = DosQueryPathInfo((PCSZ)path,
+							 FIL_STANDARD,
+							 &fs3,
+							 sizeof(fs3));
+			// 26 Sep 09 SHL fixme perms - set code on failure - need map_apiret_errno()
+			if (apiret)
+				rprintf(FERROR, "[%s] DosQueryPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+			else {
+				ULONG m = attributes | (fs3.attrFile & ~(FILE_SYSTEM | FILE_HIDDEN | FILE_ARCHIVED));
+				if (m != fs3.attrFile) {
+					ULONG old_attrFile = fs3.attrFile;
+					fs3.attrFile = m;
+					apiret = DosSetPathInfo((PCSZ)path,
+								 FIL_STANDARD,
+								 &fs3, sizeof(fs3),
+								 0);
+					if (apiret)
+						rprintf(FERROR, "[%s] DosSetPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 27 Apr 09 SHL
+					else if (verbose > 1)
+						rprintf(FINFO, "[%s] changed %s attrFile from 0x%lx to 0x%lx (attributes 0x%lx)\n", who_am_i(), path, old_attrFile, fs3.attrFile, attributes);	// 21 Jul 09 SHL
+				}
+			}
+		}
+	}
+#endif /* __OS2__ */
+#else  // !HAVE_LCHMOD
+#ifdef __OS2__
+#error __OS2__ patch requires LCHMOD defined
+#endif /* __OS2__ */
 	if (S_ISLNK(mode)) {
 # if defined HAVE_SETATTRLIST
 		struct attrlist attrList;
@@ -165,8 +273,8 @@
 		attrList.commonattr = ATTR_CMN_ACCESSMASK;
 		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
 # else
-		code = 1;
-# endif
+		code = 1;		// Can not set symlink
+# endif // HAVE_SETATTRLIST
 	} else
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
 #endif /* !HAVE_LCHMOD */
@@ -256,12 +364,55 @@
 #endif
 }
 
+#ifdef __OS2__
+
+/**
+ * Map native OS/2 attributes to something rsync can send
+ * See do_chmod for unmap logic
+ */
+
+static void map_os2_attributes(STRUCT_STAT *st)
+{
+	// If hidden, readable by none
+	if (st->st_attr & FILE_HIDDEN)
+		st->st_mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
+	// If readonly, writable by none
+	if (st->st_attr & FILE_READONLY)
+		st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+
+	// Steal group bits for native attributes without obvious mappings - hack cough
+	// If system, readable by group
+	if (st->st_attr & FILE_SYSTEM)
+		st->st_mode |= S_IRGRP;
+	else
+		st->st_mode &= ~S_IRGRP;
+	// If archived, writable by group
+	if (st->st_attr & FILE_ARCHIVED)
+		st->st_mode |= S_IWGRP;
+	else
+		st->st_mode &= ~S_IWGRP;
+}
+
+#endif
+
 int do_stat(const char *fname, STRUCT_STAT *st)
 {
 #ifdef USE_STAT64_FUNCS
 	return stat64(fname, st);
 #else
+#ifndef __OS2__
 	return stat(fname, st);
+#else
+	int code;
+	code = stat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from 0%o to 0%o (st_attr 0%o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
@@ -271,7 +422,19 @@
 # ifdef USE_STAT64_FUNCS
 	return lstat64(fname, st);
 # else
+#ifndef __OS2__
 	return lstat(fname, st);
+#else
+	// 27 Apr 09 SHL map OS/2 permissions
+	int code = lstat(fname, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %s mode from 0%o to 0%o (st_attr 0%o)\n", who_am_i(), fname, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 # endif
 #else
 	return do_stat(fname, st);
@@ -283,7 +446,19 @@
 #ifdef USE_STAT64_FUNCS
 	return fstat64(fd, st);
 #else
+#ifndef __OS2__
 	return fstat(fd, st);
+#else
+	int code;
+	code = fstat(fd, st);
+	if (!code && os2_perms) {
+		mode_t old_mode = st->st_mode;
+		map_os2_attributes(st);
+		if (verbose > 1 && old_mode != st->st_mode)
+			rprintf(FINFO, "[%s] mapped %u mode from 0%o to 0%o (st_attr 0%o)\n", who_am_i(), fd, old_mode, st->st_mode, st->st_attr);	// 21 Jul 09 SHL
+	}
+	return code;
+#endif
 #endif
 }
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/t_stub.c ../rsync-3.0.8/t_stub.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/t_stub.c	2011-02-21 11:32:48.000000000 -0800
+++ ../rsync-3.0.8/t_stub.c	2011-04-18 22:11:40.000000000 -0700
@@ -33,6 +33,12 @@
 char *module_dir;
 struct filter_list_struct daemon_filter_list;
 
+#ifdef __OS2__
+int os2_perms = 0;
+#endif
+int verbose = 0;
+
+
  void rprintf(UNUSED(enum logcode code), const char *format, ...)
 {
 	va_list ap;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/t_unsafe.c ../rsync-3.0.8/t_unsafe.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/t_unsafe.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.8/t_unsafe.c	2011-04-18 22:11:40.000000000 -0700
@@ -27,7 +27,6 @@
 int am_root = 0;
 int read_only = 0;
 int list_only = 0;
-int verbose = 0;
 int preserve_perms = 0;
 int preserve_executability = 0;
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/testsuite/rsync.fns ../rsync-3.0.8/testsuite/rsync.fns
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/testsuite/rsync.fns	2011-03-13 20:48:54.000000000 -0700
+++ ../rsync-3.0.8/testsuite/rsync.fns	2011-04-18 22:11:40.000000000 -0700
@@ -151,7 +151,7 @@
 
     echo $ECHO_N "This file has no trailing lf$ECHO_C" > "$fromdir/nolf"
     umask 0
-    ln -s nolf "$fromdir/nolf-symlink"
+    echo ln -s nolf "$fromdir/nolf-symlink"
     umask 022
 
     cat "$srcdir"/*.c > "$fromdir/text"
@@ -321,10 +321,10 @@
 build_symlinks() {
     mkdir "$fromdir"
     date >"$fromdir/referent"
-    ln -s referent "$fromdir/relative"
-    ln -s "$fromdir/referent" "$fromdir/absolute"
-    ln -s nonexistent "$fromdir/dangling"
-    ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
+    echo ln -s referent "$fromdir/relative"
+    echo ln -s "$fromdir/referent" "$fromdir/absolute"
+    echo ln -s nonexistent "$fromdir/dangling"
+    echo ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
 }
 
 test_fail() {
@@ -347,7 +347,7 @@
 }
 
 # Determine what shell command will appropriately test for links.
-ln -s foo "$scratchdir/testlink"
+echo ln -s foo "$scratchdir/testlink"
 for cmd in test /bin/test /usr/bin/test /usr/ucb/bin/test /usr/ucb/test
 do
     for switch in -h -L
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/util.c ../rsync-3.0.8/util.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/util.c	2011-03-17 11:25:12.000000000 -0700
+++ ../rsync-3.0.8/util.c	2011-05-25 16:59:24.000000000 -0700
@@ -23,6 +23,10 @@
 #include "rsync.h"
 #include "ifuncs.h"
 
+#ifdef __OS2__
+#include <os2emx.h>
+#endif
+
 extern int verbose;
 extern int module_id;
 extern int modify_window;
@@ -201,6 +205,10 @@
 	char *p;
 	int ret = 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width
+	fname += drive_spec_width(fname);		/* Bypass drive letter */
+#endif /* __OS2__ */
+
 	while (*fname == '/')
 		fname++;
 	while (strncmp(fname, "./", 2) == 0)
@@ -430,6 +438,8 @@
 {
 	int tries = 4;
 
+	// rprintf(FINFO, "* [%s] robust_rename %s->%s %s(%u)\n", who_am_i(), from, to, __FILE__, __LINE__); // 2009-04-27 SHL debug os2_perms
+
 	while (tries--) {
 		if (do_rename(from, to) == 0)
 			return 0;
@@ -454,6 +464,27 @@
 				return -2;
 			do_unlink(from);
 			return 1;
+#ifdef __OS2__ // 2009-04-27 SHL
+		// libc rename semantics differs from linux
+		// clear readonly if this caused rename to fail
+		case EACCES:
+		{
+			STRUCT_STAT st;
+			int code;
+			if (verbose)
+				rprintf(FINFO, "[%s] robust_rename retrying %s after EACCES\n", who_am_i(), to);	// 2009-07-22 SHL
+			code = do_stat(to, &st);
+			if (!code) {
+				// 2009-04-27 SHL fixme to use st_mode when libc fixed
+				if (st.st_attr & FILE_READONLY) {
+					st.st_mode |= S_IWUSR;
+					code = do_chmod(to, st.st_mode);
+					if (!code)
+						break;	// Try again
+				}
+			}
+		}
+#endif
 		default:
 			return -1;
 		}
@@ -828,10 +859,18 @@
 {
 	char *limit = name - 1, *t = name, *f = name;
 	int anchored;
+#ifdef __OS2__
+	int drive_letter_adj;	// 0 if not, 2 if yes 2008-12-15 SHL
+#endif
 
 	if (!name)
 		return 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width...
+	drive_letter_adj = drive_spec_width(name);
+	f += drive_letter_adj;			// Keep drive letter
+	t += drive_letter_adj;
+#endif /* __OS2__ */
 	if ((anchored = *f == '/') != 0) {
 		*t++ = *f++;
 #ifdef __CYGWIN__
@@ -879,10 +918,18 @@
 		while (*f && (*t++ = *f++) != '/') {}
 	}
 
+#ifndef __OS2__ // 2009-02-06 SHL
 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 		t--;
 	if (t == name)
 		*t++ = '.';
+#else
+	if (t > name + anchored + drive_letter_adj && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
+		t--;
+	if (t == name + drive_letter_adj)
+		*t++ = '.';		// Ensure not empty
+#endif
+
 	*t = '\0';
 
 	return t - name;
@@ -916,14 +963,28 @@
 	char *start, *sanp;
 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 
+	// rprintf(FINFO, "* [%s] sanitize_path p %s %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
 	if (dest != p) {
 		int plen = strlen(p);
-		if (*p == '/') {
+		int drive_letter_adj = drive_spec_width(p);	// 0 if not, 2 if yes 2008-12-15 SHL
+#ifndef __OS2__
+		if (*p == '/')
+#else // 2009-02-06 SHL use is_abs_path...
+		if (!is_abs_path(p)) {
+			if (drive_letter_adj)
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
+		} else
+#endif
+		{
 			if (!rootdir)
 				rootdir = module_dir;
 			rlen = strlen(rootdir);
 			depth = 0;
+#ifndef __OS2__
 			p++;
+#else
+			p += drive_spec_width(p) + 1;
+#endif
 		}
 		if (dest) {
 			if (rlen + plen + 1 >= MAXPATHLEN)
@@ -932,8 +993,13 @@
 			out_of_memory("sanitize_path");
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
+#ifndef __OS2__
 			if (rlen > 1)
 				dest[rlen++] = '/';
+#else
+			if (rlen > 1 + drive_letter_adj)
+				dest[rlen++] = '/';
+#endif
 		}
 	}
 
@@ -977,6 +1043,20 @@
 		}
 		/* copy one component through next slash */
 		while (*p && (*sanp++ = *p++) != '/') {}
+#if 0 // 2009-05-16 SHL fixme to be gone
+#ifndef __OS2__
+		while (*p && (*sanp++ = *p++) != '/') {}
+#else
+		while(*p) {
+			char c = *p++;
+			if (c == '\\')
+				c = '/';
+			*sanp++ = c;
+			if (c == '/')
+				break;
+		}
+#endif
+#endif
 	}
 	if (sanp == dest) {
 		/* ended up with nothing, so put in "." component */
@@ -984,16 +1064,23 @@
 	}
 	*sanp = '\0';
 
+	// rprintf(FINFO, "* [%s] sanitize_path dest %s %s(%u)\n", who_am_i(), dest, __FILE__, __LINE__); // 2009-02-06 SHL debug
+
+	// 2009-05-16 SHL  fixme to be gone
+	assert_no_dir_slashes(dest);
+
 	return dest;
 }
 
 /* Like chdir(), but it keeps track of the current directory (in the
  * global "curr_dir"), and ensures that the path size doesn't overflow.
- * Also cleans the path using the clean_fname() function. */
+ * Also cleans the path using the clean_fname() function.
+ * Returns 1 of change OK.  Otherwise 0 */
 int change_dir(const char *dir, int set_path_only)
 {
 	static int initialised;
 	unsigned int len;
+	// rprintf(FINFO, "* [%s] change_dir dir %s initialised %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", initialised, __FILE__, __LINE__); // 2009-04-27 SHL debug perms
 
 	if (!initialised) {
 		initialised = 1;
@@ -1002,6 +1089,7 @@
 			exit_cleanup(RERR_FILESELECT);
 		}
 		curr_dir_len = strlen(curr_dir);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 	}
 
 	if (!dir)	/* this call was probably just to initialize */
@@ -1011,23 +1099,49 @@
 	if (len == 1 && *dir == '.')
 		return 1;
 
-	if (*dir == '/') {
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(dir)) {
+		// Absolute path
 		if (len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifndef __OS2__ // 2008-07-28 SHL
 		if (!set_path_only && chdir(dir))
 			return 0;
 		memcpy(curr_dir, dir, len + 1);
+#else
+		if (!set_path_only) {
+			if (chdir(dir)) {
+				rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+			if (drive_spec_width(dir) && _chdrive(*dir)) {
+				rprintf(FERROR, "[%s] change_dir _chdrive failed for dir %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+		}
+		memcpy(curr_dir, dir, len + 1);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
+#endif
 	} else {
+		// Relative path
 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifdef __OS2__
+		if (drive_spec_width(dir)) {
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			errno = EINVAL;
+			return -1;
+		}
+#endif
 		curr_dir[curr_dir_len] = '/';
 		memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
 
 		if (!set_path_only && chdir(curr_dir)) {
+			rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
 			curr_dir[curr_dir_len] = '\0';
 			return 0;
 		}
@@ -1052,12 +1166,15 @@
 {
 	unsigned int len;
 
-	if (*path != '/') { /* Make path absolute. */
+	// 2009-03-06 SHL use is_abs_path
+	if (!is_abs_path(path)) { /* Make path absolute. */
 		int len = strlen(path);
+		if (drive_spec_width(path))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2008-07-28 SHL
 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
-		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
+		memcpy(curr_dir + curr_dir_len + 1, path + drive_spec_width(path), len + 1);
 		if (!(path = strdup(curr_dir)))
 			out_of_memory("normalize_path");
 		curr_dir[curr_dir_len] = '\0';
@@ -1066,7 +1183,9 @@
 			out_of_memory("normalize_path");
 	}
 
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 	len = clean_fname(path, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 
 	if (len_ptr)
 		*len_ptr = len;
@@ -1088,9 +1207,14 @@
 	if (result)
 		free(result);
 
-	if (*fn == '/')
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(fn))
 		p1 = p2 = "";
 	else {
+#ifdef __OS2__
+		if (drive_spec_width(fn))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-02-06 SHL
+#endif
 		p1 = curr_dir + module_dirlen;
 		for (p2 = p1; *p2 == '/'; p2++) {}
 		if (*p2)
@@ -1119,6 +1243,9 @@
 
 	if ((fn = strrchr(fname, '/')) != NULL) {
 		fn++;
+		// 2009-09-25 SHL fixme slashes - handle drive letter if needed
+		if (partial_dir && drive_spec_width(partial_dir))
+			rprintf(FINFO, "* [%s] partial_dir_fname partial_dir %s fname %s %s(%u)\n", who_am_i(), partial_dir, fname, __FILE__, __LINE__); // 2009-09-25 SHL debug slashes
 		if (*partial_dir != '/') {
 			int len = fn - fname;
 			strncpy(t, fname, len); /* safe */
@@ -1150,6 +1277,7 @@
 
 	if (fname != partial_fname)
 		return 1;
+	// 2009-09-25 SHL fixme slashes?
 	if (!create && *partial_dir == '/')
 		return 1;
 	if (!(fn = strrchr(partial_fname, '/')))
@@ -1420,19 +1548,29 @@
 }
 #endif
 
-#define MALLOC_MAX 0x40000000
+
+#if 0 // 2010-12-15 SHL Enable if building for Mensys with flist size limited - see util.c MALLOC_MAX
+#define MALLOC_MAX (200 * 1024 * 1024)	// MiBytes - Mensys, lower limit is NORMAL_EXTENT (256KiBytes)
+#else
+#define MALLOC_MAX 0x40000000		// 1GiByte
+#endif
+
 
 void *_new_array(unsigned long num, unsigned int size, int use_calloc)
 {
-	if (num >= MALLOC_MAX/size)
+	if (num >= MALLOC_MAX/size) {
+	        rprintf(FERROR, "* [%s] _new_array num %lu size %u failed %s(%u)\n", who_am_i(), num, size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		return NULL;
+	}
 	return use_calloc ? calloc(num, size) : malloc(num * size);
 }
 
 void *_realloc_array(void *ptr, unsigned int size, size_t num)
 {
-	if (num >= MALLOC_MAX/size)
+	if (num >= MALLOC_MAX/size) {
+	        rprintf(FERROR, "* [%s] _realloc_array num %lu size %u failed %s(%u)\n", who_am_i(), (unsigned long)num, size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		return NULL;
+	}
 	if (!ptr)
 		return malloc(size * num);
 	return realloc(ptr, size * num);
@@ -1700,3 +1838,24 @@
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+#ifdef __OS2__ // 2009-05-16 SHL
+/**
+ * Convert OS/2 backslashes to unix forward slashes
+ */
+void normalize_dir_slashes(char *path)
+{
+	// 2010-11-24 SHL rework for more speed
+	if (path) {
+		char *p = path;
+		while((p = strchr(p, '\\')) != NULL)
+			*p++ = '/';
+	}
+}
+
+void assert_no_dir_slashes(char *path)
+{
+	if (path && strchr(path, '\\') != 0)
+		rprintf(FERROR, "[%s] unexpected backslash in path %s %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2009-02-06 SHL
+}
+#endif // __OS2__
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl' -x.saved -x0diff -x0preserve_perms-2011-05-23 -x0shl -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.8/xattrs.c ../rsync-3.0.8/xattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.8/xattrs.c	2011-02-21 11:32:50.000000000 -0800
+++ ../rsync-3.0.8/xattrs.c	2011-04-18 22:11:40.000000000 -0700
@@ -113,6 +113,8 @@
 {
 	const rsync_xa *xa1 = x1;
 	const rsync_xa *xa2 = x2;
+	// rprintf(FINFO, "* [%s] rsync_xal_compare_names xa1.name %s xa2.name %s %s(%u)\n", who_am_i(), xa1->name, xa2->name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
 	return strcmp(xa1->name, xa2->name);
 }
 
@@ -144,7 +146,9 @@
 				full_fname(fname), arg);
 			return -1;
 		}
+		/* Expand buffer - get size */
 		list_len = sys_llistxattr(fname, NULL, 0);
+		/* Should not occur */
 		if (list_len < 0) {
 			arg = 0;
 			goto got_error;
@@ -243,9 +247,11 @@
 			 || (am_root < 0
 			  && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
 			   || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
-			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
+			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) {
+				// rprintf(FINFO, "* [%s] rsync_xal_get skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 				continue;
 		}
+		}
 
 		datum_len = name_len; /* Pass extra size to get_xattr_data() */
 		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -306,10 +312,12 @@
 			return 0;
 	}
 
+	// rprintf(FINFO, "* [%s] get_xattr fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 	if (rsync_xal_get(fname, sxp->xattr) < 0) {
 		free_xattr(sxp);
 		return -1;
 	}
+	// rprintf(FINFO, "* [%s] get_xattr count %d %s(%u)\n", who_am_i(), sxp->xattr ? sxp->xattr->count : -1, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
 	return 0;
 }
 
@@ -482,11 +490,13 @@
 	snd_rxa = lst->items;
 	snd_cnt = lst->count;
 
+	// rprintf(FINFO, "* [%s] xattr_diff fname %s rec_cnt %u snd_cnt %u find_all %u %s(%u)\n", who_am_i(), file->basename, rec_cnt, snd_cnt, find_all, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
+
 	/* 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) {
 		if (!find_all)
-			return 1;
+			return 1;	// Say different
 		xattrs_equal = 0;
 	}
 
@@ -508,7 +518,7 @@
 		}
 		if (!same) {
 			if (!find_all)
-				return 1;
+				return 1;	// Say different
 			xattrs_equal = 0;
 		}
 
@@ -525,6 +535,8 @@
 	if (rec_cnt)
 		xattrs_equal = 0;
 
+	// rprintf(FINFO, "* [%s] xattr_diff xattrs_equal %u %s(%u)\n", who_am_i(), xattrs_equal, __FILE__, __LINE__); // 04 Oct 09 SHL debug xattrs
+
 	return !xattrs_equal;
 }
 
@@ -675,6 +687,8 @@
 		temp_xattr.count = 0;
 	}
 
+	// rprintf(FINFO, "* [%s] receive_xattr %s read count %u am_root %u %s(%u)\n", who_am_i(), file->basename, count, am_root, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
 	for (num = 1; num <= count; num++) {
 		char *ptr, *name;
 		rsync_xa *rxa;
@@ -721,12 +735,14 @@
 			memcpy(name, RSYNC_PREFIX, RPRE_LEN);
 		} else {
 			free(ptr);
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 			continue;
 		}
 #endif
 		/* No rsync.%FOO attributes are copied w/o 2 -X options. */
 		if (preserve_xattrs < 2 && name_len > RPRE_LEN
 		 && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 			free(ptr);
 			continue;
 		}
@@ -738,13 +754,17 @@
 		rxa->num = num;
 	}
 
-	if (need_sort && count > 1)
-		qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
+	// rprintf(FINFO, "* [%s] receive_xattr temp_xattr.items %p temp_xattr.count %u %s(%u)\n", who_am_i(), temp_xattr.items, temp_xattr.count, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
+
+	// 28 Jul 08 SHL sort number used not number malloced
+	if (need_sort && temp_xattr.count > 1)
+		qsort(temp_xattr.items, temp_xattr.count, sizeof (rsync_xa), rsync_xal_compare_names);
 
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
 
 	F_XATTR(file) = ndx;
+	// rprintf(FINFO, "* [%s] receive_xattr %s ndx %u count %d %s(%u)\n", who_am_i(), file->basename, ndx, rsync_xal_l.count, __FILE__, __LINE__); // 28 Jul 08 SHL debug xattrs
 }
 
 /* Turn the xattr data in stat_x into cached xattr data, setting the index
@@ -793,6 +813,7 @@
 	size_t name_len;
 	int ret = 0;
 
+	// rprintf(FINFO, "* [%s] rsync_xal_set fname %s fnamecmp %s %s(%u)\n", who_am_i(), fname, fnamecmp, __FILE__, __LINE__); // 23 Mar 10 SHL debug libc chmod xattrs
 	/* This puts the current name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(fname)) < 0)
 		return -1;

Steven Levine

2011-12-31 16:02

manager   ~0002097

rsync-3.0.8-20111230-shl.* is a quick build to add some additional xattr error reporting.

Steven Levine

2012-12-23 04:17

manager  

rsync-3.0.9-20121221-shl.zip (341,680 bytes)

Steven Levine

2012-12-23 04:18

manager  

rsync-3.0.9-20121221-shl.diff (124,075 bytes)
Generated by diffux -N -xproto.h -xrounding.h on 12-21-12 10:43:30

diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/access.c ../rsync-3.0.9/access.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/access.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.9/access.c	2012-02-29 12:07:16.000000000 -0800
@@ -100,7 +100,9 @@
 	hints.ai_flags = AI_NUMERICHOST;
 #endif
 
-	if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	// if (getaddrinfo(addr, NULL, &hints, &resa) != 0) {
+	if ((gai = getaddrinfo(addr, NULL, &hints, &resa)) != 0) {			// 2008-07-27 SHL debug
+		// rprintf(FINFO, "* [%s] match_address gai %d %s(%u)\n", who_am_i(), gai, __FILE__, __LINE__);	// 2008-07-28 SHL debug addrinfo
 		if (p)
 			*p = '/';
 		return 0;
@@ -110,8 +112,8 @@
 	if (p)
 		*p++ = '/';
 	if (gai != 0) {
-		rprintf(FLOG, "error matching address %s: %s\n",
-			tok, gai_strerror(gai));
+		rprintf(FLOG, "* error matching address %s: %s (%d)\n",
+			tok, gai_strerror(gai), gai);
 		freeaddrinfo(resa);
 		return 0;
 	}
@@ -222,7 +224,11 @@
 	if (host)
 		strlower(host);
 
+	// rprintf(FINFO, "* [%s] access_match %s (%s) %s(%u)\n", who_am_i(), host, addr, __FILE__, __LINE__);	// 2008-07-28 SHL debug access
+
 	for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
+
+		// rprintf(FINFO, "* [%s] access_match tok %s %s(%u)\n", who_am_i(), tok, __FILE__, __LINE__);	// 2008-07-28 SHL debug access
 		if (match_hostname(host, tok) || match_address(addr, tok)) {
 			free(list2);
 			return 1;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/authenticate.c ../rsync-3.0.9/authenticate.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/authenticate.c	2011-09-10 13:38:16.000000000 -0700
+++ ../rsync-3.0.9/authenticate.c	2012-02-29 12:07:08.000000000 -0800
@@ -96,7 +96,9 @@
 	if (do_stat(fname, &st) == -1) {
 		rsyserr(FLOG, errno, "stat(%s)", fname);
 		ok = 0;
-	} else if (lp_strict_modes(module)) {
+	}
+#ifndef __OS2__	 /* 2009-06-29 SHL suppress unsupported mode checks */
+	else if (lp_strict_modes(module)) {
 		if ((st.st_mode & 06) != 0) {
 			rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
 			ok = 0;
@@ -105,6 +107,7 @@
 			ok = 0;
 		}
 	}
+#endif /* __OS2__ */
 	if (!ok) {
 		rprintf(FLOG, "continuing without secrets file\n");
 		close(fd);
@@ -170,6 +173,7 @@
 		rsyserr(FERROR, errno, "stat(%s)", filename);
 		exit_cleanup(RERR_SYNTAX);
 	}
+#ifndef __OS2__	 /* 2008-06-12 SHL suppress unsupported mode checks */
 	if ((st.st_mode & 06) != 0) {
 		rprintf(FERROR, "ERROR: password file must not be other-accessible\n");
 		exit_cleanup(RERR_SYNTAX);
@@ -178,6 +182,7 @@
 		rprintf(FERROR, "ERROR: password file must be owned by root when running as root\n");
 		exit_cleanup(RERR_SYNTAX);
 	}
+#endif /* __OS2__ */
 
 	n = read(fd, buffer, sizeof buffer - 1);
 	close(fd);
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/clientname.c ../rsync-3.0.9/clientname.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/clientname.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.9/clientname.c	2012-02-29 12:07:04.000000000 -0800
@@ -95,8 +95,10 @@
 	struct sockaddr_storage ss;
 	socklen_t ss_len;
 
-	if (initialised)
+	if (initialised) {
+		// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 2008-07-28 SHL debug
 		return name_buf;
+	}
 
 	strlcpy(name_buf, default_name, sizeof name_buf);
 	initialised = 1;
@@ -148,6 +150,8 @@
 			port_buf, sizeof port_buf) == 0)
 		check_name(fd, &ss, name_buf, sizeof name_buf);
 
+	// rprintf(FINFO, "* [%s] client_name %s %s(%u)\n", who_am_i(), name_buf, __FILE__, __LINE__);	// 2008-07-28 SHL debug
+
 	return name_buf;
 }
 
@@ -216,14 +220,17 @@
 	int name_err;
 
 	/* reverse lookup */
+	// rprintf(FINFO, "* [%s] lookup_name %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 2008-07-28 SHL debug
 	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
 			       name_buf, name_buf_size,
 			       port_buf, port_buf_size,
 			       NI_NAMEREQD | NI_NUMERICSERV);
 	if (name_err != 0) {
 		strlcpy(name_buf, default_name, name_buf_size);
-		rprintf(FLOG, "name lookup failed for %s: %s\n",
-			client_addr(fd), gai_strerror(name_err));
+		// rprintf(FINFO, "name lookup failed for %s: %s\n",
+		//	client_addr(fd), gai_strerror(name_err));
+		rprintf(FLOG, "lookup_name failed for %s: %s (%d) at %s(%u) [%s]\n",	// 2008-07-27 SHL debug
+			client_addr(fd), gai_strerror(name_err), name_err, __FILE__, __LINE__, who_am_i());	// 2008-07-28 SHL
 		return name_err;
 	}
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/clientserver.c ../rsync-3.0.9/clientserver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/clientserver.c	2011-07-16 16:14:50.000000000 -0700
+++ ../rsync-3.0.9/clientserver.c	2012-02-29 10:45:32.000000000 -0800
@@ -429,6 +429,8 @@
 	iconv_opt = NULL;
 #endif
 
+	if (verbose)
+		rprintf(FINFO, "[%s] rsync_module addr:host is %s:%s\n", who_am_i(), addr, host);	// 2008-07-28 SHL
 	if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
 		rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
 			name, host, addr);
@@ -442,6 +444,14 @@
 		return -1;
 	}
 
+// 2010-09-17 SHL libc does not do well with chroot c:/ etc.
+#ifdef __OS2__
+	if (use_chroot) {
+		io_printf(f_out, "@ERROR: use chroot not supported\n");
+		return -1;
+	}
+#endif
+
 	if (am_daemon && am_server) {
 		rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",
 			name, host, addr);
@@ -482,6 +492,7 @@
 
 	am_root = (MY_UID() == 0);
 
+#ifndef __OS2__
 	if (am_root) {
 		p = lp_uid(i);
 		if (!name_to_uid(p, &uid)) {
@@ -504,6 +515,7 @@
 		}
 	}
 
+#endif
 	/* TODO: If we're not root, but the configuration requests
 	 * that we change to some uid other than the current one, then
 	 * log a warning. */
@@ -512,6 +524,9 @@
 	 * supplementary groups. */
 
 	module_dir = lp_path(i);
+ 
+ 	// fprintf(stderr, "* [%s] module_dir %s %s(%u)\n", who_am_i(), module_dir, __FILE__, __LINE__); // 2010-09-16 SHL debug
+ 
 	if (*module_dir == '\0') {
 		rprintf(FLOG, "No path specified for module %s\n", name);
 		io_printf(f_out, "@ERROR: no path setting.\n");
@@ -541,6 +556,8 @@
 		full_module_path = module_dir = module_chdir;
 	}
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug path
+
 	if (module_dirlen == 1) {
 		module_dirlen = 0;
 		set_filter_dir("/", 1);
@@ -664,6 +681,8 @@
 	}
 #endif
 
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
 	if (use_chroot) {
 		/*
 		 * XXX: The 'use chroot' flag is a fairly reliable
@@ -685,8 +704,13 @@
 		module_chdir = module_dir;
 	}
 
-	if (!change_dir(module_chdir, CD_NORMAL))
+	// fprintf(stderr, "* [%s] module_chdir %s %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2010-09-16 SHL debug module path
+
+	if (!change_dir(module_chdir, CD_NORMAL)) {
+		// rsyserr(FERROR, errno, "[%s] chdir %s failed at %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2008-12-15 SHL debug
+		// rprintf(FINFO, "* [%s] chdir module_chdir %s failed %s(%u)\n", who_am_i(), module_chdir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 		return path_failure(f_out, module_chdir, True);
+	}
 	if (module_dirlen || !use_chroot)
 		sanitize_paths = 1;
 
@@ -1001,6 +1025,7 @@
 	close(fd);
 }
 
+#ifndef __OS2__
 /* Become a daemon, discarding the controlling terminal. */
 static void become_daemon(void)
 {
@@ -1034,6 +1059,7 @@
 		open("/dev/null", O_RDWR);
 	}
 }
+#endif // __OS2__
 
 int daemon_main(void)
 {
@@ -1056,10 +1082,14 @@
 		exit_cleanup(RERR_SYNTAX);
 	}
 
+#ifndef __OS2__
 	if (no_detach)
 		create_pid_file();
 	else
 		become_daemon();
+#else
+	create_pid_file();
+#endif
 
 	if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
 		rsync_port = RSYNC_PORT;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/compat.c ../rsync-3.0.9/compat.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/compat.c	2011-02-21 11:32:48.000000000 -0800
+++ ../rsync-3.0.9/compat.c	2012-12-20 19:25:08.000000000 -0800
@@ -44,6 +44,9 @@
 extern int prune_empty_dirs;
 extern int protocol_version;
 extern int protect_args;
+#ifdef __OS2__
+extern int preserve_os2_perms;
+#endif
 extern int preserve_uid;
 extern int preserve_gid;
 extern int preserve_acls;
@@ -65,6 +68,10 @@
 /* These index values are for the file-list's extra-attribute array. */
 int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
 
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms rework
+int os2_perms_ndx;
+#endif
+
 int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
 int sender_symlink_iconv = 0;	/* sender should convert symlink content */
 
@@ -144,6 +151,10 @@
 		acls_ndx = ++file_extra_cnt;
 	if (preserve_xattrs)
 		xattrs_ndx = ++file_extra_cnt;
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms perms
+	if (preserve_os2_perms)
+		os2_perms_ndx = ++file_extra_cnt;
+#endif
 
 	if (am_server)
 		set_allow_inc_recurse();
@@ -151,11 +162,19 @@
 	if (remote_protocol == 0) {
 		if (am_server && !local_server)
 			check_sub_protocol();
+#ifdef __OS2__ // 2012-12-20 SHL os2_perms rework
+	// Require protocol version 31 or better if using preserving os2_perms
+	// wire protocol changes incompatible with older rsync builds
+	// Otherwise clain to be protocol 30
+	// FIXME to be gone when 31 arrives for real
+	if (!preserve_os2_perms && protocol_version == 31)
+		protocol_version = 30;
+#endif
 		if (!read_batch)
 			write_int(f_out, protocol_version);
 		remote_protocol = read_int(f_in);
 		if (protocol_version > remote_protocol)
-			protocol_version = remote_protocol;
+			protocol_version = remote_protocol;	// Run at remote's protocol
 	}
 	if (read_batch && remote_protocol > protocol_version) {
 		rprintf(FERROR, "The protocol version in the batch file is too new (%d > %d).\n",
@@ -187,6 +206,15 @@
 			PROTOCOL_VERSION, am_server? "Server" : "Client");
 		exit_cleanup(RERR_PROTOCOL);
 	}
+#ifdef __OS2__ // 2012-12-20 SHL os2_perms rework
+	// Require protocol version 31 or better if using preserving os2_perms
+	// wire protocol changes incompatible with older rsync builds
+	if (preserve_os2_perms && protocol_version <= 30) {
+		rprintf(FERROR, "--protocol must be at least 31 on the %s.\n",
+			am_server? "Server" : "Client");
+		exit_cleanup(RERR_PROTOCOL);
+	}
+#endif
 	if (read_batch)
 		check_batch_flags();
 
@@ -201,11 +229,12 @@
 			exit_cleanup(RERR_PROTOCOL);
 		}
 		if (preserve_xattrs && !local_server) {
-			rprintf(FERROR,
-			    "--xattrs requires protocol 30 or higher"
+		  	preserve_xattrs = 0;	// 2009-02-06 SHL force off for old servers
+			rprintf(FWARNING,
+			    "--xattrs requires protocol 30 or higher - option disabled"
 			    " (negotiated %d).\n",
 			    protocol_version);
-			exit_cleanup(RERR_PROTOCOL);
+			// exit_cleanup(RERR_PROTOCOL);	// 2009-02-06 SHL
 		}
 	}
 
@@ -296,6 +325,7 @@
 	if (need_unsorted_flist && (!am_sender || inc_recurse))
 		unsort_ndx = ++file_extra_cnt;
 
+	// 2009-02-16 SHL fixme slashes?
 	if (partial_dir && *partial_dir != '/' && (!am_server || local_server)) {
 		int flags = MATCHFLG_NO_PREFIXES | MATCHFLG_DIRECTORY;
 		if (!am_sender || protocol_version >= 30)
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/configure.sh ../rsync-3.0.9/configure.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/configure.sh	2011-09-23 09:41:30.000000000 -0700
+++ ../rsync-3.0.9/configure.sh	2012-02-29 12:09:52.000000000 -0800
@@ -71,6 +71,8 @@
   as_echo='sh -c $as_echo_body as_echo'
 fi
 
+# 2009-06-18 SHL fixme to not be broken - 3.0.5 worked - maybe autoconf 2.6.3 broke it
+
 # The user is always right.
 if test "${PATH_SEPARATOR+set}" != set; then
   PATH_SEPARATOR=:
@@ -8440,6 +8442,15 @@
 $as_echo "#define NO_SYMLINK_XATTRS 1" >>confdefs.h
 
 	;;
+    *os2*)
+	{ echo "$as_me:$LINENO: result: Using OS/2 extattrs" >&5
+echo "${ECHO_T}Using OS/2 extattrs" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_XATTRS 1
+_ACEOF
+
+	;;
+
     *)
 	if test x"$enable_xattr_support" = x"yes"; then
 	    as_fn_error $? "Failed to find extended attribute support" "$LINENO" 5
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/exclude.c ../rsync-3.0.9/exclude.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/exclude.c	2011-09-15 07:48:30.000000000 -0700
+++ ../rsync-3.0.9/exclude.c	2012-02-29 12:06:50.000000000 -0800
@@ -298,7 +298,7 @@
 	unsigned int fn_len;
 
 	if (!parent_dirscan && *merge_file != '/') {
-		/* Return the name unchanged it doesn't have any slashes. */
+		/* Return the name unchanged if it doesn't have any slashes. */
 		if (len_ptr) {
 			const char *p = merge_file + *len_ptr;
 			while (--p > merge_file && *p != '/') {}
@@ -310,6 +310,7 @@
 			return (char *)merge_file;
 	}
 
+	// 2009-02-16 SHL fixme slash
 	fn = *merge_file == '/' ? buf : tmpbuf;
 	if (sanitize_paths) {
 		const char *r = prefix_skip ? "/" : NULL;
@@ -351,6 +352,7 @@
 void set_filter_dir(const char *dir, unsigned int dirlen)
 {
 	unsigned int len;
+	// 2009-02-16 SHL fixme slash?
 	if (*dir != '/') {
 		memcpy(dirbuf, curr_dir, curr_dir_len);
 		dirbuf[curr_dir_len] = '/';
@@ -548,6 +550,7 @@
 	int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
 	char *p, *pattern = ex->pattern;
 	const char *strings[16]; /* more than enough */
+	// 2009-02-16 SHL fixme slash?
 	const char *name = fname + (*fname == '/');
 
 	if (!*name)
@@ -605,13 +608,16 @@
 		if (litmatch_array(pattern, strings, slash_handling))
 			return ret_match;
 	} else if (anchored_match) {
-		if (strcmp(name, pattern) == 0)
+		// 2012-01-03 SHL Support case insensitive file systems
+		if (strcmp_fs(name, pattern) == 0)
 			return ret_match;
+
 	} else {
 		int l1 = strlen(name);
 		int l2 = strlen(pattern);
+		// 2012-01-03 SHL support case-insensitive file systems
 		if (l2 <= l1 &&
-		    strcmp(name+(l1-l2),pattern) == 0 &&
+		    strcmp_fs(name+(l1-l2),pattern) == 0 &&
 		    (l1==l2 || name[l1-(l2+1)] == '/')) {
 			return ret_match;
 		}
@@ -984,6 +990,25 @@
 				cp = ".cvsignore";
 				pat_len = 10;
 			}
+#ifdef __OS2__
+			else {
+				// 2009-10-19 SHL normalize
+				// 2010-09-30 SHL avoid writing to const memory
+				/* If we are passed paths from the filter they
+				   might have DOS slashes, convert to Unix slashes
+				   except for the 1st characters (fixme to doc why - I forgot)
+				   If we are processing a const string, it will already
+				   have Unix slashes so don't try to write to const memory
+				*/
+				char ch;
+				p = cp + pat_len;	// Must be non-const for gcc
+				ch = *p;		// Remember 1st character - fixme to say why
+				normalize_dir_slashes((char *)cp);	// Hack cough - override const
+				if (*p != ch)
+					*(char*)p = ch;	// Ensure leading char not changed - fixme to say why
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len, cp, strlen(cp) == pat_len, __FILE__, __LINE__);	// 2009-10-19 SHL fixme filter files
+			}
+#endif
 			len = pat_len;
 			if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
 				const char *name = cp + len;
@@ -994,6 +1019,8 @@
 				len = pat_len;
 			}
 			if (new_mflags & MATCHFLG_PERDIR_MERGE) {
+				// 2009-10-19 SHL fixme to complain if have drive letter?
+				// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 2009-10-19 SHL fixme filter files
 				if (parent_dirscan) {
 					if (!(p = parse_merge_name(cp, &len,
 								module_dirlen)))
@@ -1010,6 +1037,7 @@
 			}
 		}
 
+		// rprintf(FINFO, "* [%s] parse_rule %.*s nul? %u %s(%u)\n", who_am_i(), pat_len ? pat_len : 6, pat_len ? cp : "(null)", strlen(cp) == pat_len, __FILE__, __LINE__);	// 2009-10-19 SHL fixme filter files
 		add_rule(listp, cp, pat_len, new_mflags, xflags);
 
 		if (new_mflags & MATCHFLG_CVS_IGNORE
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/flist.c ../rsync-3.0.9/flist.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/flist.c	2011-08-27 14:58:04.000000000 -0700
+++ ../rsync-3.0.9/flist.c	2012-12-20 12:11:38.000000000 -0800
@@ -43,6 +43,9 @@
 extern int filesfrom_fd;
 extern int one_file_system;
 extern int copy_dirlinks;
+#ifdef __OS2__
+extern int preserve_os2_perms;	// 2012-12-20 SHL os2_perms rework
+#endif
 extern int preserve_uid;
 extern int preserve_gid;
 extern int preserve_acls;
@@ -347,8 +350,19 @@
 {
 	if (dirlen < 0) {
 		char *cpy = strdup(dir);
+#ifndef __OS2__ // 2009-03-06 SHL use is_abs_path...
 		if (*cpy != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (!is_abs_path(cpy)) {
+			if (drive_spec_width(cpy))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), cpy, __FILE__, __LINE__);	// 2009-02-06 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+	        }
+#endif
 		if (path_is_daemon_excluded(cpy, 0))
 			goto chdir_error;
 		dir = cpy;
@@ -362,8 +376,19 @@
 				dirlen = strlen(dir);
 		} else if (pathname == dir)
 			return 1;
+#ifndef __OS2__ // 2009-03-06 SHL use is_abs_path...
 		if (dir && *dir != '/')
 			change_dir(orig_dir, CD_SKIP_CHDIR);
+#else
+		if (dir && !is_abs_path(dir)) {
+			if (drive_spec_width(dir))
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			if (!change_dir(orig_dir, CD_SKIP_CHDIR)) {
+				if (verbose > 1)
+					rprintf(FINFO, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+		}
+#endif
 	}
 
 	pathname = dir;
@@ -376,8 +401,13 @@
 	  chdir_error:
 		io_error |= IOERR_GENERAL;
 		rsyserr(FERROR_XFER, errno, "change_dir %s failed", full_fname(dir));
-		if (dir != orig_dir)
-			change_dir(orig_dir, CD_NORMAL);
+		rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-07-21 SHL
+		if (dir != orig_dir) {
+			if (!change_dir(orig_dir, CD_NORMAL)) {
+				if (verbose > 1)
+					rprintf(FLOG, "[%s] changed to %s\n", who_am_i(), orig_dir);	// 2009-07-21 SHL
+			}
+		}
 		pathname = NULL;
 		pathname_len = 0;
 		return 0;
@@ -394,6 +424,9 @@
 {
 	static time_t modtime;
 	static mode_t mode;
+#if __OS2__ // 2012-12-19 SHL os2_perms rework
+	static uint32 os2_perms;
+#endif
 #ifdef SUPPORT_HARD_LINKS
 	static int64 dev;
 #endif
@@ -424,6 +457,14 @@
 	else
 		mode = file->mode;
 
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms rework
+	if (preserve_os2_perms) {
+		if (F_OS2_PERMS(file) == (int32)os2_perms)
+			xflags |= XMIT_SAME_OS2_PERMS;
+		else
+			os2_perms = F_OS2_PERMS(file);
+	}
+#endif
 	if (preserve_devices && IS_DEVICE(mode)) {
 		if (protocol_version < 28) {
 			if (tmp_rdev == rdev)
@@ -547,6 +588,10 @@
 	}
 	if (!(xflags & XMIT_SAME_MODE))
 		write_int(f, to_wire_mode(mode));
+#if __OS2__ // 2012-12-19 SHL os2_perms rework
+	if (preserve_os2_perms && !(xflags & XMIT_SAME_OS2_PERMS))
+		write_int(f, os2_perms);
+#endif
 	if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
 		if (protocol_version < 30)
 			write_int(f, uid);
@@ -634,6 +679,9 @@
 {
 	static int64 modtime;
 	static mode_t mode;
+#if __OS2__ // 2012-12-19 SHL os2_perms rework
+	static uint32 os2_perms;
+#endif
 #ifdef SUPPORT_HARD_LINKS
 	static int64 dev;
 #endif
@@ -769,6 +817,11 @@
 	if (chmod_modes && !S_ISLNK(mode))
 		mode = tweak_mode(mode, chmod_modes);
 
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms rework
+	if (preserve_os2_perms && !(xflags & XMIT_SAME_OS2_PERMS))
+		os2_perms = read_int(f);
+#endif
+
 	if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
 		if (protocol_version < 30)
 			uid = (uid_t)read_int(f);
@@ -918,6 +971,10 @@
 	if (unsort_ndx)
 		F_NDX(file) = flist->used + flist->ndx_start;
 
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms rework
+	if (preserve_os2_perms)
+		F_OS2_PERMS(file) = os2_perms;
+#endif
 	if (basename != thisname) {
 		file->dirname = lastdir;
 		F_DEPTH(file) = lastdir_depth + 1;
@@ -1283,6 +1340,10 @@
 	}
 #endif
 	file->mode = st.st_mode;
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms rework
+	if (preserve_os2_perms)
+		F_OS2_PERMS(file) = st.st_attr;
+#endif
 	if (preserve_uid)
 		F_OWNER(file) = st.st_uid;
 	if (preserve_gid)
@@ -1330,6 +1391,8 @@
 {
 	struct file_struct *file;
 
+	// rprintf(FINFO, "* [%s] send_file_name fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+
 	file = make_file(fname, flist, stp, flags, filter_level);
 	if (!file)
 		return NULL;
@@ -1976,6 +2039,7 @@
 	int len, dirlen;
 	STRUCT_STAT st;
 	char *p, *dir;
+	static char* the_root = "/";
 	struct file_list *flist;
 	struct timeval start_tv, end_tv;
 	int64 start_write;
@@ -2019,6 +2083,7 @@
 		if (argv[0] && !change_dir(argv[0], CD_NORMAL)) {
 			rsyserr(FERROR_XFER, errno, "change_dir %s failed",
 				full_fname(argv[0]));
+			rprintf(FERROR_XFER, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), argv[0], __FILE__, __LINE__);	// 2009-07-21 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 		use_ff_fd = 1;
@@ -2038,19 +2103,25 @@
 			if (argc-- == 0)
 				break;
 			strlcpy(fbuf, *argv++, MAXPATHLEN);
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2010-09-16 SHL debug paths
 			if (sanitize_paths)
 				sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2010-09-16 SHL debug paths
+
 		len = strlen(fbuf);
 		if (relative_paths) {
 			/* We clean up fbuf below. */
 			name_type = NORMAL_NAME;
 		} else if (!len || fbuf[len - 1] == '/') {
-			if (len == 2 && fbuf[0] == '.') {
-				/* Turn "./" into just "." rather than "./." */
+			/* Empty path or trailing / */
+			// 2009-03-06 SHL Support drive letters
+			if (len == 2 + drive_spec_width(fbuf) && fbuf[drive_spec_width(fbuf)] == '.') {
+				/* Turn trailing "./" into just "." rather than "./." */
 				fbuf[--len] = '\0';
 			} else {
+				/* Turn trailing "xyz/" into "xyz/." */
 				if (len + 1 >= MAXPATHLEN)
 					overflow_exit("send_file_list");
 				fbuf[len++] = '.';
@@ -2059,6 +2130,7 @@
 			name_type = DOTDIR_NAME;
 		} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
 		    && (len == 2 || fbuf[len-3] == '/')) {
+			/* Got ..  or trailing /.. */
 			if (len + 2 >= MAXPATHLEN)
 				overflow_exit("send_file_list");
 			fbuf[len++] = '/';
@@ -2077,18 +2149,40 @@
 			if (p) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 2009-03-06 SHL Preserve drive letter in directory name
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else
 					dir = fbuf;
-				len -= p - fbuf + 1;
-				fn = p + 1;
+				fn = p + 1;		// Point at filename part
+				len -= fn - fbuf;	//  fn length
+				// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			} else
 				fn = fbuf;
 		} else {
+			// relative-paths
 			if ((p = strstr(fbuf, "/./")) != NULL) {
 				*p = '\0';
 				if (p == fbuf)
-					dir = "/";
+					dir = the_root;
+#ifdef __OS2__
+				// 2009-03-06 SHL Preserve drive letter
+				else if (p == fbuf + (dirlen = drive_spec_width(fbuf))) {
+					if (!(dir = malloc(dirlen + 2)))
+						out_of_memory("send_file_list");
+					memcpy(dir, fbuf, dirlen);
+					dir[dirlen] = '/';
+					dir[dirlen + 1] = 0;
+				}
+#endif
 				else {
 					dir = fbuf;
 					clean_fname(dir, 0);
@@ -2102,10 +2196,15 @@
 				fn = fbuf;
 			/* A leading ./ can be used in relative mode to affect
 			 * the dest dir without its name being in the path. */
+#ifdef __OS2__
+			// 2010-11-30 SHL Point after drive letter
+			fn += drive_spec_width(fn);
+#endif
 			if (*fn == '.' && fn[1] == '/' && fn[2] && !implied_dot_dir)
 				implied_dot_dir = -1;
 			len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
 					    | CFN_DROP_TRAILING_DOT_DIR);
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug relative-paths
 			if (len == 1) {
 				if (fn[0] == '/') {
 					fn = "/.";
@@ -2130,7 +2229,8 @@
 					exit_cleanup(RERR_SYNTAX);
 				}
 			}
-		}
+			// rprintf(FINFO, "* [%s] send_file_list fn %s len %d %s(%u)\n", who_am_i(), fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug relative-paths
+		} // relative-paths
 
 		if (!*fn) {
 			len = 1;
@@ -2138,6 +2238,8 @@
 			name_type = DOTDIR_NAME;
 		}
 
+		// rprintf(FINFO, "* [%s] send_file_list dir %s fn %s len %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", fn, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug xattrs
+
 		dirlen = dir ? strlen(dir) : 0;
 		if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) {
 			if (!change_pathname(NULL, dir, -dirlen))
@@ -2156,9 +2258,16 @@
 			send_file_name(f, flist, ".", NULL, (flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR, ALL_FILTERS);
 		}
 
+		// 2009-03-06 SHL
+		if (dir && dir != the_root && dir != fbuf)
+			free(dir);	// We allocated it
+
 		if (fn != fbuf)
 			memmove(fbuf, fn, len + 1);
 
+		// rprintf(FINFO, "* [%s] send_file_list fn %s %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+		// rprintf(FINFO, "* [%s] send_file_list fbuf %s len %d %s(%u)\n", who_am_i(), fbuf, len, __FILE__, __LINE__);	// 2009-03-06 SHL debug
+
 		if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
 		 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
 		 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
@@ -2179,12 +2288,14 @@
 		}
 
 		if (inc_recurse && relative_paths && *fbuf) {
+			// 2009-03-06 SHL fixme
 			if ((p = strchr(fbuf+1, '/')) != NULL) {
 				if (p - fbuf == 1 && *fbuf == '.') {
 					if ((fn = strchr(p+1, '/')) != NULL)
 						p = fn;
 				} else
 					fn = p;
+				// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 				send_implied_dirs(f, flist, fbuf, fbuf, p, flags, name_type);
 				if (fn == p)
 					continue;
@@ -2192,6 +2303,7 @@
 		} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
 			/* Send the implied directories at the start of the
 			 * source spec, so we get their permissions right. */
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
 		}
 
@@ -2200,6 +2312,7 @@
 
 		if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
 			struct file_struct *file;
+			// rprintf(FINFO, "* [%s] send_file_list fbuf %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			file = send_file_name(f, flist, fbuf, &st,
 					      FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
 					      NO_FILTERS);
@@ -2215,9 +2328,11 @@
 				}
 			} else
 				send_if_directory(f, flist, file, fbuf, len, flags);
-		} else
+		} else {
+			// rprintf(FINFO, "* [%s] send_file_list %s %s(%u)\n", who_am_i(), fbuf, __FILE__, __LINE__);	// 2009-03-06 SHL debug
 			send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
 	}
+	} /* while */
 
 	gettimeofday(&end_tv, NULL);
 	stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000
@@ -2407,6 +2522,9 @@
 							struct file_struct *,
 							dir_flist->malloced);
 				dir_flist_malloced = dir_flist->malloced;
+				// 2010-11-30 SHL check out of memory
+				if (dir_flist->sorted == NULL)
+					out_of_memory("recv_file_list");
 			}
 			memcpy(dir_flist->sorted + dstart, dir_flist->files + dstart,
 			       (dir_flist->used - dstart) * sizeof (struct file_struct*));
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/generator.c ../rsync-3.0.9/generator.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/generator.c	2011-09-10 13:38:10.000000000 -0700
+++ ../rsync-3.0.9/generator.c	2012-12-20 22:18:52.000000000 -0800
@@ -96,6 +96,10 @@
 extern int backup_suffix_len;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct filter_list_struct daemon_filter_list;
+// 2009-10-14 SHL
+#ifdef __OS2__
+extern int preserve_os2_perms;
+#endif
 
 int ignore_perishable = 0;
 int non_perishable_cnt = 0;
@@ -143,7 +147,8 @@
 static int is_backup_file(char *fn)
 {
 	int k = strlen(fn) - backup_suffix_len;
-	return k > 0 && strcmp(fn+k, backup_suffix) == 0;
+	// 2012-01-03 SHL support case insensitive file systems
+	return k > 0 && strcmp_fs(fn+k, backup_suffix) == 0;
 }
 
 /* Delete a file or directory.  If DEL_RECURSE is set in the flags, this will
@@ -263,6 +268,7 @@
 	}
 
 	p = fname + dlen;
+	// 2009-02-16 SHL fixme slash?
 	if (dlen != 1 || *fname != '/')
 		*p++ = '/';
 	remainder = MAXPATHLEN - (p - fname);
@@ -659,7 +665,7 @@
 #endif
 	}
 
-	return 1;
+	return 1;			// No change
 }
 
 void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statret,
@@ -680,19 +686,30 @@
 		} else if (keep_time
 		 ? cmp_time(file->modtime, sxp->st.st_mtime) != 0
 		 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
-		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+		  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s file->modtime %u sxp->st.st_mtime %u %s(%u)\n", who_am_i(), fnamecmp, file->modtime, sxp->st.st_mtime, __FILE__, __LINE__);	// 2009-09-17 SHL fixme times
+			if (verbose > 1)
+				rprintf(FINFO, "%s times differ sender %u receiver %u\n", fnamecmp, file->modtime, sxp->st.st_mtime);
 			iflags |= ITEM_REPORT_TIME;
+		}
+
 #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
 		if (S_ISLNK(file->mode)) {
 			;
 		} else
 #endif
 		if (preserve_perms) {
-			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+			if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) {
+				// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode 0%o file->mode 0%o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 2009-09-17 SHL fixme perms
+				if (verbose > 1)
+					rprintf(FINFO, "%s perms differ sender %o receiver %o\n", fnamecmp, file->mode, sxp->st.st_mode);
 				iflags |= ITEM_REPORT_PERMS;
+			}
 		} else if (preserve_executability
-		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+		 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0))) {
+			// rprintf(FINFO, "* [%s] itemize fnamecmp %s sxp->st.st_mode 0%o file->mode 0%o %s(%u)\n", who_am_i(), fnamecmp, sxp->st.st_mode, file->mode, __FILE__, __LINE__);	// 2009-09-17 SHL fixme perms
 			iflags |= ITEM_REPORT_PERMS;
+		 }
 		if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 			iflags |= ITEM_REPORT_OWNER;
 		if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
@@ -1176,7 +1193,8 @@
 			if ((len = readlink(cmpbuf, lnk, MAXPATHLEN-1)) <= 0)
 				continue;
 			lnk[len] = '\0';
-			if (strcmp(lnk, F_SYMLINK(file)) != 0)
+			// 2012-01-03 SHL support case-insensitive file systems
+			if (strcmp_fs(lnk, F_SYMLINK(file)) != 0)
 				continue;
 			break;
 #endif
@@ -1375,7 +1393,8 @@
 	} else {
 		const char *dn = file->dirname ? file->dirname : ".";
 		dry_missing_dir = NULL;
-		if (parent_dirname != dn && strcmp(parent_dirname, dn) != 0) {
+		// 2012-01-03 SHL Support case-insensitive file systems
+		if (parent_dirname != dn && strcmp_fs(parent_dirname, dn) != 0) {
 			if (relative_paths && !implied_dirs
 			 && do_stat(dn, &sx.st) < 0) {
 				if (dry_run)
@@ -1524,8 +1543,10 @@
 		}
 
 #ifdef SUPPORT_XATTRS
-		if (preserve_xattrs && statret == 1)
+		if (preserve_xattrs && statret == 1) {
+			// rprintf(FINFO, "* [%s] receive_generator running copy_xattrs fnamecmpbuf %s fname %s %s(%u)\n", who_am_i(), fnamecmpbuf, fname, __FILE__, __LINE__); // 2010-03-23 SHL fixme libc chmod xattrs debug
 			copy_xattrs(fnamecmpbuf, fname);
+		}
 #endif
 		if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
 		    && verbose && code != FNONE && f_out != -1)
@@ -1641,6 +1662,16 @@
 			cur_flist->in_progress++;
 			goto cleanup;
 		}
+#ifdef __OS2__
+		// 2012-12-20 SHL os2_perms rework
+		// If source directory not archived
+		// may need to touch up after file operations complete
+		if (!need_retouch_dir_perms && preserve_os2_perms &&
+		    ~F_OS2_PERMS(file) & FILE_ARCHIVED) {
+			// rprintf(FINFO, "* [%s] recv_generator %s directory needs retouch for ~ARCHIVED %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 2012-12-20 SHL os2_perms rework
+			need_retouch_dir_perms = 1;
+		}
+#endif
 #endif
 		if (do_symlink(sl, fname) != 0) {
 			rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed",
@@ -1665,7 +1696,7 @@
 		}
 #endif
 		goto cleanup;
-	}
+	} // is_dir
 
 	if ((am_root && preserve_devices && IS_DEVICE(file->mode))
 	 || (preserve_specials && IS_SPECIAL(file->mode))) {
@@ -2097,10 +2128,18 @@
 	} else
 		start = end = ndx;
 
+	// rprintf(FINFO, "* [%s] touch_up_dirs start %u end %u %s(%u)\n", who_am_i(), start, end,  __FILE__, __LINE__); // 2009-09-17 SHL fixme dir perms
+
 	/* Fix any directory permissions that were modified during the
 	 * transfer and/or re-set any tweaked modified-time values. */
 	for (i = start; i <= end; i++, counter++) {
 		file = flist->files[i];
+#ifdef __OS2__
+		// 2012-12-20 SHL os2_perms rework - correct xattrs changes triggered by libc
+		int need_xattrs_set = preserve_xattrs && (file->flags & FLAG_DIR_CREATED);
+#endif
+		fname = f_name(file, NULL); // 2009-10-14 SHL debug dir perms
+		// rprintf(FINFO, "* [%s] touch_up_dirs checking %s directory %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 2012-12-20 SHL os2_perms rework
 		if (!S_ISDIR(file->mode)
 		 || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))
 			continue;
@@ -2111,18 +2150,73 @@
 		}
 		/* Be sure not to retouch permissions with --fake-super. */
 		fix_dir_perms = !am_root && !(file->mode & S_IWUSR);
+#ifndef __OS2__
 		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
 		 || !(need_retouch_dir_times || fix_dir_perms))
 			continue;
+else // __OS2__
+		// 2012-12-20 SHL os2_perms rework
+		// Do not bypass if preserving os2_perms or want archived flag off
+		if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR
+		 || !(need_retouch_dir_times || fix_dir_perms
+		      || preserve_os2_perms || (~F_OS2_PERMS(file) & FILE_ARCHIVED)))
+			continue;
+#endif
 		fname = f_name(file, NULL);
-		if (fix_dir_perms)
+#ifdef __OS2__
+		// 2009-10-14 SHL Need to set time before clearing archive bit
+		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);
+		}
+#endif
+		if (fix_dir_perms) {
 			do_chmod(fname, file->mode);
+#ifdef __OS2__
+			rprintf(FINFO, "* [%s] touch_up_dirs need_xattrs_set after chmod fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 2012-12-20 SHL os2_perms rework
+			need_xattrs_set = preserve_xattrs;
+			if (preserve_os2_perms) {
+				rprintf(FINFO, "* [%s] touch_up_dirs calling do_set_os2_perms for %s directory %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 2012-12-20 SHL os2_perms rework
+				do_set_os2_perms(fname, F_OS2_PERMS(file));
+			}
+			// 2010-03-25 SHL fixme to be sure can update EAs after setting read-only
+			// 2010-03-23 SHL restore xattrs changed by libc chmod
+#endif
+		}
+#ifdef __OS2__
+		// 2012-12-20 SHL os2_perms rework
+		// If preserving os2_perms and want archive flag off
+		else if (preserve_os2_perms && (~F_OS2_PERMS(file) & FILE_ARCHIVED)) {
+			// rprintf(FINFO, "* [%s] touch_up_dirs calling do_set_os2_perms for %s directory %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 2012-12-20 SHL os2_perms rework
+			do_set_os2_perms(fname, F_OS2_PERMS(file));
+		}
+#endif
+#ifndef __OS2__
 		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);
 		}
+#endif
+#ifdef __OS2__
+		if (need_xattrs_set) {
+			// 2010-03-23 SHL overwrite xattrs generated by libc chmod
+			stat_x sx;
+			// rprintf(FINFO, "* [%s] touch_up_dirs calling set_xattr for %s directory %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 2012-12-20 SHL os2_perms rework
+			if (verbose > 2)
+				rprintf(FINFO, "%s correcting %s directory EAs generated by libc chmod\n", who_am_i(), fname);
+			memset(&sx, 0, sizeof(stat_x));
+			// Should not need to provide target item list to set_xattr
+			// link_stat(fname, &sx.st, 0);
+			// sx.xattr = new(item_list);
+			// *sxp.xattr = empty_xattr;
+			set_xattr(fname, file, fname, &sx);
+			// free_xattr(&sx);
+		}
+#endif
 		if (counter >= loopchk_limit) {
 			if (allowed_lull)
 				maybe_send_keepalive();
@@ -2130,7 +2224,7 @@
 				maybe_flush_socket(0);
 			counter = 0;
 		}
-	}
+	} // for
 }
 
 void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/getaddrinfo.c ../rsync-3.0.9/lib/getaddrinfo.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/getaddrinfo.c	2009-12-12 17:20:34.000000000 -0800
+++ ../rsync-3.0.9/lib/getaddrinfo.c	2012-02-29 12:04:54.000000000 -0800
@@ -403,12 +403,16 @@
 	int ret = -1;
 	char *p = NULL;
 
+	// rprintf(FINFO, "* [%s] gethostnameinfo NI_NUMERICHOST %u %s(%u)\n", who_am_i(), flags & NI_NUMERICHOST, __FILE__, __LINE__);	// 2008-07-28 SHL debug
 	if (!(flags & NI_NUMERICHOST)) {
+		// rprintf(FINFO, "* [%s] gethostnameinfo %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 2008-07-28 SHL debug
 		struct hostent *hp = gethostbyaddr(
 				(void *)&((struct sockaddr_in *)sa)->sin_addr,
 				sizeof (struct in_addr),
 				sa->sa_family);
+		// rprintf(FINFO, "* [%s] gethostnameinfo hp %p %s(%u)\n", who_am_i(), hp, __FILE__, __LINE__);	// 2008-07-28 SHL debug
 		ret = check_hostent_err(hp);
+		// rprintf(FINFO, "* [%s] ret %d %s(%u)\n", who_am_i(), ret, __FILE__, __LINE__);	// 2008-07-28 SHL debug
 		if (ret == 0) {
 			/* Name looked up successfully. */
 			ret = snprintf(node, nodelen, "%s", hp->h_name);
@@ -424,6 +428,7 @@
 			return 0;
 		}
 
+		// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 2008-07-28 SHL debug
 		if (flags & NI_NAMEREQD) {
 			/* If we require a name and didn't get one,
 			 * automatically fail. */
@@ -431,6 +436,7 @@
 		}
 		/* Otherwise just fall into the numeric host code... */
 	}
+	// rprintf(FINFO, "* [%s] %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 2008-07-28 SHL debug
 	p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
 	ret = snprintf(node, nodelen, "%s", p);
 	if (ret < 0 || (size_t)ret >= nodelen) {
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/pool_alloc.c ../rsync-3.0.9/lib/pool_alloc.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/pool_alloc.c	2008-11-09 18:55:14.000000000 -0800
+++ ../rsync-3.0.9/lib/pool_alloc.c	2012-10-19 00:26:50.000000000 -0700
@@ -93,8 +93,10 @@
 	else if (pool->quantum > 1 && len % pool->quantum)
 		len += pool->quantum - len % pool->quantum;
 
-	if (len > pool->size)
+	if (len > pool->size) {
+	        rprintf(FERROR, "* [%s] pool_alloc len %u > pool->size %u %s(%u)\n", who_am_i(), len, pool->size, __FILE__, __LINE__);	// 2012-10-19 SHL MALLOC_MAX/memlimit debug
 		goto bomb_out;
+	}
 
 	if (!pool->extents || len > pool->extents->free) {
 		void	*start;
@@ -111,16 +113,20 @@
 		if (pool->flags & POOL_APPEND)
 			asize += sizeof (struct pool_extent);
 
-		if (!(start = new_array(char, asize)))
+		if (!(start = new_array(char, asize))) {
+			rprintf(FERROR, "* [%s] new_array asize %u failed %s(%u)\n", who_am_i(), asize, __FILE__, __LINE__);	// 2012-10-19 SHL MALLOC_MAX/memlimit debug
 			goto bomb_out;
+		}
 
 		if (pool->flags & POOL_CLEAR)
 			memset(start, 0, free);
 
 		if (pool->flags & POOL_APPEND)
 			ext = PTR_ADD(start, free);
-		else if (!(ext = new(struct pool_extent)))
+		else if (!(ext = new(struct pool_extent))) {
+			rprintf(FERROR, "* [%s] new pool_extent failed %s(%u)\n", who_am_i(), __FILE__, __LINE__);	// 2012-10-19 SHL MALLOC_MAX/memlimit debug
 			goto bomb_out;
+		}
 		if (pool->flags & POOL_QALIGN && pool->quantum > 1
 		    && (skew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
 			bound  += skew;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/sysxattrs.c ../rsync-3.0.9/lib/sysxattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/sysxattrs.c	2008-03-01 12:01:40.000000000 -0800
+++ ../rsync-3.0.9/lib/sysxattrs.c	2012-12-20 09:05:36.000000000 -0800
@@ -126,6 +126,360 @@
 	return len;
 }
 
+#elif defined(__OS2__)
+
+#define INCL_LONGLONG
+#define INCL_DOS
+#define INCL_DOSPROCESS
+#define INCL_DOSPROFILE
+#define INCL_DOSMISC
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+
+#include <os2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <types.h>
+
+static void map_os2_apiret(APIRET rc)
+{
+	switch (rc) {
+	case ERROR_SHARING_VIOLATION:
+		errno = EACCES;
+		break;
+	case 0:
+		// Should not have been called - try to do no harm
+		break;
+	default:
+		// 2009-07-31 SHL fixme to map better
+		// if (verbose > 2)
+		rprintf(FINFO, "[%s] can not map OS/2 error %lu to errno\n", who_am_i(), rc);	// 2009-07-31 SHL
+		/* Ensure non-zero */
+		if (!errno)
+			errno = EINVAL;
+
+	}
+}
+
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+	return unigetxattr(path, 0, name, value, size);
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+	return unigetxattr(0, filedes, name, value, size);
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+	return unisetxattr (path, 0, name, value, size, 0);
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+	return uniremovexattr (path, 0, name);
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+	return unilistxattr(path, 0, list, size);
+}
+
+static char *out_of_mem_msg = "out of memory allocating %lu at %s(%u)\n";
+
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
+{
+	int rc, namelen;
+	size_t reqsize;
+	EAOP2	    eaop2 = {0,0,0};
+	PGEA2LIST   pgea2list = NULL;
+	PFEA2LIST   pfea2list = NULL;
+	char * p;
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+	reqsize = sizeof(GEA2LIST) + namelen + 1;
+	pgea2list = (PGEA2LIST)calloc(reqsize, 1);
+	// 2010-11-30 SHL
+	if (pgea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pgea2list->list[0].oNextEntryOffset = 0;
+	pgea2list->list[0].cbName = namelen;
+	strcpy(pgea2list->list[0].szName, name);
+	pgea2list->cbList = sizeof(GEA2LIST) + namelen;
+
+	// max ea is 64kb
+	reqsize = sizeof(FEA2LIST) + 0x10000;
+	pfea2list = (PFEA2LIST)calloc(reqsize, 1);
+	// 2010-11-30 SHL
+	if (pfea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
+
+	eaop2.fpGEA2List = pgea2list;
+	eaop2.fpFEA2List = pfea2list;
+	eaop2.oError = 0;
+	do {
+		if (path) {
+			rc = DosQueryPathInfo((PCSZ)path, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryPathInfo(%s, FIL_QUERYEASFROMLIST) for %s failed with error %u at %s(%u)\n", who_am_i(), path, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] %s requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), path, eaop2.fpFEA2List->cbList, name);	// 2008-07-28 SHL
+		}
+		else {
+			rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
+			if (rc)
+				rprintf(FERROR, "[%s] unigetxattr: DosQueryFileInfo(%u, FIL_QUERYEASFROMLIST) for %s failed with error %u at %s(%u)\n", who_am_i(), file, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+			else if (verbose > 2)
+				rprintf(FINFO, "[%s] handle %d requested %lu FIL_QUERYEASFROMLIST bytes for %s\n", who_am_i(), file, eaop2.fpFEA2List->cbList, name);	// 2008-07-28 SHL
+		}
+		if (rc)
+			break;
+		if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0) {
+			errno = ENOATTR;
+			rc = -1;
+			break;
+		}
+		rc = pfea2list->list[0].cbValue;
+		if (value) {
+			if ((size_t)rc > size) {
+				errno = ERANGE;
+				rc = -1;
+			}
+			else {
+				p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
+				memcpy(value, p, rc);
+			}
+		}
+	} while (0);
+	if (pgea2list)
+		free(pgea2list);
+	if (pgea2list)
+		free(pfea2list);
+
+	return rc;
+}
+
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
+{
+	ssize_t gotsize = 0;
+	size_t reqsize;
+	unsigned long ulCount = -1;
+	int rc;
+	char * buf, *p = list;
+	PFEA2 pfea;
+	FILESTATUS4 stat;
+	if (!path && !file) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (path) {
+		rc = DosQueryPathInfo((PCSZ)path, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryPathInfo(%s, FIL_QUERYEASIZE) failed with error %u %s(%u)\n", who_am_i(), path, rc, __FILE__, __LINE__);	// 2008-07-28 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] %s reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), path, stat.cbList);	// 2008-07-28 SHL
+	}
+	else {
+		rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
+		if (rc)
+			rprintf(FERROR, "[%s] unilistxattr DosQueryFilInfo(%u, FIL_QUERYEASIZE) failed with error %u at %s(%u)\n", who_am_i(), file, rc, __FILE__, __LINE__);	// 2008-07-28 SHL
+		else if (verbose > 2)
+			rprintf(FINFO, "[%s] handle %d reported %lu FIL_QUERYEASIZE bytes\n", who_am_i(), file, stat.cbList);	// 2008-07-28 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	if (stat.cbList <= 4) {
+		// NO ea
+		return 0;
+	}
+	//YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
+	reqsize = stat.cbList * 2;
+	buf = (char *)_tmalloc(reqsize);
+	// 2009-09-19 SHL was trapping on large copies
+	if (!buf) {
+		rprintf(FERROR, out_of_mem_msg, reqsize, __FILE__, __LINE__);	// 2009-09-19 SHL
+		return -1;
+	}
+	rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
+	if (rc) {
+		rprintf(FERROR, "[%s] unilistxattr DosEnumAttribute failed with error %u at %s(%u)\n", who_am_i(), rc, __FILE__, __LINE__);	// 2008-07-28 SHL
+		_tfree(buf);
+		map_os2_apiret(rc);	// 2009-07-31 SHL moved here to ensure errno returned
+		return -1;
+	}
+	else if (verbose > 2) {
+		if (path)
+			rprintf(FINFO, "[%s] %s has %lu DosEnumAttribute items\n", who_am_i(), path, ulCount);	// 2008-07-28 SHL
+		else
+			rprintf(FINFO, "[%s] handle %d has %lu DosEnumAttribute items\n", who_am_i(), file, ulCount);	// 2008-07-28 SHL
+	}
+	if (ulCount > 0) {
+		for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset)) {
+			if (pfea->cbName > 0) {
+				gotsize += pfea->cbName + 1;
+				// Avoid overflow
+				if (p && (size_t)gotsize <= size) {
+					pfea->szName[pfea->cbName] = 0;
+					strcpy(p, pfea->szName);
+					p += strlen(p) + 1;
+				}
+			}
+			if (!pfea->oNextEntryOffset)
+				break;
+		}
+	}
+	_tfree(buf);
+	if ((size_t)gotsize > size) {
+		errno = ERANGE;
+		return list ? -1 : gotsize;
+	}
+	if (verbose > 2)
+		rprintf(FINFO, "[%s] returning %ld EA list bytes\n", who_am_i(), (unsigned long)gotsize);	// 2008-07-28 SHL
+	return gotsize;
+}
+
+int uniremovexattr (const char *path, int file, const char *name)
+{
+	int rc, namelen;
+	EAOP2 eaop2 = {0,0,0};
+	PFEA2LIST pfea2list = NULL;
+	char buf[300] = {0};
+
+	if ((!path && !file) || !name) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	pfea2list = (PFEA2LIST)buf;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = 0;
+	pfea2list->list[0].fEA = 0;
+	strcpy(pfea2list->list[0].szName, name);
+	pfea2list->cbList = sizeof(FEA2LIST) + namelen;
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo((PCSZ)path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) for %s failed with error %u at %s(%u)\n", who_am_i(), path, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from %s\n", who_am_i(), name, path);	// 2008-07-28 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] uniremovexattr: DosFileInfo(%u, FIL_QUERYEASIZE) for %s failed with error %u %s(%u)\n", who_am_i(), file, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] deleted EA %s from handle %d\n", who_am_i(), name, file);	// 2008-07-28 SHL
+	}
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
+#ifndef XATTR_CREATE
+#define XATTR_CREATE  1
+#endif
+#ifndef XATTR_REPLACE
+#define XATTR_REPLACE 2
+#endif
+
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
+{
+	int rc, namelen, totalsize;
+	EAOP2       eaop2 = {0,0,0};
+	PFEA2LIST   pfea2list = NULL;
+
+	if ((!path && !file) || !name || (!value && size)) {
+		errno = EINVAL;
+		return -1;
+	}
+	namelen = strlen(name);
+	if (namelen > 0xFF) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
+		ssize_t esize = unigetxattr(path, file, name, 0, 0);
+		if (flags & XATTR_CREATE && esize > 0) {
+			errno = EEXIST;
+			return -1;
+		}
+		if (flags & XATTR_REPLACE && esize < 0) {
+			errno = ENOATTR;
+			return -1;
+		}
+	}
+
+	totalsize = sizeof(FEA2LIST) + size + namelen + 1;
+
+	pfea2list = (PFEA2LIST)calloc(totalsize, 1);
+	// 2010-11-30 SHL
+	if (pfea2list == NULL) {
+		rprintf(FERROR, out_of_mem_msg, totalsize, __FILE__, __LINE__);
+		errno = ENOMEM;
+		return -1;
+	}
+	pfea2list->cbList = totalsize;
+	pfea2list->list[0].oNextEntryOffset = 0;
+	pfea2list->list[0].cbName = namelen;
+	pfea2list->list[0].cbValue = size;
+	strcpy(pfea2list->list[0].szName, name);
+	if (value) {
+		memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
+	}
+	eaop2.fpFEA2List = pfea2list;
+
+	if (path) {
+		rc = DosSetPathInfo((PCSZ)path, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetPathInfo(%s, FIL_QUERYEASIZE) for %s failed with error %u at %s(%u)\n", who_am_i(), path, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for %s\n", who_am_i(), name, path);	// 2008-07-28 SHL
+	}
+	else {
+		rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
+		if (rc)
+			rprintf(FERROR, "[%s] unisetxattr: DosSetFileInfo(%u, FIL_QUERYEASIZE) for %s failed with error %u at %s(%u)\n", who_am_i(), file, name, rc, __FILE__, __LINE__);	// 2011-12-30 SHL
+		else if (verbose > 1)
+			rprintf(FINFO, "[%s] set EA %s for handle %d\n", who_am_i(), name, file);	// 2008-07-28 SHL
+	}
+	free(pfea2list);
+	if (rc) {
+		map_os2_apiret(rc);
+		return -1;
+	}
+	return 0;
+}
+
 #else
 
 #error You need to create xattr compatibility functions.
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/sysxattrs.h ../rsync-3.0.9/lib/sysxattrs.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/sysxattrs.h	2007-04-07 10:22:24.000000000 -0700
+++ ../rsync-3.0.9/lib/sysxattrs.h	2012-02-29 10:45:32.000000000 -0800
@@ -19,6 +19,13 @@
 int sys_lremovexattr(const char *path, const char *name);
 ssize_t sys_llistxattr(const char *path, char *list, size_t size);
 
+#ifdef __OS2__
+ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size);
+ssize_t unilistxattr (const char *path, int file, char *list, size_t size);
+int uniremovexattr (const char *path, int file, const char *name);
+int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags);
+#endif
+
 #else
 
 /* No xattrs available */
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/wildmatch.c ../rsync-3.0.9/lib/wildmatch.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/lib/wildmatch.c	2007-05-21 22:58:58.000000000 -0700
+++ ../rsync-3.0.9/lib/wildmatch.c	2012-02-29 12:01:58.000000000 -0800
@@ -89,8 +89,14 @@
 	    p_ch = *++p;
 	    /* FALLTHROUGH */
 	  default:
+#ifndef __OS2__
 	    if (t_ch != p_ch)
 		return FALSE;
+#else
+	    // 2009-10-18 SHL be case insensitive
+	    if (t_ch != p_ch && (t_ch ^ p_ch) != 0x20)
+		return FALSE;
+#endif
 	    continue;
 	  case '?':
 	    /* Match anything but '/'. */
@@ -150,8 +156,14 @@
 		    p_ch = *++p;
 		    if (!p_ch)
 			return ABORT_ALL;
+#ifndef __OS2__
 		    if (t_ch == p_ch)
 			matched = TRUE;
+#else
+		    // 2009-10-18 SHL be case insensitive
+		    if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			matched = TRUE;
+#endif
 		} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
 		    p_ch = *++p;
 		    if (p_ch == '\\') {
@@ -159,6 +171,7 @@
 			if (!p_ch)
 			    return ABORT_ALL;
 		    }
+		    // 2009-10-18 SHL [a-z] ranges remain case-sensitive for now
 		    if (t_ch <= p_ch && t_ch >= prev_ch)
 			matched = TRUE;
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
@@ -173,8 +186,14 @@
 			/* Didn't find ":]", so treat like a normal set. */
 			p = s - 2;
 			p_ch = '[';
+#ifndef __OS2__
 			if (t_ch == p_ch)
 			    matched = TRUE;
+#else
+			// 2009-10-18 SHL be case insensitive
+			if (t_ch == p_ch || (t_ch ^ p_ch) == 0x20)
+			    matched = TRUE;
+#endif
 			continue;
 		    }
 		    if (CC_EQ(s,i, "alnum")) {
@@ -218,6 +237,11 @@
 		    p_ch = 0; /* This makes "prev_ch" get set to 0. */
 		} else if (t_ch == p_ch)
 		    matched = TRUE;
+#ifdef __OS2__
+		// 2009-10-18 SHL be case insensitive
+		else if ((t_ch ^ p_ch) == 0x20)
+		    matched = TRUE;
+#endif
 	    } while (prev_ch = p_ch, (p_ch = *++p) != ']');
 	    if (matched == special || t_ch == '/')
 		return FALSE;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/loadparm.c ../rsync-3.0.9/loadparm.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/loadparm.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.9/loadparm.c	2012-02-29 10:45:32.000000000 -0800
@@ -212,7 +212,7 @@
  /* read_only; */		True,
  /* strict_modes; */		True,
  /* transfer_logging; */	False,
- /* use_chroot; */		True,
+ /* use_chroot; */		False,	// 2010-09-17 SHL libc chroot not quite right
  /* write_only; */		False,
 };
 
@@ -654,10 +654,23 @@
 	    *(char *)dest_ptr = *(char *)src_ptr;
 	    break;
 
+#ifndef __OS2__
 	  case P_PATH:
 	  case P_STRING:
 	    string_set(dest_ptr,*(char **)src_ptr);
 	    break;
+#else
+	  case P_PATH:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    // 2009-03-06 SHL Force unix slashes
+	    // 2009-05-16 SHL Use normalize_dir_slashes
+	    normalize_dir_slashes(*(char **)dest_ptr);
+	    break;
+
+	  case P_STRING:
+	    string_set(dest_ptr,*(char **)src_ptr);
+	    break;
+#endif
 
 	  default:
 	    break;
@@ -725,8 +738,14 @@
      case P_PATH:
        string_set(parm_ptr,parmvalue);
        if ((cp = *(char**)parm_ptr) != NULL) {
+	   // Chop trailing slashes unless root
 	   int len = strlen(cp);
+#ifndef __OS2__
 	   while (len > 1 && cp[len-1] == '/') len--;
+#else
+	   // 2010-11-24 SHL Use drive_spec_width
+	   while (len > drive_spec_width(cp) + 1 && cp[len-1] == '/') len--;
+#endif
 	   cp[len] = '\0';
        }
        break;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/log.c ../rsync-3.0.9/log.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/log.c	2011-01-29 19:25:52.000000000 -0800
+++ ../rsync-3.0.9/log.c	2012-02-29 12:06:12.000000000 -0800
@@ -165,7 +165,8 @@
 	if (log_initialised) {
 		if (!restart)
 			return;
-		if (strcmp(logfile_name, lp_log_file(module_id)) != 0) {
+		// 2012-01-03 SHL Support case-insensitive file systems
+		if (strcmp_fs(logfile_name, lp_log_file(module_id)) != 0) {
 			if (logfile_fp) {
 				fclose(logfile_fp);
 				logfile_fp = NULL;
@@ -369,6 +370,7 @@
 	va_list ap;
 	char buf[BIGPATHBUFLEN];
 	size_t len;
+	int e = errno;			// 2009-04-27 SHL preserve errno
 
 	va_start(ap, format);
 	len = vsnprintf(buf, sizeof buf, format, ap);
@@ -401,6 +403,7 @@
 	}
 
 	rwrite(code, buf, len, 0);
+	errno = e;
 }
 
 /* This is like rprintf, but it also tries to print some
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/main.c ../rsync-3.0.9/main.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/main.c	2011-06-18 12:44:46.000000000 -0700
+++ ../rsync-3.0.9/main.c	2012-02-29 12:04:46.000000000 -0800
@@ -27,6 +27,10 @@
 #include <locale.h>
 #endif
 
+#ifdef __OS2__
+#include <umalloc.h>			// Need for _heap_walk
+#endif
+
 extern int verbose;
 extern int dry_run;
 extern int list_only;
@@ -272,10 +276,23 @@
 
 	if (verbose || do_stats) {
 		rprintf(FCLIENT, "\n");
+#ifndef __OS2__
 		rprintf(FINFO,
 			"sent %s bytes  received %s bytes  %s bytes/sec\n",
 			human_num(total_written), human_num(total_read),
 			human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
+#else
+		{
+			// 2010-10-30 SHL show elapsed time
+			time_t t = endtime - starttime + 1;	// Always round up
+			rprintf(FINFO,
+				"sent %s bytes  received %s bytes  %s bytes/sec  elapsed %02u:%02u:%02u\n",
+				human_num(total_written),
+				human_num(total_read),
+				human_dnum((total_written + total_read)/(0.5 + t), 2),
+				t / 3600, (t / 60) % 60, t % 60);
+		}
+#endif
 		rprintf(FINFO, "total size is %s  speedup is %.2f%s\n",
 			human_num(stats.total_size),
 			(double)stats.total_size / (total_written+total_read),
@@ -287,6 +304,103 @@
 }
 
 
+#ifdef __OS2__				// 2010-12-25 SHL
+#ifdef HAVE_MALLINFO
+#error HAVE_MALLINFO unexpected
+#endif
+
+// See \EMX\doc\emxlib.doc
+
+struct mallinfo {
+  int arena;
+  int ordblks;
+  int smblks;
+  int hblks;
+  int hblkhd;
+  int usmblks;
+  int fsmblks;
+  int uordblks;
+  int fordblks;
+  int keepcost;
+};
+
+static struct mallinfo os2_mallinfo;
+
+
+// 2012-02-29 SHL unused-parameter warnings expected with 3.3.5
+// 2012-02-29 SHL fixme for this to work someday
+#if defined(__OS2__)
+#if __GNUC_MAJOR__ >=5 || (__GNUC_MAJOR__ >=4 &&  __GNUC_MINOR__ >= 5)
+#pragma GCC diagnostic push	// Requires 4.5.x
+#endif
+#if __GNUC_MAJOR__ >=5 || (__GNUC_MAJOR__ >=4 &&  __GNUC_MINOR__ >= 4)
+#pragma GCC diagnostic ignored "-Wunused-parameter"	// // Requires 4.4.x
+#endif
+#endif
+
+static int os2_mallinfo_callback(const void *block, size_t size, int flag,
+				 int status, const char *fname, size_t lineno)
+{
+	int err = 0;
+	switch (status) {
+	case _HEAPOK:
+	{
+		switch (flag) {
+		case _USEDENTRY:
+			os2_mallinfo.uordblks += size;
+			break;
+		case _FREEENTRY:
+			os2_mallinfo.fordblks += size;
+			break;
+	        default:
+			err = 99;
+		} // flag
+	}
+	break;
+	case _HEAPBADBEGIN:
+	case _HEAPBADEND:
+	case _HEAPBADNODE:
+	case _HEAPEMPTY:
+		// Let _heap_walk set return code
+		break;
+	default:
+		err = 99;
+	} // status
+	return err;
+}
+
+// 2012-02-29 SHL pop requires 4.5.x
+#if defined(__OS2__)
+#if __GNUC_MAJOR__ >=5 || (__GNUC_MAJOR__ >=4 &&  __GNUC_MINOR__ >= 4)
+#pragma GCC diagnostic warning "-Wunused-parameter"	// // Requires 4.4.x
+#endif
+#if __GNUC_MAJOR__ >=5 || (__GNUC_MAJOR__ >=4 &&  __GNUC_MINOR__ >= 5)
+#pragma GCC diagnostic pop	// Requires 4.5.x
+#endif
+#endif
+
+
+
+struct mallinfo mallinfo(void)
+{
+	int err;
+	memset(&os2_mallinfo, 0, sizeof(os2_mallinfo));
+	err = _heap_walk(os2_mallinfo_callback);
+
+	if (err) {
+		// fixme to report
+	}
+
+	os2_mallinfo.arena = os2_mallinfo.uordblks + os2_mallinfo.ordblks;
+
+	return os2_mallinfo;
+}
+
+#define HAVE_MALLINFO
+
+#endif // __OS2__
+
+
 /**
  * If our C library can get malloc statistics, then show them to FINFO
  **/
@@ -324,6 +438,7 @@
 	rprintf(FINFO, "  keepcost:  %10ld   (bytes in releasable chunk)\n",
 		(long)mi.keepcost);
 #endif /* HAVE_MALLINFO */
+
 }
 
 
@@ -541,6 +656,8 @@
 			if (!change_dir(dest_path, CD_NORMAL)) {
 				rsyserr(FERROR, errno, "change_dir#1 %s failed",
 					full_fname(dest_path));
+				// 2009-07-22 SHL was FLOG?  why?
+				rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 2009-07-21 SHL
 				exit_cleanup(RERR_FILESELECT);
 			}
 			filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
@@ -602,6 +719,8 @@
 		if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
 			rsyserr(FERROR, errno, "change_dir#2 %s failed",
 				full_fname(dest_path));
+			// 2009-07-22 SHL was FLOG?  why?
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 2009-07-21 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 
@@ -622,6 +741,8 @@
 	if (!change_dir(dest_path, CD_NORMAL)) {
 		rsyserr(FERROR, errno, "change_dir#3 %s failed",
 			full_fname(dest_path));
+		// 2009-07-22 SHL was FLOG?  why?
+		rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dest_path, __FILE__, __LINE__);	// 2009-07-21 SHL
 		exit_cleanup(RERR_FILESELECT);
 	}
 	*cp = '/';
@@ -713,8 +834,9 @@
 
 	if (!relative_paths) {
 		if (!change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#3 %s failed",
+			rsyserr(FERROR, errno, "change_dir#4 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-07-21 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -885,8 +1007,9 @@
 		argc--;
 		argv++;
 		if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
-			rsyserr(FERROR, errno, "change_dir#4 %s failed",
+			rsyserr(FERROR, errno, "change_dir#5 %s failed",
 				full_fname(dir));
+			rprintf(FERROR, "[%s] change_dir %s failed %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-07-21 SHL
 			exit_cleanup(RERR_FILESELECT);
 		}
 	}
@@ -941,6 +1064,7 @@
 			if (check_filter(elp, FLOG, dir, 1) < 0)
 				goto options_rejected;
 		}
+		// 2009-09-25 SHL fixme slashes
 		if (partial_dir && *partial_dir == '/'
 		 && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
 		    options_rejected:
@@ -1099,7 +1223,7 @@
 
 	for (i = 0; argv[i]; i++) {
 		if (!(argv[i] = strdup(argv[i]))) {
-			rprintf (FERROR, "out of memory at %s(%d)\n",
+			rprintf (FERROR, "out of memory at %s(%u)\n",
 				 __FILE__, __LINE__);
 			return RERR_MALLOC;
 		}
@@ -1130,6 +1254,14 @@
 	 * command line. */
 	if ((ret = copy_argv(argv)) != 0)
 		return ret;
+#ifdef __OS2__
+	{
+		int i;
+		for (i = 0; i < argc; i++) {
+			normalize_dir_slashes(argv[i]);
+		}
+	}
+#endif
 
 	if (!read_batch) { /* for read_batch, NO source is specified */
 		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -1453,6 +1585,7 @@
 	 * (implemented by forking "pwd" and reading its output) doesn't
 	 * work when there are other child processes.  Also, on all systems
 	 * that implement getcwd that way "pwd" can't be found after chroot. */
+	// rprintf(FINFO, "* [%s] %s %s(%u)\n", who_am_i(), "(null)", __FILE__, __LINE__);	// 2008-07-28 SHL debug chdir
 	change_dir(NULL, CD_NORMAL);
 
 	init_flist();
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/Makefile.in ../rsync-3.0.9/Makefile.in
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/Makefile.in	2011-03-26 10:01:36.000000000 -0700
+++ ../rsync-3.0.9/Makefile.in	2012-04-26 10:37:20.000000000 -0700
@@ -2,6 +2,11 @@
 # Makefile
 
 prefix=@prefix@
+# 2012-04-26 SHL Drop drive letter and colon if using DESTDIR
+ifdef DESTDIR
+# 2012-04-26 SHL fixme to not hardcode d:
+prefix:=$(prefix:d:%=%)
+endif
 datarootdir=@datarootdir@
 exec_prefix=@exec_prefix@
 bindir=@bindir@
@@ -12,6 +17,7 @@
 CFLAGS=@CFLAGS@
 CPPFLAGS=@CPPFLAGS@
 EXEEXT=@EXEEXT@
+# 2009-06-14 SHL fixme to do bldlevel strings
 LDFLAGS=@LDFLAGS@
 
 INSTALLCMD=@INSTALL@
@@ -42,7 +48,8 @@
 	popt/popthelp.o popt/poptparse.o
 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
 
-TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
+# 2010-03-25 SHL
+TLS_OBJ = tls.o t_stub.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
 
 # Programs we must have to run the test cases
 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
@@ -68,6 +75,11 @@
 	-mkdir -p ${DESTDIR}${mandir}/man5
 	if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
 	if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
+	if test -f readme.os2; then ${INSTALLMAN} -m 644 readme.os2 ${DESTDIR}${prefix}; fi
+	if test -f readme.shl; then ${INSTALLMAN} -m 644 readme.shl ${DESTDIR}${prefix}; fi
+	if test -f rsync.map; then ${INSTALLMAN} -m 644 rsync.map ${DESTDIR}${prefix}; fi
+	if test -f rsync.sym; then ${INSTALLMAN} -m 644 rsync.sym ${DESTDIR}${prefix}; fi
+	if test -s "${DIFFFILE}"; then if test -f ${DIFFFILE}; then ${INSTALLMAN} -m 644 ${DIFFFILE} ${DESTDIR}${prefix}; fi; fi
 
 install-strip:
 	$(MAKE) INSTALL_STRIP='-s' install
@@ -107,11 +119,11 @@
 getfsdev$(EXEEXT): getfsdev.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
 
-TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
+TRIMSLASH_OBJ = trimslash.o t_stub.o syscall.o lib/compat.o lib/snprintf.o
 trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
-T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o lib/wildmatch.o
+T_UNSAFE_OBJ = t_unsafe.o t_stub.o syscall.o util.o lib/compat.o lib/snprintf.o lib/wildmatch.o
 t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
 
@@ -189,9 +201,10 @@
 	yodl2man -o rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
 	-$(srcdir)/tweak_manpage rsyncd.conf.5
 
+# 2009-02-06 SHL clean maps
 clean: cleantests
 	rm -f *~ $(OBJS) $(CHECK_PROGS) $(CHECK_OBJS) $(CHECK_SYMLINKS) \
-		rounding rounding.h *.old
+		rounding rounding.h *.old rsync.map rounding.map
 
 cleantests:
 	rm -rf ./testtmp*
@@ -243,11 +256,13 @@
 wildtest$(EXEEXT): wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o lib/snprintf.o @BUILD_POPT@ $(LIBS)
 
+# 2010-03-25 SHL
+
 testsuite/chown-fake.test:
-	ln -s chown.test $(srcdir)/testsuite/chown-fake.test
+	echo ln -s chown.test $(srcdir)/testsuite/chown-fake.test
 
 testsuite/devices-fake.test:
-	ln -s devices.test $(srcdir)/testsuite/devices-fake.test
+	echo ln -s devices.test $(srcdir)/testsuite/devices-fake.test
 
 testsuite/xattrs-hlink.test:
 	ln -s xattrs.test $(srcdir)/testsuite/xattrs-hlink.test
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/options.c ../rsync-3.0.9/options.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/options.c	2011-09-13 15:41:26.000000000 -0700
+++ ../rsync-3.0.9/options.c	2012-12-20 19:11:12.000000000 -0800
@@ -52,6 +52,10 @@
 int preserve_hard_links = 0;
 int preserve_acls = 0;
 int preserve_xattrs = 0;
+// 2009-06-13 SHL Added
+#ifdef __OS2__
+int preserve_os2_perms = 0;
+#endif
 int preserve_perms = 0;
 int preserve_executability = 0;
 int preserve_devices = 0;
@@ -104,8 +108,13 @@
 int safe_symlinks = 0;
 int copy_unsafe_links = 0;
 int size_only = 0;
-int daemon_bwlimit = 0;
+static int daemon_bwlimit = 0;
 int bwlimit = 0;
+#ifdef __OS2__
+static unsigned int daemon_memlimit = 0;	// MALLOC_MAX MiBytes
+static unsigned int client_memlimit = 0;	// MALLOC_MAX MiBytes
+extern int memlimit;			// MALLOC_MAX MiBytes
+#endif
 int fuzzy_basis = 0;
 size_t bwlimit_writemax = 0;
 int ignore_existing = 0;
@@ -115,7 +124,11 @@
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
+#ifndef __OS2__
 int modify_window = 0;
+#else
+int modify_window = 1;			// 2009-07-28 SHL allow for 2 second resolution
+#endif
 int blocking_io = -1;
 int checksum_seed = 0;
 int inplace = 0;
@@ -257,10 +270,16 @@
 	symtimes = "";
 #endif
 
-	rprintf(f, "%s  version %s  protocol version %d%s\n",
+	rprintf(f, "%s  version %s  protocol version %d%s (os2-perms)\n",
 		RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
 	rprintf(f, "Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.\n");
 	rprintf(f, "Web site: http://rsync.samba.org/\n");
+#ifdef __OS2__ // 2009-07-22 SHL
+	rprintf(f, "Built by Steven H. Levine " __DATE__ " " __TIME__ "\n");
+	rprintf(f, "Built with GCC " __VERSION__ "\n");
+	if (client_memlimit || daemon_memlimit)
+		rprintf(f, "Using memlimit %u MiBytes\n", memlimit);
+#endif
 	rprintf(f, "Capabilities:\n");
 	rprintf(f, "    %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n",
 		(int)(sizeof (OFF_T) * 8),
@@ -337,6 +356,9 @@
   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
   rprintf(F," -H, --hard-links            preserve hard links\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
+#ifdef __OS2__
+  rprintf(F," -2, --os2-perms             preserve native OS/2 permissions and attributes\n");
+#endif
   rprintf(F," -E, --executability         preserve the file's executability\n");
   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
 #ifdef SUPPORT_ACLS
@@ -423,6 +445,9 @@
   rprintf(F,"     --password-file=FILE    read daemon-access password from FILE\n");
   rprintf(F,"     --list-only             list the files instead of copying them\n");
   rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth; KBytes per second\n");
+#ifdef __OS2__
+  rprintf(F,"     --memlimit=MBytes       limit memory usage, MiBytes\n");
+#endif
   rprintf(F,"     --write-batch=FILE      write a batched update to FILE\n");
   rprintf(F,"     --only-write-batch=FILE like --write-batch but w/o updating destination\n");
   rprintf(F,"     --read-batch=FILE       read a batched update from FILE\n");
@@ -479,6 +504,10 @@
   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
   {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
+#ifdef __OS2__ // 2012-12-20 SHL
+  {"os2-perms",       '2', POPT_ARG_VAL,    &preserve_os2_perms, 1, 0, 0 },
+  {"no-os2-perms",     0,  POPT_ARG_VAL,    &preserve_os2_perms, 0, 0, 0 },
+#endif
   {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
@@ -605,6 +634,9 @@
   {"no-i",             0,  POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
   {"bwlimit",          0,  POPT_ARG_INT,    &bwlimit, 0, 0, 0 },
   {"no-bwlimit",       0,  POPT_ARG_VAL,    &bwlimit, 0, 0, 0 },
+#ifdef __OS2__
+  {"memlimit",         0,  POPT_ARG_INT,    &client_memlimit, 0, 0, 0 },
+#endif
   {"backup",          'b', POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
   {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
   {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
@@ -664,6 +696,9 @@
   rprintf(F,"Usage: rsync --daemon [OPTION]...\n");
   rprintf(F,"     --address=ADDRESS       bind to the specified address\n");
   rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth; KBytes per second\n");
+#ifdef __OS2__
+  rprintf(F,"     --memlimit=MBytes       limit memory usage, MiBytes\n");
+#endif
   rprintf(F,"     --config=FILE           specify alternate rsyncd.conf file\n");
   rprintf(F,"     --no-detach             do not detach from the parent\n");
   rprintf(F,"     --port=PORT             listen on alternate port number\n");
@@ -684,6 +719,9 @@
   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
   {"bwlimit",          0,  POPT_ARG_INT,    &daemon_bwlimit, 0, 0, 0 },
+#ifdef __OS2__
+  {"memlimit",         0,  POPT_ARG_INT,    &daemon_memlimit, 0, 0, 0 },
+#endif
   {"config",           0,  POPT_ARG_STRING, &config_file, 0, 0, 0 },
   {"daemon",           0,  POPT_ARG_NONE,   &daemon_opt, 0, 0, 0 },
   {"ipv4",            '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
@@ -1032,6 +1070,10 @@
 		case OPT_EXCLUDE_FROM:
 		case OPT_INCLUDE_FROM:
 			arg = poptGetOptArg(pc);
+#ifdef __OS2__
+			// 2009-10-18 SHL
+			normalize_dir_slashes((char *)arg);	// hack cough - override const
+#endif
 			if (sanitize_paths)
 				arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 			if (daemon_filter_list.head) {
@@ -1474,6 +1516,7 @@
 			char *dir;
 			if (!*backup_dir)
 				goto options_rejected;
+			// 2009-09-25 SHL FIXME slashes?
 			dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0);
 			clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS);
 			if (check_filter(elp, FLOG, dir, 1) < 0)
@@ -1573,13 +1616,30 @@
 		logfile_format = NULL;
 
 	if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
-		bwlimit = daemon_bwlimit;
+		bwlimit = daemon_bwlimit;	// Pick smaller
 	if (bwlimit) {
 		bwlimit_writemax = (size_t)bwlimit * 128;
 		if (bwlimit_writemax < 512)
 			bwlimit_writemax = 512;
 	}
 
+#ifdef __OS2__
+	if (daemon_memlimit && (!client_memlimit || client_memlimit > daemon_memlimit))
+		client_memlimit = daemon_memlimit;	// Pick smaller
+	// If makes no sense to limit to 2GB or more
+	if (client_memlimit) {
+		if (client_memlimit <= 0x80000000U / 0x100000 ) {
+			memlimit = client_memlimit * 0x100000;	// Scale to MBytes
+		}
+		else {
+			snprintf(err_buf, sizeof err_buf,
+				"--memlimit must by 2GiBytes or less: %u MiBytes\n",
+				client_memlimit);
+			return 0;
+		}
+	}
+#endif
+
 	if (sparse_files && inplace) {
 		/* Note: we don't check for this below, because --append is
 		 * OK with --sparse (as long as redos are handled right). */
@@ -1788,6 +1848,11 @@
 		argstr[x++] = 'p';
 	else if (preserve_executability && am_sender)
 		argstr[x++] = 'E';
+#ifdef __OS2__  // 2009-06-13 SHL
+	if (preserve_os2_perms)
+		argstr[x++] = '2';
+#endif
+
 #ifdef SUPPORT_ACLS
 	if (preserve_acls)
 		argstr[x++] = 'A';
@@ -1930,6 +1995,7 @@
 	}
 
 	/* Only send --suffix if it specifies a non-default value. */
+	// 2012-01-03 SHL can not use strcmp_fs here because other side might be case-sensitive
 	if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
 		/* We use the following syntax to avoid weirdness with '~'. */
 		if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
@@ -2108,6 +2174,10 @@
 			break;
 		}
 		if (*s == ':' || *s == '/') {
+#			ifdef __OS2__	// 2009-06-29 SHL don't confuse drive letter with host spec
+			if (*s == ':' && s == str + 1 && drive_spec_width(s - 1) != 0)
+				continue;
+#			endif
 			if (!hostlen)
 				hostlen = s - host_start;
 			if (*s++ == '/') {
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/params.c ../rsync-3.0.9/params.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/params.c	2007-11-22 09:51:20.000000000 -0800
+++ ../rsync-3.0.9/params.c	2012-02-29 10:45:32.000000000 -0800
@@ -166,9 +166,24 @@
   {
   pos--;
   while( pos >= 0 && isSpace(line + pos) )
-     pos--;
+     pos--;				// Find last non-whitespace
 
+#ifndef __OS2__
   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
+#else
+  // 2010-11-24 SHL handle path specs like c:\ special to avoid
+  // losing \ before it can be mapped to /
+  // Assume parsing value so name and value nul separated
+  if ( pos >= 0) {
+    if (line[pos] != '\\')
+      pos = -1;				// Not continued
+    else if (pos >= 3) {
+      if (*(line + pos - 3) == 0 && drive_spec_width(line + pos - 2) > 0)
+        pos = -1;			// Not continued
+    }
+  }
+  return pos;
+#endif
   } /* Continuation */
 
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/readme.shl ../rsync-3.0.9/readme.shl
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/readme.shl	1969-12-31 16:00:00.000000000 -0800
+++ ../rsync-3.0.9/readme.shl	2012-12-20 18:07:30.000000000 -0800
@@ -0,0 +1,141 @@
+
+Rsync v3.0.9 compiled with GCC 4.4.7 & kLibc v0.6.5 by Steven H. Levine
+
+Requires libc065.dll available from
+  ftp://ftp.netlabs.org/pub/libc/libc-0.6.5-csd5.zip
+  ftp://ftp.netlabs.org/pub/libc/libc-0_6_5-csd5.wpi
+  dated 15 Apr 2012 or newer
+
+These are Steven Levine's notes
+See readme.os2 for Paul Smedley's notes
+
+===============================================================================
+
+WARNING WARNING WIL ROBINSION
+
+This rsync build and all newer rsync builds since 20 Dec 2012 have a new 
+implementation of --os2-perms support.  The new implementation does not 
+require multiple passes to bring the source and destination into complete 
+sync.  However, this required changes to the wire protocol that make it 
+incompatible with rsync builds dated 19 Oct 2012 and older if the --os2-perms 
+options is used.  If the --os2-perms options is not used, there should be no 
+problems.
+
+===============================================================================
+
+Changes in this version (newest first):
+
+- 3.0.9
+
+  - Rework --os2-perms to allow one-pass sync when --xattrs requested
+  - Support --memlimit=MiBytes option, limit memory usage (defaults to 1GiByte)
+  - Switch to gcc 4.4.7 and kLibc 0.6.5
+  - Enable -Zhigh-mem -Zargs-wild -Zargs-resp
+  - Applied 3.0.8 patches
+
+- 3.0.8
+
+  - Switch to gcc 4.4.6 and kLibc 0.6.4
+  - Added more case-insensitive file system support for
+    exclude patterns and well-known file name extensions
+  - Added some more xattrs debug logic (issue# 495)
+  - Updated to rsync v3.0.8 sources
+  - Now building with gcc 4.5.2 - requires gcc452.dll
+
+- 3.0.7
+
+  - --stats -vv now shows memory statistics
+  - --relative now works with drive letters
+  - added some more alloc failure checks
+  - rsync conf now accepts root paths like c:\
+  - --stats shows elapsed time
+  - Filter pattern matches are now case-insensitive
+  - Added logic to ensure directory xattrs updated after libc chmod changes xattrs
+  - Started work on supporting testsuite
+  - Applied 3.0.6 patches
+
+Binary builds are available at
+
+  http://mantis.smedley.info/view.php?id=366
+
+Known issues
+
+- Newly created directories do not always get correct libc extended attributes
+  Next rsync run will set the libc extended attributes to the correct values
+
+- --links probably not fully compatible with --os2_perms
+
+eCS/OS2 specific changes:
+
+- Supports OS/2 extended attributes
+  Enable with --xattrs
+  The default is --no-xattrs
+- Supports drive letters
+- Supports OS/2 style backslashes in path names
+- Supports preserving native OS/2 readonly permissions along
+  with the system, hidden and archive file/directory attributes
+  Enable with --os2-perms
+  The default is --no-os2-perms
+- Supports 2 second native file time resolution
+  Defaults --modify-window to 1 second
+  Disable with --modify-window=0
+- Falls back to shared open if standard open fails
+  Allows open files to be backed up if owner allows reading
+
+Building from source:
+
+- Requires gcc 3.3.5 or better and the usual set of tools
+
+- Apply patches from diff file with
+
+  patch -p0 <diff-file
+
+- Configure with
+
+  export LDFLAGS='-Zmap -Zomf -t'
+  export ac_executable_extensions=.exe
+  export PATH_SEPARATOR=';'
+  sh ./configure --enable-xattr-support
+
+  Unfortunately autoconf 2.6.3 broke a some configure features
+  that worked out of the box in rsync 3.0.5
+
+- Configure works better if PATH contains no backslashes
+
+- Build with
+
+  make
+
+- To create distribution zip file
+
+  Compress rsync with
+    lxlite -X- -B- rsync.exe
+
+  Generate .diff with
+    diff -r ... > rsync-x.y.z-yyyymmdd-iii.diff
+     where x.y.z is rsync version (i.e. 3.0.6) and
+     yyyymmdd is distribution date (i.e. 20090924)
+     iii is your initials (i.e. shl)
+
+  Export DESTDIR to override prefix (see makefile install target)
+    (i.e. export DESTDIR=/tmp)
+
+  Export DIFFFILE to name .diff file to include in distibution
+    (i.e. export DIFFFILE=rsync-3.0.6-20090924-iii)
+
+  Run make install
+
+  cd to $DESTDIR/$prefix
+    (i.e. /tmp/usr/local)
+
+  Create distribution zip with
+    zip -r9o rsync-x.y.z-yyyymmdd.zip * -x '*.zip'
+     where x.y.z is rsync version and
+     yyyymmdd is distribution date
+
+Have fun,
+
+Steven Levine
+Costa Mesa, California, USA
+
+2012-12-20 SHL
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/receiver.c ../rsync-3.0.9/receiver.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/receiver.c	2011-03-26 10:01:36.000000000 -0700
+++ ../rsync-3.0.9/receiver.c	2012-02-29 10:45:32.000000000 -0800
@@ -491,7 +491,7 @@
 				handle_delayed_updates(local_name);
 			send_msg(MSG_DONE, "", 0, 0);
 			continue;
-		}
+		} // NDX_DONE
 
 		if (ndx - cur_flist->ndx_start >= 0)
 			file = cur_flist->files[ndx - cur_flist->ndx_start];
@@ -700,8 +700,9 @@
 			int exists = fd1 != -1;
 #ifdef SUPPORT_ACLS
 			const char *dn = file->dirname ? file->dirname : ".";
+			// 2012-01-03 SHL Support case-insensitive file systems
 			if (parent_dirname != dn
-			 && strcmp(parent_dirname, dn) != 0) {
+			 && strcmp_fs(parent_dirname, dn) != 0) {
 				dflt_perms = default_perms_for_dir(dn);
 				parent_dirname = dn;
 			}
@@ -830,8 +831,8 @@
 			if (inc_recurse)
 				send_msg_int(MSG_NO_SEND, ndx);
 			break;
-		}
-	}
+		} // switch
+	} // while
 	if (make_backups < 0)
 		make_backups = -make_backups;
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/rsync.c ../rsync-3.0.9/rsync.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/rsync.c	2011-02-22 10:48:12.000000000 -0800
+++ ../rsync-3.0.9/rsync.c	2012-12-20 17:01:24.000000000 -0800
@@ -32,6 +32,9 @@
 extern int preserve_acls;
 extern int preserve_xattrs;
 extern int preserve_perms;
+#ifdef __OS2__
+extern int preserve_os2_perms;
+#endif
 extern int preserve_executability;
 extern int preserve_times;
 extern int am_root;
@@ -383,6 +386,8 @@
 	mode_t new_mode = file->mode;
 	int inherit;
 
+	// rprintf(FINFO, "* [%s] set_file_attrs fname %s mode 0%o file %p sxp %p %s(%u)\n", who_am_i(), fname, file->mode, file, sxp, __FILE__, __LINE__); // 2011-05-23 SHL debug os2_perms
+
 	if (!sxp) {
 		if (dry_run)
 			return 1;
@@ -419,6 +424,7 @@
 #ifdef SUPPORT_XATTRS
 	if (am_root < 0)
 		set_stat_xattr(fname, file, new_mode);
+	// 2012-12-20 SHL - FIXME to delay if sure chmod will be called
 	if (preserve_xattrs && fnamecmp)
 		set_xattr(fname, file, fnamecmp, sxp);
 #endif
@@ -503,6 +509,7 @@
 
 #ifdef HAVE_CHMOD
 	if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
+		// rprintf(FINFO, "* [%s] set_file_attrs fname %s sxp->st.st_mode 0%o new_mode 0%o %s(%u)\n", who_am_i(), fname, sxp->st.st_mode, new_mode, __FILE__, __LINE__); // 2009-04-27 SHL debug perms
 		int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
 		if (ret < 0) {
 			rsyserr(FERROR_XFER, errno,
@@ -512,9 +519,34 @@
 		}
 		if (ret == 0) /* ret == 1 if symlink could not be set */
 			updated = 1;
+#ifdef __OS2__
+		// 2012-12-20 SHL os2_perms rework
+		// libc chmod messes up MODE xattrs so we fix here
+		if (am_root >= 0 && ret == 0 && preserve_xattrs) {
+			if (preserve_xattrs && fnamecmp)
+				set_xattr(fname, file, fnamecmp, sxp);
+		}
+#endif
 	}
 #endif
 
+#ifdef __OS2__ // 2012-12-20 SHL os2_perms rework
+#	define OS2_PERMS_BITS (FILE_NORMAL | FILE_READONLY | \
+			       FILE_HIDDEN | FILE_SYSTEM | FILE_ARCHIVED)
+
+	if (!BITS_EQUAL(sxp->st.st_attr, F_OS2_PERMS(file), OS2_PERMS_BITS)) {
+		if (preserve_os2_perms) {
+			int ret = do_set_os2_perms(fname, F_OS2_PERMS(file));
+			if (ret < 0) {
+				rsyserr(FERROR_XFER, errno,
+					"failed to set OS/2 attributes on %s",
+					full_fname(fname));
+				goto cleanup;
+			}
+		}
+		updated = 1;
+	}
+#endif
 	if (verbose > 1 && flags & ATTRS_REPORT) {
 		if (updated)
 			rprintf(FCLIENT, "%s\n", fname);
@@ -560,8 +592,13 @@
 		    int overwriting_basis)
 {
 	int ret;
+	// 2009-02-16 SHL fixme slashes - can we have drive letter here?
 	const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
+	// 2009-02-16 SHL fixme slashes - can we have drive letter here?
+	if (partialptr && drive_spec_width(partialptr))
+		rprintf(FINFO, "* [%s] finish_transfer partialptr %s fname %s fnamecmp %s %s(%u)\n", who_am_i(), partialptr, fname, fnamecmp, __FILE__, __LINE__); // 2009-09-25 SHL debug slashes
+
 	if (inplace) {
 		if (verbose > 2)
 			rprintf(FINFO, "finishing %s\n", fname);
@@ -585,6 +622,7 @@
 		rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
 	ret = robust_rename(fnametmp, fname, temp_copy_name,
 			    file->mode & INITACCESSPERMS);
+
 	if (ret < 0) {
 		rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
 			ret == -2 ? "copy" : "rename",
@@ -597,6 +635,7 @@
 	}
 	if (ret == 0) {
 		/* The file was moved into place (not copied), so it's done. */
+		// rprintf(FINFO, "* [%s] finish_transfer robust_rename moved file %s(%u)\n", who_am_i(), __FILE__, __LINE__); // 2011-05-23 SHL debug os2_perms
 		return 1;
 	}
 	/* The file was copied, so tweak the perms of the copied file.  If it
@@ -604,6 +643,8 @@
 	fnametmp = temp_copy_name ? temp_copy_name : fname;
 
   do_set_file_attrs:
+	// rprintf(FINFO, "* [%s] finish_transfer before set_file_attrs %s %s(%u)\n", who_am_i(), fnametmp, __FILE__, __LINE__); // 2011-05-23 SHL debug os2_perms
+
 	set_file_attrs(fnametmp, file, NULL, fnamecmp,
 		       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/rsync.h ../rsync-3.0.9/rsync.h
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/rsync.h	2011-02-21 11:32:50.000000000 -0800
+++ ../rsync-3.0.9/rsync.h	2012-12-20 18:45:40.000000000 -0800
@@ -62,6 +62,10 @@
 #define XMIT_HLINK_FIRST (1<<12)	/* protocols 30 - now (HLINKED files only) */
 #define XMIT_IO_ERROR_ENDLIST (1<<12)	/* protocols 31*- now (w/XMIT_EXTENDED_FLAGS) (also protocol 30 w/'f' compat flag) */
 
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms rework
+#define XMIT_SAME_OS2_PERMS (1<<15)
+#endif
+
 /* These flags are used in the live flist data. */
 
 #define FLAG_TOP_DIR (1<<0)	/* sender/receiver/generator */
@@ -96,7 +100,11 @@
 			     == ((unsigned)(b2) & (unsigned)(mask)))
 
 /* update this if you make incompatible changes */
+#ifndef __OS2__
 #define PROTOCOL_VERSION 30
+#else
+#define PROTOCOL_VERSION 31
+#endif
 
 /* This is used when working on a new protocol version in CVS, and should
  * be a new non-zero value for each CVS change that affects the protocol.
@@ -655,6 +663,17 @@
 extern int acls_ndx;
 extern int xattrs_ndx;
 
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms rework
+extern int os2_perms_ndx;
+// st_attr bits - from OS/2 Toolkit - avoid need to include os2.h just for this
+#define FILE_NORMAL			0x0000
+#define FILE_READONLY			0x0001
+#define FILE_HIDDEN			0x0002
+#define FILE_SYSTEM			0x0004
+#define FILE_DIRECTORY			0x0010
+#define FILE_ARCHIVED			0x0020
+#endif
+
 #define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
 #define EXTRA_LEN (sizeof (union file_extras))
 #define PTR_EXTRA_CNT ((sizeof (char *) + EXTRA_LEN - 1) / EXTRA_LEN)
@@ -693,6 +712,10 @@
 #define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
 #define F_NDX(f) REQ_EXTRA(f, unsort_ndx)->num
 
+#ifdef __OS2__ // 2012-12-19 SHL os2_perms rework
+#define F_OS2_PERMS(f) REQ_EXTRA(f, os2_perms_ndx)->num /* st_attr */
+#endif
+
 /* These items are per-entry optional: */
 #define F_HL_GNUM(f) OPT_EXTRA(f, LEN64_BUMP(f))->num /* non-dirs */
 #define F_HL_PREV(f) OPT_EXTRA(f, LEN64_BUMP(f)+inc_recurse)->num /* non-dirs */
@@ -1168,3 +1191,22 @@
 #ifdef MAINTAINER_MODE
 const char *get_panic_action(void);
 #endif
+
+// 2009-03-05 SHL support drive letters
+#ifndef __OS2__
+#define drive_spec_width(p) 0
+#define is_abs_path(p) (*(p) == '/')
+#else
+#define drive_spec_width(p) ((isalpha(*(p)) && *((p) + 1) == ':') ? 2 : 0)
+#define is_abs_path(p) (*((p) + drive_spec_width(p)) == '/')
+#endif
+
+// 2012-01-03 SHL support case insensitive file systems
+#ifndef __OS2__
+// case sensitive file system
+#define strcmp_fs strcmp
+#else
+// case insensitive file system
+#define strcmp_fs stricmp
+#endif
+
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/runtests.sh ../rsync-3.0.9/runtests.sh
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/runtests.sh	2011-09-15 07:27:22.000000000 -0700
+++ ../rsync-3.0.9/runtests.sh	2012-02-29 10:45:32.000000000 -0800
@@ -242,8 +242,8 @@
     $setfacl_nodef "$scratchdir" || true
     chmod g-s "$scratchdir"
     case "$srcdir" in
-    /*) ln -s "$srcdir" "$scratchdir/src" ;;
-    *)  ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
+    /*) echo ln -s "$srcdir" "$scratchdir/src" ;;
+    *)  echo ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
     esac
     return 0
 }
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/sender.c ../rsync-3.0.9/sender.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/sender.c	2009-12-12 17:23:02.000000000 -0800
+++ ../rsync-3.0.9/sender.c	2012-02-29 12:05:58.000000000 -0800
@@ -366,7 +366,7 @@
 		send_msg_int(MSG_IO_ERROR, io_error);
 
 	if (verbose > 2)
-		rprintf(FINFO, "send files finished\n");
+		rprintf(FINFO, "send_files finished\n");	// 2009-03-06 SHL
 
 	match_report();
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/syscall.c ../rsync-3.0.9/syscall.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/syscall.c	2011-02-21 11:32:50.000000000 -0800
+++ ../rsync-3.0.9/syscall.c	2012-12-20 17:04:08.000000000 -0800
@@ -28,6 +28,24 @@
 #ifdef HAVE_SYS_ATTR_H
 #include <sys/attr.h>
 #endif
+// 2009-03-06 SHL libc io.h conflicts with rsync io.h - need to cheat to define setmode
+#if defined HAVE_SETMODE && O_BINARY && __OS2__
+// From gcc io.h
+int setmode (int, int);
+// From gcc os2emx.h
+#endif
+#ifdef __OS2__ // 2009-08-01 SHL
+// 2009-08-01 SHL libc io.h conflicts with rsync io.h - need to cheat to define _sopen
+int _sopen (__const__ char *, int, int, ...);	// hack cough
+#include "share.h"			// SH_DENYNO
+#endif
+
+#if defined __OS2__
+// 2009-04-27 SHL Need definitions for FILE_...
+#define INCL_DOS
+// #include <os2.h>
+#include <os2emx.h>
+#endif
 
 extern int dry_run;
 extern int am_root;
@@ -35,6 +53,10 @@
 extern int list_only;
 extern int preserve_perms;
 extern int preserve_executability;
+// 2009-06-13 SHL
+#ifdef __OS2__
+extern int preserve_os2_perms;
+#endif
 
 #define RETURN_ERROR_IF(x,e) \
 	do { \
@@ -138,12 +160,32 @@
 
 int do_open(const char *pathname, int flags, mode_t mode)
 {
+#ifdef __OS2__
+	int fd;
+#endif
 	if (flags != O_RDONLY) {
 		RETURN_ERROR_IF(dry_run, 0);
 		RETURN_ERROR_IF_RO_OR_LO;
 	}
 
+#ifndef __OS2__
 	return open(pathname, flags | O_BINARY, mode);
+#else
+	// 2009-07-31 SHL if open fails, try shared open in case file already opened for write
+	fd = open(pathname, flags | O_BINARY, mode);
+	if (fd == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
+		fd = _sopen(pathname, flags | O_BINARY, SH_DENYNO, mode);
+		if (fd != -1)
+			rprintf(FINFO, "[%s] opened %s for shared write - file may change during sync\n", who_am_i(), pathname);
+		else if (verbose) {
+			int e = errno;
+			rsyserr(FINFO, errno, "do_open _sopen fallback failed for %s", pathname);
+			errno = e;
+		}
+
+	}
+	return fd;
+#endif
 }
 
 #ifdef HAVE_CHMOD
@@ -152,9 +194,14 @@
 	int code;
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+
 #ifdef HAVE_LCHMOD
+	// 2012-12-19 SHL os2_perms rework
 	code = lchmod(path, mode & CHMOD_BITS);
-#else
+#else  // !HAVE_LCHMOD
+#ifdef __OS2__
+#error __OS2__ patch requires LCHMOD defined
+#endif /* __OS2__ */
 	if (S_ISLNK(mode)) {
 # if defined HAVE_SETATTRLIST
 		struct attrlist attrList;
@@ -165,8 +212,8 @@
 		attrList.commonattr = ATTR_CMN_ACCESSMASK;
 		code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
 # else
-		code = 1;
-# endif
+		code = 1;		// Can not set symlink
+# endif // HAVE_SETATTRLIST
 	} else
 		code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
 #endif /* !HAVE_LCHMOD */
@@ -176,6 +223,58 @@
 }
 #endif
 
+#ifdef __OS2__
+// 2012-12-19 SHL os2_perms rework
+
+/* Update OS/2 file/directory attributes
+ * Assume read/only handled by chmod
+ * Handles archived, system and hidden here
+ */
+
+int do_set_os2_perms(const char *path, int32 os2_perms)
+{
+	FILESTATUS3 fs3;
+	APIRET apiret;
+	if (dry_run) return 0;
+	// 2012-12-19 SHL FIXME - RETURN_ERROR_IF_RO_OR_LO;
+
+	// rprintf(FINFO, "* [%s] do_set_os2_perms path %s requested mode 0x%x %s(%u)\n", who_am_i(), path, os2_perms, __FILE__, __LINE__);	// 2011-05-23 SHL debug os2_perms rework
+
+	// Adjust native attributes not handled by chmod - system, hidden, archived
+	// Maybe libc will do this someday
+	// chmod already handles readonly
+	// Adjust attributes if any but archived set or if archived not set in requested attributes
+	apiret = DosQueryPathInfo((PCSZ)path,
+				  FIL_STANDARD,
+				  &fs3,
+				  sizeof(fs3));
+	if (apiret)
+		rprintf(FERROR, "[%s] DosQueryPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 2009-04-27 SHL
+	else {
+		ULONG m = os2_perms | (fs3.attrFile & ~(FILE_SYSTEM | FILE_HIDDEN | FILE_ARCHIVED));
+		if (m != fs3.attrFile) {
+			ULONG old_attrFile = fs3.attrFile;
+			fs3.attrFile = m;
+			apiret = DosSetPathInfo((PCSZ)path,
+						 FIL_STANDARD,
+						 &fs3, sizeof(fs3),
+						 0);
+			if (apiret)
+				rprintf(FERROR, "[%s] DosSetPathInfo(%s) failed with error %lu at %s(%u)\n", who_am_i(), path, apiret, __FILE__, __LINE__);	// 2009-04-27 SHL
+			else if (verbose > 1)
+				rprintf(FINFO, "[%s] changed %s attrFile from 0x%lx to 0x%lx\n", who_am_i(), path, old_attrFile, fs3.attrFile);	// 2012-12-20 SHL os2_perms rework
+		}
+	}
+	if (apiret) {
+		// 2012-12-19 SHL FIXME to map better someday
+		errno = EPERM;
+		return -1;
+	}
+	return 0;
+}
+
+#endif // __OS2__
+
 int do_rename(const char *fname1, const char *fname2)
 {
 	if (dry_run) return 0;
@@ -271,6 +370,7 @@
 # ifdef USE_STAT64_FUNCS
 	return lstat64(fname, st);
 # else
+// 2012-12-19 SHL os2_perms rework
 	return lstat(fname, st);
 # endif
 #else
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/t_stub.c ../rsync-3.0.9/t_stub.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/t_stub.c	2011-02-21 11:32:48.000000000 -0800
+++ ../rsync-3.0.9/t_stub.c	2012-12-20 08:55:14.000000000 -0800
@@ -33,6 +33,12 @@
 char *module_dir;
 struct filter_list_struct daemon_filter_list;
 
+#ifdef __OS2__
+int preserve_os2_perms = 0;
+#endif
+int verbose = 0;
+
+
  void rprintf(UNUSED(enum logcode code), const char *format, ...)
 {
 	va_list ap;
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/t_unsafe.c ../rsync-3.0.9/t_unsafe.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/t_unsafe.c	2009-01-17 13:41:34.000000000 -0800
+++ ../rsync-3.0.9/t_unsafe.c	2012-02-29 10:45:32.000000000 -0800
@@ -27,7 +27,6 @@
 int am_root = 0;
 int read_only = 0;
 int list_only = 0;
-int verbose = 0;
 int preserve_perms = 0;
 int preserve_executability = 0;
 
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/testsuite/rsync.fns ../rsync-3.0.9/testsuite/rsync.fns
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/testsuite/rsync.fns	2011-03-13 20:48:54.000000000 -0700
+++ ../rsync-3.0.9/testsuite/rsync.fns	2012-02-29 10:45:32.000000000 -0800
@@ -151,7 +151,7 @@
 
     echo $ECHO_N "This file has no trailing lf$ECHO_C" > "$fromdir/nolf"
     umask 0
-    ln -s nolf "$fromdir/nolf-symlink"
+    echo ln -s nolf "$fromdir/nolf-symlink"
     umask 022
 
     cat "$srcdir"/*.c > "$fromdir/text"
@@ -321,10 +321,10 @@
 build_symlinks() {
     mkdir "$fromdir"
     date >"$fromdir/referent"
-    ln -s referent "$fromdir/relative"
-    ln -s "$fromdir/referent" "$fromdir/absolute"
-    ln -s nonexistent "$fromdir/dangling"
-    ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
+    echo ln -s referent "$fromdir/relative"
+    echo ln -s "$fromdir/referent" "$fromdir/absolute"
+    echo ln -s nonexistent "$fromdir/dangling"
+    echo ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
 }
 
 test_fail() {
@@ -347,7 +347,7 @@
 }
 
 # Determine what shell command will appropriately test for links.
-ln -s foo "$scratchdir/testlink"
+echo ln -s foo "$scratchdir/testlink"
 for cmd in test /bin/test /usr/bin/test /usr/ucb/bin/test /usr/ucb/test
 do
     for switch in -h -L
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/util.c ../rsync-3.0.9/util.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/util.c	2011-04-22 15:51:54.000000000 -0700
+++ ../rsync-3.0.9/util.c	2012-12-21 01:40:08.000000000 -0800
@@ -23,6 +23,10 @@
 #include "rsync.h"
 #include "ifuncs.h"
 
+#ifdef __OS2__
+#include <os2emx.h>
+#endif
+
 extern int verbose;
 extern int module_id;
 extern int modify_window;
@@ -36,6 +40,7 @@
 extern char *partial_dir;
 extern struct filter_list_struct daemon_filter_list;
 
+
 int sanitize_paths = 0;
 
 char curr_dir[MAXPATHLEN];
@@ -201,6 +206,10 @@
 	char *p;
 	int ret = 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width
+	fname += drive_spec_width(fname);		/* Bypass drive letter */
+#endif /* __OS2__ */
+
 	while (*fname == '/')
 		fname++;
 	while (strncmp(fname, "./", 2) == 0)
@@ -430,6 +439,8 @@
 {
 	int tries = 4;
 
+	// rprintf(FINFO, "* [%s] robust_rename %s->%s %s(%u)\n", who_am_i(), from, to, __FILE__, __LINE__); // 2009-04-27 SHL debug os2_perms
+
 	while (tries--) {
 		if (do_rename(from, to) == 0)
 			return 0;
@@ -454,6 +465,27 @@
 				return -2;
 			do_unlink(from);
 			return 1;
+#ifdef __OS2__ // 2009-04-27 SHL
+		// libc rename semantics differs from linux
+		// clear readonly if this caused rename to fail
+		case EACCES:
+		{
+			STRUCT_STAT st;
+			int code;
+			if (verbose)
+				rprintf(FINFO, "[%s] robust_rename retrying %s after EACCES\n", who_am_i(), to);	// 2009-07-22 SHL
+			code = do_stat(to, &st);
+			if (!code) {
+				// 2009-04-27 SHL fixme to use st_mode when libc fixed
+				if (st.st_attr & FILE_READONLY) {
+					st.st_mode |= S_IWUSR;
+					code = do_chmod(to, st.st_mode);
+					if (!code)
+						break;	// Try again
+				}
+			}
+		}
+#endif
 		default:
 			return -1;
 		}
@@ -828,10 +860,18 @@
 {
 	char *limit = name - 1, *t = name, *f = name;
 	int anchored;
+#ifdef __OS2__
+	int drive_letter_adj;	// 0 if not, 2 if yes 2008-12-15 SHL
+#endif
 
 	if (!name)
 		return 0;
 
+#ifdef __OS2__ // 2009-03-06 SHL use drive_spec_width...
+	drive_letter_adj = drive_spec_width(name);
+	f += drive_letter_adj;			// Keep drive letter
+	t += drive_letter_adj;
+#endif /* __OS2__ */
 	if ((anchored = *f == '/') != 0) {
 		*t++ = *f++;
 #ifdef __CYGWIN__
@@ -879,10 +919,18 @@
 		while (*f && (*t++ = *f++) != '/') {}
 	}
 
+#ifndef __OS2__ // 2009-02-06 SHL
 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 		t--;
 	if (t == name)
 		*t++ = '.';
+#else
+	if (t > name + anchored + drive_letter_adj && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
+		t--;
+	if (t == name + drive_letter_adj)
+		*t++ = '.';		// Ensure not empty
+#endif
+
 	*t = '\0';
 
 	return t - name;
@@ -916,14 +964,28 @@
 	char *start, *sanp;
 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 
+	// rprintf(FINFO, "* [%s] sanitize_path p %s %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
 	if (dest != p) {
 		int plen = strlen(p);
-		if (*p == '/') {
+		int drive_letter_adj = drive_spec_width(p);	// 0 if not, 2 if yes 2008-12-15 SHL
+#ifndef __OS2__
+		if (*p == '/')
+#else // 2009-02-06 SHL use is_abs_path...
+		if (!is_abs_path(p)) {
+			if (drive_letter_adj)
+				rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), p, __FILE__, __LINE__);	// 2009-02-06 SHL
+		} else
+#endif
+		{
 			if (!rootdir)
 				rootdir = module_dir;
 			rlen = strlen(rootdir);
 			depth = 0;
+#ifndef __OS2__
 			p++;
+#else
+			p += drive_spec_width(p) + 1;
+#endif
 		}
 		if (dest) {
 			if (rlen + plen + 1 >= MAXPATHLEN)
@@ -932,8 +994,13 @@
 			out_of_memory("sanitize_path");
 		if (rlen) {
 			memcpy(dest, rootdir, rlen);
+#ifndef __OS2__
 			if (rlen > 1)
 				dest[rlen++] = '/';
+#else
+			if (rlen > 1 + drive_letter_adj)
+				dest[rlen++] = '/';
+#endif
 		}
 	}
 
@@ -977,6 +1044,20 @@
 		}
 		/* copy one component through next slash */
 		while (*p && (*sanp++ = *p++) != '/') {}
+#if 0 // 2009-05-16 SHL fixme to be gone
+#ifndef __OS2__
+		while (*p && (*sanp++ = *p++) != '/') {}
+#else
+		while(*p) {
+			char c = *p++;
+			if (c == '\\')
+				c = '/';
+			*sanp++ = c;
+			if (c == '/')
+				break;
+		}
+#endif
+#endif
 	}
 	if (sanp == dest) {
 		/* ended up with nothing, so put in "." component */
@@ -984,16 +1065,23 @@
 	}
 	*sanp = '\0';
 
+	// rprintf(FINFO, "* [%s] sanitize_path dest %s %s(%u)\n", who_am_i(), dest, __FILE__, __LINE__); // 2009-02-06 SHL debug
+
+	// 2009-05-16 SHL  fixme to be gone
+	assert_no_dir_slashes(dest);
+
 	return dest;
 }
 
 /* Like chdir(), but it keeps track of the current directory (in the
  * global "curr_dir"), and ensures that the path size doesn't overflow.
- * Also cleans the path using the clean_fname() function. */
+ * Also cleans the path using the clean_fname() function.
+ * Returns 1 of change OK.  Otherwise 0 */
 int change_dir(const char *dir, int set_path_only)
 {
 	static int initialised;
 	unsigned int len;
+	// rprintf(FINFO, "* [%s] change_dir dir %s initialised %d %s(%u)\n", who_am_i(), dir ? dir : "(null)", initialised, __FILE__, __LINE__); // 2009-04-27 SHL debug perms
 
 	if (!initialised) {
 		initialised = 1;
@@ -1002,6 +1090,7 @@
 			exit_cleanup(RERR_FILESELECT);
 		}
 		curr_dir_len = strlen(curr_dir);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2009-02-06 SHL debug
 	}
 
 	if (!dir)	/* this call was probably just to initialize */
@@ -1011,24 +1100,50 @@
 	if (len == 1 && *dir == '.')
 		return 1;
 
-	if (*dir == '/') {
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(dir)) {
+		// Absolute path
 		if (len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifndef __OS2__ // 2008-07-28 SHL
 		if (!set_path_only && chdir(dir))
 			return 0;
 		memcpy(curr_dir, dir, len + 1);
+#else
+		if (!set_path_only) {
+			if (chdir(dir)) {
+				rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+			if (drive_spec_width(dir) && _chdrive(*dir)) {
+				rprintf(FERROR, "[%s] change_dir _chdrive failed for dir %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2008-07-28 SHL
+				return 0;
+			}
+		}
+		memcpy(curr_dir, dir, len + 1);
+		// rprintf(FINFO, "* [%s] change_dir curr_dir %s %s(%u)\n", who_am_i(), curr_dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
+#endif
 	} else {
+		// Relative path
 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 			errno = ENAMETOOLONG;
 			return 0;
 		}
+#ifdef __OS2__
+		if (drive_spec_width(dir)) {
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__);	// 2009-02-06 SHL
+			errno = EINVAL;
+			return -1;
+		}
+#endif
 		if (!(curr_dir_len && curr_dir[curr_dir_len-1] == '/'))
 			curr_dir[curr_dir_len++] = '/';
 		memcpy(curr_dir + curr_dir_len, dir, len + 1);
 
 		if (!set_path_only && chdir(curr_dir)) {
+			rprintf(FERROR, "[%s] change_dir chdir failed for %s at %s(%u)\n", who_am_i(), dir, __FILE__, __LINE__); // 2008-07-28 SHL debug
 			curr_dir[curr_dir_len] = '\0';
 			return 0;
 		}
@@ -1053,12 +1168,15 @@
 {
 	unsigned int len;
 
-	if (*path != '/') { /* Make path absolute. */
+	// 2009-03-06 SHL use is_abs_path
+	if (!is_abs_path(path)) { /* Make path absolute. */
 		int len = strlen(path);
+		if (drive_spec_width(path))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2008-07-28 SHL
 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 			return NULL;
 		curr_dir[curr_dir_len] = '/';
-		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
+		memcpy(curr_dir + curr_dir_len + 1, path + drive_spec_width(path), len + 1);
 		if (!(path = strdup(curr_dir)))
 			out_of_memory("normalize_path");
 		curr_dir[curr_dir_len] = '\0';
@@ -1067,7 +1185,9 @@
 			out_of_memory("normalize_path");
 	}
 
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 	len = clean_fname(path, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
+	// fprintf(stderr, "* [%s] path %s at %s(%u)\n", who_am_i(), path, __FILE__, __LINE__); // 2010-09-17 SHL debug
 
 	if (len_ptr)
 		*len_ptr = len;
@@ -1089,11 +1209,24 @@
 	if (result)
 		free(result);
 
-	if (*fn == '/')
+	// 2009-03-06 SHL use is_abs_path
+	if (is_abs_path(fn))
 		p1 = p2 = "";
 	else {
+#ifdef __OS2__
+		if (drive_spec_width(fn))
+			rprintf(FERROR, "[%s] relative directory with drive letter not supported for %s at %s(%u)\n", who_am_i(), fn, __FILE__, __LINE__);	// 2009-02-06 SHL
+#endif
 		p1 = curr_dir + module_dirlen;
+#ifndef __OS2__
 		for (p2 = p1; *p2 == '/'; p2++) {}
+#else
+		// 2012-12-20 SHL
+		p2 = p1;
+		if (!module_dirlen)
+			p2 += drive_spec_width(curr_dir);
+		for (; *p2 == '/'; p2++) {}
+#endif
 		if (*p2)
 			p2 = "/";
 	}
@@ -1120,6 +1253,9 @@
 
 	if ((fn = strrchr(fname, '/')) != NULL) {
 		fn++;
+		// 2009-09-25 SHL fixme slashes - handle drive letter if needed
+		if (partial_dir && drive_spec_width(partial_dir))
+			rprintf(FINFO, "* [%s] partial_dir_fname partial_dir %s fname %s %s(%u)\n", who_am_i(), partial_dir, fname, __FILE__, __LINE__); // 2009-09-25 SHL debug slashes
 		if (*partial_dir != '/') {
 			int len = fn - fname;
 			strncpy(t, fname, len); /* safe */
@@ -1151,6 +1287,7 @@
 
 	if (fname != partial_fname)
 		return 1;
+	// 2009-09-25 SHL fixme slashes?
 	if (!create && *partial_dir == '/')
 		return 1;
 	if (!(fn = strrchr(partial_fname, '/')))
@@ -1421,19 +1558,29 @@
 }
 #endif
 
-#define MALLOC_MAX 0x40000000
+#ifdef __OS2__
+unsigned int memlimit = 0x40000000;	// Overridden by --memlimit
+#define MALLOC_MAX memlimit		// MiBytes
+#else
+#define MALLOC_MAX 0x40000000		// 1GiByte
+#endif
+
 
 void *_new_array(unsigned long num, unsigned int size, int use_calloc)
 {
-	if (num >= MALLOC_MAX/size)
+	if (num >= MALLOC_MAX/size) {
+	        rprintf(FERROR, "* [%s] _new_array num %lu size %u failed %s(%u)\n", who_am_i(), num, size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		return NULL;
+	}
 	return use_calloc ? calloc(num, size) : malloc(num * size);
 }
 
 void *_realloc_array(void *ptr, unsigned int size, size_t num)
 {
-	if (num >= MALLOC_MAX/size)
+	if (num >= MALLOC_MAX/size) {
+	        rprintf(FERROR, "* [%s] _realloc_array num %lu size %u failed %s(%u)\n", who_am_i(), (unsigned long)num, size, __FILE__, __LINE__);	// 2010-12-23 SHL MALLOC_MAX debug
 		return NULL;
+	}
 	if (!ptr)
 		return malloc(size * num);
 	return realloc(ptr, size * num);
@@ -1469,11 +1616,13 @@
 		s_len = fn_len - (s - fn);
 		fn_len = s - fn;
 		if (s_len == 4) {
-			if (strcmp(s+1, "bak") == 0
-			 || strcmp(s+1, "old") == 0)
+			// 2012-01-03 SHL Support case-insensitive file systems
+			if (strcmp_fs(s+1, "bak") == 0
+			 || strcmp_fs(s+1, "old") == 0)
 				continue;
 		} else if (s_len == 5) {
-			if (strcmp(s+1, "orig") == 0)
+			// 2012-01-03 SHL Support case-insensitive file systems
+			if (strcmp_fs(s+1, "orig") == 0)
 				continue;
 		} else if (s_len > 2 && had_tilde
 		    && s[1] == '~' && isDigit(s + 2))
@@ -1701,3 +1850,24 @@
 	}
 	return (char*)lp->items + (lp->count++ * item_size);
 }
+
+#ifdef __OS2__ // 2009-05-16 SHL
+/**
+ * Convert OS/2 backslashes to unix forward slashes
+ */
+void normalize_dir_slashes(char *path)
+{
+	// 2010-11-24 SHL rework for more speed
+	if (path) {
+		char *p = path;
+		while((p = strchr(p, '\\')) != NULL)
+			*p++ = '/';
+	}
+}
+
+void assert_no_dir_slashes(char *path)
+{
+	if (path && strchr(path, '\\') != 0)
+		rprintf(FERROR, "[%s] unexpected backslash in path %s %s(%u)\n", who_am_i(), path, __FILE__, __LINE__);	// 2009-02-06 SHL
+}
+#endif // __OS2__
diff -ruw -N -xproto.h -xrounding.h -x'*.cache' -x'*.diff' -x'*.exe' -x'*.log' -x'*.map' -x'*.o' -x'*.status' -x'*.sym' -xconfig.h -xMakefile -xshconfig -x'*_shl.cmd' -x'*_shl.site' -x'*_shl' -x.saved -x0diff -x0shl -x0zips -xautom4te.cache -xctags.tag -xdummy -xSHLNotes.txt I:/sla_dev2_browse/rsync/rsync-3.0.9/xattrs.c ../rsync-3.0.9/xattrs.c
--- I:/sla_dev2_browse/rsync/rsync-3.0.9/xattrs.c	2011-09-22 09:02:20.000000000 -0700
+++ ../rsync-3.0.9/xattrs.c	2012-12-20 23:46:22.000000000 -0800
@@ -116,6 +116,8 @@
 {
 	const rsync_xa *xa1 = x1;
 	const rsync_xa *xa2 = x2;
+	// rprintf(FINFO, "* [%s] rsync_xal_compare_names xa1.name %s xa2.name %s %s(%u)\n", who_am_i(), xa1->name, xa2->name, __FILE__, __LINE__); // 2008-07-28 SHL debug xattrs
+
 	return strcmp(xa1->name, xa2->name);
 }
 
@@ -143,11 +145,13 @@
 			arg = (double)namebuf_len;
 		  got_error:
 			rsyserr(FERROR_XFER, errno,
-				"get_xattr_names: llistxattr(\"%s\",%.0f) failed",
+				"get_xattr_names: llistxattr(%s,%.0f) failed",
 				full_fname(fname), arg);
 			return -1;
 		}
+		/* Expand buffer - get size */
 		list_len = sys_llistxattr(fname, NULL, 0);
+		/* Should not occur */
 		if (list_len < 0) {
 			arg = 0;
 			goto got_error;
@@ -179,7 +183,7 @@
 		if (errno == ENOTSUP || no_missing_error)
 			return NULL;
 		rsyserr(FERROR_XFER, errno,
-			"get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed",
+			"get_xattr_data: lgetxattr(%s,\"%s\",0) failed",
 			full_fname(fname), name);
 		return NULL;
 	}
@@ -196,11 +200,11 @@
 		if (len != datum_len) {
 			if (len == (size_t)-1) {
 				rsyserr(FERROR_XFER, errno,
-				    "get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
+				    "get_xattr_data: lgetxattr(%s,\"%s\",%ld)"
 				    " failed", full_fname(fname), name, (long)datum_len);
 			} else {
 				rprintf(FERROR_XFER,
-				    "get_xattr_data: lgetxattr(\"%s\",\"%s\",%ld)"
+				    "get_xattr_data: lgetxattr(%s,\"%s\",%ld)"
 				    " returned %ld\n", full_fname(fname), name,
 				    (long)datum_len, (long)len);
 			}
@@ -246,9 +250,11 @@
 			 || (am_root < 0
 			  && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
 			   || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
-			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
+			   || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) {
+				// rprintf(FINFO, "* [%s] rsync_xal_get skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 2009-10-04 SHL debug xattrs
 				continue;
 		}
+		}
 
 		datum_len = name_len; /* Pass extra size to get_xattr_data() */
 		if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
@@ -309,10 +315,12 @@
 			return 0;
 	}
 
+	// rprintf(FINFO, "* [%s] get_xattr fname %s %s(%u)\n", who_am_i(), fname, __FILE__, __LINE__); // 2009-10-04 SHL debug xattrs
 	if (rsync_xal_get(fname, sxp->xattr) < 0) {
 		free_xattr(sxp);
 		return -1;
 	}
+	// rprintf(FINFO, "* [%s] get_xattr count %d %s(%u)\n", who_am_i(), sxp->xattr ? sxp->xattr->count : -1, __FILE__, __LINE__); // 2009-10-04 SHL debug xattrs
 	return 0;
 }
 
@@ -347,7 +355,7 @@
 		if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
 			int save_errno = errno ? errno : EINVAL;
 			rsyserr(FERROR_XFER, errno,
-				"copy_xattrs: lsetxattr(\"%s\",\"%s\") failed",
+				"copy_xattrs: lsetxattr(%s,\"%s\") failed",
 				full_fname(dest), name);
 			errno = save_errno;
 			return -1;
@@ -485,11 +493,13 @@
 	snd_rxa = lst->items;
 	snd_cnt = lst->count;
 
+	// rprintf(FINFO, "* [%s] xattr_diff fname %s rec_cnt %u snd_cnt %u find_all %u %s(%u)\n", who_am_i(), file->basename, rec_cnt, snd_cnt, find_all, __FILE__, __LINE__); // 2009-10-04 SHL debug xattrs
+
 	/* 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) {
 		if (!find_all)
-			return 1;
+			return 1;	// Say different
 		xattrs_equal = 0;
 	}
 
@@ -511,7 +521,7 @@
 		}
 		if (!same) {
 			if (!find_all)
-				return 1;
+				return 1;	// Say different
 			xattrs_equal = 0;
 		}
 
@@ -528,6 +538,8 @@
 	if (rec_cnt)
 		xattrs_equal = 0;
 
+	// rprintf(FINFO, "* [%s] xattr_diff xattrs_equal %u %s(%u)\n", who_am_i(), xattrs_equal, __FILE__, __LINE__); // 2009-10-04 SHL debug xattrs
+
 	return !xattrs_equal;
 }
 
@@ -678,6 +690,8 @@
 		temp_xattr.count = 0;
 	}
 
+	// rprintf(FINFO, "* [%s] receive_xattr %s read count %u am_root %u %s(%u)\n", who_am_i(), file->basename, count, am_root, __FILE__, __LINE__); // 2008-07-28 SHL debug xattrs
+
 	for (num = 1; num <= count; num++) {
 		char *ptr, *name;
 		rsync_xa *rxa;
@@ -724,12 +738,14 @@
 			memcpy(name, RSYNC_PREFIX, RPRE_LEN);
 		} else {
 			free(ptr);
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 2008-07-28 SHL debug xattrs
 			continue;
 		}
 #endif
 		/* No rsync.%FOO attributes are copied w/o 2 -X options. */
 		if (preserve_xattrs < 2 && name_len > RPRE_LEN
 		 && name[RPRE_LEN] == '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
+			// rprintf(FINFO, "* [%s] receive_xattr skipping %s %s(%u)\n", who_am_i(), name, __FILE__, __LINE__); // 2008-07-28 SHL debug xattrs
 			free(ptr);
 			continue;
 		}
@@ -741,13 +757,17 @@
 		rxa->num = num;
 	}
 
-	if (need_sort && count > 1)
-		qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names);
+	// rprintf(FINFO, "* [%s] receive_xattr temp_xattr.items %p temp_xattr.count %u %s(%u)\n", who_am_i(), temp_xattr.items, temp_xattr.count, __FILE__, __LINE__); // 2008-07-28 SHL debug xattrs
+
+	// 2008-07-28 SHL sort number used not number malloced
+	if (need_sort && temp_xattr.count > 1)
+		qsort(temp_xattr.items, temp_xattr.count, sizeof (rsync_xa), rsync_xal_compare_names);
 
 	ndx = rsync_xal_l.count; /* pre-incremented count */
 	rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */
 
 	F_XATTR(file) = ndx;
+	// rprintf(FINFO, "* [%s] receive_xattr %s ndx %u count %d %s(%u)\n", who_am_i(), file->basename, ndx, rsync_xal_l.count, __FILE__, __LINE__); // 2008-07-28 SHL debug xattrs
 }
 
 /* Turn the xattr data in stat_x into cached xattr data, setting the index
@@ -794,6 +814,7 @@
 	size_t name_len;
 	int ret = 0;
 
+	// rprintf(FINFO, "* [%s] rsync_xal_set fname %s fnamecmp %s %s(%u)\n", who_am_i(), fname, fnamecmp, __FILE__, __LINE__); // 2010-03-23 SHL debug libc chmod xattrs
 	/* This puts the current name list into the "namebuf" buffer. */
 	if ((list_len = get_xattr_names(fname)) < 0)
 		return -1;
@@ -830,7 +851,7 @@
 				; /* 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",
+					"rsync_xal_set: lsetxattr(%s,\"%s\") failed",
 					full_fname(fname), name);
 				ret = -1;
 			} else /* make sure caller sets mtime */
@@ -851,7 +872,7 @@
 
 		if (sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len) < 0) {
 			rsyserr(FERROR_XFER, errno,
-				"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
+				"rsync_xal_set: lsetxattr(%s,\"%s\") failed",
 				full_fname(fname), name);
 			ret = -1;
 		} else /* make sure caller sets mtime */
@@ -881,7 +902,7 @@
 		if (i == xalp->count) {
 			if (sys_lremovexattr(fname, name) < 0) {
 				rsyserr(FERROR_XFER, errno,
-					"rsync_xal_set: lremovexattr(\"%s\",\"%s\") failed",
+					"rsync_xal_set: lremovexattr(%s,\"%s\") failed",
 					full_fname(fname), name);
 				ret = -1;
 			} else /* make sure caller sets mtime */
@@ -943,7 +964,7 @@
 	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",
+			"set_xattr_acl: lsetxattr(%s,\"%s\") failed",
 			full_fname(fname), name);
 		return -1;
 	}

Steven Levine

2012-12-23 04:19

manager   ~0002387

rsync-3.0.9-20121221-shl

Changes in this version (newest first):

  - Rework --os2-perms to allow one-pass sync when --xattrs requested
  - Bump PROTOCOL_VERSION to 31
  - Support --memlimit=MiBytes option, limit memory usage (defaults to 1GiByte)
  - Switch to gcc 4.4.7 and kLibc 0.6.5
  - Enable -Zhigh-mem -Zargs-wild -Zargs-resp

Steven Levine

2017-11-30 06:15

manager   ~0003155

rsync-3.0.9.1-20171111-shl

Changes in this version (newest first):

  - Ensure MAXPATHLEN set to 260 if not already set (rsync.h)
  - Ensure tmp path names do not exceed OS/2 259 character limit (receiver.c)
  - Try DosQueryFileInfo if DosQueryPathInfo fails with ERROR_SHARING_VIOLATION (sysxattrs.c)
  - Avoid touch_up_dirs noise messages
  - Switch to gcc 4.9.2 and kLIBC 0.6.6
  - Retry DosSetPathInfo operations that fail with ERROR_SHARING_VIOLATION (syscall.c)

rsync-3.0.9.1-20171111-shl.zip (365,290 bytes)

Issue History

Date Modified Username Field Change
2009-07-30 12:00 Steven Levine New Issue
2009-07-30 12:00 Steven Levine File Added: rsync-3.0.6-20090728-shl.diff
2009-07-30 12:00 Steven Levine Status new => assigned
2009-07-30 12:00 Steven Levine Assigned To => Steven Levine
2009-09-24 09:01 Steven Levine File Added: rsync-3.0.6-20090918-shl.diff
2009-09-24 09:01 Steven Levine Note Added: 0001409
2009-09-25 12:21 Steven Levine File Added: rsync-3.0.6-20090924-shl.diff
2009-09-25 12:21 Steven Levine File Added: rsync-3.0.6-20090924-shl.zip
2009-09-25 12:22 Steven Levine File Deleted: rsync-3.0.6-20090728-shl.diff
2009-10-15 10:54 Steven Levine File Added: rsync-3.0.6-20091014-shl.diff
2009-10-15 10:55 Steven Levine File Added: rsync-3.0.6-20091014-shl.zip
2009-10-15 10:55 Steven Levine Note Added: 0001420
2009-10-15 10:56 Steven Levine File Deleted: rsync-3.0.6-20090918-shl.diff
2010-04-14 04:29 Steven Levine File Added: rsync-3.0.7-20100413-shl.diff
2010-04-14 04:34 Steven Levine Note Added: 0001534
2010-08-16 13:18 Steven Levine File Added: rsync-3.0.7-os2-20100409.zip
2010-08-16 13:23 Steven Levine File Deleted: rsync-3.0.7-os2-20100409.zip
2010-08-16 13:29 Steven Levine File Added: rsync-3.0.7-20100413-shl.zip
2010-08-16 13:31 Steven Levine Note Added: 0001710
2010-10-31 05:33 Steven Levine Summary rsync 3.0.6 patch collector => rsync 3.0.x patch collector
2010-10-31 05:33 Steven Levine Description Updated View Revisions
2010-11-25 08:52 Steven Levine File Added: rsync-3.0.7-20101124-shl.diff
2010-11-25 08:52 Steven Levine File Added: rsync-3.0.7-20101124-shl.zip
2010-11-25 08:54 Steven Levine Note Added: 0001769
2011-04-26 14:44 Steven Levine File Added: rsync-3.0.8-20110425-shl.zip
2011-04-26 14:44 Steven Levine File Added: rsync-3.0.8-20110425-shl.diff
2011-04-26 14:47 Steven Levine Note Added: 0001912
2011-07-03 03:21 Steven Levine File Added: rsync-3.0.8-20110702-shl.zip
2011-07-03 03:22 Steven Levine File Added: rsync-3.0.8-20110702-shl.diff
2011-07-03 03:31 Steven Levine File Deleted: rsync-3.0.8-20110702-shl.zip
2011-07-03 03:31 Steven Levine File Deleted: rsync-3.0.8-20110702-shl.diff
2011-07-03 03:32 Steven Levine File Added: rsync-3.0.8-20110702-shl.zip
2011-07-03 03:32 Steven Levine File Added: rsync-3.0.8-20110702-shl.diff
2011-07-03 03:36 Steven Levine File Deleted: rsync-3.0.8-20110702-shl.zip
2011-07-03 03:36 Steven Levine File Added: rsync-3.0.8-20110702-shl.zip
2011-07-03 03:38 Steven Levine Note Added: 0001933
2011-07-03 03:42 Steven Levine File Deleted: rsync-3.0.8-20110702-shl.zip
2011-07-03 03:43 Steven Levine File Added: rsync-3.0.8-20110702-shl.zip
2011-12-31 16:00 Steven Levine File Added: rsync-3.0.8-20111230-shl.zip
2011-12-31 16:01 Steven Levine File Added: rsync-3.0.8-20111230-shl.diff
2011-12-31 16:02 Steven Levine Note Added: 0002097
2012-12-23 04:17 Steven Levine File Added: rsync-3.0.9-20121221-shl.zip
2012-12-23 04:18 Steven Levine File Added: rsync-3.0.9-20121221-shl.diff
2012-12-23 04:19 Steven Levine Note Added: 0002387
2012-12-23 04:20 Steven Levine Relationship added related to 0000514
2017-11-30 06:15 Steven Levine File Added: rsync-3.0.9.1-20171111-shl.zip
2017-11-30 06:15 Steven Levine Note Added: 0003155
2017-11-30 06:16 Steven Levine Product Version 3.0.6 => 3.0.9