aboutsummaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorThomas Koenig <Thomas.Koenig@online.de>2006-12-06 19:25:44 +0000
committerThomas Koenig <tkoenig@gcc.gnu.org>2006-12-06 19:25:44 +0000
commitb4c811bd14e0b3ea5a995b711aae60ee1d3daaab (patch)
treeca8a396e07dee2ad42be8eab7d5520d8281b63b1 /libgfortran
parent0307c64eea66674bd3dd9a42fed80cf748e2acf8 (diff)
downloadgcc-b4c811bd14e0b3ea5a995b711aae60ee1d3daaab.zip
gcc-b4c811bd14e0b3ea5a995b711aae60ee1d3daaab.tar.gz
gcc-b4c811bd14e0b3ea5a995b711aae60ee1d3daaab.tar.bz2
re PR libfortran/30009 ([4.1 only] Unformatted reads exceeding storage units gives EOF instead of ERR)
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-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. From-SVN: r119592
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog18
-rw-r--r--libgfortran/io/transfer.c58
-rw-r--r--libgfortran/libgfortran.h1
-rw-r--r--libgfortran/runtime/error.c4
4 files changed, 49 insertions, 32 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 8844e9a..eca621b 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 4270d61..163557d 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 644a0ad..c6b31ed 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 122f6d1..3595564 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;