diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 089232fa404a7d28fc4b89311dc5a3568f678da5..58837bc40ac72b2bc526d8666b1d30906a634e4b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2006-12-06  Thomas Koenig  <Thomas.Koenig@online.de>
+
+	PR libfortran/30009
+	PR libfortran/30056
+	* gfortran.dg/read_eof_4.f90:  Add tests.
+	* gfortran.dg/readwrite_unf_direct_eor_1.f90:  New test.
+	* gfortran.dg/unf_read_corrupted_1.f90: New test.
+
 2006-12-05  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/29729
diff --git a/gcc/testsuite/gfortran.dg/read_eof_4.f90 b/gcc/testsuite/gfortran.dg/read_eof_4.f90
index b8ca5a78e57fb08b0d88772b508433b1e4eb2579..ee95268d50dc13a857f44b4bb94ebb99cbcf8a3c 100644
--- a/gcc/testsuite/gfortran.dg/read_eof_4.f90
+++ b/gcc/testsuite/gfortran.dg/read_eof_4.f90
@@ -1,16 +1,30 @@
 ! { dg-do run }
-! PR 27575 : This test checks the error checking for end of file condition.
+! PR 27575 and PR 30009: This test checks the error checking for end
+! of file condition.
 ! Derived from test case in PR.
-! Submitted by Jerry DeLisle <jvdelisle@verizon.net>.
+! Submitted by Jerry DeLisle <jvdelisle@verizon.net>, modified by
+! Thomas Koenig <Thomas.Koenig@online.de>
+
       program test
       integer i1,i2,i3
       open(unit=11,form='unformatted')
-      write(11)i1, i2     
+      write (11) 1, 2
+      write (11) 3, 4
       close(11,status='keep')
+
       open(unit=11,form='unformatted')
-      read(11, eND=100) i1, i2, i3
+
+      read(11, ERR=100) i1, i2, i3
       call abort()
- 100  read(11, end=110) i3
-      call abort() 
- 110  close(11,status='delete')
+  100 continue
+      if (i1 /= 1 .or. i2 /= 2) call abort
+
+      read(11, ERR=110) i1, i2, i3
+      call abort()
+  110 continue
+      if (i1 /= 3 .or. i2 /= 4) call abort
+
+      read(11, end=120) i3
+      call abort()
+ 120  close(11,status='delete')
       end
diff --git a/gcc/testsuite/gfortran.dg/readwrite_unf_direct_eor_1.f90 b/gcc/testsuite/gfortran.dg/readwrite_unf_direct_eor_1.f90
new file mode 100644
index 0000000000000000000000000000000000000000..2c19eba39276f98e32520a989c1798dd207719a8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/readwrite_unf_direct_eor_1.f90
@@ -0,0 +1,13 @@
+! { dg-do run }
+! PR 30056 - exceeding the record length was misrepresented as an EOF
+!            on read and ignored on write 
+      program main
+      integer i,j
+      open (10, form="unformatted", access="direct", recl=4)
+      write (10, rec=1, err=10) 1,2
+      call abort()
+ 10   continue
+      read (10,  rec=1, err=20) i, j
+      call abort()
+ 20   continue
+      end
diff --git a/gcc/testsuite/gfortran.dg/unf_read_corrupted_1.f90 b/gcc/testsuite/gfortran.dg/unf_read_corrupted_1.f90
new file mode 100644
index 0000000000000000000000000000000000000000..166d52915306da0f6537782663d4ada0ec0d6da9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unf_read_corrupted_1.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+! Test the error message when an unformatted file has become
+! corrupted.
+program main
+  implicit none
+  integer :: i1, i2
+  integer :: ios
+  character(len=50) :: msg
+
+  ! Write out a truncated unformatted sequential file by
+  ! using unformatted stream.
+
+  open (10, form="unformatted", access="stream", file="foo.dat", &
+  status="unknown")
+  write (10) 16, 1
+  close (10, status="keep")
+
+  ! Try to read
+  open (10, file="foo.dat", form="unformatted", access="sequential")
+  i1 = 0
+  i2 = 0
+  read (10, iostat=ios, iomsg=msg) i1, i2
+  if (ios == 0) call abort
+  if (i1 /= 1) call abort
+  if (msg /= "Unformatted file structure has been corrupted") call abort
+  close (10, status="delete")
+end program main
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 8844e9ad336d873e5d95320c50915b6588f3b5e3..eca621b172e075a974c96ffd9db7c8a1f236978f 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,21 @@
+2006-12-06  Thomas Koenig  <Thomas.Koenig@online.de>
+
+	PR libfortran/30009
+	PR libfortran/30056
+	* libgfortran.h:  Add ERROR_CORRUPT_FILE to error_codes.
+	* runtime/error.c (translate_error):  Add handling for
+	ERROR_CORRUPT_FILE.
+	* io/transfer.c (read_block_direct):  Add comment about
+	EOR for stream files.
+	Remove test for no bytes left for direct access files.
+	Generate an ERROR_SHORT_RECORD if the read was short.
+	For unformatted sequential files:  Check endfile condition.
+	Remove test for no bytes left.  End of file here means
+	that the file structure has been corrupted.  Pre-position
+	the file for the next record in case of error.
+	(write_buf):  Whitespace fix.  Subtract the number of bytes
+	written from bytes_left.
+
 2006-12-04  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
 	PR libfortran/30005
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 4270d61e693cb01410bafd6645330317e3a79f45..163557d49b3a5f8fc61a79df7dfa0c1ad8923638 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -374,7 +374,8 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
 
       if (to_read_record != have_read_record)
 	{
-	  /* Short read,  e.g. if we hit EOF.  */
+	  /* Short read,  e.g. if we hit EOF.  For stream files,
+	   we have to set the end-of-file condition.  */
 	  generate_error (&dtp->common, ERROR_END, NULL);
 	  return;
 	}
@@ -388,13 +389,6 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
 	  short_record = 1;
 	  to_read_record = (size_t) dtp->u.p.current_unit->bytes_left;
 	  *nbytes = to_read_record;
-
-	  if (dtp->u.p.current_unit->bytes_left == 0)
-	    {
-	      dtp->u.p.current_unit->endfile = AT_ENDFILE;
-	      generate_error (&dtp->common, ERROR_END, NULL);
-	      return;
-	    }
 	}
 
       else
@@ -411,10 +405,12 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
 	  return;
 	}
 
-      if (to_read_record != *nbytes)  /* Short read, e.g. if we hit EOF.  */
+      if (to_read_record != *nbytes)  
 	{
+	  /* Short read, e.g. if we hit EOF.  Apparently, we read
+	   more than was written to the last record.  */
 	  *nbytes = to_read_record;
-	  generate_error (&dtp->common, ERROR_END, NULL);
+	  generate_error (&dtp->common, ERROR_SHORT_RECORD, NULL);
 	  return;
 	}
 
@@ -430,6 +426,12 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
      until the request has been fulfilled or the record has run out
      of continuation subrecords.  */
 
+  if (dtp->u.p.current_unit->endfile == AT_ENDFILE)
+    {
+      generate_error (&dtp->common, ERROR_END, NULL);
+      return;
+    }
+
   /* Check whether we exceed the total record length.  */
 
   if (dtp->u.p.current_unit->flags.has_recl)
@@ -453,25 +455,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
 	{
 	  to_read_subrecord = (size_t) dtp->u.p.current_unit->bytes_left_subrecord;
 	  to_read_record -= to_read_subrecord;
-
-	  if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
-	    {
-	      if (dtp->u.p.current_unit->continued)
-		{
-		  /* Skip to the next subrecord */
-		  next_record_r_unf (dtp, 0);
-		  us_read (dtp, 1);
-		  continue;
-		}
-	      else
-		{
-		  dtp->u.p.current_unit->endfile = AT_ENDFILE;
-		  generate_error (&dtp->common, ERROR_END, NULL);
-		  return;
-		}
-	    }
 	}
-
       else
 	{
 	  to_read_subrecord = to_read_record;
@@ -490,11 +474,15 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
 
       have_read_record += have_read_subrecord;
 
-      if (to_read_subrecord != have_read_subrecord)  /* Short read,
-							e.g. if we hit EOF.  */
+      if (to_read_subrecord != have_read_subrecord)  
+			
 	{
+	  /* Short read, e.g. if we hit EOF.  This means the record
+	     structure has been corrupted, or the trailing record
+	     marker would still be present.  */
+
 	  *nbytes = have_read_record;
-	  generate_error (&dtp->common, ERROR_END, NULL);
+	  generate_error (&dtp->common, ERROR_CORRUPT_FILE, NULL);
 	  return;
 	}
 
@@ -507,6 +495,11 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
 	    }
 	  else
 	    {
+	      /* Let's make sure the file position is correctly set for the
+		 next read statement.  */
+
+	      next_record_r_unf (dtp, 0);
+	      us_read (dtp, 0);
 	      generate_error (&dtp->common, ERROR_SHORT_RECORD, NULL);
 	      return;
 	    }
@@ -637,7 +630,8 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes)
 	  return FAILURE;
 	}
 
-      dtp->u.p.current_unit->strm_pos += (gfc_offset) nbytes; 
+      dtp->u.p.current_unit->strm_pos += (gfc_offset) nbytes;
+      dtp->u.p.current_unit->bytes_left -= (gfc_offset) nbytes;
 
       return SUCCESS;
 
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 644a0adc7844557bfaaf50d283d58948c9ef38c3..c6b31ed908a8ff0358381a284a7ab84615fea608 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -416,6 +416,7 @@ typedef enum
   ERROR_ALLOCATION,
   ERROR_DIRECT_EOR,
   ERROR_SHORT_RECORD,
+  ERROR_CORRUPT_FILE,
   ERROR_LAST			/* Not a real error, the last error # + 1.  */
 }
 error_codes;
diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
index 122f6d14bab426f596b4a45b5ae37441fbd52e0d..35955644ba5fab94593bd7edb242a41ccdce885c 100644
--- a/libgfortran/runtime/error.c
+++ b/libgfortran/runtime/error.c
@@ -440,6 +440,10 @@ translate_error (int code)
       p = "I/O past end of record on unformatted file";
       break;
 
+    case ERROR_CORRUPT_FILE:
+      p = "Unformatted file structure has been corrupted";
+      break;
+
     default:
       p = "Unknown error code";
       break;