X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/e19452a96c164ddb14941cf4977d44534631bfbe..09b7f5dbb189f6d1a3543d8f4f2f22b20d5fd3da:/main.c diff --git a/main.c b/main.c index bfd0341b..11344eb2 100644 --- a/main.c +++ b/main.c @@ -23,8 +23,6 @@ time_t starttime = 0; struct stats stats; -extern int csum_length; - extern int verbose; static void report(int f) @@ -34,16 +32,23 @@ static void report(int f) extern int am_sender; extern int am_daemon; extern int do_stats; + extern int remote_version; + int send_stats; if (am_daemon) { log_exit(0, __FILE__, __LINE__); if (f == -1 || !am_sender) return; } + send_stats = verbose || (remote_version >= 20); if (am_server) { - if (verbose && am_sender) { + if (am_sender && send_stats) { + int64 w; + /* store total_written in a temporary + because write_longint changes it */ + w = stats.total_written; write_longint(f,stats.total_read); - write_longint(f,stats.total_written); + write_longint(f,w); write_longint(f,stats.total_size); } return; @@ -51,24 +56,22 @@ static void report(int f) /* this is the client */ - if (!am_sender && verbose) { - /* note that if (!verbose && do_stats) then these values will - be taken from the receiver side's copy. The total size - is identical but the bytes read and written are slightly - different. It's done this way to avoid modifying the - protocol to support --stats without -v. */ + if (!am_sender && send_stats) { + int64 r; stats.total_written = read_longint(f); - stats.total_read = read_longint(f); + /* store total_read in a temporary, read_longint changes it */ + r = read_longint(f); stats.total_size = read_longint(f); - - /* when the total_read was set above just now it would not - have included the last two longints, but the last - read_longint would have compensated for one of them. - Compensate for the other one too by adding 8. */ - stats.total_read += sizeof(int64); + stats.total_read = r; } if (do_stats) { + if (!am_sender && !send_stats) { + /* missing the bytes written by the generator */ + rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n"); + rprintf(FINFO, "Use --stats -v to show stats\n"); + return; + } rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files); rprintf(FINFO,"Number of files transferred: %d\n", stats.num_transferred_files); @@ -203,7 +206,7 @@ static char *get_local_name(struct file_list *flist,char *name) return name; } - if (flist->count == 1) + if (flist->count <= 1) return name; if (do_mkdir(name,0777 & ~orig_umask) != 0) { @@ -258,10 +261,6 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) argv[0] = "."; } - set_nonblocking(f_out); - if (f_in != f_out) - set_nonblocking(f_in); - flist = send_file_list(f_out,argc,argv); if (!flist || flist->count == 0) { exit_cleanup(0); @@ -279,24 +278,44 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) int pid; int status=0; int recv_pipe[2]; + int error_pipe[2]; extern int preserve_hard_links; + extern int delete_after; + extern int recurse; + extern int delete_mode; if (preserve_hard_links) init_hard_links(flist); - if (pipe(recv_pipe) < 0) { + if (!delete_after) { + /* I moved this here from recv_files() to prevent a race condition */ + if (recurse && delete_mode && !local_name && flist->count>0) { + delete_files(flist); + } + } + + if (fd_pair(recv_pipe) < 0) { rprintf(FERROR,"pipe failed in do_recv\n"); exit_cleanup(RERR_SOCKETIO); } + + if (fd_pair(error_pipe) < 0) { + rprintf(FERROR,"error pipe failed in do_recv\n"); + exit_cleanup(RERR_SOCKETIO); + } io_flush(); if ((pid=do_fork()) == 0) { close(recv_pipe[0]); + close(error_pipe[0]); if (f_in != f_out) close(f_out); - set_nonblocking(f_in); - set_nonblocking(recv_pipe[1]); + /* we can't let two processes write to the socket at one time */ + io_multiplexing_close(); + + /* set place to send errors */ + set_error_fd(error_pipe[1]); recv_files(f_in,flist,local_name,recv_pipe[1]); report(f_in); @@ -306,18 +325,18 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) } close(recv_pipe[1]); + close(error_pipe[1]); io_close_input(f_in); if (f_in != f_out) close(f_in); - set_nonblocking(f_out); - set_nonblocking(recv_pipe[0]); - io_start_buffering(f_out); + io_set_error_fd(error_pipe[0]); + generate_files(f_out,flist,local_name,recv_pipe[0]); io_flush(); - waitpid(pid, &status, 0); + wait_process(pid, &status); return status; } @@ -329,10 +348,20 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) char *local_name=NULL; char *dir = NULL; extern int delete_mode; + extern int delete_excluded; extern int am_daemon; + extern int module_id; + extern int am_sender; if (verbose > 2) rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid()); + + if (am_daemon && lp_read_only(module_id) && !am_sender) { + rprintf(FERROR,"ERROR: module is read only\n"); + exit_cleanup(RERR_SYNTAX); + return; + } + if (argc > 0) { dir = argv[0]; @@ -345,12 +374,12 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) } } - if (delete_mode) + if (delete_mode && !delete_excluded) recv_exclude_list(f_in); flist = recv_file_list(f_in); - if (!flist || flist->count == 0) { - rprintf(FERROR,"server_recv: nothing to do\n"); + if (!flist) { + rprintf(FERROR,"server_recv: recv_file_list error\n"); exit_cleanup(RERR_FILESELECT); } @@ -371,13 +400,13 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) { extern int cvs_exclude; extern int am_sender; + extern int remote_version; - set_nonblocking(f_out); - if (f_in != f_out) - set_nonblocking(f_in); - setup_protocol(f_out, f_in); + if (remote_version >= 23) + io_start_multiplex_out(f_out); + if (am_sender) { recv_exclude_list(f_in); if (cvs_exclude) @@ -396,30 +425,31 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[]) char *local_name = NULL; extern int am_sender; extern int list_only; + extern int remote_version; setup_protocol(f_out,f_in); + + if (remote_version >= 23) + io_start_multiplex_in(f_in); if (am_sender) { extern int cvs_exclude; extern int delete_mode; + extern int delete_excluded; if (cvs_exclude) add_cvs_excludes(); - if (delete_mode) + if (delete_mode && !delete_excluded) send_exclude_list(f_out); flist = send_file_list(f_out,argc,argv); if (verbose > 3) rprintf(FINFO,"file list sent\n"); - set_nonblocking(f_out); - if (f_in != f_out) - set_nonblocking(f_in); - send_files(flist,f_out,f_in); if (pid != -1) { if (verbose > 3) rprintf(FINFO,"client_run waiting on %d\n",pid); io_flush(); - waitpid(pid, &status, 0); + wait_process(pid, &status); } report(-1); exit_cleanup(status); @@ -443,7 +473,7 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[]) if (verbose > 3) rprintf(FINFO,"client_run2 waiting on %d\n",pid); io_flush(); - waitpid(pid, &status, 0); + wait_process(pid, &status); } return status | status2;