X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/6957ae33a931950d03cbba0d0cb78be1920f26f3..c32d024071bd1519de936be65eaf8687260926ac:/main.c diff --git a/main.c b/main.c index a5467782..e54ae8b0 100644 --- a/main.c +++ b/main.c @@ -25,6 +25,19 @@ struct stats stats; extern int verbose; + +/**************************************************************************** +wait for a process to exit, calling io_flush while waiting +****************************************************************************/ +void wait_process(pid_t pid, int *status) +{ + while (waitpid(pid, status, WNOHANG) == 0) { + msleep(20); + io_flush(); + } + *status = WEXITSTATUS(*status); +} + static void report(int f) { time_t t = time(NULL); @@ -112,6 +125,7 @@ static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f char *tok,*dir=NULL; extern int local_server; extern char *rsync_path; + extern int blocking_io; if (!local_server) { if (!cmd) @@ -144,6 +158,9 @@ static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f args[argc++] = rsync_path; server_options(args,&argc); + + + if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1; } args[argc++] = "."; @@ -236,6 +253,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) char *dir = argv[0]; extern int relative_paths; extern int recurse; + extern int remote_version; if (verbose > 2) rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid()); @@ -267,7 +285,12 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) } send_files(flist,f_out,f_in); + io_flush(); report(f_out); + if (remote_version >= 24) { + /* final goodbye message */ + read_int(f_in); + } io_flush(); exit_cleanup(0); } @@ -283,6 +306,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) extern int delete_after; extern int recurse; extern int delete_mode; + extern int remote_version; if (preserve_hard_links) init_hard_links(flist); @@ -294,12 +318,12 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) } } - if (pipe(recv_pipe) < 0) { + if (fd_pair(recv_pipe) < 0) { rprintf(FERROR,"pipe failed in do_recv\n"); exit_cleanup(RERR_SOCKETIO); } - if (pipe(error_pipe) < 0) { + if (fd_pair(error_pipe) < 0) { rprintf(FERROR,"error pipe failed in do_recv\n"); exit_cleanup(RERR_SOCKETIO); } @@ -318,15 +342,20 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) set_error_fd(error_pipe[1]); recv_files(f_in,flist,local_name,recv_pipe[1]); + io_flush(); report(f_in); + write_int(recv_pipe[1],1); + close(recv_pipe[1]); io_flush(); - _exit(0); + /* finally we go to sleep until our parent kills us + with a USR2 signal. We sleep for a short time as on + some OSes a signal won't interrupt a sleep! */ + while (1) msleep(20); } close(recv_pipe[1]); close(error_pipe[1]); - io_close_input(f_in); if (f_in != f_out) close(f_in); io_start_buffering(f_out); @@ -335,7 +364,15 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) generate_files(f_out,flist,local_name,recv_pipe[0]); + read_int(recv_pipe[0]); + close(recv_pipe[0]); + if (remote_version >= 24) { + /* send a final goodbye message */ + write_int(f_out, -1); + } io_flush(); + + kill(pid, SIGUSR2); wait_process(pid, &status); return status; } @@ -350,9 +387,18 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) 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]; @@ -391,9 +437,16 @@ 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; setup_protocol(f_out, f_in); + set_nonblocking(f_in); + set_nonblocking(f_out); + + if (remote_version >= 23) + io_start_multiplex_out(f_out); + if (am_sender) { recv_exclude_list(f_in); if (cvs_exclude) @@ -411,9 +464,15 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[]) int status = 0, status2 = 0; char *local_name = NULL; extern int am_sender; - extern int list_only; + extern int remote_version; + + set_nonblocking(f_in); + set_nonblocking(f_out); setup_protocol(f_out,f_in); + + if (remote_version >= 23) + io_start_multiplex_in(f_in); if (am_sender) { extern int cvs_exclude; @@ -434,17 +493,26 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[]) io_flush(); wait_process(pid, &status); } + if (remote_version >= 24) { + /* final goodbye message */ + read_int(f_in); + } report(-1); exit_cleanup(status); } - if (argc == 0) list_only = 1; + if (argc == 0) { + extern int list_only; + list_only = 1; + } send_exclude_list(f_out); flist = recv_file_list(f_in); if (!flist || flist->count == 0) { - rprintf(FINFO,"client: nothing to do\n"); + rprintf(FINFO, "client: nothing to do: " + "perhaps you need to specify some filenames or " + "the --recursive option?\n"); exit_cleanup(0); } @@ -489,11 +557,12 @@ static int start_client(int argc, char *argv[]) extern int am_sender; extern char *shell_cmd; extern int rsync_port; + char *argv0 = strdup(argv[0]); - if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) { + if (strncasecmp(URL_PREFIX, argv0, strlen(URL_PREFIX)) == 0) { char *host, *path; - host = argv[0] + strlen(URL_PREFIX); + host = argv0 + strlen(URL_PREFIX); p = strchr(host,'/'); if (p) { *p = 0; @@ -509,12 +578,12 @@ static int start_client(int argc, char *argv[]) return start_socket_client(host, path, argc-1, argv+1); } - p = find_colon(argv[0]); + p = find_colon(argv0); if (p) { if (p[1] == ':') { *p = 0; - return start_socket_client(argv[0], p+2, argc-1, argv+1); + return start_socket_client(argv0, p+2, argc-1, argv+1); } if (argc < 1) { @@ -576,6 +645,11 @@ static int start_client(int argc, char *argv[]) usage(FERROR); exit_cleanup(RERR_SYNTAX); } + + if (argc == 0 && !am_sender) { + extern int list_only; + list_only = 1; + } pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out); @@ -592,6 +666,10 @@ static RETSIGTYPE sigusr1_handler(int val) { exit_cleanup(RERR_SIGNAL); } +static RETSIGTYPE sigusr2_handler(int val) { + _exit(0); +} + int main(int argc,char *argv[]) { extern int am_root; @@ -601,6 +679,7 @@ int main(int argc,char *argv[]) extern int am_server; signal(SIGUSR1, sigusr1_handler); + signal(SIGUSR2, sigusr2_handler); starttime = time(NULL); am_root = (getuid() == 0); @@ -656,6 +735,8 @@ int main(int argc,char *argv[]) #endif if (am_server) { + set_nonblocking(STDIN_FILENO); + set_nonblocking(STDOUT_FILENO); start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv); }