Hello everyone,

I have run into the same issue which the fname-convert patch solves:

http://rsync.samba.org/ftp/unpacked/rsync/patches/fname-convert.diff

i.e. rsyncing between and latin 1 and utf-8 locales.

First I'd really like to thank Eran Tromer for providing the patch as
this fixes my immediate issue!  I've attached an updated version which
applies to the rsync-2.6.5 release and includes updates to proto.h.

I must admit, I would have been fully pleased with a libiconv solution
that merely interprets the file names in the character set defined be
the current locale of the process and converted into UTF-8 internally
for comparison/transfer to the remote system, and converts the UTF-8
representation back to the charset defined by the local process on when
writing files.  But this would have needed both rsync versions to
support this feature, couldn't handle conversion if the file names on
the local system could not be interpreted in the locale of the process
and of course lacks the extreme flexibility of the conversion which this
solution allows.

It think it would be great if this patch (or something similar) could
make it into the trunk.

Let me also thank Paul Slootman for pointing me to this patch!

Thanks a lot folks!
David Ayers
diff -uNr ../rsync-2.6.5/cleanup.c ./cleanup.c
--- ../rsync-2.6.5/cleanup.c	2005-03-05 19:58:38.000000000 +0100
+++ ./cleanup.c	2005-07-28 11:09:21.852494680 +0200
@@ -25,6 +25,7 @@
 extern int keep_partial;
 extern int log_got_error;
 extern char *partial_dir;
+extern char *fname_convert_cmd;
 
 /**
  * Close all open sockets and files, allowing a (somewhat) graceful
@@ -125,6 +126,8 @@
 				!partial_dir);
 	}
 	io_flush(FULL_FLUSH);
+	if (fname_convert_cmd)
+		cleanup_fname_convert();
 	if (cleanup_fname)
 		do_unlink(cleanup_fname);
 	if (code)
diff -uNr ../rsync-2.6.5/errcode.h ./errcode.h
--- ../rsync-2.6.5/errcode.h	2005-04-13 01:04:10.000000000 +0200
+++ ./errcode.h	2005-07-28 11:09:21.941481152 +0200
@@ -34,6 +34,7 @@
 #define RERR_STREAMIO   12      /* error in rsync protocol data stream */
 #define RERR_MESSAGEIO  13      /* errors with program diagnostics */
 #define RERR_IPC        14      /* error in IPC code */
+#define RERR_FNAMECONV  15      /* error in filename conversion */
 
 #define RERR_SIGNAL     20      /* status returned when sent SIGUSR1, SIGINT */
 #define RERR_WAITCHILD  21      /* some error returned by waitpid() */
diff -uNr ../rsync-2.6.5/flist.c ./flist.c
--- ../rsync-2.6.5/flist.c	2005-05-27 20:15:18.000000000 +0200
+++ ./flist.c	2005-07-28 11:09:21.943480848 +0200
@@ -57,6 +57,7 @@
 extern int protocol_version;
 extern int sanitize_paths;
 extern int orig_umask;
+extern char *fname_convert_cmd;
 extern struct stats stats;
 extern struct file_list *the_file_list;
 
@@ -339,7 +340,10 @@
 
 	io_write_phase = "send_file_entry";
 
-	f_name_to(file, fname);
+	if (fname_convert_cmd && !am_server) /* fname conversion always done on client */
+		convert_fname(fname, f_name(file), MAXPATHLEN);
+	else
+		f_name_to(file, fname);
 
 	flags = base_flags;
 
@@ -555,6 +559,9 @@
 
 	strlcpy(lastname, thisname, MAXPATHLEN);
 
+	if (fname_convert_cmd && !am_server) /* fname conversion always done on client */
+		convert_fname(thisname, lastname, MAXPATHLEN);
+
 	clean_fname(thisname, 0);
 
 	if (sanitize_paths)
@@ -1085,6 +1092,9 @@
 	start_write = stats.total_written;
 	gettimeofday(&start_tv, NULL);
 
+	if (!am_server)
+		init_fname_convert();
+
 	flist = flist_new(WITH_HLINK, "send_file_list");
 
 	io_start_buffering_out();
@@ -1279,6 +1289,9 @@
 	stats.flist_size = stats.total_written - start_write;
 	stats.num_files = flist->count;
 
+	if (fname_convert_cmd && !am_server)
+		cleanup_fname_convert();
+
 	if (verbose > 3)
 		output_flist(flist);
 
@@ -1300,6 +1313,9 @@
 
 	start_read = stats.total_read;
 
+	if (fname_convert_cmd && !am_server)
+		init_fname_convert();
+
 	flist = flist_new(WITH_HLINK, "recv_file_list");
 
 	flist->count = 0;
@@ -1352,6 +1368,9 @@
 			io_error |= read_int(f);
 	}
 
+	if (fname_convert_cmd && !am_server)
+		cleanup_fname_convert();
+
 	if (verbose > 3)
 		output_flist(flist);
 
diff -uNr ../rsync-2.6.5/fnameconv.c ./fnameconv.c
--- ../rsync-2.6.5/fnameconv.c	1970-01-01 01:00:00.000000000 +0100
+++ ./fnameconv.c	2005-07-28 11:29:59.202388904 +0200
@@ -0,0 +1,220 @@
+/*  -*- c-file-style: "linux" -*-
+ *
+ * Copyright (C) 2004 by Eran Tromer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Handles filename conversion through an external process. Implements
+ * two modes of operation:
+ * In persistent mode, a single filename converter is kept running;
+ * for each query we feed it a single line and read back a single
+ * line. This will fail for programs that used buffered I/O, and will
+ * get into a deadlock.
+ * In non-persistent mode, a converter is invoked and killed for each
+ * query. This has a very high overhead, but will work for any
+ * program.
+ * We start in persistence mode, and if we suspect a deadlock (i.e.,
+ * nothing happens for FNAME_CONV_PERSISTENCE_TIMEOUT milliseconds)
+ * then we smoothly fall back to non-persistent mode.
+ *
+ * Filename conversion errors are always considered fatal, since an
+ * incorrectly named file could cause unpredictable damage.
+ */
+
+#include <rsync.h>
+
+#define FNAME_CONV_PERSISTENCE_TIMEOUT 3000 /* milliseconds */
+
+static int conv_persistent = 1;
+static pid_t conv_pid = -1;
+static int conv_write_fd = -1, conv_read_fd;
+extern char *fname_convert_cmd;
+extern int blocking_io;
+
+/**
+ * Splits cmd on spaces.
+ */
+static void split_on_spaces(char *cmd, char **parts) {
+	int nparts = 0;
+	char *tok;
+	char *cmd2 = strdup(cmd);
+	if (!cmd2) {
+		rprintf(FERROR, "Out of memory while parsing filename filter %s\n", cmd);
+		exit_cleanup(RERR_MALLOC);
+	}
+
+	for (tok = strtok(cmd2, " "); tok; tok = strtok(NULL, " ")) {
+		if (nparts >= MAX_ARGS) {
+			rprintf(FERROR, "Filename conversion command is too long: %s\n", cmd);
+			exit_cleanup(RERR_SYNTAX);
+		}
+		parts[nparts++] = tok;
+	}
+	parts[nparts] = NULL;
+}
+
+
+/**
+ * Runs the filename converter process. Should be called before filename
+ * conversion begins (actually it's not necessarh, but it keeps the proress report
+ * nice and clean.
+ **/
+void init_fname_convert(void)
+{
+	if (fname_convert_cmd && conv_pid < 0) {
+		char *args[MAX_ARGS];
+
+		if (verbose > 2)
+			rprintf(FINFO, "Running filename converter: %s\n", fname_convert_cmd);
+		split_on_spaces(fname_convert_cmd, args);
+		/* Invoke child pipe with non-blocking IO and without registering it for
+		 * autocleanup (the latter may blow up the all_pids table, and is not needed
+		 * since we have our own cleanup handler. */
+		conv_pid = piped_child(args, &conv_read_fd, &conv_write_fd, 0, 0);
+		set_nonblocking(conv_write_fd);
+		set_nonblocking(conv_read_fd);
+	}
+}
+
+/**
+ * Kills the filename converter process. Should be called when the file
+ * list creation is done. We assume that the converter will terminate
+ * soon after its standard input is closed.
+ **/
+void cleanup_fname_convert()
+{
+	if (conv_pid >= 0) {
+		int status;
+		if (conv_write_fd >= 0) {
+			close(conv_write_fd);
+			conv_write_fd = -1;
+		}
+		close(conv_read_fd);
+		waitpid(conv_pid, &status, 0);
+		conv_pid = -1;
+	}
+}
+
+/**
+ * Converts the filename from src into dest, using at most maxlen
+ * characters of dest.
+ **/
+void convert_fname(char *dest, const char *src, unsigned int maxlen)
+{
+	int res;
+	const char *srcp;
+	char *destp;
+	unsigned int srcrem, dstrem;
+
+	init_fname_convert();
+
+	/* Send and receive strings simultaneously to avoid deadlock: */
+	srcrem = strlen(src)+1; /* chars left to send (incl. terminating LF) */
+	dstrem = maxlen-1;      /* free chars left in dest                   */
+	srcp = src;
+	destp = dest;
+	while(1) {
+		/* Write as much as possible: */
+		if (srcrem > 1) {
+			res = write(conv_write_fd, srcp, srcrem-1);
+			if (res < 0 && errno != EAGAIN) {
+				rprintf(FERROR, "Error writing to fname converter (filename: %s): %s\n", strerror(errno), src);
+				exit_cleanup(RERR_FNAMECONV);
+			}
+			if (res > 0) { /* wrote something */
+				srcp += res;
+				srcrem -= res;
+			}
+		}
+		if (srcrem == 1) { /* final LF */
+			res = write(conv_write_fd, "\n", 1);
+			if (res < 0 && errno != EAGAIN) {
+				rprintf(FERROR, "Error writing to fname converter (filename: %s): %s\n", strerror(errno), src);
+				exit_cleanup(RERR_FNAMECONV);
+			}
+			if (res > 0) { /* wrote final LF */
+				srcrem = 0;
+				if (!conv_persistent) {
+					close(conv_write_fd);
+					conv_write_fd = -1;
+				}
+			}
+		}
+
+		/* Read as much as possible: */
+		res = read(conv_read_fd, destp, dstrem);
+		if (res < 0 && errno != EAGAIN) {
+			rprintf(FERROR, "Error reading from filename converter (filename: %s):%s \n", strerror(errno), src);
+			exit_cleanup(RERR_FNAMECONV);
+		}
+		if (res == 0) { /* EOF */
+			rprintf(FERROR, "EOF from filename converter (filename: %s)\n", src);
+			exit_cleanup(RERR_FNAMECONV);
+		}
+		if (res > 0) {
+			destp += res;
+			dstrem -= res;
+			if (destp[-1] == '\n' || destp[-1] == '\r')
+				break; /* End of line. Yippy! */
+			if (dstrem == 0) {
+				rprintf(FINFO, "Name converter output too long (filename: %s)\n", src);
+				exit_cleanup(RERR_FNAMECONV);
+			}
+		}
+
+		/* Await activity */
+		if (!await_fds(conv_read_fd, !srcrem ? -1 : conv_write_fd, FNAME_CONV_PERSISTENCE_TIMEOUT)) {
+			if (srcrem == 0 && conv_persistent) {
+				/* We finished writing but nothing happens. It looks like the converter program
+				 * is using buffered I/O and thus wait to read more input, but we can't give it
+				 * the next filename yet. Fall back to non-persistent mode.                      */
+				if (verbose > 0)
+					rprintf(FINFO, "Filename converter blocked, disabling persistence to recover.\n");
+
+				conv_persistent = 0;
+				close(conv_write_fd);
+				conv_write_fd = -1;
+			}
+		}
+	}
+
+	/* Cleanup and sanity check */
+	if (!conv_persistent)
+		cleanup_fname_convert();
+	if (srcrem > 0) {
+		close(conv_write_fd);
+		rprintf(FERROR, "Name converter produced output before reading all its input for file: %s\n", src);
+		exit_cleanup(RERR_FNAMECONV);
+	}
+
+	/* Chop newline chars */
+	destp--;
+	if (destp > dest && *destp == '\n')
+		--destp;
+	if (destp > dest && *destp == '\r')
+		--destp;
+	if (++destp == dest) {
+		rprintf(FERROR, "Name converter output is empty (filename: %s)\n", src);
+		exit_cleanup(RERR_FNAMECONV);
+	}
+	*destp = 0;
+	/* Also, we may have a leading CR left over from a CRLF of the previous line */
+	if (*dest == '\n')
+		memmove(dest, dest+1, destp-dest-1);
+
+	if (verbose > 2)
+		rprintf(FINFO, "Converted filename: %s -> %s\n", src, dest);
+}
diff -uNr ../rsync-2.6.5/generator.c ./generator.c
--- ../rsync-2.6.5/generator.c	2005-05-22 22:52:32.000000000 +0200
+++ ./generator.c	2005-07-28 11:09:22.033467168 +0200
@@ -583,7 +583,14 @@
  * start sending checksums.
  *
  * Note that f_out is set to -1 when doing final directory-permission and
- * modification-time repair. */
+ * modification-time repair.
+ *
+ * TODO: The filename seen in recv_generator is after filename
+ * conversion.  In verbose mode, directories, symlinks and device
+ * files are printf()ed here but regular files are rprintf()ed on the
+ * sender (unconverted). To solve the above, move all progress
+ * reporting to the sender. */
 static void recv_generator(char *fname, struct file_struct *file, int ndx,
 			   int itemizing, int maybe_PERMS_REPORT,
 			   enum logcode code, int f_out)
diff -uNr ../rsync-2.6.5/log.c ./log.c
--- ../rsync-2.6.5/log.c	2005-04-14 18:08:10.000000000 +0200
+++ ./log.c	2005-07-28 11:09:22.120453944 +0200
@@ -65,6 +65,7 @@
 	{ RERR_STREAMIO   , "error in rsync protocol data stream" },
 	{ RERR_MESSAGEIO  , "errors with program diagnostics" },
 	{ RERR_IPC        , "error in IPC code" },
+	{ RERR_FNAMECONV  , "error in filename conversion" },
 	{ RERR_SIGNAL     , "received SIGUSR1 or SIGINT" },
 	{ RERR_WAITCHILD  , "some error returned by waitpid()" },
 	{ RERR_MALLOC     , "error allocating core memory buffers" },
diff -uNr ../rsync-2.6.5/main.c ./main.c
--- ../rsync-2.6.5/main.c	2005-05-12 09:43:14.000000000 +0200
+++ ./main.c	2005-07-28 11:09:22.122453640 +0200
@@ -373,7 +373,7 @@
 			whole_file = 1;
 		ret = local_child(argc, args, f_in, f_out, child_main);
 	} else
-		ret = piped_child(args,f_in,f_out);
+		ret = piped_child(args, f_in, f_out, blocking_io, 1);
 
 	if (dir)
 		free(dir);
diff -uNr ../rsync-2.6.5/Makefile.in ./Makefile.in
--- ../rsync-2.6.5/Makefile.in	2004-11-02 17:47:15.000000000 +0100
+++ ./Makefile.in	2005-07-28 11:09:21.851494832 +0200
@@ -35,7 +35,7 @@
 	main.o checksum.o match.o syscall.o log.o backup.o
 OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o \
 	fileio.o batch.o clientname.o
-OBJS3=progress.o pipe.o
+OBJS3=progress.o pipe.o fnameconv.o
 DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
 popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
 	popt/popthelp.o popt/poptparse.o
diff -uNr ../rsync-2.6.5/options.c ./options.c
--- ../rsync-2.6.5/options.c	2005-05-19 10:52:17.000000000 +0200
+++ ./options.c	2005-07-28 11:09:22.210440264 +0200
@@ -138,6 +138,7 @@
 char *config_file = NULL;
 char *shell_cmd = NULL;
 char *log_format = NULL;
+char *fname_convert_cmd = NULL;
 char *password_file = NULL;
 char *rsync_path = RSYNC_PATH;
 char *backup_dir = NULL;
@@ -321,6 +322,7 @@
   rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
   rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
   rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
+  rprintf(F,"     --fname-convert=CMD     invoke CMD for filename conversion\n");
   rprintf(F," -z, --compress              compress file data during the transfer\n");
   rprintf(F," -C, --cvs-exclude           auto-ignore files the same way CVS does\n");
   rprintf(F," -f, --filter=RULE           add a file-filtering RULE\n");
@@ -433,6 +435,7 @@
   {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
   {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
   {"fuzzy",           'y', POPT_ARG_NONE,   &fuzzy_basis, 0, 0, 0 },
+  {"fname-convert",    0,  POPT_ARG_STRING, &fname_convert_cmd, 0, 0, 0 },
   /* TODO: Should this take an optional int giving the compression level? */
   {"compress",        'z', POPT_ARG_NONE,   &do_compression, 0, 0, 0 },
   {"stats",            0,  POPT_ARG_NONE,   &do_stats, 0, 0, 0 },
diff -uNr ../rsync-2.6.5/pipe.c ./pipe.c
--- ../rsync-2.6.5/pipe.c	2005-04-09 20:59:42.000000000 +0200
+++ ./pipe.c	2005-07-28 11:09:22.211440112 +0200
@@ -23,7 +23,6 @@
 
 extern int am_sender;
 extern int am_server;
-extern int blocking_io;
 extern int orig_umask;
 extern int filesfrom_fd;
 
@@ -39,8 +38,10 @@
  * If blocking_io is set then use blocking io on both fds. That can be
  * used to cope with badly broken rsh implementations like the one on
  * Solaris.
+ *
+ * If register_child is nonzero then the child is registered for autocleanup.
  **/
-pid_t piped_child(char **command, int *f_in, int *f_out)
+pid_t piped_child(char **command, int *f_in, int *f_out, int blocking_io, int register_child)
 {
 	pid_t pid;
 	int to_child_pipe[2];
@@ -55,7 +56,7 @@
 		exit_cleanup(RERR_IPC);
 	}
 
-	pid = do_fork();
+	pid = register_child ? do_fork() : fork();
 	if (pid == -1) {
 		rsyserr(FERROR, errno, "fork");
 		exit_cleanup(RERR_IPC);
diff -uNr ../rsync-2.6.5/proto.h ./proto.h
--- ../rsync-2.6.5/proto.h	2005-05-19 10:52:11.000000000 +0200
+++ ./proto.h	2005-07-28 11:32:34.630760200 +0200
@@ -24,6 +24,7 @@
 void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
 		 int fd_r, int fd_w);
 void cleanup_set_pid(pid_t pid);
+void cleanup_fname_convert();
 char *client_addr(int fd);
 char *client_name(int fd);
 void client_sockaddr(int fd,
@@ -80,6 +81,8 @@
 int f_name_cmp(struct file_struct *f1, struct file_struct *f2);
 char *f_name_to(struct file_struct *f, char *fbuf);
 char *f_name(struct file_struct *f);
+void convert_fname(char *dest, const char *src, unsigned int maxlen);
+void init_fname_convert(void);
 struct file_list *get_dirlist(char *dirname, int dlen,
 			      int ignore_filter_rules);
 void itemize(struct file_struct *file, int ndx, int statret, STRUCT_STAT *st,
@@ -206,7 +209,7 @@
 BOOL pm_process( char *FileName,
                  BOOL (*sfunc)(char *),
                  BOOL (*pfunc)(char *, char *) );
-pid_t piped_child(char **command, int *f_in, int *f_out);
+pid_t piped_child(char **command, int *f_in, int *f_out, int blocking_io, int register_child);
 pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
 		  int (*child_main)(int, char*[]));
 void end_progress(OFF_T size);
@@ -250,6 +253,8 @@
 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_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
+char await_fds(int read_fd, int write_fd, int timeout_ms);
 char *d_name(struct dirent *di);
 void set_compression(char *fname);
 void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
diff -uNr ../rsync-2.6.5/syscall.c ./syscall.c
--- ../rsync-2.6.5/syscall.c	2005-04-06 04:08:21.000000000 +0200
+++ ./syscall.c	2005-07-28 11:09:22.211440112 +0200
@@ -259,3 +259,34 @@
 	return di->d_name;
 #endif
 }
+
+/**
+ * A wrapper around select(2) that guarantees Linux-like updating of
+ * the timeout argument to contain the time left, so we can simply
+ * re-invoke in case of EINTR or EAGAIN.  On BSD, select(2) doesn't
+ * change the timeout argument by itself.
+ **/
+int do_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+  	struct timeval intended, before, after;
+	int result;
+
+	if (timeout == NULL)
+		return select(n, readfds, writefds, exceptfds, timeout);
+
+	intended = *timeout;
+	gettimeofday(&before, NULL);
+	result = select(n, readfds, writefds, exceptfds, timeout);
+	gettimeofday(&after, NULL);
+	timeout->tv_sec = intended.tv_sec - (after.tv_sec - before.tv_sec);
+	timeout->tv_usec = intended.tv_usec - (after.tv_usec - before.tv_usec);
+	if (timeout->tv_usec >= 1000000) {
+		++timeout->tv_sec;
+		timeout->tv_usec -= 1000000;
+	} else if (timeout->tv_usec < 0) {
+		--(timeout)->tv_sec;
+		timeout->tv_usec += 1000000;
+	}
+
+	return result;
+}
diff -uNr ../rsync-2.6.5/util.c ./util.c
--- ../rsync-2.6.5/util.c	2005-05-03 18:44:47.000000000 +0200
+++ ./util.c	2005-07-28 11:09:22.297427040 +0200
@@ -1338,3 +1338,56 @@
 
 	return a[len2-1];
 }
+
+/**
+ * Blocks until one of the following happens:
+ * - read_fd is nonnegative and has data to read
+ * - write_fd is nonnegative and can be written to
+ * - something terrible happened to either
+ * - the timeout (in milliseconds) has elapsed
+ * Return value is zero iff the timeout occured.
+ */
+char await_fds(int read_fd, int write_fd, int timeout_ms)
+{
+	fd_set read_fds, write_fds, except_fds;
+	struct timeval tv;
+	int res;
+
+	tv.tv_sec = timeout_ms / 1000;
+	tv.tv_usec = (timeout_ms % 1000) * 1000;
+
+	while (1) {
+		int maxfd = 0;
+		FD_ZERO(&read_fds);
+		FD_ZERO(&write_fds);
+		FD_ZERO(&except_fds);
+		if (write_fd >= 0) {
+			FD_SET(write_fd, &write_fds);
+			FD_SET(write_fd, &except_fds);
+			if (write_fd > maxfd)
+				maxfd = write_fd;
+		}
+		if (read_fd >= 0) {
+			FD_SET(read_fd, &read_fds);
+			FD_SET(read_fd, &except_fds);
+			if (read_fd > maxfd)
+				maxfd = read_fd;
+		}
+
+		res = do_select(maxfd+1, &read_fds, &write_fds, &except_fds, &tv);
+		if (res > 0)
+			return 1;
+		if (res < 0) {
+			if (errno == EINTR || errno == EAGAIN)
+				continue; /* Retry */
+			rprintf(FERROR, "Error awaiting fname converter: %s\n", strerror(errno));
+			exit_cleanup(RERR_FNAMECONV);
+		}
+		if (read_fd >= 0 && (FD_ISSET(read_fd, &read_fds) || FD_ISSET(read_fd, &except_fds)))
+			return 1;
+		if (write_fd >= 0 && (FD_ISSET(write_fd, &write_fds) || FD_ISSET(write_fd, &except_fds)))
+			return 1;
+		return 0; /* res == 0 and no FDs set, hence a timeout. */
+	}
+}
-- 
To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to