From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3415 invoked by alias); 4 Mar 2004 15:13:33 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 3391 invoked from network); 4 Mar 2004 15:13:30 -0000 Received: from unknown (HELO sunsite.ms.mff.cuni.cz) (195.113.19.66) by sources.redhat.com with SMTP; 4 Mar 2004 15:13:30 -0000 Received: from sunsite.ms.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8) with ESMTP id i24D4cnd001053; Thu, 4 Mar 2004 14:04:38 +0100 Received: (from jakub@localhost) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8/Submit) id i24D4bc6001051; Thu, 4 Mar 2004 14:04:37 +0100 Date: Thu, 04 Mar 2004 15:13:00 -0000 From: Jakub Jelinek To: Ulrich Drepper Cc: Glibc hackers , twoerner@redhat.com Subject: [PATCH] Fix iconv -c Message-ID: <20040304130437.GK3822@sunsite.ms.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2004-03/txt/msg00003.txt.bz2 Hi! iconv -c doesn't seem to work properly. For a testcase, see http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=117021 The problem is, if iconv () returns -1/EILSEQ, iconv -c will not flush the state encoding, process further characters if iconv () has not processed yet all input, and will stop processing other files on the command line. 2004-03-04 Jakub Jelinek * iconv/iconv_prog.c (process_block): Handle omit_invalid. If iconv returns EILSEQ with omit_invalid, continue converting and return 1 if no other errors are seen. (main): Set status to EXIT_FAILURE whenever process_* returns nonzero, but only stop processing further files if iy returns negative value. --- libc/iconv/iconv_prog.c.jj 2004-01-12 10:52:33.000000000 +0100 +++ libc/iconv/iconv_prog.c 2004-03-04 15:46:31.169002268 +0100 @@ -280,7 +280,7 @@ conversion from `%s' and to `%s' are not struct stat st; char *addr; #endif - int fd; + int fd, ret; if (verbose) printf ("%s:\n", argv[remaining]); @@ -313,43 +313,42 @@ conversion from `%s' and to `%s' are not _("error while closing input `%s'"), argv[remaining]); - if (process_block (cd, addr, st.st_size, output) < 0) - { - /* Something went wrong. */ - status = EXIT_FAILURE; + ret = process_block (cd, addr, st.st_size, output); - /* We don't need the input data anymore. */ - munmap ((void *) addr, st.st_size); + /* We don't need the input data anymore. */ + munmap ((void *) addr, st.st_size); + if (ret != 0) + status = EXIT_FAILURE; + + if (ret < 0) + { /* We cannot go on with producing output since it might lead to problem because the last output might leave the output stream in an undefined state. */ break; } - - /* We don't need the input data anymore. */ - munmap ((void *) addr, st.st_size); } else #endif /* _POSIX_MAPPED_FILES */ { /* Read the file in pieces. */ - if (process_fd (cd, fd, output) != 0) - { - /* Something went wrong. */ - status = EXIT_FAILURE; + ret = process_fd (cd, fd, output); + + /* Now close the file. */ + close (fd); - /* We don't need the input file anymore. */ - close (fd); + if (ret != 0) + /* Something went wrong. */ + status = EXIT_FAILURE; + if (ret < 0) + { /* We cannot go on with producing output since it might lead to problem because the last output might leave the output stream in an undefined state. */ break; } - - /* Now close the file. */ - close (fd); } } while (++remaining < argc); @@ -438,6 +437,7 @@ process_block (iconv_t cd, char *addr, s char *outptr; size_t outlen; size_t n; + int ret = 0; while (len > 0) { @@ -445,6 +445,15 @@ process_block (iconv_t cd, char *addr, s outlen = OUTBUF_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) { /* We have something to write out. */ @@ -469,7 +478,7 @@ conversion stopped due to problem in wri character sets we have to flush the state now. */ outptr = outbuf; outlen = OUTBUF_SIZE; - (void) iconv (cd, NULL, NULL, &outptr, &outlen); + n = iconv (cd, NULL, NULL, &outptr, &outlen); if (outptr != outbuf) { @@ -489,7 +498,14 @@ conversion stopped due to problem in wri errno = errno_save; } - break; + if (n != (size_t) -1) + break; + + if (omit_invalid && errno == EILSEQ) + { + ret = 1; + break; + } } if (errno != E2BIG) @@ -518,7 +534,7 @@ incomplete character or shift sequence a } } - return 0; + return ret; } Jakub