lib/util/charset Preserve 'pull' errors even when converting via UTF16
authorAndrew Bartlett <abartlet@samba.org>
Mon, 11 Apr 2011 11:34:21 +0000 (21:34 +1000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 13 Apr 2011 04:47:08 +0000 (14:47 +1000)
When we do not have a direct iconv handle between any two charsets, we
must go iva UTF16.  However, we should still return the same buffer
and error code as if we were able to go direct - including the partial
conversion and the error code.

This is important for locating the invalid multibyte character in the
stream, for example.

Andrew Bartlett

Signed-off-by: Andrew Tridgell <tridge@samba.org>
lib/util/charset/iconv.c

index 045fd1329be852f474fa7e5d21f0b85c0c8af400..16ce92ea82b5d7cdaf26655e8ef53991923f1f49 100644 (file)
@@ -193,14 +193,15 @@ _PUBLIC_ size_t smb_iconv(smb_iconv_t cd,
                while (*inbytesleft > 0) {
                        char *bufp1 = cvtbuf;
                        const char *bufp2 = cvtbuf;
-
+                       int saved_errno = errno;
+                       bool pull_failed = false;
                        bufsize = SMB_ICONV_BUFSIZE;
 
                        if (cd->pull(cd->cd_pull,
                                     inbuf, inbytesleft, &bufp1, &bufsize) == -1
                            && errno != E2BIG) {
-                               talloc_free(cvtbuf);
-                               return -1;
+                               saved_errno = errno;
+                               pull_failed = true;
                        }
 
                        bufsize = SMB_ICONV_BUFSIZE - bufsize;
@@ -210,6 +211,10 @@ _PUBLIC_ size_t smb_iconv(smb_iconv_t cd,
                                     outbuf, outbytesleft) == -1) {
                                talloc_free(cvtbuf);
                                return -1;
+                       } else if (pull_failed) {
+                               /* We want the pull errno if possible */
+                               errno = saved_errno;
+                               return -1;
                        }
                }
                talloc_free(cvtbuf);