This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch, libgfortran] Fix PR26499 End of File incorrectly positioned after binary I/O.


:ADDPATCH fortran:

Hi,

The attached patch fixes this problem. In st_read_done there is logic to handle end-of-file conditions for unformatted sequential writes. This bug was caused by a conditional that never went true so the file never was truncated when it was supposed to. Evidently over th evolutions current_record was suppose to hold a record number. Now it is just a flag telling whether or not to pre_position the file. It has a value of either 0 or 1 so it was always less than the last_record count.

We may want to change this to a bit in dtp and free up current_record to be used to actually hold a record number.

After getting truncate to actually be called I then noticed during testing that gfortran.dg/write_to_null.f90 was failing. The reason for this is that before truncate was never getting called, now that it is it should not fail on /dev/null. According to notes and my search of the past PRs, behavior of truncate for /dev/null is not defined so we might as well pass a SUCCESS rather than a FAILURE in that case.

Regression tested, NIST tested, many IO tested.

OK for trunk and 4.1.1 ?

Regards,

Jerry

2006-03-02 Jerry DeLisle <jvdelisle@gcc.gnu.org>

	PR libgfortran/26499
	* 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/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,2209 ----
  	break;
  
        case NO_ENDFILE:
! 	/* 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;
! { dg-do run }
! PR 26499 : Positioning of EOF after backspaces and write.
! This test verifies that the last write truncates the file.
! Submitted by Jerry DeLisle <jvdelisle@verizon.net>.
      program test
      integer at,eof
      dimension idata(5)
      open(unit=11,form='unformatted')
      write(11)idata
      write(11)idata
      write(11)idata
      backspace(11)
      backspace(11)
      write(11)idata
      close(11, status="keep")  
      open(unit=11,form='unformatted')
      rewind(11)
      read(11)idata
      read(11)idata
      read(11, end=250)idata
      call abort()
 250  continue
      end


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]