X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/50b31539c26885ec2ff9d566e771f7a1ac2a1e20..41cfde6be388364f9bf7dfa9a532625b1f660df7:/main.c diff --git a/main.c b/main.c index 4f3fd909..20c93c25 100644 --- a/main.c +++ b/main.c @@ -59,6 +59,7 @@ extern int filesfrom_fd; extern pid_t cleanup_child_pid; extern char *files_from; extern char *remote_filesfrom_file; +extern char *compare_dest; extern char *rsync_path; extern char *shell_cmd; extern char *batch_name; @@ -461,7 +462,8 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) { int pid; int status = 0; - int error_pipe[2]; + int error_pipe[2], name_pipe[2]; + BOOL need_name_pipe = compare_dest && !dry_run; /* The receiving side mustn't obey this, or an existing symlink that * points to an identical file won't be replaced by the referent. */ @@ -476,8 +478,9 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) delete_files(flist); } - if (fd_pair(error_pipe) < 0) { - rprintf(FERROR,"error pipe failed in do_recv\n"); + if (fd_pair(error_pipe) < 0 + || (need_name_pipe && fd_pair(name_pipe) < 0)) { + rsyserr(FERROR, errno, "pipe failed in do_recv"); exit_cleanup(RERR_SOCKETIO); } @@ -485,6 +488,11 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) if ((pid = do_fork()) == 0) { close(error_pipe[0]); + if (need_name_pipe) { + close(name_pipe[1]); + set_blocking(name_pipe[0]); + } else + name_pipe[0] = -1; if (f_in != f_out) close(f_out); @@ -494,7 +502,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) /* set place to send errors */ set_msg_fd_out(error_pipe[1]); - recv_files(f_in,flist,local_name); + recv_files(f_in, flist, local_name, name_pipe[0]); io_flush(FULL_FLUSH); report(f_in); @@ -513,6 +521,11 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) stop_write_batch(); close(error_pipe[1]); + if (need_name_pipe) { + close(name_pipe[0]); + set_nonblocking(name_pipe[1]); + } else + name_pipe[1] = -1; if (f_in != f_out) close(f_in); @@ -520,7 +533,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) set_msg_fd_in(error_pipe[0]); - generate_files(f_out, flist, local_name); + generate_files(f_out, flist, local_name, name_pipe[1]); get_redo_num(); /* Read final MSG_DONE and any prior messages. */ report(-1); @@ -657,6 +670,16 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) if (protocol_version >= 23 && !read_batch) io_start_multiplex_in(); + /* We set our stderr file handle to blocking because ssh might have + * set it to non-blocking. This can be particularly troublesome if + * stderr is a clone of stdout, because ssh would have set our stdout + * to non-blocking at the same time (which can easily cause us to lose + * output from our print statements). This kluge shouldn't cause ssh + * any problems for how we use it. Note also that we delayed setting + * this until after the above protocol setup so that we know for sure + * that ssh is done twiddling its file descriptors. */ + set_blocking(STDERR_FILENO); + if (am_sender) { keep_dirlinks = 0; /* Must be disabled on the sender. */ io_start_buffering_out();