From 951e826b75c4a4e6bc066e248d7489fb6eba6fde Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sun, 13 Jul 2008 20:51:08 -0700 Subject: [PATCH] Added the --info=FLAGS an --debug=FLAGS options, which allows fine-grained output control (in addition to the coarse -v). --- NEWS | 7 + acls.c | 2 +- backup.c | 11 +- batch.c | 2 +- cleanup.c | 12 +- clientserver.c | 8 +- compat.c | 3 +- exclude.c | 13 +- flist.c | 52 +++--- generator.c | 93 +++++----- hlink.c | 11 +- io.c | 2 +- log.c | 13 +- main.c | 46 +++-- match.c | 30 ++-- options.c | 390 ++++++++++++++++++++++++++++++++++++++-- pipe.c | 2 +- progress.c | 43 +++-- receiver.c | 38 ++-- rsync.c | 23 ++- rsync.h | 46 ++++- rsync.yo | 109 ++++++++--- sender.c | 32 ++-- socket.c | 8 +- t_unsafe.c | 2 +- testsuite/00-hello.test | 6 +- testsuite/rsync.fns | 2 +- uidlist.c | 9 +- util.c | 9 +- 29 files changed, 756 insertions(+), 268 deletions(-) diff --git a/NEWS b/NEWS index 924e7885..7be38f2b 100644 --- a/NEWS +++ b/NEWS @@ -7,11 +7,18 @@ Changes since 3.0.3: - Changed the way --progress overwrites its prior output in order to make it nearly impossible for the progress to get overwritten by an error. + - Improved the keep-alive in-loop check in the generator to work properly + in incremental recursion mode. + ENHANCEMENTS: - Added the --remote-option=OPT (-M OPT) command-line option that is useful for things like sending a remote --log-file=FILE or --fake-super option. + - Added the --info=FLAGS and --debug=FLAGS options to allow finer-grained + control over what is output. Added an extra type of --progress output + using --info=progress2. + - Rsync will not send an -e option to the server if the user specifies the --protocol=29 option. This lets rsync3 use an overly-restrictive server. diff --git a/acls.c b/acls.c index d9023e2f..3e829ad9 100644 --- a/acls.c +++ b/acls.c @@ -1081,7 +1081,7 @@ int default_perms_for_dir(const char *dir) /* Apply the permission-bit entries of the default ACL, if any. */ if (racl.user_obj != NO_ENTRY) { perms = rsync_acl_get_perms(&racl); - if (verbose > 2) + if (DEBUG_GTE(ACL, 1)) rprintf(FINFO, "got ACL-based default perms %o for directory %s\n", perms, dir); } diff --git a/backup.c b/backup.c index 934f838d..60c85b17 100644 --- a/backup.c +++ b/backup.c @@ -20,7 +20,6 @@ #include "rsync.h" -extern int verbose; extern int am_root; extern int preserve_acls; extern int preserve_xattrs; @@ -62,7 +61,7 @@ static int make_simple_backup(const char *fname) while (1) { if (do_rename(fname, fnamebak) == 0) { - if (verbose > 1) { + if (INFO_GTE(BACKUP, 1)) { rprintf(FINFO, "backed up %s to %s\n", fname, fnamebak); } @@ -260,7 +259,7 @@ static int keep_backup(const char *fname) } } else save_errno = 0; - if (verbose > 2 && save_errno == 0) { + if (DEBUG_GTE(BACKUP, 1) && save_errno == 0) { rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname); } @@ -285,7 +284,7 @@ static int keep_backup(const char *fname) } ret_code = do_rmdir(fname); - if (verbose > 2) { + if (DEBUG_GTE(BACKUP, 1)) { rprintf(FINFO, "make_backup: RMDIR %s returns %i\n", full_fname(fname), ret_code); } @@ -296,7 +295,7 @@ static int keep_backup(const char *fname) if (!kept && preserve_links && S_ISLNK(file->mode)) { const char *sl = F_SYMLINK(file); if (safe_symlinks && unsafe_symlink(sl, buf)) { - if (verbose) { + if (INFO_GTE(SYMSAFE, 1)) { rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n", full_fname(buf), sl); } @@ -345,7 +344,7 @@ static int keep_backup(const char *fname) preserve_xattrs = save_preserve_xattrs; unmake_file(file); - if (verbose > 1) { + if (INFO_GTE(BACKUP, 1)) { rprintf(FINFO, "backed up %s to %s\n", fname, buf); } diff --git a/batch.c b/batch.c index 033368a3..ac89583a 100644 --- a/batch.c +++ b/batch.c @@ -135,7 +135,7 @@ void check_batch_flags(void) set ? "Please" : "Do not"); exit_cleanup(RERR_SYNTAX); } - if (verbose) { + if (INFO_GTE(MISC, 1)) { rprintf(FINFO, "%sing the %s option to match the batchfile.\n", set ? "Sett" : "Clear", flag_name[i]); diff --git a/cleanup.c b/cleanup.c index 279b5326..91467825 100644 --- a/cleanup.c +++ b/cleanup.c @@ -27,7 +27,7 @@ extern int am_daemon; extern int io_error; extern int keep_partial; extern int got_xfer_error; -extern int progress_is_active; +extern int output_needs_newline; extern char *partial_dir; extern char *logfile_name; @@ -116,12 +116,12 @@ NORETURN void _exit_cleanup(int code, const char *file, int line) exit_code = unmodified_code = code; - if (progress_is_active) { + if (output_needs_newline) { fputc('\n', stdout); - progress_is_active = 0; + output_needs_newline = 0; } - if (verbose > 3) { + if (DEBUG_GTE(EXIT, 2)) { rprintf(FINFO, "_exit_cleanup(code=%d, file=%s, line=%d): entered\n", code, file, line); @@ -184,13 +184,13 @@ NORETURN void _exit_cleanup(int code, const char *file, int line) code = exit_code = RERR_PARTIAL; } - if (code || am_daemon || (logfile_name && (am_server || !verbose))) + if (code || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1)))) log_exit(code, file, line); /* FALLTHROUGH */ #include "case_N.h" - if (verbose > 2) { + if (DEBUG_GTE(EXIT, 1)) { rprintf(FINFO, "_exit_cleanup(code=%d, file=%s, line=%d): " "about to call exit(%d)\n", diff --git a/clientserver.c b/clientserver.c index f78c61c3..2ba7dbd7 100644 --- a/clientserver.c +++ b/clientserver.c @@ -23,7 +23,6 @@ #include "ifuncs.h" extern int quiet; -extern int verbose; extern int dry_run; extern int output_motd; extern int list_only; @@ -267,7 +266,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char sargs[sargc] = NULL; - if (verbose > 1) + if (DEBUG_GTE(CMD, 1)) print_child_argv("sending daemon args:", sargs); io_printf(f_out, "%.*s\n", modlen, modname); @@ -747,7 +746,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host) read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request); orig_argv = argv; - verbose = 0; /* future verbosity is controlled by client options */ + reset_output_levels(); /* future verbosity is controlled by client options */ ret = parse_arguments(&argc, (const char ***) &argv); if (protect_args && ret) { orig_early_argv = orig_argv; @@ -798,8 +797,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host) #ifndef DEBUG /* don't allow the logs to be flooded too fast */ - if (verbose > lp_max_verbosity(i)) - verbose = lp_max_verbosity(i); + limit_output_verbosity(lp_max_verbosity(i)); #endif if (protocol_version < 23 diff --git a/compat.c b/compat.c index ef220e2d..811f6ec3 100644 --- a/compat.c +++ b/compat.c @@ -25,7 +25,6 @@ int remote_protocol = 0; int file_extra_cnt = 0; /* count of file-list extras that everyone gets */ int inc_recurse = 0; -extern int verbose; extern int am_server; extern int am_sender; extern int local_server; @@ -157,7 +156,7 @@ void setup_protocol(int f_out,int f_in) exit_cleanup(RERR_PROTOCOL); } - if (verbose > 3) { + if (DEBUG_GTE(PROTO, 1)) { rprintf(FINFO, "(%s) Protocol versions: remote=%d, negotiated=%d\n", am_server? "Server" : "Client", remote_protocol, protocol_version); } diff --git a/exclude.c b/exclude.c index 085d2642..080aa492 100644 --- a/exclude.c +++ b/exclude.c @@ -22,7 +22,6 @@ #include "rsync.h" -extern int verbose; extern int am_server; extern int am_sender; extern int eol_nulls; @@ -123,7 +122,7 @@ static void add_rule(struct filter_list_struct *listp, const char *pat, const char *cp; unsigned int pre_len, suf_len, slash_cnt = 0; - if (verbose > 2) { + if (DEBUG_GTE(FILTER, 2)) { rprintf(FINFO, "[%s] add_rule(%s%.*s%s)%s\n", who_am_i(), get_rule_prefix(mflags, pat, 0, NULL), (int)pat_len, pat, @@ -455,7 +454,7 @@ void *push_local_filters(const char *dir, unsigned int dirlen) struct filter_struct *ex = mergelist_parents[i]; struct filter_list_struct *lp = ex->u.mergelist; - if (verbose > 2) { + if (DEBUG_GTE(FILTER, 2)) { rprintf(FINFO, "[%s] pushing filter list%s\n", who_am_i(), lp->debug_type); } @@ -495,7 +494,7 @@ void pop_local_filters(void *mem) struct filter_struct *ex = mergelist_parents[i]; struct filter_list_struct *lp = ex->u.mergelist; - if (verbose > 2) { + if (DEBUG_GTE(FILTER, 2)) { rprintf(FINFO, "[%s] popping filter list%s\n", who_am_i(), lp->debug_type); } @@ -629,7 +628,7 @@ static void report_filter_result(enum logcode code, char const *name, * then it is stripped out by add_rule(). So as a special * case we add it back in here. */ - if (verbose >= 2) { + if (DEBUG_GTE(FILTER, 1)) { static char *actions[2][2] = { {"show", "hid"}, {"risk", "protect"} }; const char *w = who_am_i(); @@ -973,7 +972,7 @@ void parse_rule(struct filter_list_struct *listp, const char *pattern, } if (new_mflags & MATCHFLG_CLEAR_LIST) { - if (verbose > 2) { + if (DEBUG_GTE(FILTER, 2)) { rprintf(FINFO, "[%s] clearing filter list%s\n", who_am_i(), listp->debug_type); @@ -1047,7 +1046,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname, } else fp = stdin; - if (verbose > 2) { + if (DEBUG_GTE(FILTER, 2)) { rprintf(FINFO, "[%s] parse_filter_file(%s,%x,%x)%s\n", who_am_i(), fname, mflags, xflags, fp ? "" : " [not found]"); diff --git a/flist.c b/flist.c index 18b239ef..e0cad798 100644 --- a/flist.c +++ b/flist.c @@ -25,14 +25,12 @@ #include "rounding.h" #include "io.h" -extern int verbose; extern int am_root; extern int am_server; extern int am_daemon; extern int am_sender; extern int am_generator; extern int inc_recurse; -extern int do_progress; extern int always_checksum; extern int module_id; extern int ignore_errors; @@ -67,6 +65,7 @@ extern int protocol_version; extern int sanitize_paths; extern int munge_symlinks; extern int need_unsorted_flist; +extern int output_needs_newline; extern int unsort_ndx; extern struct stats stats; extern char *filesfrom_host; @@ -129,7 +128,7 @@ static void output_flist(struct file_list *flist); void init_flist(void) { - if (verbose > 4) { + if (DEBUG_GTE(FLIST, 4)) { rprintf(FINFO, "FILE_STRUCT_LEN=%d, EXTRA_LEN=%d\n", (int)FILE_STRUCT_LEN, (int)EXTRA_LEN); } @@ -140,14 +139,13 @@ void init_flist(void) static int show_filelist_p(void) { - return verbose && xfer_dirs && !am_server && !inc_recurse; + return INFO_GTE(FLIST, 1) && xfer_dirs && !am_server && !inc_recurse; } static void start_filelist_progress(char *kind) { rprintf(FCLIENT, "%s ... ", kind); - if (verbose > 1 || do_progress) - rprintf(FCLIENT, "\n"); + output_needs_newline = 1; rflush(FINFO); } @@ -158,18 +156,20 @@ static void emit_filelist_progress(int count) static void maybe_emit_filelist_progress(int count) { - if (do_progress && show_filelist_p() && (count % 100) == 0) + if (INFO_GTE(FLIST, 2) && show_filelist_p() && (count % 100) == 0) emit_filelist_progress(count); } static void finish_filelist_progress(const struct file_list *flist) { - if (do_progress) { + if (INFO_GTE(FLIST, 2)) { /* This overwrites the progress line */ rprintf(FINFO, "%d file%sto consider\n", flist->used, flist->used == 1 ? " " : "s "); - } else + } else { + output_needs_newline = 0; rprintf(FINFO, "done\n"); + } } void show_flist_stats(void) @@ -196,7 +196,7 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf) return -1; linkbuf[llen] = '\0'; if (copy_unsafe_links && unsafe_symlink(linkbuf, path)) { - if (verbose > 1) { + if (INFO_GTE(SYMSAFE, 1)) { rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n", path, linkbuf); } @@ -316,7 +316,7 @@ static void flist_expand(struct file_list *flist, int extra) new_ptr = realloc_array(flist->files, struct file_struct *, flist->malloced); - if (verbose >= 2 && flist->malloced != FLIST_START) { + if (DEBUG_GTE(FLIST, 1) && flist->malloced != FLIST_START) { rprintf(FCLIENT, "[%s] expand file_list pointer array to %.0f bytes, did%s move\n", who_am_i(), (double)sizeof flist->files[0] * flist->malloced, @@ -1110,7 +1110,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, if (one_file_system && st.st_dev != filesystem_dev && BITS_SETnUNSET(flags, FLAG_CONTENT_DIR, FLAG_TOP_DIR)) { if (one_file_system > 1) { - if (verbose > 1) { + if (INFO_GTE(MOUNT, 1)) { rprintf(FINFO, "[%s] skipping mount-point dir %s\n", who_am_i(), thisname); @@ -1159,7 +1159,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, pool = NULL; } - if (verbose > 2) { + if (DEBUG_GTE(FLIST, 2)) { rprintf(FINFO, "[%s] make_file(%s,*,%d)\n", who_am_i(), thisname, filter_level); } @@ -1829,7 +1829,7 @@ void send_extra_file_list(int f, int at_least) file_total += flist->used; stats.flist_size += stats.total_written - start_write; stats.num_files += flist->used; - if (verbose > 3) + if (DEBUG_GTE(FLIST, 3)) output_flist(flist); if (DIR_FIRST_CHILD(dp) >= 0) { @@ -1880,7 +1880,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) rprintf(FLOG, "building file list\n"); if (show_filelist_p()) start_filelist_progress("building file list"); - else if (inc_recurse && verbose && !am_server) + else if (inc_recurse && INFO_GTE(FLIST, 1) && !am_server) rprintf(FCLIENT, "sending incremental file list\n"); start_write = stats.total_written; @@ -2155,10 +2155,10 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) stats.flist_size = stats.total_written - start_write; stats.num_files = flist->used; - if (verbose > 3) + if (DEBUG_GTE(FLIST, 3)) output_flist(flist); - if (verbose > 2) + if (DEBUG_GTE(FLIST, 2)) rprintf(FINFO, "send_file_list done\n"); if (inc_recurse) { @@ -2192,7 +2192,7 @@ struct file_list *recv_file_list(int f) rprintf(FLOG, "receiving file list\n"); if (show_filelist_p()) start_filelist_progress("receiving file list"); - else if (inc_recurse && verbose && !am_server && !first_flist) + else if (inc_recurse && INFO_GTE(FLIST, 1) && !am_server && !first_flist) rprintf(FCLIENT, "receiving incremental file list\n"); start_read = stats.total_read; @@ -2231,14 +2231,14 @@ struct file_list *recv_file_list(int f) maybe_emit_filelist_progress(flist->used); - if (verbose > 2) { + if (DEBUG_GTE(FLIST, 2)) { rprintf(FINFO, "recv_file_name(%s)\n", f_name(file, NULL)); } } file_total += flist->used; - if (verbose > 2) + if (DEBUG_GTE(FLIST, 2)) rprintf(FINFO, "received %d names\n", flist->used); if (show_filelist_p()) @@ -2292,10 +2292,10 @@ struct file_list *recv_file_list(int f) flist->parent_ndx = -1; } - if (verbose > 3) + if (DEBUG_GTE(FLIST, 3)) output_flist(flist); - if (verbose > 2) + if (DEBUG_GTE(FLIST, 2)) rprintf(FINFO, "recv_file_list done\n"); stats.flist_size += stats.total_read - start_read; @@ -2323,7 +2323,7 @@ void recv_additional_file_list(int f) NDX_FLIST_OFFSET - dir_flist->used + 1); exit_cleanup(RERR_PROTOCOL); } - if (verbose > 3) { + if (DEBUG_GTE(FLIST, 3)) { rprintf(FINFO, "[%s] receiving flist for dir %d\n", who_am_i(), ndx); } @@ -2545,7 +2545,7 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root) keep = j, drop = i; if (!am_sender) { - if (verbose > 1) { + if (DEBUG_GTE(DUP, 1)) { rprintf(FINFO, "removing duplicate name %s from file list (%d)\n", f_name(file, fbuf), drop + flist->ndx_start); @@ -2903,7 +2903,7 @@ struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules) send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen, 0); xfer_dirs = save_xfer_dirs; recurse = save_recurse; - if (do_progress) + if (INFO_GTE(PROGRESS, 1)) flist_count_offset += dirlist->used; prune_empty_dirs = 0; @@ -2911,7 +2911,7 @@ struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules) flist_sort_and_clean(dirlist, 0); prune_empty_dirs = save_prune_empty_dirs; - if (verbose > 3) + if (DEBUG_GTE(FLIST, 3)) output_flist(dirlist); return dirlist; diff --git a/generator.c b/generator.c index 11cba3c8..22f2851e 100644 --- a/generator.c +++ b/generator.c @@ -22,7 +22,6 @@ #include "rsync.h" -extern int verbose; extern int dry_run; extern int do_xfers; extern int stdout_format_has_i; @@ -31,7 +30,6 @@ extern int am_root; extern int am_server; extern int am_daemon; extern int inc_recurse; -extern int do_progress; extern int relative_paths; extern int implied_dirs; extern int keep_dirlinks; @@ -160,7 +158,7 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) char *what; int ok; - if (verbose > 2) { + if (DEBUG_GTE(DEL, 2)) { rprintf(FINFO, "delete_item(%s) mode=%o flags=%d\n", fbuf, (int)mode, (int)flags); } @@ -251,7 +249,7 @@ static enum delret delete_dir_contents(char *fname, uint16 flags) int j, dlen; char *p; - if (verbose > 3) { + if (DEBUG_GTE(DEL, 3)) { rprintf(FINFO, "delete_dir_contents(%s) flags=%d\n", fname, flags); } @@ -284,7 +282,7 @@ static enum delret delete_dir_contents(char *fname, uint16 flags) struct file_struct *fp = dirlist->files[j]; if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) { - if (verbose > 1) { + if (DEBUG_GTE(DEL, 1)) { rprintf(FINFO, "mount point, %s, pins parent directory\n", f_name(fp, NULL)); @@ -479,7 +477,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev) return; } - if (verbose > 2) + if (DEBUG_GTE(DEL, 2)) rprintf(FINFO, "delete_in_dir(%s)\n", fbuf); if (allowed_lull) @@ -516,7 +514,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev) if (!F_IS_ACTIVE(fp)) continue; if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) { - if (verbose > 1) + if (INFO_GTE(MOUNT, 1)) rprintf(FINFO, "cannot delete mount point: %s\n", f_name(fp, NULL)); continue; @@ -564,7 +562,7 @@ static void do_delete_pass(void) continue; } - if (verbose > 1 && file->flags & FLAG_TOP_DIR) + if (DEBUG_GTE(DEL, 1) && file->flags & FLAG_TOP_DIR) rprintf(FINFO, "deleting in %s\n", fbuf); if (link_stat(fbuf, &st, keep_dirlinks) < 0 @@ -575,7 +573,7 @@ static void do_delete_pass(void) } delete_in_dir(NULL, NULL, &dev_zero); - if (do_progress && !am_server) + if (INFO_GTE(FLIST, 2) && !am_server) rprintf(FINFO, " \r"); } @@ -686,7 +684,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre } iflags &= 0xffff; - if ((iflags & (SIGNIFICANT_ITEM_FLAGS|ITEM_REPORT_XATTR) || verbose > 1 + if ((iflags & (SIGNIFICANT_ITEM_FLAGS|ITEM_REPORT_XATTR) || INFO_GTE(NAME, 2) || stdout_format_has_i > 1 || (xname && *xname)) && !read_batch) { if (protocol_version >= 29) { if (ndx >= 0) @@ -805,7 +803,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) if ((int64)sum->count != l) sum->count = -1; - if (sum->count && verbose > 2) { + if (sum->count && DEBUG_GTE(CHKSUM, 2)) { rprintf(FINFO, "count=%.0f rem=%ld blength=%ld s2length=%d flength=%.0f\n", (double)sum->count, (long)sum->remainder, (long)sum->blength, @@ -857,7 +855,7 @@ static int generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy) sum1 = get_checksum1(map, n1); get_checksum2(map, n1, sum2); - if (verbose > 3) { + if (DEBUG_GTE(CHKSUM, 3)) { rprintf(FINFO, "chunk[%.0f] offset=%.0f len=%ld sum1=%08lx\n", (double)i, (double)offset - n1, (long)n1, @@ -899,7 +897,7 @@ static int find_fuzzy(struct file_struct *file, struct file_list *dirlist) if (F_LENGTH(fp) == F_LENGTH(file) && cmp_time(fp->modtime, file->modtime) == 0) { - if (verbose > 4) { + if (DEBUG_GTE(FUZZY, 2)) { rprintf(FINFO, "fuzzy size/modtime match for %s\n", name); @@ -914,7 +912,7 @@ static int find_fuzzy(struct file_struct *file, struct file_list *dirlist) /* Add some extra weight to how well the suffixes match. */ dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len) * 10; - if (verbose > 4) { + if (DEBUG_GTE(FUZZY, 2)) { rprintf(FINFO, "fuzzy distance for %s = %d.%05d\n", name, (int)(dist>>16), (int)(dist&0xFFFF)); } @@ -947,7 +945,7 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru } cleanup_set(copy_to, NULL, NULL, -1, -1); if (copy_file(src, copy_to, fd_w, file->mode, 0) < 0) { - if (verbose) { + if (INFO_GTE(COPY, 1)) { rsyserr(FINFO, errno, "copy_file %s => %s", full_fname(src), copy_to); } @@ -1017,7 +1015,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, goto try_a_copy; if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, j); - if (!maybe_ATTRS_REPORT && (verbose > 1 || stdout_format_has_i > 1)) { + if (!maybe_ATTRS_REPORT && (INFO_GTE(NAME, 2) || stdout_format_has_i > 1)) { itemize(cmpbuf, file, ndx, 1, sxp, ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0, ""); @@ -1026,7 +1024,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, #endif if (itemizing) itemize(cmpbuf, file, ndx, 0, sxp, 0, 0, NULL); - if (verbose > 1 && maybe_ATTRS_REPORT) + if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT) rprintf(FCLIENT, "%s is uptodate\n", fname); return -2; } @@ -1040,8 +1038,8 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, if (itemizing) itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL); if (maybe_ATTRS_REPORT - && ((!itemizing && verbose && match_level == 2) - || (verbose > 1 && match_level == 3))) { + && ((!itemizing && INFO_GTE(NAME, 1) && match_level == 2) + || (INFO_GTE(NAME, 2) && match_level == 3))) { code = match_level == 3 ? FCLIENT : FINFO; rprintf(code, "%s%s\n", fname, match_level == 3 ? " is uptodate" : ""); @@ -1181,13 +1179,13 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx, #endif match_level = 2; if (itemizing && stdout_format_has_i - && (verbose > 1 || stdout_format_has_i > 1)) { + && (INFO_GTE(NAME, 2) || stdout_format_has_i > 1)) { int chg = compare_dest && type != TYPE_DIR ? 0 : ITEM_LOCAL_CHANGE + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0); char *lp = match_level == 3 ? "" : NULL; itemize(cmpbuf, file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp); } - if (verbose > 1 && maybe_ATTRS_REPORT) { + if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT) { rprintf(FCLIENT, "%s%s is uptodate\n", fname, type == TYPE_DIR ? "/" : ""); } @@ -1273,7 +1271,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, : inc_recurse && ndx != cur_flist->ndx_start - 1 ? -1 : 1; - if (verbose > 2) + if (DEBUG_GTE(GENR, 1)) rprintf(FINFO, "recv_generator(%s,%d)\n", fname, ndx); if (list_only) { @@ -1377,7 +1375,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, else if (F_IS_HLINKED(file)) handle_skipped_hlink(file, itemizing, code, f_out); #endif - if (verbose > 1) { + if (INFO_GTE(SKIP, 1)) { rprintf(FINFO, "not creating new %s \"%s\"\n", is_dir ? "directory" : "file", fname); } @@ -1390,7 +1388,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (ignore_existing > 0 && statret == 0 && (!is_dir || !S_ISDIR(sx.st.st_mode))) { - if (verbose > 1 && is_dir >= 0) + if (INFO_GTE(SKIP, 1) && is_dir >= 0) rprintf(FINFO, "%s exists\n", fname); #ifdef SUPPORT_HARD_LINKS if (F_IS_HLINKED(file)) @@ -1473,7 +1471,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, copy_xattrs(fnamecmpbuf, fname); #endif if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0) - && verbose && code != FNONE && f_out != -1) + && INFO_GTE(NAME, 1) && code != FNONE && f_out != -1) rprintf(code, "%s/\n", fname); /* We need to ensure that the dirs in the transfer have writable @@ -1528,7 +1526,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, #ifdef SUPPORT_LINKS const char *sl = F_SYMLINK(file); if (safe_symlinks && unsafe_symlink(sl, fname)) { - if (verbose) { + if (INFO_GTE(NAME, 1)) { if (solo_file) fname = f_name(file, NULL); rprintf(FINFO, @@ -1592,7 +1590,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, itemize(fname, file, ndx, statret, &sx, ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL); } - if (code != FNONE && verbose) + if (code != FNONE && INFO_GTE(NAME, 1)) rprintf(code, "%s -> %s\n", fname, sl); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) @@ -1662,7 +1660,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, goto cleanup; } #endif - if (verbose > 2) { + if (DEBUG_GTE(GENR, 1)) { rprintf(FINFO, "mknod(%s, 0%o, [%ld,%ld])\n", fname, (int)file->mode, (long)major(rdev), (long)minor(rdev)); @@ -1676,7 +1674,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, itemize(fname, file, ndx, statret, &sx, ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL); } - if (code != FNONE && verbose) + if (code != FNONE && INFO_GTE(NAME, 1)) rprintf(code, "%s\n", fname); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) @@ -1696,7 +1694,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, } if (max_size > 0 && F_LENGTH(file) > max_size) { - if (verbose > 1) { + if (INFO_GTE(SKIP, 1)) { if (solo_file) fname = f_name(file, NULL); rprintf(FINFO, "%s is over max-size\n", fname); @@ -1704,7 +1702,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, goto cleanup; } if (min_size > 0 && F_LENGTH(file) < min_size) { - if (verbose > 1) { + if (INFO_GTE(SKIP, 1)) { if (solo_file) fname = f_name(file, NULL); rprintf(FINFO, "%s is under min-size\n", fname); @@ -1714,7 +1712,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (update_only > 0 && statret == 0 && cmp_time(sx.st.st_mtime, file->modtime) > 0) { - if (verbose > 1) + if (INFO_GTE(SKIP, 1)) rprintf(FINFO, "%s is newer\n", fname); #ifdef SUPPORT_HARD_LINKS if (F_IS_HLINKED(file)) @@ -1764,7 +1762,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (j >= 0) { fuzzy_file = fuzzy_dirlist->files[j]; f_name(fuzzy_file, fnamecmpbuf); - if (verbose > 2) { + if (DEBUG_GTE(FUZZY, 1)) { rprintf(FINFO, "fuzzy basis selected for %s: %s\n", fname, fnamecmpbuf); } @@ -1905,12 +1903,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, fnamecmp_type = FNAMECMP_BACKUP; } - if (verbose > 3) { + if (DEBUG_GTE(CHKSUM, 3)) { rprintf(FINFO, "gen mapped %s of size %.0f\n", fnamecmp, (double)sx.st.st_size); } - if (verbose > 2) + if (DEBUG_GTE(CHKSUM, 2)) rprintf(FINFO, "generating and sending sums for %d\n", ndx); notify_others: @@ -1981,7 +1979,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, #endif set_file_attrs(backupptr, back_file, NULL, NULL, 0); preserve_xattrs = save_preserve_xattrs; - if (verbose > 1) { + if (INFO_GTE(BACKUP, 1)) { rprintf(FINFO, "backed up %s to %s\n", fname, backupptr); } @@ -2041,7 +2039,7 @@ static void touch_up_dirs(struct file_list *flist, int ndx) if (!S_ISDIR(file->mode) || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)) continue; - if (verbose > 3) { + if (DEBUG_GTE(TIME, 2)) { fname = f_name(file, NULL); rprintf(FINFO, "touch_up_dirs: %s (%d)\n", NS(fname), i); @@ -2155,7 +2153,8 @@ void generate_files(int f_out, const char *local_name) char fbuf[MAXPATHLEN]; int itemizing; enum logcode code; - int save_do_progress = do_progress; + int save_info_flist = info_levels[INFO_FLIST]; + int save_info_progress = info_levels[INFO_PROGRESS]; if (protocol_version >= 29) { itemizing = 1; @@ -2182,7 +2181,7 @@ void generate_files(int f_out, const char *local_name) | (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0); implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30; - if (verbose > 2) + if (DEBUG_GTE(GENR, 1)) rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid()); if (delete_before && !solo_file && cur_flist->used > 0) @@ -2193,11 +2192,11 @@ void generate_files(int f_out, const char *local_name) if (!deldelay_buf) out_of_memory("delete-delay"); } - do_progress = 0; + info_levels[INFO_FLIST] = info_levels[INFO_PROGRESS] = 0; if (append_mode > 0 || whole_file < 0) whole_file = 0; - if (verbose >= 2) { + if (DEBUG_GTE(FLIST, 1)) { rprintf(FINFO, "delta-transmission %s\n", whole_file ? "disabled for local transfer or --whole-file" @@ -2286,7 +2285,7 @@ void generate_files(int f_out, const char *local_name) if (delete_during) delete_in_dir(NULL, NULL, &dev_zero); phase++; - if (verbose > 2) + if (DEBUG_GTE(GENR, 1)) rprintf(FINFO, "generate_files phase=%d\n", phase); while (1) { @@ -2297,7 +2296,7 @@ void generate_files(int f_out, const char *local_name) } phase++; - if (verbose > 2) + if (DEBUG_GTE(GENR, 1)) rprintf(FINFO, "generate_files phase=%d\n", phase); write_ndx(f_out, NDX_DONE); @@ -2315,7 +2314,7 @@ void generate_files(int f_out, const char *local_name) if (protocol_version >= 29) { phase++; - if (verbose > 2) + if (DEBUG_GTE(GENR, 1)) rprintf(FINFO, "generate_files phase=%d\n", phase); if (delay_updates) write_ndx(f_out, NDX_DONE); @@ -2324,7 +2323,9 @@ void generate_files(int f_out, const char *local_name) wait_for_receiver(); } - do_progress = save_do_progress; + info_levels[INFO_FLIST] = save_info_flist; + info_levels[INFO_PROGRESS] = save_info_progress; + if (delete_during == 2) do_delayed_deletions(fbuf); if (delete_after && !solo_file && file_total > 0) @@ -2341,6 +2342,6 @@ void generate_files(int f_out, const char *local_name) io_error |= IOERR_DEL_LIMIT; } - if (verbose > 2) + if (DEBUG_GTE(GENR, 1)) rprintf(FINFO, "generate_files finished\n"); } diff --git a/hlink.c b/hlink.c index 1e8adc86..d6d0ecfc 100644 --- a/hlink.c +++ b/hlink.c @@ -22,7 +22,6 @@ #include "rsync.h" -extern int verbose; extern int dry_run; extern int list_only; extern int am_sender; @@ -215,7 +214,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx, ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0, ""); } - if (verbose > 1 && maybe_ATTRS_REPORT) + if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT) rprintf(FCLIENT, "%s is uptodate\n", fname); file->flags |= FLAG_HLINK_DONE; return 0; @@ -236,7 +235,7 @@ static int maybe_hard_link(struct file_struct *file, int ndx, ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0, realname); } - if (code != FNONE && verbose) + if (code != FNONE && INFO_GTE(NAME, 1)) rprintf(code, "%s => %s\n", fname, realname); return 0; } @@ -377,10 +376,10 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname, continue; statret = 1; if (stdout_format_has_i == 0 - || (verbose < 2 && stdout_format_has_i < 2)) { + || (!INFO_GTE(NAME, 2) && stdout_format_has_i < 2)) { itemizing = 0; code = FNONE; - if (verbose > 1 && maybe_ATTRS_REPORT) + if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT) rprintf(FCLIENT, "%s is uptodate\n", fname); } break; @@ -426,7 +425,7 @@ int hard_link_one(struct file_struct *file, const char *fname, if (do_link(oldname, fname) < 0) { enum logcode code; if (terse) { - if (!verbose) + if (!INFO_GTE(NAME, 1)) return 0; code = FINFO; } else diff --git a/io.c b/io.c index 6a91ffd5..b21dff42 100644 --- a/io.c +++ b/io.c @@ -408,7 +408,7 @@ static void read_msg_fd(void) /* Read extra file list from receiver. */ assert(iobuf_in != NULL); assert(iobuf_f_in == fd); - if (verbose > 3) { + if (DEBUG_GTE(FLIST, 2)) { rprintf(FINFO, "[%s] receiving flist for dir %d\n", who_am_i(), IVAL(buf,0)); } diff --git a/log.c b/log.c index 9100f5db..4a4c404e 100644 --- a/log.c +++ b/log.c @@ -22,7 +22,6 @@ #include "rsync.h" #include "ifuncs.h" -extern int verbose; extern int dry_run; extern int am_daemon; extern int am_server; @@ -37,7 +36,6 @@ extern int protocol_version; extern int preserve_times; extern int uid_ndx; extern int gid_ndx; -extern int progress_is_active; extern int stdout_format_has_i; extern int stdout_format_has_o_or_i; extern int logfile_format_has_i; @@ -64,6 +62,7 @@ static FILE *logfile_fp; struct stats stats; int got_xfer_error = 0; +int output_needs_newline = 0; struct { int code; @@ -321,9 +320,9 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8) exit_cleanup(RERR_MESSAGEIO); } - if (progress_is_active) { + if (output_needs_newline) { fputc('\n', f); - progress_is_active = 0; + output_needs_newline = 0; } trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r') @@ -445,7 +444,7 @@ void rflush(enum logcode code) if (am_daemon || code == FLOG) return; - if (code == FINFO && !am_server) + if (!am_server && (code == FINFO || code == FCLIENT)) f = stdout; else f = stderr; @@ -767,7 +766,7 @@ void maybe_log_item(struct file_struct *file, int iflags, int itemizing, { int significant_flags = iflags & SIGNIFICANT_ITEM_FLAGS; int see_item = itemizing && (significant_flags || *buf - || stdout_format_has_i > 1 || (verbose > 1 && stdout_format_has_i)); + || stdout_format_has_i > 1 || (INFO_GTE(NAME, 2) && stdout_format_has_i)); int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags; if (am_server) { if (logfile_name && !dry_run && see_item @@ -791,7 +790,7 @@ void log_delete(const char *fname, int mode) x.file.mode = mode; - if (!verbose && !stdout_format) + if (!INFO_GTE(DEL, 1) && !stdout_format) ; else if (am_server && protocol_version >= 29 && len < MAXPATHLEN) { if (S_ISDIR(mode)) diff --git a/main.c b/main.c index 6881c8e6..5ca82106 100644 --- a/main.c +++ b/main.c @@ -27,7 +27,6 @@ #include #endif -extern int verbose; extern int dry_run; extern int list_only; extern int am_root; @@ -38,9 +37,9 @@ extern int am_daemon; extern int inc_recurse; extern int blocking_io; extern int remove_source_files; +extern int output_needs_newline; extern int need_messages_from_generator; extern int kluge_around_eof; -extern int do_stats; extern int got_xfer_error; extern int module_id; extern int copy_links; @@ -183,7 +182,7 @@ static void handle_stats(int f) total_read = stats.total_read; total_written = stats.total_written; - if (do_stats && verbose > 1) { + if (INFO_GTE(STATS, 3)) { /* These come out from every process */ show_malloc_stats(); show_flist_stats(); @@ -239,7 +238,7 @@ static void handle_stats(int f) static void output_summary(void) { - if (do_stats) { + 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", @@ -268,7 +267,7 @@ static void output_summary(void) human_num(total_read)); } - if (verbose || do_stats) { + if (INFO_GTE(STATS, 1)) { rprintf(FCLIENT, "\n"); rprintf(FINFO, "sent %s bytes received %s bytes %s bytes/sec\n", @@ -434,7 +433,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in args[argc] = NULL; - if (verbose > 3) { + if (DEBUG_GTE(CMD, 2)) { for (i = 0; i < argc; i++) rprintf(FCLIENT, "cmd[%d]=%s ", i, args[i]); rprintf(FCLIENT, "\n"); @@ -499,7 +498,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path) int statret; char *cp; - if (verbose > 2) { + if (DEBUG_GTE(RECV, 1)) { rprintf(FINFO, "get_local_name count=%d %s\n", file_total, NS(dest_path)); } @@ -580,7 +579,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path) && strcmp(flist->files[flist->low]->basename, ".") == 0) flist->files[0]->flags |= FLAG_DIR_CREATED; - if (verbose) + if (INFO_GTE(NAME, 1)) rprintf(FINFO, "created directory %s\n", dest_path); if (dry_run) { @@ -682,7 +681,7 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[]) struct file_list *flist; char *dir = argv[0]; - if (verbose > 2) { + if (DEBUG_GTE(SEND, 1)) { rprintf(FINFO, "server_sender starting pid=%ld\n", (long)getpid()); } @@ -775,6 +774,11 @@ static int do_recv(int f_in, int f_out, char *local_name) io_flush(FULL_FLUSH); handle_stats(f_in); + if (output_needs_newline) { + fputc('\n', stdout); + output_needs_newline = 0; + } + send_msg(MSG_DONE, "", 1, 0); write_varlong(error_pipe[1], stats.total_read, 3); io_flush(FULL_FLUSH); @@ -848,15 +852,17 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[]) int exit_code; struct file_list *flist; char *local_name = NULL; - int save_verbose = verbose; + int negated_levels; if (filesfrom_fd >= 0) { /* We can't mix messages with files-from data on the socket, - * so temporarily turn off verbose messages. */ - verbose = 0; - } + * so temporarily turn off info/debug messages. */ + negate_output_levels(); + negated_levels = 1; + } else + negated_levels = 0; - if (verbose > 2) { + if (DEBUG_GTE(RECV, 1)) { rprintf(FINFO, "server_recv(%d) starting pid=%ld\n", argc, (long)getpid()); } @@ -901,7 +907,9 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[]) } if (inc_recurse && file_total == 1) recv_additional_file_list(f_in); - verbose = save_verbose; + + if (negated_levels) + negate_output_levels(); if (argc > 0) local_name = get_local_name(flist,argv[0]); @@ -1017,7 +1025,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) start_write_batch(f_out); flist = send_file_list(f_out, argc, argv); set_msg_fd_in(-1); - if (verbose > 3) + if (DEBUG_GTE(FLIST, 3)) rprintf(FINFO,"file list sent\n"); if (protocol_version >= 23) @@ -1030,7 +1038,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) if (protocol_version >= 24) read_final_goodbye(f_in); if (pid != -1) { - if (verbose > 3) + if (DEBUG_GTE(EXIT, 2)) rprintf(FINFO,"client_run waiting on %d\n", (int) pid); io_flush(FULL_FLUSH); wait_process_with_flush(pid, &exit_code); @@ -1072,7 +1080,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) } if (pid != -1) { - if (verbose > 3) + if (DEBUG_GTE(RECV, 1)) rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid); io_flush(FULL_FLUSH); wait_process_with_flush(pid, &exit_code); @@ -1254,7 +1262,7 @@ static int start_client(int argc, char *argv[]) } } - if (verbose > 3) { + if (DEBUG_GTE(CMD, 2)) { rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n", NS(shell_cmd), NS(shell_machine), NS(shell_user), remote_argv ? NS(remote_argv[0]) : ""); diff --git a/match.c b/match.c index 280e09fc..bb40ebfe 100644 --- a/match.c +++ b/match.c @@ -21,8 +21,6 @@ #include "rsync.h" -extern int verbose; -extern int do_progress; extern int checksum_seed; extern int append_mode; @@ -108,7 +106,7 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf, int32 n = (int32)(offset - last_match); /* max value: block_size (int32) */ int32 j; - if (verbose > 2 && i >= 0) { + if (DEBUG_GTE(CHKSUM, 2) && i >= 0) { rprintf(FINFO, "match at %.0f last_match=%.0f j=%d len=%ld n=%ld\n", (double)offset, (double)last_match, i, @@ -133,7 +131,7 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf, else last_match = offset; - if (buf && do_progress) + if (buf && INFO_GTE(PROGRESS, 1)) show_progress(last_match, buf->file_size); } @@ -152,7 +150,7 @@ static void hash_search(int f,struct sum_struct *s, * coding of the output to work more efficiently. */ want_i = 0; - if (verbose > 2) { + if (DEBUG_GTE(CHKSUM, 2)) { rprintf(FINFO, "hash search b=%ld len=%.0f\n", (long)s->blength, (double)len); } @@ -164,14 +162,14 @@ static void hash_search(int f,struct sum_struct *s, sum = get_checksum1((char *)map, k); s1 = sum & 0xFFFF; s2 = sum >> 16; - if (verbose > 3) + if (DEBUG_GTE(CHKSUM, 3)) rprintf(FINFO, "sum=%.8x k=%ld\n", sum, (long)k); offset = 0; end = len + 1 - s->sums[s->count-1].len; - if (verbose > 3) { + if (DEBUG_GTE(CHKSUM, 3)) { rprintf(FINFO, "hash search s->blength=%ld len=%.0f count=%.0f\n", (long)s->blength, (double)len, (double)s->count); } @@ -180,7 +178,7 @@ static void hash_search(int f,struct sum_struct *s, int done_csum2 = 0; int32 i; - if (verbose > 4) { + if (DEBUG_GTE(CHKSUM, 4)) { rprintf(FINFO, "offset=%.0f sum=%04x%04x\n", (double)offset, s2 & 0xFFFF, s1 & 0xFFFF); } @@ -213,7 +211,7 @@ static void hash_search(int f,struct sum_struct *s, && !(s->sums[i].flags & SUMFLG_SAME_OFFSET)) continue; - if (verbose > 3) { + if (DEBUG_GTE(CHKSUM, 3)) { rprintf(FINFO, "potential match at %.0f i=%ld sum=%08x\n", (double)offset, (long)i, sum); @@ -344,7 +342,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len) if (append_mode == 2) { OFF_T j = 0; for (j = CHUNK_SIZE; j < s->flength; j += CHUNK_SIZE) { - if (buf && do_progress) + if (buf && INFO_GTE(PROGRESS, 1)) show_progress(last_match, buf->file_size); sum_update(map_ptr(buf, last_match, CHUNK_SIZE), CHUNK_SIZE); @@ -352,7 +350,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len) } if (last_match < s->flength) { int32 n = (int32)(s->flength - last_match); - if (buf && do_progress) + if (buf && INFO_GTE(PROGRESS, 1)) show_progress(last_match, buf->file_size); sum_update(map_ptr(buf, last_match, n), n); } @@ -364,12 +362,12 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len) if (len > 0 && s->count > 0) { build_hash_table(s); - if (verbose > 2) + if (DEBUG_GTE(CHKSUM, 2)) rprintf(FINFO,"built hash table\n"); hash_search(f, s, buf, len); - if (verbose > 2) + if (DEBUG_GTE(CHKSUM, 2)) rprintf(FINFO,"done hash search\n"); } else { OFF_T j; @@ -384,11 +382,11 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len) if (buf && buf->status != 0) file_sum[0]++; - if (verbose > 2) + if (DEBUG_GTE(CHKSUM, 2)) rprintf(FINFO,"sending file_sum\n"); write_buf(f, file_sum, sum_len); - if (verbose > 2) + if (DEBUG_GTE(CHKSUM, 2)) rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n", false_alarms, hash_hits, matches); @@ -400,7 +398,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len) void match_report(void) { - if (verbose <= 1) + if (!DEBUG_GTE(CHKSUM, 1)) return; rprintf(FINFO, diff --git a/options.c b/options.c index d534cec1..1bdea189 100644 --- a/options.c +++ b/options.c @@ -99,8 +99,6 @@ int recurse = 0; int allow_inc_recurse = 1; int xfer_dirs = -1; int am_daemon = 0; -int do_stats = 0; -int do_progress = 0; int connect_timeout = 0; int keep_partial = 0; int safe_symlinks = 0; @@ -178,7 +176,6 @@ static int remote_option_alloc = 0; int remote_option_cnt = 0; const char **remote_options = NULL; -int verbose = 0; int quiet = 0; int output_motd = 1; int log_before_transfer = 0; @@ -199,6 +196,93 @@ char *iconv_opt = ICONV_OPTION; struct chmod_mode_struct *chmod_modes = NULL; +static char *debug_verbosity[] = { + /*0*/ NULL, + /*1*/ NULL, + /*2*/ "bind,cmd,chksum,connect,del,dup,filter,flist", + /*3*/ "acl,backup,chksum2,del2,exit,filter2,flist2,fuzzy,genr,own,recv,send,time", + /*4*/ "cmd2,chksum3,del3,exit2,flist3,iconv,own2,proto,time2", + /*5*/ "chdir,chksum4,flist4,fuzzy2,hlink", +}; + +#define MAX_VERBOSITY ((int)(sizeof debug_verbosity / sizeof debug_verbosity[0]) - 1) + +static char *info_verbosity[MAX_VERBOSITY] = { + /*0*/ NULL, + /*1*/ "copy,del,flist,misc,name,stats,symsafe", + /*2*/ "backup,misc2,mount,name2,remove,skip", +}; + +#define MAX_OUT_LEVEL 4 /* The largest N allowed for any flagN word. */ + +short info_levels[COUNT_INFO], debug_levels[COUNT_DEBUG]; + +#define DEFAULT_PRIORITY 0 /* Default/implied/--verbose set values. */ +#define HELP_PRIORITY 1 /* The help output uses this level. */ +#define USER_PRIORITY 2 /* User-specified via --info or --debug */ +#define LIMIT_PRIORITY 3 /* Overriding priority when limiting values. */ + +#define W_CLI (1<<0) /* client side */ +#define W_SRV (1<<1) /* server side */ +#define W_SND (1<<2) /* sending side */ +#define W_REC (1<<3) /* receiving side */ + +struct output_struct { + char *name; /* The name of the info/debug flag. */ + char *help; /* The description of the info/debug flag. */ + short flag; /* The flag's value, for consistency check. */ + short where; /* Bits indicating where the flag is used. */ + short priority; /* See *_PRIORITY defines. */ +}; + +#define INFO_WORD(flag, where, help) { #flag, help, INFO_##flag, where, 0 } + +static struct output_struct info_words[] = { + INFO_WORD(BACKUP, W_REC, "Mention files backed up"), + INFO_WORD(COPY, W_REC, "Mention files copied locally on the receiving side"), + INFO_WORD(DEL, W_REC, "Mention deletions on the receiving side"), + INFO_WORD(FLIST, W_CLI, "Mention file-list receiving/sending (levels 1-2)"), + INFO_WORD(MISC, W_SND|W_REC, "Mention miscellaneous information (levels 1-2)"), + INFO_WORD(MOUNT, W_SND|W_REC, "Mention mounts that were found or skipped"), + INFO_WORD(NAME, W_SND|W_REC, "Mention 1) updated file/dir names, 2) unchanged names"), + INFO_WORD(PROGRESS, W_CLI, "Mention 1) per-file progress or 2) total transfer progress"), + INFO_WORD(REMOVE, W_SND, "Mention files removed on the sending side"), + INFO_WORD(SKIP, W_REC, "Mention files that are skipped due to options used"), + INFO_WORD(STATS, W_CLI|W_SRV, "Mention statistics at end of run (levels 1-3)"), + INFO_WORD(SYMSAFE, W_SND|W_REC, "Mention symlinks that are unsafe"), + { NULL, "--info", 0, 0, 0 } +}; + +#define DEBUG_WORD(flag, where, help) { #flag, help, DEBUG_##flag, where, 0 } + +static struct output_struct debug_words[] = { + DEBUG_WORD(ACL, W_SND|W_REC, "Debug extra ACL info"), + DEBUG_WORD(BACKUP, W_REC, "Debug backup actions (levels 1-2)"), + DEBUG_WORD(BIND, W_CLI, "Debug socket bind actions"), + DEBUG_WORD(CHDIR, W_CLI|W_SRV, "Debug when the current directory changes"), + DEBUG_WORD(CONNECT, W_CLI, "Debug connection events"), + DEBUG_WORD(CHKSUM, W_SND|W_REC, "Debug delta-transfer checksumming (levels 1-4)"), + DEBUG_WORD(CMD, W_CLI, "Debug commands+options that are issued (levels 1-2)"), + DEBUG_WORD(DEL, W_REC, "Debug delete actions (levels 1-3)"), + DEBUG_WORD(DUP, W_REC, "Debug weeding of duplicate names"), + DEBUG_WORD(EXIT, W_CLI|W_SRV, "Debug exit events (levels 1-2)"), + DEBUG_WORD(FILTER, W_SND|W_REC, "Debug filter actions (levels 1-2)"), + DEBUG_WORD(FLIST, W_SND|W_REC, "Debug file-list operations (levels 1-4)"), + DEBUG_WORD(FUZZY, W_REC, "Debug fuzzy scoring (levels 1-2)"), + DEBUG_WORD(GENR, W_REC, "Debug generator functions"), + DEBUG_WORD(HLINK, W_SND|W_REC, "Debug hard-link actions"), + DEBUG_WORD(ICONV, W_CLI|W_SRV, "Debug iconv (character conversion)"), + DEBUG_WORD(OWN, W_REC, "Debug ownership changes in users & groups (levels 1-2)"), + DEBUG_WORD(PROTO, W_CLI|W_SRV, "Debug protocol information"), + DEBUG_WORD(RECV, W_REC, "Debug receiver functions"), + DEBUG_WORD(SEND, W_SND, "Debug sender functions"), + DEBUG_WORD(TIME, W_REC, "Debug setting of modified times (levels 1-2)"), + { NULL, "--debug", 0, 0, 0 } +}; + +static int verbose = 0; +static int do_stats = 0; +static int do_progress = 0; static int daemon_opt; /* sets am_daemon after option error-reporting */ static int omit_dir_times = 0; static int F_option_cnt = 0; @@ -216,6 +300,252 @@ static char tmp_partialdir[] = ".~tmp~"; * address, or a hostname. **/ char *bind_address; +static void output_item_help(struct output_struct *words); + +/* This constructs a string that represents all the options set for either + * the --info or --debug setting, skipping any implied options (by -v, etc.). + * This is used both when conveying the user's options to the server, and + * when the help output wants to tell the user what options are implied. */ +static char *make_output_option(struct output_struct *words, short *levels, short where) +{ + char *str = words == info_words ? "--info=" : "--debug="; + int j, counts[MAX_OUT_LEVEL+1], pos, skipped = 0, len = 0, max = 0, lev = 0; + int word_count = words == info_words ? COUNT_INFO : COUNT_DEBUG; + char *buf; + + memset(counts, 0, sizeof counts); + + for (j = 0; words[j].name; j++) { + if (words[j].flag != j) { + rprintf(FERROR, "rsync: internal error on %s%s: %d != %d\n", + words == info_words ? "INFO_" : "DEBUG_", + words[j].name, words[j].flag, j); + exit_cleanup(RERR_UNSUPPORTED); + } + if (!(words[j].where & where)) + continue; + if (words[j].priority == DEFAULT_PRIORITY) { + /* Implied items don't need to be mentioned. */ + skipped++; + continue; + } + len += len ? 1 : strlen(str); + len += strlen(words[j].name); + len += levels[j] == 1 ? 0 : 1; + + if (words[j].priority == HELP_PRIORITY) + continue; /* no abbreviating for help */ + + assert(levels[j] <= MAX_OUT_LEVEL); + if (++counts[levels[j]] > max) { + /* Determine which level has the most items. */ + lev = levels[j]; + max = counts[lev]; + } + } + + /* Sanity check the COUNT_* define against the length of the table. */ + if (j != word_count) { + rprintf(FERROR, "rsync: internal error: %s is wrong! (%d != %d)\n", + words == info_words ? "COUNT_INFO" : "COUNT_DEBUG", + j, word_count); + exit_cleanup(RERR_UNSUPPORTED); + } + + if (!len) + return NULL; + + len++; + if (!(buf = new_array(char, len))) + out_of_memory("make_output_option"); + pos = 0; + + if (skipped || max < 5) + lev = -1; + else { + if (lev == 0) + pos += snprintf(buf, len, "%sNONE", str); + else if (lev == 1) + pos += snprintf(buf, len, "%sALL", str); + else + pos += snprintf(buf, len, "%sALL%d", str, lev); + } + + for (j = 0; words[j].name && pos < len; j++) { + if (words[j].priority == DEFAULT_PRIORITY || levels[j] == lev || !(words[j].where & where)) + continue; + if (pos) + buf[pos++] = ','; + else + pos += strlcpy(buf+pos, str, len-pos); + if (pos < len) + pos += strlcpy(buf+pos, words[j].name, len-pos); + /* Level 1 is implied by the name alone. */ + if (levels[j] != 1 && pos < len) + buf[pos++] = '0' + levels[j]; + } + + buf[pos] = '\0'; + + return buf; +} + +static void parse_output_words(struct output_struct *words, short *levels, + const char *str, int priority) +{ + const char *s; + int j, len, lev; + + if (!str) + return; + + while (*str) { + if ((s = strchr(str, ',')) != NULL) + len = s++ - str; + else + len = strlen(str); + while (len && isDigit(str+len-1)) + len--; + lev = isDigit(str+len) ? atoi(str+len) : 1; + if (lev > MAX_OUT_LEVEL) + lev = MAX_OUT_LEVEL; + if (len == 4 && strncasecmp(str, "help", 4) == 0) { + output_item_help(words); + exit_cleanup(0); + } + if (len == 4 && strncasecmp(str, "none", 4) == 0) + len = lev = 0; + else if (len == 3 && strncasecmp(str, "all", 3) == 0) + len = 0; + for (j = 0; words[j].name; j++) { + if (!len + || (strncasecmp(str, words[j].name, len) == 0 && !words[j].name[len])) { + if (priority >= words[j].priority) { + words[j].priority = priority; + levels[j] = lev; + } + if (len) + break; + } + } + if (len && !words[j].name) { + rprintf(FERROR, "Unknown %s item: %.*s\n", words[j].help, len, str); + exit_cleanup(RERR_SYNTAX); + } + if (!s) + break; + str = s; + } +} + +/* Tell the user what all the info or debug flags mean. */ +static void output_item_help(struct output_struct *words) +{ + short *levels = words == info_words ? info_levels : debug_levels; + char buf[128], *opt, *fmt = "%-10s %s\n"; + int j; + + rprintf(FINFO, "Use OPT or OPT1 for level 1 output, OPT2 for level 2, etc.; OPT0 silences.\n"); + rprintf(FINFO, "\n"); + for (j = 0; words[j].name; j++) + rprintf(FINFO, fmt, words[j].name, words[j].help); + rprintf(FINFO, "\n"); + + snprintf(buf, sizeof buf, "Set all %s options (e.g. all%d)", + words[j].help, MAX_OUT_LEVEL); + rprintf(FINFO, fmt, "ALL", buf); + + snprintf(buf, sizeof buf, "Silence all %s options (same as all0)", + words[j].help); + rprintf(FINFO, fmt, "NONE", buf); + + rprintf(FINFO, fmt, "HELP", "Output this help message"); + rprintf(FINFO, "\n"); + rprintf(FINFO, "Options added for each increase in verbose level:\n"); + + for (j = 1; j <= MAX_VERBOSITY; j++) { + reset_output_levels(); + if (words == info_words) + parse_output_words(info_words, levels, info_verbosity[j], HELP_PRIORITY); + else + parse_output_words(debug_words, levels, debug_verbosity[j], HELP_PRIORITY); + opt = make_output_option(words, levels, W_CLI|W_SRV|W_SND|W_REC); + if (opt) { + rprintf(FINFO, "%d) %s\n", j, strchr(opt, '=')+1); + free(opt); + } + } + + reset_output_levels(); +} + +/* The --verbose option now sets info+debug flags. */ +static void set_output_verbosity(int level, int priority) +{ + int j; + + if (level > MAX_VERBOSITY) + level = MAX_VERBOSITY; + + for (j = 1; j <= level; j++) { + parse_output_words(info_words, info_levels, info_verbosity[j], priority); + parse_output_words(debug_words, debug_levels, debug_verbosity[j], priority); + } +} + +/* Limit the info+debug flag levels given a verbose-option level limit. */ +void limit_output_verbosity(int level) +{ + short info_limits[COUNT_INFO], debug_limits[COUNT_DEBUG]; + int j; + + if (level > MAX_VERBOSITY) + return; + + memset(info_limits, 0, sizeof info_limits); + memset(debug_limits, 0, sizeof debug_limits); + + /* Compute the level limits in the above arrays. */ + for (j = 1; j <= level; j++) { + parse_output_words(info_words, info_limits, info_verbosity[j], LIMIT_PRIORITY); + parse_output_words(debug_words, debug_limits, debug_verbosity[j], LIMIT_PRIORITY); + } + + for (j = 0; j < COUNT_INFO; j++) { + if (info_levels[j] > info_limits[j]) + info_levels[j] = info_limits[j]; + } + + for (j = 0; j < COUNT_DEBUG; j++) { + if (debug_levels[j] > debug_limits[j]) + debug_levels[j] = debug_limits[j]; + } +} + +void reset_output_levels(void) +{ + int j; + + memset(info_levels, 0, sizeof info_levels); + memset(debug_levels, 0, sizeof debug_levels); + + for (j = 0; j < COUNT_INFO; j++) + info_words[j].priority = DEFAULT_PRIORITY; + + for (j = 0; j < COUNT_DEBUG; j++) + debug_words[j].priority = DEFAULT_PRIORITY; +} + +void negate_output_levels(void) +{ + int j; + + for (j = 0; j < COUNT_INFO; j++) + info_levels[j] *= -1; + + for (j = 0; j < COUNT_DEBUG; j++) + debug_levels[j] *= -1; +} static void print_rsync_version(enum logcode f) { @@ -318,6 +648,8 @@ void usage(enum logcode F) rprintf(F,"\n"); rprintf(F,"Options\n"); rprintf(F," -v, --verbose increase verbosity\n"); + rprintf(F," --info=FLAGS fine-grained informational verbosity\n"); + rprintf(F," --debug=FLAGS fine-grained debug verbosity\n"); rprintf(F," -q, --quiet suppress non-error messages\n"); rprintf(F," --no-motd suppress daemon-mode MOTD (see manpage caveat)\n"); rprintf(F," -c, --checksum skip based on checksum, not mod-time & size\n"); @@ -451,7 +783,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP, OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE, - OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, + OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG, OPT_SERVER, OPT_REFUSED_BASE = 9000}; static struct poptOption long_options[] = { @@ -461,6 +793,8 @@ static struct poptOption long_options[] = { {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 }, {"no-verbose", 0, POPT_ARG_VAL, &verbose, 0, 0, 0 }, {"no-v", 0, POPT_ARG_VAL, &verbose, 0, 0, 0 }, + {"info", 0, POPT_ARG_STRING, 0, OPT_INFO, 0, 0 }, + {"debug", 0, POPT_ARG_STRING, 0, OPT_DEBUG, 0, 0 }, {"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 }, {"motd", 0, POPT_ARG_VAL, &output_motd, 1, 0, 0 }, {"no-motd", 0, POPT_ARG_VAL, &output_motd, 0, 0, 0 }, @@ -1254,6 +1588,16 @@ int parse_arguments(int *argc_p, const char ***argv_p) } break; + case OPT_INFO: + arg = poptGetOptArg(pc); + parse_output_words(info_words, info_levels, arg, USER_PRIORITY); + break; + + case OPT_DEBUG: + arg = poptGetOptArg(pc); + parse_output_words(debug_words, debug_levels, arg, USER_PRIORITY); + break; + case OPT_HELP: usage(FINFO); exit_cleanup(0); @@ -1307,6 +1651,13 @@ int parse_arguments(int *argc_p, const char ***argv_p) exit_cleanup(0); } + set_output_verbosity(verbose, DEFAULT_PRIORITY); + + if (do_stats && !am_server) { + parse_output_words(info_words, info_levels, + verbose > 1 ? "stats3" : "stats2", DEFAULT_PRIORITY); + } + #ifdef ICONV_OPTION if (iconv_opt && protect_args != 2) { if (!am_server && strcmp(iconv_opt, "-") == 0) @@ -1523,7 +1874,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) backup_dir_buf[backup_dir_len++] = '/'; backup_dir_buf[backup_dir_len] = '\0'; } - if (verbose > 1 && !am_sender) + if (INFO_GTE(BACKUP, 1) && !am_sender) rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf); } else if (!backup_suffix_len && (!am_server || !am_sender)) { snprintf(err_buf, sizeof err_buf, @@ -1558,11 +1909,10 @@ int parse_arguments(int *argc_p, const char ***argv_p) log_before_transfer = !am_server; } - if (do_progress) { - if (am_server) - do_progress = 0; - else if (!verbose && !log_before_transfer && !am_server) - verbose = 1; + if (do_progress && !am_server) { + if (!log_before_transfer && INFO_EQ(NAME, 0)) + parse_output_words(info_words, info_levels, "name", DEFAULT_PRIORITY); + parse_output_words(info_words, info_levels, "flist2,progress", DEFAULT_PRIORITY); } if (dry_run) @@ -1570,7 +1920,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) set_io_timeout(io_timeout); - if (verbose && !stdout_format) { + if (INFO_GTE(NAME, 1) && !stdout_format) { stdout_format = "%n%L"; log_before_transfer = !am_server; } @@ -1733,6 +2083,7 @@ void server_options(char **args, int *argc_p) { static char argstr[64]; int ac = *argc_p; + short where; char *arg; int i, x; @@ -1860,13 +2211,13 @@ void server_options(char **args, int *argc_p) #endif } - argstr[x] = '\0'; - - if (x > (int)sizeof argstr) { /* Not possible... */ + if (x >= (int)sizeof argstr) { /* Not possible... */ rprintf(FERROR, "argstr overflow in server_options().\n"); exit_cleanup(RERR_MALLOC); } + argstr[x] = '\0'; + args[ac++] = argstr; #ifdef ICONV_OPTION @@ -2049,7 +2400,6 @@ void server_options(char **args, int *argc_p) * and it may be an older version that doesn't know this * option, so don't send it if client is the sender. */ - int i; for (i = 0; i < basis_dir_cnt; i++) { args[ac++] = dest_option; args[ac++] = basis_dir[i]; @@ -2057,6 +2407,16 @@ void server_options(char **args, int *argc_p) } } + /* What flags do we need to send to the other side? */ + where = (am_server ? W_CLI : W_SRV) | (am_sender ? W_REC : W_SND); + arg = make_output_option(info_words, info_levels, where); + if (arg) + args[ac++] = arg; + + arg = make_output_option(debug_words, debug_levels, where); + if (arg) + args[ac++] = arg; + if (append_mode) { if (append_mode > 1) args[ac++] = "--append"; diff --git a/pipe.c b/pipe.c index f32d63e6..755da545 100644 --- a/pipe.c +++ b/pipe.c @@ -51,7 +51,7 @@ pid_t piped_child(char **command, int *f_in, int *f_out) int to_child_pipe[2]; int from_child_pipe[2]; - if (verbose >= 2) + if (DEBUG_GTE(CMD, 1)) print_child_argv("opening connection using:", command); if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) { diff --git a/progress.c b/progress.c index 25033b8b..afd8ef63 100644 --- a/progress.c +++ b/progress.c @@ -24,6 +24,7 @@ extern int am_server; extern int need_unsorted_flist; +extern int output_needs_newline; extern struct stats stats; extern struct file_list *cur_flist; @@ -40,8 +41,6 @@ struct progress_history { OFF_T ofs; }; -int progress_is_active = 0; - static struct progress_history ph_start; static struct progress_history ph_list[PROGRESS_HISTORY_SECS]; static int newest_hpos, oldest_hpos; @@ -66,16 +65,26 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now, { char rembuf[64], eol[128]; const char *units; - int pct = ofs == size ? 100 : (int) (100.0 * ofs / size); unsigned long diff; double rate, remain; + int pct; if (is_last) { - snprintf(eol, sizeof eol, + int len = snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n", stats.num_transferred_files, stats.num_files - current_file_index - 1, stats.num_files); + if (INFO_GTE(PROGRESS, 2)) { + static int last_len = 0; + /* Drop \n and pad with spaces if line got shorter. */ + if (last_len < --len) + last_len = len; + eol[last_len] = '\0'; + while (last_len > len) + eol[--last_len] = ' '; + is_last = 0; + } /* Compute stats based on the starting info. */ if (!ph_start.time.tv_sec || !(diff = msdiff(&ph_start.time, now))) @@ -112,18 +121,21 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now, (int) remain % 60); } - progress_is_active = 0; + output_needs_newline = 0; + pct = ofs == size ? 100 : (int) (100.0 * ofs / size); rprintf(FCLIENT, "\r%12s %3d%% %7.2f%s %s%s", human_num(ofs), pct, rate, units, rembuf, eol); if (!is_last) { - progress_is_active = 1; - fflush(stdout); + output_needs_newline = 1; + rflush(FCLIENT); } } void set_current_file_index(struct file_struct *file, int ndx) { - if (need_unsorted_flist) + if (!file) + current_file_index = cur_flist->used + cur_flist->ndx_start - 1; + else if (need_unsorted_flist) current_file_index = flist_find(cur_flist, file) + cur_flist->ndx_start; else current_file_index = ndx; @@ -135,9 +147,14 @@ void end_progress(OFF_T size) if (!am_server) { struct timeval now; gettimeofday(&now, NULL); - rprint_progress(size, size, &now, True); + if (INFO_GTE(PROGRESS, 2)) { + rprint_progress(stats.total_transferred_size, + stats.total_size, &now, True); + } else { + rprint_progress(size, size, &now, True); + memset(&ph_start, 0, sizeof ph_start); + } } - memset(&ph_start, 0, sizeof ph_start); } void show_progress(OFF_T ofs, OFF_T size) @@ -193,5 +210,9 @@ void show_progress(OFF_T ofs, OFF_T size) return; #endif - rprint_progress(ofs, size, &now, False); + if (INFO_GTE(PROGRESS, 2)) { + rprint_progress(stats.total_transferred_size, + stats.total_size, &now, False); + } else + rprint_progress(ofs, size, &now, False); } diff --git a/receiver.c b/receiver.c index ce6b7394..2ba1ab95 100644 --- a/receiver.c +++ b/receiver.c @@ -21,11 +21,9 @@ #include "rsync.h" -extern int verbose; extern int dry_run; extern int do_xfers; extern int am_server; -extern int do_progress; extern int inc_recurse; extern int log_before_transfer; extern int stdout_format_has_i; @@ -180,7 +178,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, if (fd_r >= 0 && size_r > 0) { int32 read_size = MAX(sum.blength * 2, 16*1024); mapbuf = map_file(fd_r, size_r, read_size, sum.blength); - if (verbose > 2) { + if (DEBUG_GTE(CHKSUM, 2)) { rprintf(FINFO, "recv mapped %s of size %.0f\n", fname_r, (double)size_r); } @@ -196,7 +194,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, sum.flength -= sum.blength - sum.remainder; if (append_mode == 2) { for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) { - if (do_progress) + if (INFO_GTE(PROGRESS, 1)) show_progress(offset, total_size); sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE), CHUNK_SIZE); @@ -204,7 +202,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, } if (offset < sum.flength) { int32 len = (int32)(sum.flength - offset); - if (do_progress) + if (INFO_GTE(PROGRESS, 1)) show_progress(offset, total_size); sum_update(map_ptr(mapbuf, offset, len), len); } @@ -218,11 +216,11 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, } while ((i = recv_token(f_in, &data)) != 0) { - if (do_progress) + if (INFO_GTE(PROGRESS, 1)) show_progress(offset, total_size); if (i > 0) { - if (verbose > 3) { + if (DEBUG_GTE(CHKSUM, 3)) { rprintf(FINFO,"data recv %d at %.0f\n", i,(double)offset); } @@ -246,7 +244,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, stats.matched_data += len; - if (verbose > 3) { + if (DEBUG_GTE(CHKSUM, 3)) { rprintf(FINFO, "chunk[%d] of size %ld at %.0f offset=%.0f\n", i, (long)len, (double)offset2, (double)offset); @@ -288,7 +286,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, ftruncate(fd, offset); #endif - if (do_progress) + if (INFO_GTE(PROGRESS, 1)) end_progress(total_size); if (fd != -1 && offset > 0 && sparse_end(fd) != 0) { @@ -304,7 +302,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, unmap_file(mapbuf); read_buf(f_in, file_sum2, sum_len); - if (verbose > 2) + if (DEBUG_GTE(CHKSUM, 2)) rprintf(FINFO,"got file_sum\n"); if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0) return 0; @@ -328,7 +326,7 @@ static void handle_delayed_updates(char *local_name) if ((partialptr = partial_dir_fname(fname)) != NULL) { if (make_backups > 0 && !make_backup(fname)) continue; - if (verbose > 2) { + if (DEBUG_GTE(RECV, 1)) { rprintf(FINFO, "renaming %s to %s\n", partialptr, fname); } @@ -396,7 +394,7 @@ int recv_files(int f_in, char *local_name) #endif int ndx, recv_ok; - if (verbose > 2) + if (DEBUG_GTE(RECV, 1)) rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used); if (delay_updates) @@ -409,6 +407,10 @@ int recv_files(int f_in, char *local_name) ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type, xname, &xlen); if (ndx == NDX_DONE) { + if (!am_server && INFO_GTE(PROGRESS, 2) && cur_flist) { + set_current_file_index(NULL, 0); + end_progress(0); + } if (inc_recurse && first_flist) { flist_free(first_flist); if (first_flist) @@ -423,7 +425,7 @@ int recv_files(int f_in, char *local_name) } if (++phase > max_phase) break; - if (verbose > 2) + if (DEBUG_GTE(RECV, 1)) rprintf(FINFO, "recv_files phase=%d\n", phase); if (phase == 2 && delay_updates) handle_delayed_updates(local_name); @@ -437,7 +439,7 @@ int recv_files(int f_in, char *local_name) file = dir_flist->files[cur_flist->parent_ndx]; fname = local_name ? local_name : f_name(file, fbuf); - if (verbose > 2) + if (DEBUG_GTE(RECV, 1)) rprintf(FINFO, "recv_files(%s)\n", fname); #ifdef SUPPORT_XATTRS @@ -482,7 +484,7 @@ int recv_files(int f_in, char *local_name) } } - if (!am_server && do_progress) + if (!am_server && INFO_GTE(PROGRESS, 1)) set_current_file_index(file, ndx); stats.num_transferred_files++; stats.total_transferred_size += F_LENGTH(file); @@ -671,7 +673,7 @@ int recv_files(int f_in, char *local_name) /* log the transfer */ if (log_before_transfer) log_item(FCLIENT, file, &initial_stats, iflags, NULL); - else if (!am_server && verbose && do_progress) + else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1)) rprintf(FINFO, "%s\n", fname); /* recv file data */ @@ -722,7 +724,7 @@ int recv_files(int f_in, char *local_name) break; case 0: { enum logcode msgtype = redoing ? FERROR_XFER : FWARNING; - if (msgtype == FERROR_XFER || verbose) { + if (msgtype == FERROR_XFER || INFO_GTE(NAME, 1)) { char *errstr, *redostr, *keptstr; if (!(keep_partial && partialptr) && !inplace) keptstr = "discarded"; @@ -762,7 +764,7 @@ int recv_files(int f_in, char *local_name) if (phase == 2 && delay_updates) /* for protocol_version < 29 */ handle_delayed_updates(local_name); - if (verbose > 2) + if (DEBUG_GTE(RECV, 1)) rprintf(FINFO,"recv_files finished\n"); return 0; diff --git a/rsync.c b/rsync.c index 85244c88..734a373d 100644 --- a/rsync.c +++ b/rsync.c @@ -27,7 +27,6 @@ #include #endif -extern int verbose; extern int dry_run; extern int preserve_acls; extern int preserve_xattrs; @@ -84,7 +83,7 @@ void setup_iconv(void) /* It's OK if this fails... */ ic_chck = iconv_open(defset, defset); - if (verbose > 3) { + if (DEBUG_GTE(ICONV, 1)) { if (ic_chck == (iconv_t)-1) { rprintf(FINFO, "note: iconv_open(\"%s\", \"%s\") failed (%d)" @@ -126,7 +125,7 @@ void setup_iconv(void) exit_cleanup(RERR_UNSUPPORTED); } - if (verbose > 1) { + if (INFO_GTE(MISC, 2)) { rprintf(FINFO, "%s charset: %s\n", am_server ? "server" : "client", *charset ? charset : "[LOCALE]"); @@ -218,7 +217,7 @@ void send_protected_args(int fd, char *args[]) for (i = 0; args[i]; i++) {} /* find first NULL */ args[i] = "rsync"; /* set a new arg0 */ - if (verbose > 1) + if (DEBUG_GTE(CMD, 1)) print_child_argv("protected args:", args + i + 1); do { #ifdef ICONV_OPTION @@ -247,7 +246,7 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, int len, iflags = 0; struct file_list *flist; uchar fnamecmp_type = FNAMECMP_FNAME; - int ndx, save_verbose = verbose; + int ndx; read_loop: while (1) { @@ -275,17 +274,17 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, } /* Send everything read from f_in to msg_fd_out. */ - if (verbose > 3) { + if (DEBUG_GTE(FLIST, 2)) { rprintf(FINFO, "[%s] receiving flist for dir %d\n", who_am_i(), ndx); } - verbose = 0; + negate_output_levels(); /* turn off all info/debug output */ send_msg_int(MSG_FLIST, ndx); start_flist_forward(f_in); flist = recv_file_list(f_in); flist->parent_ndx = ndx; stop_flist_forward(); - verbose = save_verbose; + negate_output_levels(); /* restore info/debug output */ } iflags = protocol_version >= 29 ? read_shortint(f_in) @@ -448,7 +447,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, } else #endif if (change_uid || change_gid) { - if (verbose > 2) { + if (DEBUG_GTE(OWN, 1)) { if (change_uid) { rprintf(FINFO, "set uid of %s from %u to %u\n", @@ -507,7 +506,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, } #endif - if (verbose > 1 && flags & ATTRS_REPORT) { + if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) { if (updated) rprintf(FCLIENT, "%s\n", fname); else @@ -555,7 +554,7 @@ int finish_transfer(const char *fname, const char *fnametmp, const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL; if (inplace) { - if (verbose > 2) + if (DEBUG_GTE(RECV, 1)) rprintf(FINFO, "finishing %s\n", fname); fnametmp = fname; goto do_set_file_attrs; @@ -573,7 +572,7 @@ int finish_transfer(const char *fname, const char *fnametmp, ok_to_set_time ? 0 : ATTRS_SKIP_MTIME); /* move tmp file over real file */ - if (verbose > 2) + if (DEBUG_GTE(RECV, 1)) rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname); ret = robust_rename(fnametmp, fname, temp_copy_name, file->mode & INITACCESSPERMS); diff --git a/rsync.h b/rsync.h index 77f9b3a7..fdc7a032 100644 --- a/rsync.h +++ b/rsync.h @@ -1120,7 +1120,51 @@ size_t strlcat(char *d, const char *s, size_t bufsize); #define FD_ZERO(fdsetp) memset(fdsetp, 0, sizeof (fd_set)) #endif -extern int verbose; +extern short info_levels[], debug_levels[]; + +#define INFO_GTE(flag, lvl) (info_levels[INFO_##flag] >= (lvl)) +#define INFO_EQ(flag, lvl) (info_levels[INFO_##flag] == (lvl)) +#define DEBUG_GTE(flag, lvl) (debug_levels[DEBUG_##flag] >= (lvl)) +#define DEBUG_EQ(flag, lvl) (debug_levels[DEBUG_##flag] == (lvl)) + +#define INFO_BACKUP 0 +#define INFO_COPY (INFO_BACKUP+1) +#define INFO_DEL (INFO_COPY+1) +#define INFO_FLIST (INFO_DEL+1) +#define INFO_MISC (INFO_FLIST+1) +#define INFO_MOUNT (INFO_MISC+1) +#define INFO_NAME (INFO_MOUNT+1) +#define INFO_PROGRESS (INFO_NAME+1) +#define INFO_REMOVE (INFO_PROGRESS+1) +#define INFO_SKIP (INFO_REMOVE+1) +#define INFO_STATS (INFO_SKIP+1) +#define INFO_SYMSAFE (INFO_STATS+1) + +#define COUNT_INFO (INFO_SYMSAFE+1) + +#define DEBUG_ACL 0 +#define DEBUG_BACKUP (DEBUG_ACL+1) +#define DEBUG_BIND (DEBUG_BACKUP+1) +#define DEBUG_CHDIR (DEBUG_BIND+1) +#define DEBUG_CONNECT (DEBUG_CHDIR+1) +#define DEBUG_CHKSUM (DEBUG_CONNECT+1) +#define DEBUG_CMD (DEBUG_CHKSUM+1) +#define DEBUG_DEL (DEBUG_CMD+1) +#define DEBUG_DUP (DEBUG_DEL+1) +#define DEBUG_EXIT (DEBUG_DUP+1) +#define DEBUG_FILTER (DEBUG_EXIT+1) +#define DEBUG_FLIST (DEBUG_FILTER+1) +#define DEBUG_FUZZY (DEBUG_FLIST+1) +#define DEBUG_GENR (DEBUG_FUZZY+1) +#define DEBUG_HLINK (DEBUG_GENR+1) +#define DEBUG_ICONV (DEBUG_HLINK+1) +#define DEBUG_OWN (DEBUG_ICONV+1) +#define DEBUG_PROTO (DEBUG_OWN+1) +#define DEBUG_RECV (DEBUG_PROTO+1) +#define DEBUG_SEND (DEBUG_RECV+1) +#define DEBUG_TIME (DEBUG_SEND+1) + +#define COUNT_DEBUG (DEBUG_TIME+1) #ifndef HAVE_INET_NTOP const char *inet_ntop(int af, const void *src, char *dst, size_t size); diff --git a/rsync.yo b/rsync.yo index 33773129..1b30c7a4 100644 --- a/rsync.yo +++ b/rsync.yo @@ -314,6 +314,8 @@ manpagesection(OPTIONS SUMMARY) Here is a short summary of the options available in rsync. Please refer to the detailed description below for a complete description. verb( -v, --verbose increase verbosity + --info=FLAGS fine-grained informational verbosity + --debug=FLAGS fine-grained debug verbosity -q, --quiet suppress non-error messages --no-motd suppress daemon-mode MOTD (see caveat) -c, --checksum skip based on checksum, not mod-time & size @@ -465,23 +467,61 @@ dit(bf(--version)) print the rsync version number and exit. dit(bf(-v, --verbose)) This option increases the amount of information you are given during the transfer. By default, rsync works silently. A single bf(-v) will give you information about what files are being -transferred and a brief summary at the end. Two bf(-v) flags will give you +transferred and a brief summary at the end. Two bf(-v) options will give you information on what files are being skipped and slightly more -information at the end. More than two bf(-v) flags should only be used if +information at the end. More than two bf(-v) options should only be used if you are debugging rsync. -Note that the names of the transferred files that are output are done using -a default bf(--out-format) of "%n%L", which tells you just the name of the -file and, if the item is a link, where it points. At the single bf(-v) -level of verbosity, this does not mention when a file gets its attributes -changed. If you ask for an itemized list of changed attributes (either -bf(--itemize-changes) or adding "%i" to the bf(--out-format) setting), the -output (on the client) increases to mention all items that are changed in -any way. See the bf(--out-format) option for more details. +In a modern rsync, the bf(-v) option is equivalent to the setting of groups +of bf(--info) and bf(--debug) options. You can choose to use these newer +options in addition to, or in place of using bf(--verbose), as any +fine-grained settings override the implied settings of bf(-v). Both +bf(--info) and bf(--debug) have a way to ask for help that tells you +exactly what flags are set for each increase in verbosity. + +dit(bf(--info=FLAGS)) +This option lets you have fine-grained control over the +information +output you want to see. An individual flag name may be followed by a level +number, with 0 meaning to silence that output, 1 being the default output +level, and higher numbers increasing the output of that flag (for those +that support higher levels). Use +bf(--info=help) +to see all the available flag names, what they output, and what flag names +are added for each increase in the verbose level. Some examples: + +verb( rsync -a --info=progress2 src/ dest/ + rsync -avv --info=stats2,misc1,flist0 src/ dest/ ) + +Note that bf(--info=name)'s output is affected by the bf(--out-format) and +bf(--itemize-changes) (bf(-i)) options. See those options for more +information on what is output and when. + +This option was added to 3.1.0, so an older rsync on the server side might +reject your attempts at fine-grained control (if one or more flags needed +to be send to the server and the server was too old to understand them). + +dit(bf(--debug=FLAGS)) +This option lets you have fine-grained control over the +debug +output you want to see. An individual flag name may be followed by a level +number, with 0 meaning to silence that output, 1 being the default output +level, and higher numbers increasing the output of that flag (for those +that support higher levels). Use +bf(--debug=help) +to see all the available flag names, what they output, and what flag names +are added for each increase in the verbose level. Some examples: + +verb( rsync -avvv --debug=none src/ dest/ + rsync -avA --del --debug=del2,acl src/ dest/ ) + +This option was added to 3.1.0, so an older rsync on the server side might +reject your attempts at fine-grained control (if one or more flags needed +to be send to the server and the server was too old to understand them). dit(bf(-q, --quiet)) This option decreases the amount of information you are given during the transfer, notably suppressing information messages -from the remote server. This flag is useful when invoking rsync from +from the remote server. This option name is useful when invoking rsync from cron. dit(bf(--no-motd)) This option affects the information that is output @@ -1756,22 +1796,22 @@ you are talking to a recent enough rsync that it logs deletions instead of outputting them as a verbose message). dit(bf(--out-format=FORMAT)) This allows you to specify exactly what the -rsync client outputs to the user on a per-update basis. The format is a text -string containing embedded single-character escape sequences prefixed with -a percent (%) character. For a list of the possible escape characters, see -the "log format" setting in the rsyncd.conf manpage. - -Specifying this option will mention each file, dir, etc. that gets updated -in a significant way (a transferred file, a recreated symlink/device, or a -touched directory). In addition, if the itemize-changes escape (%i) is -included in the string, the logging of names increases to mention any -item that is changed in any way (as long as the receiving side is at least -2.6.4). See the bf(--itemize-changes) option for a description of the -output of "%i". - -The bf(--verbose) option implies a format of "%n%L", but you can use -bf(--out-format) without bf(--verbose) if you like, or you can override -the format of its per-file output using this option. +rsync client outputs to the user on a per-update basis. The format is a +text string containing embedded single-character escape sequences prefixed +with a percent (%) character. A default format of "%n%L" is assumed if +either bf(--info=name) or bf(-v) is specified (this tells you just the name +of the file and, if the item is a link, where it points). For a full list +of the possible escape characters, see the "log format" setting in the +rsyncd.conf manpage. + +Specifying the bf(--out-format) option implies the bf(--info=name) option, +which will mention each file, dir, etc. that gets updated in a significant +way (a transferred file, a recreated symlink/device, or a touched +directory). In addition, if the itemize-changes escape (%i) is included in +the string (e.g. if the bf(--itemize-changes) option was used), the logging +of names increases to mention any item that is changed in any way (as long +as the receiving side is at least 2.6.4). See the bf(--itemize-changes) +option for a description of the output of "%i". Rsync will output the out-format string prior to a file's transfer unless one of the transfer-statistic escapes is requested, in which case the @@ -1804,7 +1844,9 @@ in the rsyncd.conf manpage. dit(bf(--stats)) This tells rsync to print a verbose set of statistics on the file transfer, allowing you to tell how effective rsync's delta-transfer -algorithm is for your data. +algorithm is for your data. This option is equivalent to bf(--info=stats2) +if combined with 0 or 1 bf(-v) options, or bf(--info=stats3) if combined +with 2 or more bf(-v) options. The current statistics are as follows: quote(itemization( it() bf(Number of files) is the count of all "files" (in the generic @@ -1977,7 +2019,9 @@ in place of the hide-filter (if that is more natural to you). dit(bf(--progress)) This option tells rsync to print information showing the progress of the transfer. This gives a bored user something to watch. -Implies bf(--verbose) if it wasn't already specified. +With a modern rsync this is the same as specifying +bf(--info=flist2,name,progress), but any user-supplied settings for those +info flags takes precedence (e.g. "--info=flist0 --progress"). While rsync is transferring a regular file, it updates a progress line that looks like this: @@ -2012,6 +2056,13 @@ dit(bf(-P)) The bf(-P) option is equivalent to bf(--partial) bf(--progress). It purpose is to make it much easier to specify these two options for a long transfer that may be interrupted. +There is also a bf(--info=progress2) option that outputs statistics based +on the whole transfer, rather than individual files. Use this flag without +outputting a filename (e.g. avoid bf(-v) or specify bf(--info=name0) if you +want to see how the transfer is doing without scrolling the screen with a +lot of names. (You don't need to specify the bf(--progress) option in +order to use bf(--info=progress2).) + dit(bf(--password-file)) This option allows you to provide a password in a file for accessing an rsync daemon. The file must not be world readable. It should contain just the password as a single line. diff --git a/sender.c b/sender.c index f7728772..6aa5aeb8 100644 --- a/sender.c +++ b/sender.c @@ -21,7 +21,6 @@ #include "rsync.h" -extern int verbose; extern int dry_run; extern int do_xfers; extern int am_server; @@ -39,7 +38,6 @@ extern int protocol_version; extern int remove_source_files; extern int updating_basis_file; extern int make_backups; -extern int do_progress; extern int inplace; extern int batch_fd; extern int write_batch; @@ -71,7 +69,7 @@ static struct sum_struct *receive_sums(int f) s->sums = NULL; - if (verbose > 3) { + if (DEBUG_GTE(CHKSUM, 3)) { rprintf(FINFO, "count=%.0f n=%ld rem=%ld\n", (double)s->count, (long)s->blength, (long)s->remainder); } @@ -105,7 +103,7 @@ static struct sum_struct *receive_sums(int f) if (allowed_lull && !(i % lull_mod)) maybe_send_keepalive(); - if (verbose > 3) { + if (DEBUG_GTE(CHKSUM, 3)) { rprintf(FINFO, "chunk[%d] len=%d offset=%.0f sum1=%08x\n", i, s->sums[i].len, (double)s->sums[i].offset, @@ -140,7 +138,7 @@ void successful_send(int ndx) f_name(file, fname); if (do_unlink(fname) == 0) { - if (verbose > 1) + if (INFO_GTE(REMOVE, 1)) rprintf(FINFO, "sender removed %s\n", fname); } else rsyserr(FERROR, errno, "sender failed to remove %s", fname); @@ -182,7 +180,7 @@ void send_files(int f_in, int f_out) int f_xfer = write_batch < 0 ? batch_fd : f_out; int ndx, j; - if (verbose > 2) + if (DEBUG_GTE(SEND, 1)) rprintf(FINFO, "send_files starting\n"); while (1) { @@ -193,6 +191,10 @@ void send_files(int f_in, int f_out) ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type, xname, &xlen); if (ndx == NDX_DONE) { + if (!am_server && INFO_GTE(PROGRESS, 2) && cur_flist) { + set_current_file_index(NULL, 0); + end_progress(0); + } if (inc_recurse && first_flist) { flist_free(first_flist); if (first_flist) { @@ -202,7 +204,7 @@ void send_files(int f_in, int f_out) } if (++phase > max_phase) break; - if (verbose > 2) + if (DEBUG_GTE(SEND, 1)) rprintf(FINFO, "send_files phase=%d\n", phase); write_ndx(f_out, NDX_DONE); continue; @@ -225,7 +227,7 @@ void send_files(int f_in, int f_out) continue; f_name(file, fname); - if (verbose > 2) + if (DEBUG_GTE(SEND, 1)) rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname); #ifdef SUPPORT_XATTRS @@ -265,7 +267,7 @@ void send_files(int f_in, int f_out) updating_basis_file = inplace && (protocol_version >= 29 ? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0); - if (!am_server && do_progress) + if (!am_server && INFO_GTE(PROGRESS, 1)) set_current_file_index(file, ndx); stats.num_transferred_files++; stats.total_transferred_size += F_LENGTH(file); @@ -321,7 +323,7 @@ void send_files(int f_in, int f_out) } else mbuf = NULL; - if (verbose > 2) { + if (DEBUG_GTE(CHKSUM, 2)) { rprintf(FINFO, "send_files mapped %s%s%s of size %.0f\n", path,slash,fname, (double)st.st_size); } @@ -330,18 +332,18 @@ void send_files(int f_in, int f_out) fnamecmp_type, xname, xlen); write_sum_head(f_xfer, s); - if (verbose > 2) + if (DEBUG_GTE(CHKSUM, 2)) rprintf(FINFO, "calling match_sums %s%s%s\n", path,slash,fname); if (log_before_transfer) log_item(FCLIENT, file, &initial_stats, iflags, NULL); - else if (!am_server && verbose && do_progress) + else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1)) rprintf(FCLIENT, "%s\n", fname); set_compression(fname); match_sums(f_xfer, s, mbuf, st.st_size); - if (do_progress) + if (INFO_GTE(PROGRESS, 1)) end_progress(st.st_size); log_item(log_code, file, &initial_stats, iflags, NULL); @@ -359,7 +361,7 @@ void send_files(int f_in, int f_out) free_sums(s); - if (verbose > 2) + if (DEBUG_GTE(SEND, 1)) rprintf(FINFO, "sender finished %s%s%s\n", path,slash,fname); /* Flag that we actually sent this entry. */ @@ -368,7 +370,7 @@ void send_files(int f_in, int f_out) if (make_backups < 0) make_backups = -make_backups; - if (verbose > 2) + if (DEBUG_GTE(SEND, 1)) rprintf(FINFO, "send files finished\n"); match_report(); diff --git a/socket.c b/socket.c index 8d4a89db..2b3271cf 100644 --- a/socket.c +++ b/socket.c @@ -232,7 +232,7 @@ int open_socket_out(char *host, int port, const char *bind_addr, } *cp++ = '\0'; strlcpy(portbuf, cp, sizeof portbuf); - if (verbose >= 2) { + if (DEBUG_GTE(CONNECT, 1)) { rprintf(FINFO, "connection via http proxy %s port %s\n", h, portbuf); } @@ -361,7 +361,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr, *t = '\0'; } - if (verbose >= 2) { + if (DEBUG_GTE(CONNECT, 1)) { rprintf(FINFO, "%sopening tcp connection to %s port %d\n", prog ? "Using RSYNC_CONNECT_PROG instead of " : "", host, port); @@ -473,7 +473,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr, /* Only output the socket()/bind() messages if we were totally * unsuccessful, or if the daemon is being run with -vv. */ for (s = 0; s < ecnt; s++) { - if (!i || verbose > 1) + if (!i || DEBUG_GTE(BIND, 1)) rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]), 0); free(errmsgs[s]); } @@ -829,7 +829,7 @@ int sock_exec(const char *prog) rsyserr(FERROR, errno, "socketpair_tcp failed"); return -1; } - if (verbose >= 2) + if (DEBUG_GTE(CMD, 1)) rprintf(FINFO, "Running socket program: \"%s\"\n", prog); if (fork() == 0) { close(fd[0]); diff --git a/t_unsafe.c b/t_unsafe.c index 44662bdb..943185a6 100644 --- a/t_unsafe.c +++ b/t_unsafe.c @@ -27,9 +27,9 @@ int dry_run = 0; int am_root = 0; int read_only = 0; int list_only = 0; -int verbose = 0; int preserve_perms = 0; int preserve_executability = 0; +short info_levels[10], debug_levels[10]; int main(int argc, char **argv) diff --git a/testsuite/00-hello.test b/testsuite/00-hello.test index d7774bb0..d4a84752 100644 --- a/testsuite/00-hello.test +++ b/testsuite/00-hello.test @@ -2,4 +2,8 @@ echo $0 running -$RSYNC --version || exit 1 +$RSYNC --version || test_fail '--version output failed' + +$RSYNC --info=help || test_fail '--info=help output failed' + +$RSYNC --debug=help || test_fail '--debug=help output failed' diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns index e17fe5ac..2947a5f9 100644 --- a/testsuite/rsync.fns +++ b/testsuite/rsync.fns @@ -268,7 +268,7 @@ log file = $logfile log format = %i %h [%a] %m (%u) %l %f%L transfer logging = yes exclude = ? foobar.baz -max verbosity = 9 +max verbosity = 4 uid = 0 gid = 0 diff --git a/uidlist.c b/uidlist.c index 3d9c774e..d9ca7a28 100644 --- a/uidlist.c +++ b/uidlist.c @@ -26,7 +26,6 @@ #include "rsync.h" #include "io.h" -extern int verbose; extern int am_root; extern int preserve_uid; extern int preserve_gid; @@ -126,7 +125,7 @@ static int is_in_group(gid_t gid) } if (n == ngroups) gidset[ngroups++] = mygid; - if (verbose > 3) { + if (DEBUG_GTE(OWN, 2)) { int pos; char *gidbuf = new_array(char, ngroups*21+32); if (!gidbuf) @@ -152,7 +151,7 @@ static int is_in_group(gid_t gid) static gid_t mygid = GID_NONE; if (mygid == GID_NONE) { mygid = MY_GID(); - if (verbose > 3) + if (DEBUG_GTE(OWN, 2)) rprintf(FINFO, "process has gid %u\n", (unsigned)mygid); } return gid == mygid; @@ -167,7 +166,7 @@ static struct idlist *recv_add_uid(uid_t id, const char *name) node = add_to_list(&uidlist, id, name, id2, 0); - if (verbose > 3) { + if (DEBUG_GTE(OWN, 2)) { rprintf(FINFO, "uid %u(%s) maps to %u\n", (unsigned)id, name ? name : "", (unsigned)id2); } @@ -184,7 +183,7 @@ static struct idlist *recv_add_gid(gid_t id, const char *name) node = add_to_list(&gidlist, id, name, id2, !am_root && !is_in_group(id2) ? FLAG_SKIP_GROUP : 0); - if (verbose > 3) { + if (DEBUG_GTE(OWN, 2)) { rprintf(FINFO, "gid %u(%s) maps to %u\n", (unsigned)id, name ? name : "", (unsigned)id2); } diff --git a/util.c b/util.c index c71830bd..0b3dc380 100644 --- a/util.c +++ b/util.c @@ -23,7 +23,6 @@ #include "rsync.h" #include "ifuncs.h" -extern int verbose; extern int dry_run; extern int module_id; extern int modify_window; @@ -130,7 +129,7 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode) return 1; #endif - if (verbose > 2) { + if (DEBUG_GTE(TIME, 1)) { rprintf(FINFO, "set modtime of %s to (%ld) %s", fname, (long)modtime, asctime(localtime(&modtime))); @@ -397,7 +396,7 @@ int robust_unlink(const char *fname) counter = 1; } while ((rc = access(path, 0)) == 0 && counter != start); - if (verbose > 0) { + if (INFO_GTE(MISC, 1)) { rprintf(FWARNING, "renaming %s to %s because of text busy\n", fname, path); } @@ -1019,7 +1018,7 @@ int change_dir(const char *dir, int set_path_only) curr_dir_depth = count_dir_elements(curr_dir + module_dirlen); } - if (verbose >= 5 && !set_path_only) + if (DEBUG_GTE(CHDIR, 1) && !set_path_only) rprintf(FINFO, "[%s] change_dir(%s)\n", who_am_i(), curr_dir); return 1; @@ -1583,7 +1582,7 @@ void *expand_item_list(item_list *lp, size_t item_size, overflow_exit("expand_item_list"); /* Using _realloc_array() lets us pass the size, not a type. */ new_ptr = _realloc_array(lp->items, item_size, new_size); - if (verbose >= 4) { + if (DEBUG_GTE(FLIST, 3)) { rprintf(FINFO, "[%s] expand %s to %.0f bytes, did%s move\n", who_am_i(), desc, (double)new_size * item_size, new_ptr == lp->items ? " not" : ""); -- 2.34.1