changeset 5795:d2c0ff38ad5c

Report lstream errors when encoding/decoding. See <CAHCOHQ=FAieD-2nP303fMvwkii8HK2z+X7gRZ2+4PH1CA5_-NA@mail.gmail.com> in xemacs-patches.
author Jerry James <james@xemacs.org>
date Wed, 14 May 2014 14:16:24 -0600
parents 2d20d57d4e7b
children acf1c26e3019
files src/ChangeLog src/file-coding.c src/lstream.c src/lstream.h
diffstat 4 files changed, 101 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed May 07 13:33:50 2014 -0600
+++ b/src/ChangeLog	Wed May 14 14:16:24 2014 -0600
@@ -1,3 +1,22 @@
+2014-05-06  Jerry James  <james@xemacs.org>
+
+	* file-coding.c (encode_decode_coding_region): Signal an error if
+	Lstream_read encounters an error (returns -1).
+	(detect_coding_type): Ditto.  Add an argument for the stream error.
+	(look_for_coding_system_magic_cookie): Ditto.
+	(determine_real_coding_system): Pass new stream error argument.
+	(undecided_convert): Ditto.
+	(Ffind_coding_system_magic_cookie_in_file): Ditto.
+	* lstream.c (Lstream_errno): New function.
+	(struct filedesc_stream): Add saved_errno member.
+	(make_filedesc_stream_1): Initialize it.
+	(filedesc_reader): Set it.
+	(filedesc_writer): Set it.
+	(filedesc_error): New function.
+	(lstream_type_create): Record that filedesc has an error method.
+	* lstream.h (struct lstream_implementation): Add error member.
+	(Lstream_errno): Declare.
+
 2014-01-27  Michael Sperber  <mike@xemacs.org>
 
 	* symbols.c (Fdefine_function): Allow optional `docstring'
--- a/src/file-coding.c	Wed May 07 13:33:50 2014 -0600
+++ b/src/file-coding.c	Wed May 14 14:16:24 2014 -0600
@@ -2294,6 +2294,23 @@
       Bytecount size_in_bytes =
 	Lstream_read (istr, tempbuf, sizeof (tempbuf));
 
+      if (size_in_bytes < 0)
+	{
+	  int err = Lstream_errno (istr);
+	  if (err)
+	    signal_error_2 (Qtext_conversion_error,
+			    direction == CODING_DECODE
+			    ? "Internal error while decoding"
+			    : "Internal error while encoding",
+			    XCODING_SYSTEM_NAME (coding_system),
+			    lisp_strerror (err));
+	  else
+	    signal_error (Qtext_conversion_error,
+			  direction == CODING_DECODE
+			  ? "Internal error while decoding"
+			  : "Internal error while encoding",
+			  XCODING_SYSTEM_NAME (coding_system));
+	}
       if (!size_in_bytes)
 	break;
       newpos = lisp_buffer_stream_startpos (istr);
@@ -3563,12 +3580,17 @@
 
 static int
 detect_coding_type (struct detection_state *st, const UExtbyte *src,
-		    Bytecount n)
+		    Bytecount n, int err)
 {
   Bytecount n2 = n;
   const UExtbyte *src2 = src;
   int i;
 
+  if (n < 0)
+    signal_error (Qtext_conversion_error,
+		  "Error reading file to determine coding system",
+		  err ? lisp_strerror (err) : Qnil);
+
 #ifdef DEBUG_XEMACS
   if (!NILP (Vdebug_coding_detection))
     {
@@ -3784,12 +3806,19 @@
 
 static Lisp_Object
 look_for_coding_system_magic_cookie (const UExtbyte *data, Bytecount len,
-                                     Boolint find_coding_system_p)
+                                     Boolint find_coding_system_p, int err)
 {
   const UExtbyte *p;
   const UExtbyte *scan_end;
   Bytecount cookie_len;
 
+  if (len < 0)
+    {
+      signal_error (Qtext_conversion_error,
+		    "Internal error while looking for coding cookie",
+		    err ? lisp_strerror (err) : Qnil);
+    }
+
   /* Look for initial "-*-"; mode line prefix */
   for (p = data,
        scan_end = data + len - LENGTH ("-*-coding:?-*-");
@@ -3864,13 +3893,14 @@
   UExtbyte buf[4096];
   Bytecount nread = Lstream_read (stream, buf, sizeof (buf));
   Lisp_Object coding_system
-    = look_for_coding_system_magic_cookie (buf, nread, 1);
+    = look_for_coding_system_magic_cookie (buf, nread, 1,
+					   Lstream_errno (stream));
 
   if (NILP (coding_system))
     {
       while (1)
 	{
-	  if (detect_coding_type (st, buf, nread))
+	  if (detect_coding_type (st, buf, nread, Lstream_errno (stream)))
 	    break;
 	  nread = Lstream_read (stream, buf, sizeof (buf));
 	  if (nread == 0)
@@ -3968,6 +3998,7 @@
 	XCODING_SYSTEM_TYPE_DATA (str->codesys, undecided);
       struct undecided_coding_stream *data =
 	CODING_STREAM_TYPE_DATA (str, undecided);
+      int err = 0;
 
       if (str->eof)
 	{
@@ -4011,6 +4042,7 @@
 
 	  first_time = 1;
 	  data->c.initted = 1;
+	  err = Lstream_errno (str->other_end);
 	}
 
       /* If necessary, do encoding-detection now.  We do this when we're a
@@ -4028,13 +4060,14 @@
 		/* #### This is cheesy.  What we really ought to do is buffer
 		   up a certain minimum amount of data to get a better result.
 		   */
-		data->actual = look_for_coding_system_magic_cookie (src, n, 1);
+		data->actual =
+		  look_for_coding_system_magic_cookie (src, n, 1, err);
 	      if (NILP (data->actual))
 		{
 		  /* #### This is cheesy.  What we really ought to do is buffer
 		     up a certain minimum amount of data so as to get a less
 		     random result when doing subprocess detection. */
-		  detect_coding_type (data->st, src, n);
+		  detect_coding_type (data->st, src, n, err);
 		  data->actual = detected_coding_system (data->st);
 		  /* kludge to prevent infinite recursion */
 		  if (XCODING_SYSTEM(data->actual)->methods->enumtype == undecided_coding_system)
@@ -4291,7 +4324,7 @@
   Lisp_Object lstream;
   UExtbyte buf[4096];
   Bytecount nread;
-  int fd = -1;
+  int fd = -1, err;
   struct stat st;
 
   filename = Fexpand_file_name (filename, Qnil);
@@ -4312,10 +4345,11 @@
   lstream = make_filedesc_input_stream (fd, 0, -1, 0);
   Lstream_set_buffering (XLSTREAM (lstream), LSTREAM_UNBUFFERED, 0);
   nread = Lstream_read (XLSTREAM (lstream), buf, sizeof (buf));
+  err = Lstream_errno (XLSTREAM (lstream));
   Lstream_delete (XLSTREAM (lstream));
   retry_close (fd);
 
-  return look_for_coding_system_magic_cookie (buf, nread, 0);
+  return look_for_coding_system_magic_cookie (buf, nread, 0, err);
 }
 
 
--- a/src/lstream.c	Wed May 07 13:33:50 2014 -0600
+++ b/src/lstream.c	Wed May 14 14:16:24 2014 -0600
@@ -742,6 +742,12 @@
   return Lstream_read_1 (lstr, data, size, 0);
 }
 
+int
+Lstream_errno (Lstream *lstr)
+{
+  return (lstr->imp->error) ? (lstr->imp->error) (lstr) : 0;
+}
+
 Charcount
 Lstream_character_tell (Lstream *lstr)
 {
@@ -1118,6 +1124,7 @@
   int current_pos;
   int end_pos;
   int chars_sans_newline;
+  int saved_errno;
   unsigned int closing :1;
   unsigned int allow_quit :1;
   unsigned int blocked_ok :1;
@@ -1146,6 +1153,7 @@
   fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
   fstr->blocking_error_p = 0;
   fstr->chars_sans_newline = 0;
+  fstr->saved_errno = 0;
   fstr->starting_pos = lseek (filedesc, offset, SEEK_CUR);
   fstr->current_pos = max (fstr->starting_pos, 0);
   if (count < 0)
@@ -1192,6 +1200,7 @@
 {
   Bytecount nread;
   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
+  str->saved_errno = 0;
   if (str->end_pos >= 0)
     size = min (size, (Bytecount) (str->end_pos - str->current_pos));
   nread = str->allow_quit ?
@@ -1202,7 +1211,10 @@
   if (nread == 0)
     return 0; /* LSTREAM_EOF; */
   if (nread < 0)
-    return LSTREAM_ERROR;
+    {
+      str->saved_errno = errno;
+      return LSTREAM_ERROR;
+    }
   return nread;
 }
 
@@ -1228,6 +1240,8 @@
   Bytecount retval;
   int need_newline = 0;
 
+  str->saved_errno = 0;
+
   /* This function would be simple if it were not for the blasted
      PTY max-bytes stuff.  Why the hell can't they just have written
      the PTY drivers right so this problem doesn't exist?
@@ -1266,7 +1280,10 @@
     }
   str->blocking_error_p = 0;
   if (retval < 0)
-    return LSTREAM_ERROR;
+    {
+      str->saved_errno = errno;
+      return LSTREAM_ERROR;
+    }
   /**** end non-PTY-crap ****/
 
   if (str->pty_flushing)
@@ -1298,7 +1315,10 @@
 		      return 0;
 		    }
 		  else
-		    return LSTREAM_ERROR;
+		    {
+		      str->saved_errno = errno;
+		      return LSTREAM_ERROR;
+		    }
 		}
 	      else
 		return retval;
@@ -1334,7 +1354,10 @@
 		  return 0;
 		}
 	      else
-		return LSTREAM_ERROR;
+		{
+		  str->saved_errno = errno;
+		  return LSTREAM_ERROR;
+		}
 	    }
 	  else
 	    return retval;
@@ -1345,6 +1368,13 @@
 }
 
 static int
+filedesc_error (Lstream *stream)
+{
+  struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
+  return str->saved_errno;
+}
+
+static int
 filedesc_rewinder (Lstream *stream)
 {
   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
@@ -1926,6 +1956,7 @@
 
   LSTREAM_HAS_METHOD (filedesc, reader);
   LSTREAM_HAS_METHOD (filedesc, writer);
+  LSTREAM_HAS_METHOD (filedesc, error);
   LSTREAM_HAS_METHOD (filedesc, was_blocked_p);
   LSTREAM_HAS_METHOD (filedesc, rewinder);
   LSTREAM_HAS_METHOD (filedesc, seekable_p);
--- a/src/lstream.h	Wed May 07 13:33:50 2014 -0600
+++ b/src/lstream.h	Wed May 14 14:16:24 2014 -0600
@@ -174,6 +174,10 @@
      in an attempt to block (EWOULDBLOCK). If this method does not
      exists, the implementation returns 0 */
   int (*was_blocked_p) (Lstream *stream);
+  /* If the reader or writer method returned LSTREAM_ERROR, the errno
+     associated with the error, or zero if there was no system error or this
+     method is not implemented. */
+  int (*error) (Lstream *stream);
   /* Rewind the stream.  If this is NULL, the stream is not seekable. */
   int (*rewinder) (Lstream *stream);
   /* Indicate whether this stream is seekable -- i.e. it can be rewound.
@@ -306,6 +310,7 @@
 Charcount Lstream_character_tell (Lstream *);
 int Lstream_write (Lstream *lstr, const void *data,
 		   Bytecount size);
+int Lstream_errno (Lstream *lstr);
 int Lstream_was_blocked_p (Lstream *lstr);
 void Lstream_unread (Lstream *lstr, const void *data, Bytecount size);
 int Lstream_rewind (Lstream *lstr);