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

Jerry DeLisle jvdelisle@verizon.net
Wed Mar 8 06:58:00 GMT 2006


PING(2)

Jerry DeLisle wrote:
> :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;



More information about the Fortran mailing list