Make sure that we don't try to use iconv() without iconv.h.
[rsync/rsync.git] / log.c
diff --git a/log.c b/log.c
index a1df72d..91b57d4 100644 (file)
--- a/log.c
+++ b/log.c
@@ -26,6 +26,9 @@
   <mbp@samba.org>, Oct 2000.
   */
 #include "rsync.h"
+#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
+#include <iconv.h>
+#endif
 
 extern int verbose;
 extern int dry_run;
@@ -43,6 +46,9 @@ extern int log_format_has_o_or_i;
 extern int daemon_log_format_has_o_or_i;
 extern char *auth_user;
 extern char *log_format;
+#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
+extern iconv_t ic_chck;
+#endif
 
 static int log_initialised;
 static int logfile_was_closed;
@@ -198,8 +204,12 @@ static void filtered_fwrite(const char *buf, int len, FILE *f)
                  && isdigit(*(uchar*)(s+2))
                  && isdigit(*(uchar*)(s+3))
                  && isdigit(*(uchar*)(s+4)))
-                || !isprint(*(uchar*)s)
-                || *(uchar*)s < ' ') {
+#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
+                || (*(uchar*)s < ' ' && *s != '\t')
+#else
+                || ((!isprint(*(uchar*)s) || *(uchar*)s < ' ') && *s != '\t')
+#endif
+               ) {
                        if (s != buf && fwrite(buf, s - buf, 1, f) != 1)
                                exit_cleanup(RERR_MESSAGEIO);
                        fprintf(f, "\\%04o", *(uchar*)s);
@@ -218,18 +228,21 @@ void rwrite(enum logcode code, char *buf, int len)
        int trailing_CR_or_NL;
        FILE *f = NULL;
 
-       if (quiet && code == FINFO)
-               return;
-
        if (len < 0)
                exit_cleanup(RERR_MESSAGEIO);
 
+       if (quiet && code == FINFO)
+               return;
+
        if (am_server && msg_fd_out >= 0) {
                /* Pass the message to our sibling. */
                send_msg((enum msgcode)code, buf, len);
                return;
        }
 
+       if (code == FSOCKERR) /* This gets simplified for a non-sibling. */
+               code = FERROR;
+
        if (code == FCLIENT)
                code = FINFO;
        else if (am_daemon) {
@@ -265,10 +278,11 @@ void rwrite(enum logcode code, char *buf, int len)
        case FERROR:
                log_got_error = 1;
                f = stderr;
-               break;
+               goto pre_scan;
        case FINFO:
                f = am_server ? stderr : stdout;
-               while (len && (*buf == '\n' || *buf == '\t')) {
+       pre_scan:
+               while (len > 1 && *buf == '\n') {
                        fputc(*buf, f);
                        buf++;
                        len--;
@@ -284,7 +298,30 @@ void rwrite(enum logcode code, char *buf, int len)
        trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
                          ? buf[--len] : 0;
 
-       filtered_fwrite(buf, len, f);
+#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
+       if (ic_chck != (iconv_t)-1) {
+               char convbuf[1024];
+               char *in_buf = buf, *out_buf = convbuf;
+               size_t in_cnt = len, out_cnt = sizeof convbuf - 1;
+
+               iconv(ic_chck, NULL, 0, NULL, 0);
+               while (iconv(ic_chck, &in_buf,&in_cnt,
+                                &out_buf,&out_cnt) == (size_t)-1) {
+                       if (out_buf != convbuf) {
+                               filtered_fwrite(convbuf, out_buf - convbuf, f);
+                               out_buf = convbuf;
+                               out_cnt = sizeof convbuf - 1;
+                       }
+                       if (errno == E2BIG)
+                               continue;
+                       fprintf(f, "\\%04o", *(uchar*)in_buf++);
+                       in_cnt--;
+               }
+               if (out_buf != convbuf)
+                       filtered_fwrite(convbuf, out_buf - convbuf, f);
+       } else
+#endif
+               filtered_fwrite(buf, len, f);
 
        if (trailing_CR_or_NL) {
                fputc(trailing_CR_or_NL, f);
@@ -442,12 +479,40 @@ static void log_formatted(enum logcode code, char *format, char *op,
                                 (double)file->length);
                        n = buf2;
                        break;
+               case 'U':
+                       strlcat(fmt, "ld", sizeof fmt);
+                       snprintf(buf2, sizeof buf2, fmt,
+                                (long)file->uid);
+                       n = buf2;
+                       break;
+               case 'G':
+                       if (file->gid == GID_NONE)
+                               n = "DEFAULT";
+                       else {
+                               strlcat(fmt, "ld", sizeof fmt);
+                               snprintf(buf2, sizeof buf2, fmt,
+                                        (long)file->gid);
+                               n = buf2;
+                       }
+                       break;
                case 'p':
                        strlcat(fmt, "ld", sizeof fmt);
                        snprintf(buf2, sizeof buf2, fmt,
                                 (long)getpid());
                        n = buf2;
                        break;
+               case 'M':
+                       n = timestring(file->modtime);
+                       {
+                               char *cp = n;
+                               while ((cp = strchr(cp, ' ')) != NULL)
+                                       *cp = '-';
+                       }
+                       break;
+               case 'B':
+                       n = buf2 + MAXPATHLEN - PERMSTRING_SIZE;
+                       permstring(n - 1, file->mode); /* skip the type char */
+                       break;
                case 'o':
                        n = op;
                        break;
@@ -535,18 +600,17 @@ static void log_formatted(enum logcode code, char *format, char *op,
                             : !(iflags & ITEM_TRANSFER) ? '.'
                             : !local_server && *op == 's' ? '<' : '>';
                        n[1] = S_ISDIR(file->mode) ? 'd'
+                            : IS_SPECIAL(file->mode) ? 'S'
                             : IS_DEVICE(file->mode) ? 'D'
                             : S_ISLNK(file->mode) ? 'L' : 'f';
                        n[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
                        n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
                        n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
-                            : !preserve_times || IS_DEVICE(file->mode)
-                                              || S_ISLNK(file->mode) ? 'T' : 't';
+                            : !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
                        n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
                        n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
                        n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
-                       n[8] = !(iflags & ITEM_REPORT_XATTRS) ? '.' : 'a';
-                       n[9] = '\0';
+                       n[8] = '\0';
 
                        if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
                                char ch = iflags & ITEM_IS_NEW ? '+' : '?';
@@ -706,11 +770,11 @@ void log_exit(int code, const char *file, int line)
 
                /* VANISHED is not an error, only a warning */
                if (code == RERR_VANISHED) {
-                       rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d)\n", 
-                               name, code, file, line);
+                       rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s]\n", 
+                               name, code, file, line, who_am_i());
                } else {
-                       rprintf(FERROR, "rsync error: %s (code %d) at %s(%d)\n",
-                               name, code, file, line);
+                       rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s]\n",
+                               name, code, file, line, who_am_i());
                }
        }
 }