Point out that the file_struct in log_delete is zero-initialized because
[rsync/rsync.git] / log.c
diff --git a/log.c b/log.c
index 0aa5b25..46e0a63 100644 (file)
--- a/log.c
+++ b/log.c
@@ -37,13 +37,13 @@ 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;
@@ -70,6 +70,9 @@ 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;
         char const *name;
@@ -92,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 }
 };
 
@@ -260,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 (send_msgs_to_gen) {
+       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);
@@ -325,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);
        }
 
@@ -359,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);
@@ -467,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];
@@ -640,26 +658,24 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
                        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,
                                 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,
                                 do_big_num(b, humanize, NULL));
@@ -785,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)
@@ -800,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,
@@ -825,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;
 
@@ -852,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);
 }
 
 /*