:REVIEWPATCH:
This is the third installment of this patch. Dale developed a test
program that tests many combinations using rewind instead of backspace
and found another failure.
The attached revised patch is against current trunk and replaces the
previous two patches I submitted. I will include the test cases
already given plus one more.
Once again, OK for trunk and 4.1.1? (Sorry for the repeats, but I
fix them as they come.)
Regards,
Jerry
2006-03-03 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/26499
* io/file_pos (st_rewind): Flush always.
* io/unix.c (fd_truncate): Return SUCCESS rather than FAILURE for
special files like /dev/null.
* io/transfer.c (st_write_done): Remove broken logic that prevented
calling fd_truncate.
------------------------------------------------------------------------
Index: io/file_pos.c
===================================================================
*** io/file_pos.c (revision 111630)
--- io/file_pos.c (working copy)
*************** st_rewind (st_parameter_filepos *fpp)
*** 246,260 ****
"Cannot REWIND a file opened for DIRECT access");
else
{
! /* If we have been writing to the file, the last written record
! is the last record in the file, so truncate the file now.
! Reset to read mode so two consecutive rewind statements do not
! delete the file contents. Flush buffer when switching
mode. */
! if (u->mode == WRITING)
! {
! flush (u->s);
! struncate (u->s);
! }
u->mode = READING;
u->last_record = 0;
if (sseek (u->s, 0) == FAILURE)
--- 246,259 ----
"Cannot REWIND a file opened for DIRECT access");
else
{
! /* Flush the buffers. If we have been writing to the file,
the last
! written record is the last record in the file, so
truncate the
! file now. Reset to read mode so two consecutive rewind
! statements do not delete the file contents. */
! flush (u->s);
! if (u->mode == WRITING)
! struncate (u->s);
! u->mode = READING;
u->last_record = 0;
if (sseek (u->s, 0) == FAILURE)
Index: io/unix.c
===================================================================
*** io/unix.c (revision 111630)
--- io/unix.c (working copy)
*************** fd_truncate (unix_stream * s)
*** 586,592 ****
/* non-seekable files, like terminals and fifo's fail the lseek.
Using ftruncate on a seekable special file (like /dev/null)
! is undefined, so we treat it as if the ftruncate failed.
*/
#ifdef HAVE_FTRUNCATE
if (s->special_file || ftruncate (s->fd, s->logical_offset))
--- 586,592 ----
/* non-seekable files, like terminals and fifo's fail the lseek.
Using ftruncate on a seekable special file (like /dev/null)
! is undefined, so we treat it as if the ftruncate succeeded.
*/
#ifdef HAVE_FTRUNCATE
if (s->special_file || ftruncate (s->fd, s->logical_offset))
*************** fd_truncate (unix_stream * s)
*** 597,603 ****
#endif
{
s->physical_offset = s->file_length = 0;
! return FAILURE;
}
s->physical_offset = s->file_length = s->logical_offset;
--- 597,603 ----
#endif
{
s->physical_offset = s->file_length = 0;
! return SUCCESS;
}
s->physical_offset = s->file_length = s->logical_offset;
Index: io/transfer.c
===================================================================
*** io/transfer.c (revision 111630)
--- io/transfer.c (working copy)
*************** st_write_done (st_parameter_dt *dtp)
*** 2189,2195 ****
/* Deal with endfile conditions associated with sequential
files. */
! if (dtp->u.p.current_unit != NULL &&
dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
switch (dtp->u.p.current_unit->endfile)
{
case AT_ENDFILE: /* Remain at the endfile record. */
--- 2189,2196 ----
/* Deal with endfile conditions associated with sequential
files. */
! if (dtp->u.p.current_unit != NULL ! &&
dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
switch (dtp->u.p.current_unit->endfile)
{
case AT_ENDFILE: /* Remain at the endfile record. */
*************** st_write_done (st_parameter_dt *dtp)
*** 2200,2211 ****
break;
case NO_ENDFILE:
! if (dtp->u.p.current_unit->current_record >
dtp->u.p.current_unit->last_record)
! {
! /* Get rid of whatever is after this record. */
! if (struncate (dtp->u.p.current_unit->s) == FAILURE)
! generate_error (&dtp->common, ERROR_OS, NULL);
! }
dtp->u.p.current_unit->endfile = AT_ENDFILE;
break;
--- 2201,2210 ----
break;
case NO_ENDFILE:
! /* Get rid of whatever is after this record. */
! flush (dtp->u.p.current_unit->s);
! if (struncate (dtp->u.p.current_unit->s) == FAILURE)
! generate_error (&dtp->common, ERROR_OS, NULL);
dtp->u.p.current_unit->endfile = AT_ENDFILE;
break;