[PATCH 21.5] Report lstream errors when encoding/decoding

Jerry James <[email protected]>
Newsgroups gmane.emacs.xemacs.patches
Message-ID <CAHCOHQ=FAieD-2nP303fMvwkii8HK2z+X7gRZ2+4PH1CA5_-NA@mail.gmail.com>
PATCH 21.5

This is the latest version of the patch to throw an error if we
encounter an error while trying to do an lstream read when decoding or
encoding.  This version adds a new function, Lstream_errno(), to
retrieve the latest value of errno generated when trying to do an
Lstream_read() or Lstream_write().  Currently only the filedesc
lstream implements the corresponding method.  The patch is attached.
-- 
Jerry James
http://www.jamezone.org/

_______________________________________________
XEmacs-Patches mailing list
[email protected]
http://lists.xemacs.org/mailman/listinfo/xemacs-patches
xemacs-lread.patch (text/x-patch, 9.2 KB)
diff -r cf0201de66df src/ChangeLog
--- a/src/ChangeLog	Fri Apr 25 23:38:16 2014 +0200
+++ b/src/ChangeLog	Tue May 06 10:33:38 2014 -0600
@@ -1,3 +1,22 @@
+2014-05-06  Jerry James  <[email protected]>
+
+	* 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  <[email protected]>
 
 	* symbols.c (Fdefine_function): Allow optional `docstring'
diff -r cf0201de66df src/file-coding.c
--- a/src/file-coding.c	Fri Apr 25 23:38:16 2014 +0200
+++ b/src/file-coding.c	Tue May 06 10:33:38 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);
 }
 
 
diff -r cf0201de66df src/lstream.c
--- a/src/lstream.c	Fri Apr 25 23:38:16 2014 +0200
+++ b/src/lstream.c	Tue May 06 10:33:38 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);
diff -r cf0201de66df src/lstream.h
--- a/src/lstream.h	Fri Apr 25 23:38:16 2014 +0200
+++ b/src/lstream.h	Tue May 06 10:33:38 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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.