X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/41cfde6be388364f9bf7dfa9a532625b1f660df7..32cbfe7b17ba8ec661fc27fd773909709d100e8a:/main.c diff --git a/main.c b/main.c index 20c93c25..3cc21b59 100644 --- a/main.c +++ b/main.c @@ -23,23 +23,19 @@ time_t starttime = 0; -extern struct stats stats; +extern int verbose; +extern int dry_run; +extern int list_only; extern int am_root; extern int am_server; extern int am_sender; extern int am_generator; extern int am_daemon; -extern int verbose; extern int blocking_io; -extern int cvs_exclude; -extern int delete_mode; -extern int delete_excluded; -extern int delete_after; +extern int remove_sent_files; extern int daemon_over_rsh; +extern int need_messages_from_generator; extern int do_stats; -extern int dry_run; -extern int list_only; -extern int local_server; extern int log_got_error; extern int module_id; extern int orig_umask; @@ -48,8 +44,11 @@ extern int keep_dirlinks; extern int preserve_hard_links; extern int protocol_version; extern int recurse; +extern int fuzzy_basis; extern int relative_paths; extern int rsync_port; +extern int inplace; +extern int make_backups; extern int whole_file; extern int read_batch; extern int write_batch; @@ -57,17 +56,19 @@ extern int batch_fd; extern int batch_gen_fd; extern int filesfrom_fd; extern pid_t cleanup_child_pid; +extern struct stats stats; extern char *files_from; extern char *remote_filesfrom_file; -extern char *compare_dest; +extern char *partial_dir; +extern char *basis_dir[]; extern char *rsync_path; extern char *shell_cmd; extern char *batch_name; +int local_server = 0; -/* there's probably never more than at most 2 outstanding child processes, - * but set it higher just in case. - */ +/* There's probably never more than at most 2 outstanding child processes, + * but set it higher, just in case. */ #define MAXCHILDPROCS 5 struct pid_status { @@ -146,6 +147,10 @@ static void report(int f) write_longint(f, total_read); write_longint(f, total_written); write_longint(f, stats.total_size); + if (protocol_version >= 29) { + write_longint(f, stats.flist_buildtime); + write_longint(f, stats.flist_xfertime); + } } return; } @@ -158,12 +163,20 @@ static void report(int f) total_written = read_longint(f); total_read = read_longint(f); stats.total_size = read_longint(f); + if (protocol_version >= 29) { + stats.flist_buildtime = read_longint(f); + stats.flist_xfertime = read_longint(f); + } } else if (write_batch) { /* The --read-batch process is going to be a client * receiver, so we need to give it the stats. */ write_longint(batch_fd, total_read); write_longint(batch_fd, total_written); write_longint(batch_fd, stats.total_size); + if (protocol_version >= 29) { + write_longint(batch_fd, stats.flist_buildtime); + write_longint(batch_fd, stats.flist_xfertime); + } } if (do_stats) { @@ -179,6 +192,14 @@ static void report(int f) rprintf(FINFO,"Matched data: %.0f bytes\n", (double)stats.matched_data); rprintf(FINFO,"File list size: %d\n", stats.flist_size); + if (stats.flist_buildtime) { + rprintf(FINFO, + "File list generation time: %.3f seconds\n", + (double)stats.flist_buildtime / 1000); + rprintf(FINFO, + "File list transfer time: %.3f seconds\n", + (double)stats.flist_xfertime / 1000); + } rprintf(FINFO,"Total bytes sent: %.0f\n", (double)total_written); rprintf(FINFO,"Total bytes received: %.0f\n", @@ -211,22 +232,30 @@ static void show_malloc_stats(void) mi = mallinfo(); rprintf(FINFO, "\n" RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n", - getpid(), - am_server ? "server " : "", - am_daemon ? "daemon " : "", - who_am_i()); - rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena); - rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks); - rprintf(FINFO, " smblks: %10d\n", mi.smblks); - rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks); - rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd); - rprintf(FINFO, " allmem: %10d (bytes from sbrk + mmap)\n", - mi.arena + mi.hblkhd); - rprintf(FINFO, " usmblks: %10d\n", mi.usmblks); - rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks); - rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks); - rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks); - rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost); + getpid(), am_server ? "server " : "", + am_daemon ? "daemon " : "", who_am_i()); + rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n", + (long)mi.arena); + rprintf(FINFO, " ordblks: %10ld (chunks not in use)\n", + (long)mi.ordblks); + rprintf(FINFO, " smblks: %10ld\n", + (long)mi.smblks); + rprintf(FINFO, " hblks: %10ld (chunks from mmap)\n", + (long)mi.hblks); + rprintf(FINFO, " hblkhd: %10ld (bytes from mmap)\n", + (long)mi.hblkhd); + rprintf(FINFO, " allmem: %10ld (bytes from sbrk + mmap)\n", + (long)mi.arena + mi.hblkhd); + rprintf(FINFO, " usmblks: %10ld\n", + (long)mi.usmblks); + rprintf(FINFO, " fsmblks: %10ld\n", + (long)mi.fsmblks); + rprintf(FINFO, " uordblks: %10ld (bytes used)\n", + (long)mi.uordblks); + rprintf(FINFO, " fordblks: %10ld (bytes free)\n", + (long)mi.fordblks); + rprintf(FINFO, " keepcost: %10ld (bytes in releasable chunk)\n", + (long)mi.keepcost); #endif /* HAVE_MALLINFO */ } @@ -267,7 +296,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path, dash_l_set = 1; } -#if HAVE_REMSH +#ifdef HAVE_REMSH /* remsh (on HPUX) takes the arguments the other way around */ args[argc++] = machine; if (user && !(daemon_over_rsh && dash_l_set)) { @@ -312,7 +341,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path, if (verbose > 3) { rprintf(FINFO,"cmd="); for (i = 0; i < argc; i++) - rprintf(FINFO,"%s ",args[i]); + rprintf(FINFO, "%s ", safe_fname(args[i])); rprintf(FINFO,"\n"); } @@ -382,7 +411,7 @@ static char *get_local_name(struct file_list *flist,char *name) exit_cleanup(RERR_FILEIO); } if (verbose > 0) - rprintf(FINFO, "created directory %s\n", name); + rprintf(FINFO, "created directory %s\n", safe_fname(name)); if (dry_run) { dry_run++; @@ -415,6 +444,12 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) exit_cleanup(RERR_SYNTAX); return; } + if (am_daemon && lp_read_only(module_id) && remove_sent_files) { + rprintf(FERROR, + "ERROR: --remove-sent-files cannot be used with a read-only module\n"); + exit_cleanup(RERR_SYNTAX); + return; + } if (!relative_paths && !push_dir(dir)) { rsyserr(FERROR, errno, "push_dir#3 %s failed", @@ -432,7 +467,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[]) argv[i] += l+1; } - if (argc == 0 && recurse) { + if (argc == 0 && (recurse || list_only)) { argc = 1; argv--; argv[0] = "."; @@ -463,7 +498,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], name_pipe[2]; - BOOL need_name_pipe = compare_dest && !dry_run; + BOOL need_name_pipe = (basis_dir[0] || partial_dir || fuzzy_basis + || (inplace && make_backups)) && !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. */ @@ -472,21 +508,20 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) if (preserve_hard_links) init_hard_links(flist); - 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(error_pipe) < 0 || (need_name_pipe && fd_pair(name_pipe) < 0)) { rsyserr(FERROR, errno, "pipe failed in do_recv"); - exit_cleanup(RERR_SOCKETIO); + 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]); @@ -535,7 +570,6 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *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); io_flush(FULL_FLUSH); if (protocol_version >= 24) { @@ -557,6 +591,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", @@ -582,19 +623,20 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) } io_start_buffering_in(); - if (delete_mode && !delete_excluded) - recv_exclude_list(f_in); + recv_filter_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); @@ -634,10 +676,10 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) if (am_sender) { keep_dirlinks = 0; /* Must be disabled on the sender. */ + if (need_messages_from_generator) + io_start_multiplex_in(); - recv_exclude_list(f_in); - if (cvs_exclude) - add_cvs_excludes(); + recv_filter_list(f_in); do_server_sender(f_in, f_out, argc, argv); } else { do_server_recv(f_in, f_out, argc, argv); @@ -657,9 +699,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) char *local_name = NULL; cleanup_child_pid = pid; - if (read_batch) { - assert(am_sender == 0); - } else { + if (!read_batch) { set_nonblocking(f_in); set_nonblocking(f_out); } @@ -683,10 +723,9 @@ 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 (cvs_exclude) - add_cvs_excludes(); - if (delete_mode && !delete_excluded) - send_exclude_list(f_out); + if (!remote_filesfrom_file) + set_msg_fd_in(f_in); + send_filter_list(f_out); if (remote_filesfrom_file) filesfrom_fd = f_in; @@ -694,6 +733,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"); @@ -715,11 +755,13 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) exit_cleanup(status); } + if (need_messages_from_generator && !read_batch) + io_start_multiplex_out(); + if (argc == 0) - list_only = 1; + list_only |= 1; - if (!read_batch) - send_exclude_list(f_out); + send_filter_list(read_batch ? -1 : f_out); if (filesfrom_fd >= 0) { io_set_filesfrom_fds(filesfrom_fd, f_out); @@ -934,10 +976,10 @@ static int start_client(int argc, char *argv[]) if (verbose > 3) { rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n", - shell_cmd?shell_cmd:"", - shell_machine?shell_machine:"", - shell_user?shell_user:"", - shell_path?shell_path:""); + shell_cmd ? safe_fname(shell_cmd) : "", + shell_machine ? safe_fname(shell_machine) : "", + shell_user ? safe_fname(shell_user) : "", + shell_path ? safe_fname(shell_path) : ""); } /* for remote source, only single dest arg can remain ... */ @@ -947,9 +989,8 @@ static int start_client(int argc, char *argv[]) } /* ... or no dest at all */ - if (!am_sender && argc == 0) { - list_only = 1; - } + if (!am_sender && argc == 0) + list_only |= 1; pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path, &f_in,&f_out); @@ -1126,7 +1167,7 @@ int main(int argc,char *argv[]) } if (batch_fd < 0) { rsyserr(FERROR, errno, "Batch file %s open error", - batch_name); + full_fname(batch_name)); exit_cleanup(RERR_FILEIO); } if (read_batch) @@ -1141,9 +1182,6 @@ int main(int argc,char *argv[]) exit_cleanup(RERR_SYNTAX); } - if (dry_run) - verbose = MAX(verbose,1); - if (am_server) { set_nonblocking(STDIN_FILENO); set_nonblocking(STDOUT_FILENO);