X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/d9c7edf63f9da2d30dced5629734551dc874e47a..e80a7654127e03b6bac23c1efc2226129bbc8bfe:/main.c diff --git a/main.c b/main.c index 95e25b30..25cd1064 100644 --- a/main.c +++ b/main.c @@ -24,10 +24,14 @@ time_t starttime = 0; extern struct stats stats; +extern char *files_from; +extern int filesfrom_fd; +extern char *remote_filesfrom_file; extern int am_server; extern int am_sender; extern int am_daemon; extern int verbose; +extern int protocol_version; /* there's probably never more than at most 2 outstanding child processes, * but set it higher just in case. @@ -79,10 +83,9 @@ static void report(int f) { time_t t = time(NULL); extern int do_stats; - extern int remote_version; int send_stats; - if (do_stats) { + if (do_stats && verbose > 1) { /* These come out from every process */ show_malloc_stats(); show_flist_stats(); @@ -93,7 +96,7 @@ static void report(int f) if (f == -1 || !am_sender) return; } - send_stats = verbose || (remote_version >= 20); + send_stats = verbose || protocol_version >= 20; if (am_server) { if (am_sender && send_stats) { int64 w; @@ -139,12 +142,12 @@ static void report(int f) rprintf(FINFO,"File list size: %d\n", stats.flist_size); rprintf(FINFO,"Total bytes written: %.0f\n", (double)stats.total_written); - rprintf(FINFO,"Total bytes read: %.0f\n\n", + rprintf(FINFO,"Total bytes read: %.0f\n", (double)stats.total_read); } if (verbose || do_stats) { - rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n", + rprintf(FINFO,"\nwrote %.0f bytes read %.0f bytes %.2f bytes/sec\n", (double)stats.total_written, (double)stats.total_read, (stats.total_written+stats.total_read)/(0.5 + (t-starttime))); @@ -282,6 +285,7 @@ oom: static char *get_local_name(struct file_list *flist,char *name) { STRUCT_STAT st; + int e; extern int orig_umask; if (verbose > 2) @@ -307,7 +311,7 @@ static char *get_local_name(struct file_list *flist,char *name) return name; } - if (flist->count <= 1) + if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/')) return name; if (do_mkdir(name,0777 & ~orig_umask) != 0) { @@ -338,7 +342,6 @@ 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()); @@ -372,7 +375,7 @@ 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) { + if (protocol_version >= 24) { /* final goodbye message */ read_int(f_in); } @@ -391,7 +394,6 @@ 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); @@ -452,7 +454,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) read_int(recv_pipe[0]); close(recv_pipe[0]); - if (remote_version >= 24) { + if (protocol_version >= 24) { /* send a final goodbye message */ write_int(f_out, -1); } @@ -501,6 +503,15 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) if (delete_mode && !delete_excluded) 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. */ + io_set_filesfrom_fds(filesfrom_fd, f_out); + filesfrom_fd = -1; + } + if (read_batch) flist = batch_flist; else @@ -533,7 +544,6 @@ int child_main(int argc, char *argv[]) void start_server(int f_in, int f_out, int argc, char *argv[]) { extern int cvs_exclude; - extern int remote_version; extern int read_batch; setup_protocol(f_out, f_in); @@ -541,7 +551,7 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) set_nonblocking(f_in); set_nonblocking(f_out); - if (remote_version >= 23) + if (protocol_version >= 23) io_start_multiplex_out(f_out); if (am_sender) { @@ -567,7 +577,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) struct file_list *flist = NULL; int status = 0, status2 = 0; char *local_name = NULL; - extern int remote_version; extern pid_t cleanup_child_pid; extern int write_batch; extern int read_batch; @@ -582,7 +591,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) setup_protocol(f_out,f_in); - if (remote_version >= 23) + if (protocol_version >= 23) io_start_multiplex_in(f_in); if (am_sender) { @@ -593,13 +602,15 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) add_cvs_excludes(); if (delete_mode && !delete_excluded) send_exclude_list(f_out); + if (remote_filesfrom_file) + filesfrom_fd = f_in; if (!read_batch) /* dw -- don't write to pipe */ flist = send_file_list(f_out,argc,argv); if (verbose > 3) rprintf(FINFO,"file list sent\n"); send_files(flist,f_out,f_in); - if (remote_version >= 24) { + if (protocol_version >= 24) { /* final goodbye message */ read_int(f_in); } @@ -621,6 +632,11 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) if (!write_batch) send_exclude_list(f_out); + if (filesfrom_fd >= 0) { + io_set_filesfrom_fds(filesfrom_fd, f_out); + filesfrom_fd = -1; + } + flist = recv_file_list(f_in); if (!flist || flist->count == 0) { rprintf(FINFO, "client: nothing to do: " @@ -643,22 +659,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) return MAX(status, status2); } -static char *find_colon(char *s) -{ - char *p, *p2; - - p = strchr(s,':'); - if (!p) return NULL; - - /* now check to see if there is a / in the string before the : - if there is then - discard the colon on the assumption that the : is part of a filename */ - p2 = strchr(s,'/'); - if (p2 && p2 < p) return NULL; - - return p; -} - - static int copy_argv (char *argv[]) { int i; @@ -727,6 +727,13 @@ static int start_client(int argc, char *argv[]) if (!read_batch) { p = find_colon(argv[0]); if (p) { + if (remote_filesfrom_file + && remote_filesfrom_file != files_from + 1 + && strncmp(files_from, argv[0], p-argv[0]+1) != 0) { + rprintf(FERROR, + "--files-from hostname is not transfer hostname\n"); + exit_cleanup(RERR_SYNTAX); + } if (p[1] == ':') { /* double colon */ *p = 0; if (!shell_cmd) { @@ -772,8 +779,20 @@ static int start_client(int argc, char *argv[]) } p = find_colon(argv[argc-1]); + if (p && remote_filesfrom_file + && remote_filesfrom_file != files_from + 1 + && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) { + rprintf(FERROR, + "--files-from hostname is not transfer hostname\n"); + exit_cleanup(RERR_SYNTAX); + } if (!p) { local_server = 1; + if (remote_filesfrom_file) { + rprintf(FERROR, + "--files-from is remote but transfer is local\n"); + exit_cleanup(RERR_SYNTAX); + } } else if (p[1] == ':') { /* double colon */ *p = 0; if (!shell_cmd) { @@ -854,17 +873,20 @@ static int start_client(int argc, char *argv[]) } -static RETSIGTYPE sigusr1_handler(int UNUSED(val)) { +static RETSIGTYPE sigusr1_handler(UNUSED(int val)) +{ exit_cleanup(RERR_SIGNAL); } -static RETSIGTYPE sigusr2_handler(int UNUSED(val)) { +static RETSIGTYPE sigusr2_handler(UNUSED(int val)) +{ extern int log_got_error; if (log_got_error) _exit(RERR_PARTIAL); _exit(0); } -static RETSIGTYPE sigchld_handler(int UNUSED(val)) { +static RETSIGTYPE sigchld_handler(UNUSED(int val)) +{ #ifdef WNOHANG int cnt, status; pid_t pid; @@ -922,7 +944,7 @@ const char *get_panic_action(void) * should just look at the environment variable, but I'm a bit leery * of a signal sending us into a busy loop. **/ -static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig)) +static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig)) { char cmd_buf[300]; int ret; @@ -1033,6 +1055,5 @@ int main(int argc,char *argv[]) else exit_cleanup(ret); - exit(ret); - /* NOTREACHED */ + return ret; }