summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Davison <wayned@samba.org>2008-07-13 20:51:08 -0700
committerWayne Davison <wayned@samba.org>2008-07-13 20:51:08 -0700
commit951e826b75c4a4e6bc066e248d7489fb6eba6fde (patch)
tree64352078b8e10472e8a6af286dbb4cc5b6214f3d
parentd8d13893489ba8245d2ff1e67fbb5c46dd047ef6 (diff)
downloadrsync-951e826b75c4a4e6bc066e248d7489fb6eba6fde.tar.gz
Added the --info=FLAGS an --debug=FLAGS options, which allows
fine-grained output control (in addition to the coarse -v).
-rw-r--r--NEWS7
-rw-r--r--acls.c2
-rw-r--r--backup.c11
-rw-r--r--batch.c2
-rw-r--r--cleanup.c12
-rw-r--r--clientserver.c8
-rw-r--r--compat.c3
-rw-r--r--exclude.c13
-rw-r--r--flist.c52
-rw-r--r--generator.c93
-rw-r--r--hlink.c11
-rw-r--r--io.c2
-rw-r--r--log.c13
-rw-r--r--main.c46
-rw-r--r--match.c30
-rw-r--r--options.c390
-rw-r--r--pipe.c2
-rw-r--r--progress.c43
-rw-r--r--receiver.c38
-rw-r--r--rsync.c23
-rw-r--r--rsync.h46
-rw-r--r--rsync.yo109
-rw-r--r--sender.c32
-rw-r--r--socket.c8
-rw-r--r--t_unsafe.c2
-rw-r--r--testsuite/00-hello.test6
-rw-r--r--testsuite/rsync.fns2
-rw-r--r--uidlist.c9
-rw-r--r--util.c9
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 <locale.h>
#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 <langinfo.h>
#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" : "");