X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/18882701d2f775869f3402b7f26c69246b5be212..07bff66fb5740d91fde22e733ca180f8e9acbb57:/main.c diff --git a/main.c b/main.c index 03af24bb..28803c8b 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,15 +478,26 @@ 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"); - exit_cleanup(RERR_SOCKETIO); + 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_IPC); } io_flush(NORMAL_FLUSH); - if ((pid = do_fork()) == 0) { + if ((pid = do_fork()) == -1) { + rsyserr(FERROR, errno, "fork failed in do_recv"); + exit_cleanup(RERR_IPC); + } + + if (pid == 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 +507,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 +526,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 +538,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); @@ -544,6 +562,13 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) struct file_list *flist; char *local_name = NULL; char *dir = NULL; + int save_verbose = verbose; + + if (filesfrom_fd >= 0) { + /* We can't mix messages with files-from data on the socket, + * so temporarily turn off verbose messages. */ + verbose = 0; + } if (verbose > 2) { rprintf(FINFO, "server_recv(%d) starting pid=%ld\n", @@ -573,15 +598,17 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) recv_exclude_list(f_in); if (filesfrom_fd >= 0) { - /* We're receiving the file info from the sender, so we need - * the IO routines to automatically write out the names onto - * our f_out socket as we read the list info from the sender. - * This avoids both deadlock and extra delays/buffers. */ + /* We need to send the files-from names to the sender at the + * same time that we receive the file-list from them, so we + * need the IO routines to automatically write out the names + * onto our f_out socket as we read the file-list. This + * avoids both deadlock and extra delays/buffers. */ io_set_filesfrom_fds(filesfrom_fd, f_out); filesfrom_fd = -1; } flist = recv_file_list(f_in); + verbose = save_verbose; if (!flist) { rprintf(FERROR,"server_recv: recv_file_list error\n"); exit_cleanup(RERR_FILESELECT); @@ -670,6 +697,8 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) if (am_sender) { keep_dirlinks = 0; /* Must be disabled on the sender. */ io_start_buffering_out(); + if (!remote_filesfrom_file) + set_msg_fd_in(f_in); if (cvs_exclude) add_cvs_excludes(); if (delete_mode && !delete_excluded) @@ -681,6 +710,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) start_write_batch(f_out); if (!read_batch) /* don't write to pipe */ flist = send_file_list(f_out,argc,argv); + set_msg_fd_in(-1); if (verbose > 3) rprintf(FINFO,"file list sent\n");