Give iconvbufs() an ICB_INIT flag.
authorWayne Davison <wayned@samba.org>
Sat, 24 Oct 2009 05:51:29 +0000 (22:51 -0700)
committerWayne Davison <wayned@samba.org>
Sat, 24 Oct 2009 05:51:29 +0000 (22:51 -0700)
flist.c
io.c
log.c
rsync.c
rsync.h

diff --git a/flist.c b/flist.c
index 5a1ab9d..d0777d2 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -731,7 +731,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
                INIT_CONST_XBUF(outbuf, thisname);
                INIT_XBUF(inbuf, lastname, basename_len, (size_t)-1);
 
-               if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) {
+               if (iconvbufs(ic_recv, &inbuf, &outbuf, ICB_INIT) < 0) {
                        io_error |= IOERR_GENERAL;
                        rprintf(FERROR_UTF8,
                            "[%s] cannot convert filename: %s (%s)\n",
@@ -1049,7 +1049,7 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
                                read_sbuf(f, inbuf.buf, inbuf.len);
                                INIT_XBUF(outbuf, bp, 0, alloc_len);
 
-                               if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) {
+                               if (iconvbufs(ic_recv, &inbuf, &outbuf, ICB_INIT) < 0) {
                                        io_error |= IOERR_GENERAL;
                                        rprintf(FERROR_XFER,
                                            "[%s] cannot convert symlink data for: %s (%s)\n",
@@ -1464,14 +1464,14 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
                        if (file->dirname) {
                                INIT_XBUF_STRLEN(inbuf, (char*)file->dirname);
                                outbuf.size -= 2; /* Reserve room for '/' & 1 more char. */
-                               if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0)
+                               if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0)
                                        goto convert_error;
                                outbuf.size += 2;
                                fbuf[outbuf.len++] = '/';
                        }
 
                        INIT_XBUF_STRLEN(inbuf, (char*)file->basename);
-                       if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
+                       if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0) {
                          convert_error:
                                io_error |= IOERR_GENERAL;
                                rprintf(FERROR_XFER,
@@ -1485,7 +1485,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
                        if (symlink_len && sender_symlink_iconv) {
                                INIT_XBUF(inbuf, (char*)symlink_name, symlink_len, (size_t)-1);
                                INIT_CONST_XBUF(outbuf, symlink_buf);
-                               if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
+                               if (iconvbufs(ic_send, &inbuf, &outbuf, ICB_INIT) < 0) {
                                        io_error |= IOERR_GENERAL;
                                        f_name(file, fbuf);
                                        rprintf(FERROR_XFER,
diff --git a/io.c b/io.c
index b0f0204..3ece9c3 100644 (file)
--- a/io.c
+++ b/io.c
@@ -378,7 +378,7 @@ static void forward_filesfrom_data(void)
        }
        if (len) {
                char *f = x.buf + x.pos;
-               char *t = f; /* Keep any non-zero offset to avoid iconv reset. */
+               char *t = x.buf;
                char *eob = f + len;
                /* Eliminate any multi-'\0' runs. */
                while (f != eob) {
@@ -393,7 +393,7 @@ static void forward_filesfrom_data(void)
        if (filesfrom_convert) {
                /* TODO would it help to translate each string between nulls separately? */
                x.len = len;
-               iconvbufs(ic_send, &x, &iobuf.out, ICB_INCLUDE_BAD|ICB_INCLUDE_INCOMPLETE|ICB_CIRCULAR_OUT);
+               iconvbufs(ic_send, &x, &iobuf.out, ICB_INCLUDE_BAD|ICB_INCLUDE_INCOMPLETE|ICB_CIRCULAR_OUT|ICB_INIT);
        } else
 #endif
        if (len) {
@@ -803,7 +803,7 @@ int send_msg(enum msgcode code, const char *buf, size_t len, int convert)
 
                len = iobuf.msg.len;
                iconvbufs(ic_send, &inbuf, &iobuf.msg,
-                         ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_CIRCULAR_OUT);
+                         ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_CIRCULAR_OUT | ICB_INIT);
                if (inbuf.len > 0) {
                        rprintf(FERROR, "overflowed iobuf.msg buffer in send_msg");
                        exit_cleanup(RERR_UNSUPPORTED);
@@ -1039,7 +1039,7 @@ int read_line(int fd, char *buf, size_t bufsiz, int flags)
                iconv_buf.pos = 0;
                iconv_buf.len = s - iconv_buf.buf;
                iconvbufs(ic_recv, &iconv_buf, &outbuf,
-                         ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
+                         ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_INIT);
                outbuf.buf[outbuf.len] = '\0';
                return outbuf.len;
        }
@@ -1301,13 +1301,14 @@ static void read_a_msg(void)
                        INIT_XBUF(inbuf, ibuf, 0, (size_t)-1);
 
                        while (msg_bytes) {
+                               inbuf.pos = 0;
                                inbuf.len = msg_bytes > sizeof ibuf ? sizeof ibuf : msg_bytes;
                                memcpy(inbuf.buf, perform_io(inbuf.len, PIO_INPUT_AND_CONSUME), inbuf.len);
                                if (!(msg_bytes -= inbuf.len)
                                 && !ibuf[inbuf.len-1])
                                        inbuf.len--, add_null = 1;
                                if (iconvbufs(ic_send, &inbuf, &outbuf,
-                                   ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE) < 0)
+                                   ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_INIT) < 0)
                                        goto overflow;
                        }
                        if (add_null) {
diff --git a/log.c b/log.c
index 0aa5b25..61d01ce 100644 (file)
--- a/log.c
+++ b/log.c
@@ -359,7 +359,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);
diff --git a/rsync.c b/rsync.c
index 3008e2d..2d0de92 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -160,8 +160,8 @@ static void wrap_overflow(xbuf *out, int siz)
  * "flags", any badly-encoded chars are included verbatim in the "out" xbuf,
  * so EILSEQ will not be returned.  Likewise for ICB_INCLUDE_INCOMPLETE with
  * respect to an incomplete multi-byte char at the end, which ensures that
- * EINVAL is not returned.  Anytime "in.pos" is 0 we will reset the iconv()
- * state prior to processing the characters. */
+ * EINVAL is not returned.  If ICB_INIT is set, the iconv() conversion state
+ * is initialized prior to processing the characters. */
 int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
 {
        ICONV_CONST char *ibuf;
@@ -171,7 +171,7 @@ int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
        if (!out->size && flags & ICB_EXPAND_OUT)
                alloc_xbuf(out, 1024);
 
-       if (!in->pos)
+       if (flags & ICB_INIT)
                iconv(ic, NULL, 0, NULL, 0);
 
        ibuf = in->buf + in->pos;
@@ -265,7 +265,7 @@ void send_protected_args(int fd, char *args[])
                else if (convert) {
                        INIT_XBUF_STRLEN(inbuf, args[i]);
                        iconvbufs(ic_send, &inbuf, &outbuf,
-                                 ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
+                                 ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_INIT);
                        outbuf.buf[outbuf.len] = '\0';
                        write_buf(fd, outbuf.buf, outbuf.len + 1);
                        outbuf.len = 0;
diff --git a/rsync.h b/rsync.h
index c5e7691..e6a6260 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -901,6 +901,7 @@ typedef struct {
 #define ICB_INCLUDE_BAD (1<<1)
 #define ICB_INCLUDE_INCOMPLETE (1<<2)
 #define ICB_CIRCULAR_OUT (1<<3)
+#define ICB_INIT (1<<4)
 
 #define RL_EOL_NULLS (1<<0)
 #define RL_DUMP_COMMENTS (1<<1)