@@ -540,36 +540,39 @@ process_part (iconv_t cd, char **addr, size_t *len, size_t offset,
char *outptr;
size_t outlen;
size_t n;
- int ret = 0;
+ int invalid_sequence_seen = 0;
- while (*len > 0)
+ for (;;)
{
outptr = outbuf;
outlen = BUF_SIZE;
n = iconv (cd, addr, len, &outptr, &outlen);
- if (n == (size_t) -1 && omit_invalid && errno == EILSEQ)
- {
- ret = 1;
- if (*len == 0)
- n = 0;
- else
- errno = E2BIG;
- }
-
if (outptr != outbuf)
{
- ret = write_output (outbuf, outptr, output, output_file);
+ int ret = write_output (outbuf, outptr, output, output_file);
if (ret != 0)
- break;
+ return ret;
}
+ /* Done with the input buffer. */
+ if (n != (size_t) -1)
+ break;
+
/* Incomplete multibyte characters might be completed by the next
chunk, so do not treat them as an error here. */
- if (n != (size_t) -1 || errno == EINVAL)
+ if (errno == EINVAL)
+ break;
+
+ if (omit_invalid && errno == EILSEQ)
{
- ret = 0;
- break;
+ /* Remember that we saw an invalid character for the sake of our
+ exit status, but otherwise carry on. */
+ invalid_sequence_seen = 1;
+ if (*len == 0)
+ break;
+ else
+ errno = E2BIG;
}
if (errno != E2BIG)
@@ -581,7 +584,7 @@ process_part (iconv_t cd, char **addr, size_t *len, size_t offset,
}
}
- return ret;
+ return invalid_sequence_seen;
}
static int
@@ -589,6 +592,7 @@ process_block (iconv_t cd, char *addr, size_t len, FILE **output,
const char *output_file)
{
char *start = addr;
+ int invalid_sequence_seen = 0;
/* Process everything in one go. */
int ret = process_part (cd, &addr, &len, 0, output, output_file);
@@ -600,12 +604,24 @@ process_block (iconv_t cd, char *addr, size_t len, FILE **output,
sequence at the end. */
if (len > 0)
{
+ /* Incomplete multibyte sequences at the end of the input are not any
+ more invalid than spurious bytes anywhere else. */
+ if (omit_invalid)
+ return 1;
+
errno = EINVAL;
report_iconv_error (addr - start);
return -1;
}
- return flush_state (cd, output, output_file, addr - start);
+ if (ret > 0)
+ invalid_sequence_seen = ret;
+
+ ret = flush_state (cd, output, output_file, addr - start);
+ if (ret != 0)
+ return ret;
+ else
+ return invalid_sequence_seen;
}
@@ -616,11 +632,12 @@ process_fd (iconv_t cd, int fd, FILE **output, const char *output_file)
size_t len = 0;
size_t offset = 0;
ssize_t n;
+ int ret;
+ int invalid_sequence_seen = 0;
/* Read into the buffer past unconsumed bytes from the last iteration. */
while ((n = read (fd, inbuf + len, BUF_SIZE - len)) > 0)
{
- int ret;
char *inptr;
len += n;
@@ -628,8 +645,13 @@ process_fd (iconv_t cd, int fd, FILE **output, const char *output_file)
inptr = inbuf;
/* Process what we have read. */
ret = process_part (cd, &inptr, &len, offset, output, output_file);
- if (ret != 0)
+ if (ret < 0)
return ret;
+
+ /* Remember this for the sake of our exit status, but carry on. */
+ if (ret > 0)
+ invalid_sequence_seen = ret;
+
/* Keep track of overall position in the input for error reporting. */
offset = saturating_add (offset, inptr - inbuf);
@@ -653,7 +675,11 @@ process_fd (iconv_t cd, int fd, FILE **output, const char *output_file)
return -1;
}
- return flush_state (cd, output, output_file, offset);
+ ret = flush_state (cd, output, output_file, offset);
+ if (ret != 0)
+ return ret;
+ else
+ return invalid_sequence_seen;
}