X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/6d56efa6ea66afa2e6f4eb79d9dd5f3b54b723c3..62342430bfd6e792ef437597bcb30b6def087a95:/main.c diff --git a/main.c b/main.c index 73440865..8c2307a8 100644 --- a/main.c +++ b/main.c @@ -4,7 +4,7 @@ * Copyright (C) 1996-2001 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * Copyright (C) 2001, 2002 Martin Pool - * Copyright (C) 2003-2008 Wayne Davison + * Copyright (C) 2003-2009 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ */ #include "rsync.h" -#include "ifuncs.h" +#include "inums.h" #include "io.h" #if defined CONFIG_LOCALE && defined HAVE_LOCALE_H #include @@ -32,16 +32,16 @@ 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 inc_recurse; extern int blocking_io; -extern int human_readable; +extern int always_checksum; extern int remove_source_files; extern int output_needs_newline; extern int need_messages_from_generator; extern int kluge_around_eof; extern int got_xfer_error; +extern int msgs2stderr; extern int module_id; extern int copy_links; extern int copy_dirlinks; @@ -68,23 +68,29 @@ extern int connect_timeout; extern pid_t cleanup_child_pid; extern unsigned int module_dirlen; extern struct stats stats; +extern char *stdout_format; +extern char *logfile_format; extern char *filesfrom_host; extern char *partial_dir; extern char *dest_option; -extern char *basis_dir[]; extern char *rsync_path; extern char *shell_cmd; extern char *batch_name; extern char *password_file; +extern char *backup_dir; extern char curr_dir[MAXPATHLEN]; +extern char backup_dir_buf[MAXPATHLEN]; +extern char *basis_dir[MAX_BASIS_DIRS+1]; extern struct file_list *first_flist; -extern struct filter_list_struct daemon_filter_list; +extern filter_rule_list daemon_filter_list; uid_t our_uid; +int am_generator = 0; int local_server = 0; int daemon_over_rsh = 0; mode_t orig_umask = 0; int batch_gen_fd = -1; +int sender_keeps_checksum = 0; /* There's probably never more than at most 2 outstanding child processes, * but set it higher, just in case. */ @@ -167,6 +173,30 @@ static void wait_process_with_flush(pid_t pid, int *exit_code_ptr) *exit_code_ptr = WEXITSTATUS(status); } +void write_del_stats(int f) +{ + if (read_batch) + write_int(f, NDX_DEL_STATS); + else + send_msg(MSG_DEL_STATS, "", 0, 0); + write_varint(f, stats.deleted_files - stats.deleted_dirs + - stats.deleted_symlinks - stats.deleted_devices + - stats.deleted_specials); + write_varint(f, stats.deleted_dirs); + write_varint(f, stats.deleted_symlinks); + write_varint(f, stats.deleted_devices); + write_varint(f, stats.deleted_specials); +} + +void read_del_stats(int f) +{ + stats.deleted_files = read_varint(f); + stats.deleted_files += stats.deleted_dirs = read_varint(f); + stats.deleted_files += stats.deleted_symlinks = read_varint(f); + stats.deleted_files += stats.deleted_devices = read_varint(f); + stats.deleted_files += stats.deleted_specials = read_varint(f); +} + /* This function gets called from all 3 processes. We want the client side * to actually output the text, but the sender is the only process that has * all the stats we need. So, if we're a client sender, we do the report. @@ -237,47 +267,72 @@ static void handle_stats(int f) } } +static void output_itemized_counts(const char *prefix, int *counts) +{ + static char *labels[] = { "reg", "dir", "link", "dev", "special" }; + char buf[1024], *pre = " ("; + int j, len = 0; + int total = counts[0]; + if (total) { + counts[0] -= counts[1] + counts[2] + counts[3] + counts[4]; + for (j = 0; j < 5; j++) { + if (counts[j]) { + len += snprintf(buf+len, sizeof buf - len - 2, + "%s%s: %s", + pre, labels[j], comma_num(counts[j])); + pre = ", "; + } + } + buf[len++] = ')'; + } + buf[len] = '\0'; + rprintf(FINFO, "%s: %s%s\n", prefix, comma_num(total), buf); +} + static void output_summary(void) { if (INFO_GTE(STATS, 2)) { rprintf(FCLIENT, "\n"); - rprintf(FINFO,"Number of files: %d\n", stats.num_files); - rprintf(FINFO,"Number of files transferred: %d\n", - stats.num_transferred_files); + output_itemized_counts("Number of files", &stats.num_files); + if (protocol_version >= 29) + output_itemized_counts("Number of created files", &stats.created_files); + if (protocol_version >= 31) + output_itemized_counts("Number of deleted files", &stats.deleted_files); + rprintf(FINFO,"Number of regular files transferred: %s\n", + comma_num(stats.xferred_files)); rprintf(FINFO,"Total file size: %s bytes\n", - big_num(stats.total_size, human_readable)); + human_num(stats.total_size)); rprintf(FINFO,"Total transferred file size: %s bytes\n", - big_num(stats.total_transferred_size, human_readable)); + human_num(stats.total_transferred_size)); rprintf(FINFO,"Literal data: %s bytes\n", - big_num(stats.literal_data, human_readable)); + human_num(stats.literal_data)); rprintf(FINFO,"Matched data: %s bytes\n", - big_num(stats.matched_data, human_readable)); + human_num(stats.matched_data)); rprintf(FINFO,"File list size: %s\n", - big_num(stats.flist_size, human_readable)); + human_num(stats.flist_size)); if (stats.flist_buildtime) { rprintf(FINFO, - "File list generation time: %.3f seconds\n", - (double)stats.flist_buildtime / 1000); + "File list generation time: %s seconds\n", + comma_dnum((double)stats.flist_buildtime / 1000, 3)); rprintf(FINFO, - "File list transfer time: %.3f seconds\n", - (double)stats.flist_xfertime / 1000); + "File list transfer time: %s seconds\n", + comma_dnum((double)stats.flist_xfertime / 1000, 3)); } rprintf(FINFO,"Total bytes sent: %s\n", - big_num(total_written, human_readable)); + human_num(total_written)); rprintf(FINFO,"Total bytes received: %s\n", - big_num(total_read, human_readable)); + human_num(total_read)); } if (INFO_GTE(STATS, 1)) { rprintf(FCLIENT, "\n"); rprintf(FINFO, "sent %s bytes received %s bytes %s bytes/sec\n", - big_num(total_written, human_readable), - big_num(total_read, human_readable), + human_num(total_written), human_num(total_read), human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2)); - rprintf(FINFO, "total size is %s speedup is %.2f%s\n", - big_num(stats.total_size, human_readable), - (double)stats.total_size / (total_written+total_read), + rprintf(FINFO, "total size is %s speedup is %s%s\n", + human_num(stats.total_size), + comma_dnum((double)stats.total_size / (total_written+total_read), 2), write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : ""); } @@ -470,7 +525,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in #ifdef ICONV_CONST setup_iconv(); #endif - if (protect_args) + if (protect_args && !daemon_over_rsh) send_protected_args(*f_out_p, args); } @@ -658,7 +713,7 @@ static void check_alt_basis_dirs(void) } /* This is only called by the sender. */ -static void read_final_goodbye(int f_in) +static void read_final_goodbye(int f_in, int f_out) { int i, iflags, xlen; uchar fnamecmp_type; @@ -667,8 +722,19 @@ static void read_final_goodbye(int f_in) if (protocol_version < 29) i = read_int(f_in); else { - i = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type, - xname, &xlen); + i = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type, xname, &xlen); + if (protocol_version >= 31 && i == NDX_DONE) { + if (am_sender) + write_ndx(f_out, NDX_DONE); + else { + if (batch_gen_fd >= 0) { + while (read_int(batch_gen_fd) != NDX_DEL_STATS) {} + read_del_stats(batch_gen_fd); + } + send_msg(MSG_DONE, "", 0, 0); + } + i = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type, xname, &xlen); + } } if (i != NDX_DONE) { @@ -727,7 +793,7 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[]) io_flush(FULL_FLUSH); handle_stats(f_out); if (protocol_version >= 24) - read_final_goodbye(f_in); + read_final_goodbye(f_in, f_out); io_flush(FULL_FLUSH); exit_cleanup(0); } @@ -753,6 +819,16 @@ static int do_recv(int f_in, int f_out, char *local_name) exit_cleanup(RERR_IPC); } + if (backup_dir) { + int ret = make_path(backup_dir_buf, MKP_DROP_NAME); /* drops trailing slash */ + if (ret < 0) + exit_cleanup(RERR_SYNTAX); + if (ret) + rprintf(FINFO, "Created backup_dir %s\n", backup_dir_buf); + else if (INFO_GTE(BACKUP, 1)) + rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf); + } + io_flush(NORMAL_FLUSH); if ((pid = do_fork()) == -1) { @@ -788,15 +864,10 @@ static int do_recv(int f_in, int f_out, char *local_name) /* Handle any keep-alive packets from the post-processing work * that the generator does. */ if (protocol_version >= 29) { - int iflags, xlen; - uchar fnamecmp_type; - char xname[MAXPATHLEN]; - kluge_around_eof = -1; /* This should only get stopped via a USR2 signal. */ - read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type, - xname, &xlen); + read_final_goodbye(f_in, f_out); rprintf(FERROR, "Invalid packet at end of run [%s]\n", who_am_i()); @@ -856,7 +927,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[]) char *local_name = NULL; int negated_levels; - if (filesfrom_fd >= 0) { + if (filesfrom_fd >= 0 && !msgs2stderr) { /* We can't mix messages with files-from data on the socket, * so temporarily turn off info/debug messages. */ negate_output_levels(); @@ -929,7 +1000,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[]) if (daemon_filter_list.head) { char **dir_p; - struct filter_list_struct *elp = &daemon_filter_list; + filter_rule_list *elp = &daemon_filter_list; for (dir_p = basis_dir; *dir_p; dir_p++) { char *dir = *dir_p; @@ -1013,6 +1084,12 @@ 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. */ + + if (always_checksum + && (log_format_has(stdout_format, 'C') + || log_format_has(logfile_format, 'C'))) + sender_keeps_checksum = 1; + if (protocol_version >= 30) io_start_multiplex_out(); else @@ -1026,7 +1103,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) if (write_batch && !am_server) start_write_batch(f_out); flist = send_file_list(f_out, argc, argv); - set_msg_fd_in(-1); if (DEBUG_GTE(FLIST, 3)) rprintf(FINFO,"file list sent\n"); @@ -1038,7 +1114,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) io_flush(FULL_FLUSH); handle_stats(-1); if (protocol_version >= 24) - read_final_goodbye(f_in); + read_final_goodbye(f_in, f_out); if (pid != -1) { if (DEBUG_GTE(EXIT, 2)) rprintf(FINFO,"client_run waiting on %d\n", (int) pid); @@ -1197,8 +1273,8 @@ static int start_client(int argc, char *argv[]) rprintf(FERROR, "remote destination is not allowed with --read-batch\n"); exit_cleanup(RERR_SYNTAX); } - remote_argv = argv + argc - 1; - remote_argc = 1; + remote_argv = argv += argc - 1; + remote_argc = argc = 1; } if (am_sender) {