X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/1d891835e7933f2c82bf636b0f27a936dc432e5c..c1c2c8ff6048202e9f682948b86772f98145610c:/log.c diff --git a/log.c b/log.c index 6d66e20a..46e0a638 100644 --- a/log.c +++ b/log.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998-2001 Andrew Tridgell * Copyright (C) 2000-2001 Martin Pool - * Copyright (C) 2003-2008 Wayne Davison + * Copyright (C) 2003-2009 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,7 +20,8 @@ */ #include "rsync.h" -#include "ifuncs.h" +#include "itypes.h" +#include "inums.h" extern int dry_run; extern int am_daemon; @@ -30,20 +31,19 @@ extern int am_generator; extern int local_server; extern int quiet; extern int module_id; -extern int msg_fd_out; extern int checksum_len; extern int allow_8bit_chars; extern int protocol_version; extern int always_checksum; extern int preserve_times; extern int msgs2stderr; -extern int uid_ndx; -extern int gid_ndx; extern int stdout_format_has_i; extern int stdout_format_has_o_or_i; extern int logfile_format_has_i; extern int logfile_format_has_o_or_i; extern int receiver_symlink_times; +extern int64 total_data_written; +extern int64 total_data_read; extern mode_t orig_umask; extern char *auth_user; extern char *stdout_format; @@ -56,9 +56,10 @@ extern iconv_t ic_chck; extern iconv_t ic_recv; #endif extern char curr_dir[MAXPATHLEN]; -extern char *module_dir; +extern char *full_module_path; extern unsigned int module_dirlen; extern char sender_file_sum[MAX_DIGEST_LEN]; +extern const char undetermined_hostname[]; static int log_initialised; static int logfile_was_closed; @@ -67,6 +68,10 @@ struct stats stats; int got_xfer_error = 0; int output_needs_newline = 0; +int send_msgs_to_gen = 0; + +static int64 initial_data_written; +static int64 initial_data_read; struct { int code; @@ -90,13 +95,13 @@ struct { { RERR_MALLOC , "error allocating core memory buffers" }, { RERR_PARTIAL , "some files/attrs were not transferred (see previous errors)" }, { RERR_VANISHED , "some files vanished before they could be transferred" }, + { RERR_DEL_LIMIT , "the --max-delete limit stopped deletions" }, { RERR_TIMEOUT , "timeout in data send/receive" }, { RERR_CONTIMEOUT , "timeout waiting for daemon connection" }, { RERR_CMD_FAILED , "remote shell failed" }, { RERR_CMD_KILLED , "remote shell killed" }, { RERR_CMD_RUN , "remote command could not be run" }, { RERR_CMD_NOTFOUND,"remote command not found" }, - { RERR_DEL_LIMIT , "the --max-delete limit stopped deletions" }, { 0, NULL } }; @@ -258,10 +263,16 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8) if (len < 0) exit_cleanup(RERR_MESSAGEIO); - if (msgs2stderr && code != FLOG) - goto output_msg; - - if (am_server && msg_fd_out >= 0) { + if (msgs2stderr) { + if (!am_daemon) { + if (code == FLOG) + return; + goto output_msg; + } + if (code == FCLIENT) + return; + code = FLOG; + } else if (send_msgs_to_gen) { assert(!is_utf8); /* Pass the message to our sibling in native charset. */ send_msg((enum msgcode)code, buf, len, 0); @@ -323,13 +334,17 @@ output_msg: got_xfer_error = 1; /* FALL THROUGH */ case FERROR: + case FERROR_UTF8: + case FERROR_SOCKET: case FWARNING: f = stderr; break; + case FLOG: case FINFO: case FCLIENT: break; default: + fprintf(stderr, "Unknown logcode in rwrite(): %d [%s]\n", (int)code, who_am_i()); exit_cleanup(RERR_MESSAGEIO); } @@ -357,7 +372,7 @@ output_msg: INIT_XBUF(inbuf, (char*)buf, len, (size_t)-1); while (inbuf.len) { - iconvbufs(ic, &inbuf, &outbuf, 0); + iconvbufs(ic, &inbuf, &outbuf, inbuf.pos ? 0 : ICB_INIT); ierrno = errno; if (outbuf.len) { filtered_fwrite(f, convbuf, outbuf.len, 0); @@ -465,10 +480,15 @@ void rflush(enum logcode code) fflush(f); } +void remember_initial_stats(void) +{ + initial_data_read = total_data_read; + initial_data_written = total_data_written; +} + /* A generic logging routine for send/recv, with parameter substitiution. */ static void log_formatted(enum logcode code, const char *format, const char *op, - struct file_struct *file, const char *fname, - struct stats *initial_stats, int iflags, + struct file_struct *file, const char *fname, int iflags, const char *hlink) { char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32]; @@ -491,21 +511,36 @@ static void log_formatted(enum logcode code, const char *format, const char *op, buf[total] = '\0'; for (p = buf; (p = strchr(p, '%')) != NULL; ) { + int humanize = 0; s = p++; c = fmt + 1; + while (*p == '\'') { + humanize++; + p++; + } if (*p == '-') *c++ = *p++; while (isDigit(p) && c - fmt < (int)(sizeof fmt) - 8) *c++ = *p++; + while (*p == '\'') { + humanize++; + p++; + } if (!*p) break; *c = '\0'; n = NULL; + /* Note for %h and %a: it doesn't matter what fd we pass to + * client_{name,addr} because rsync_module will already have + * forced the answer to be cached (assuming, of course, for %h + * that lp_reverse_lookup(module_id) is true). */ switch (*p) { case 'h': - if (am_daemon) - n = client_name(0); + if (am_daemon) { + n = lp_reverse_lookup(module_id) + ? client_name(0) : undetermined_hostname; + } break; case 'a': if (am_daemon) @@ -514,7 +549,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op, case 'l': strlcat(fmt, "s", sizeof fmt); snprintf(buf2, sizeof buf2, fmt, - big_num(F_LENGTH(file), 0)); + do_big_num(F_LENGTH(file), humanize, NULL)); n = buf2; break; case 'U': @@ -617,33 +652,33 @@ static void log_formatted(enum logcode code, const char *format, const char *op, n = timestring(time(NULL)); break; case 'P': - n = module_dir; + n = full_module_path; break; case 'u': n = auth_user; break; case 'b': - if (am_sender) { - b = stats.total_written - - initial_stats->total_written; - } else { - b = stats.total_read - - initial_stats->total_read; - } + if (!(iflags & ITEM_TRANSFER)) + b = 0; + else if (am_sender) + b = total_data_written - initial_data_written; + else + b = total_data_read - initial_data_read; strlcat(fmt, "s", sizeof fmt); - snprintf(buf2, sizeof buf2, fmt, big_num(b, 0)); + snprintf(buf2, sizeof buf2, fmt, + do_big_num(b, humanize, NULL)); n = buf2; break; case 'c': - if (!am_sender) { - b = stats.total_written - - initial_stats->total_written; - } else { - b = stats.total_read - - initial_stats->total_read; - } + if (!(iflags & ITEM_TRANSFER)) + b = 0; + else if (!am_sender) + b = total_data_written - initial_data_written; + else + b = total_data_read - initial_data_read; strlcat(fmt, "s", sizeof fmt); - snprintf(buf2, sizeof buf2, fmt, big_num(b, 0)); + snprintf(buf2, sizeof buf2, fmt, + do_big_num(b, humanize, NULL)); n = buf2; break; case 'C': @@ -766,10 +801,12 @@ int log_format_has(const char *format, char esc) return 0; for (p = format; (p = strchr(p, '%')) != NULL; ) { - if (*++p == '-') + for (p++; *p == '\''; p++) {} /*SHARED ITERATOR*/ + if (*p == '-') p++; while (isDigit(p)) p++; + while (*p == '\'') p++; if (!*p) break; if (*p == esc) @@ -781,19 +818,14 @@ int log_format_has(const char *format, char esc) /* Log the transfer of a file. If the code is FCLIENT, the output just goes * to stdout. If it is FLOG, it just goes to the log file. Otherwise we * output to both. */ -void log_item(enum logcode code, struct file_struct *file, - struct stats *initial_stats, int iflags, const char *hlink) +void log_item(enum logcode code, struct file_struct *file, int iflags, const char *hlink) { const char *s_or_r = am_sender ? "send" : "recv"; - if (code != FLOG && stdout_format && !am_server) { - log_formatted(FCLIENT, stdout_format, s_or_r, - file, NULL, initial_stats, iflags, hlink); - } - if (code != FCLIENT && logfile_format && *logfile_format) { - log_formatted(FLOG, logfile_format, s_or_r, - file, NULL, initial_stats, iflags, hlink); - } + if (code != FLOG && stdout_format && !am_server) + log_formatted(FCLIENT, stdout_format, s_or_r, file, NULL, iflags, hlink); + if (code != FCLIENT && logfile_format && *logfile_format) + log_formatted(FLOG, logfile_format, s_or_r, file, NULL, iflags, hlink); } void maybe_log_item(struct file_struct *file, int iflags, int itemizing, @@ -806,20 +838,21 @@ void maybe_log_item(struct file_struct *file, int iflags, int itemizing, if (am_server) { if (logfile_name && !dry_run && see_item && (significant_flags || logfile_format_has_i)) - log_item(FLOG, file, &stats, iflags, buf); + log_item(FLOG, file, iflags, buf); } else if (see_item || local_change || *buf || (S_ISDIR(file->mode) && significant_flags)) { enum logcode code = significant_flags || logfile_format_has_i ? FINFO : FCLIENT; - log_item(code, file, &stats, iflags, buf); + log_item(code, file, iflags, buf); } } void log_delete(const char *fname, int mode) { + /* Zero-initialized */ static struct { union file_extras ex[4]; /* just in case... */ struct file_struct file; - } x; + } x; /* Zero-initialized due to static declaration. */ int len = strlen(fname); const char *fmt; @@ -833,15 +866,14 @@ void log_delete(const char *fname, int mode) send_msg(MSG_DELETED, fname, len, am_generator); } else { fmt = stdout_format_has_o_or_i ? stdout_format : "deleting %n"; - log_formatted(FCLIENT, fmt, "del.", &x.file, fname, &stats, - ITEM_DELETED, NULL); + log_formatted(FCLIENT, fmt, "del.", &x.file, fname, ITEM_DELETED, NULL); } if (!logfile_name || dry_run || !logfile_format) return; fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n"; - log_formatted(FLOG, fmt, "del.", &x.file, fname, &stats, ITEM_DELETED, NULL); + log_formatted(FLOG, fmt, "del.", &x.file, fname, ITEM_DELETED, NULL); } /* @@ -854,9 +886,9 @@ void log_exit(int code, const char *file, int line) { if (code == 0) { rprintf(FLOG,"sent %s bytes received %s bytes total size %s\n", - big_num(stats.total_written, 0), - big_num(stats.total_read, 0), - big_num(stats.total_size, 0)); + comma_num(stats.total_written), + comma_num(stats.total_read), + comma_num(stats.total_size)); } else if (am_server != 2) { const char *name;