This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix iconv -c


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  <jakub@redhat.com>

	* 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]