[gfortran] patch for pr15472 and sequential unformatted I/O

Bud Davis bdavis@gcc.gnu.org
Sun Jul 4 18:56:00 GMT 2004


On Sun, 2004-07-04 at 12:25, Paul Brook wrote:
 
> 
> Uh, sorry about this, but I've spotted something else :(
 
in the words of the esteemed tobi schlueter; "that's what patch review
is for".

i would much rather deal with these now, than later..

both places were possible problems, added comments and some logic 
changes to both of them.

went over the logic (executed with printf's in the code!) both
with a terminal device and a fifo. both give error messages when 
seeks are attempted, and s->file_length is not overwritten.

test results unchanged.  no test suite failures i686/gnu/linux.


--bud


Index: unix.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/unix.c,v
retrieving revision 1.6
diff -c -3 -p -r1.6 unix.c
*** unix.c	26 Jun 2004 11:49:06 -0000	1.6
--- unix.c	4 Jul 2004 18:50:34 -0000
*************** typedef struct
*** 90,96 ****
    gfc_offset physical_offset;	/* Current physical file offset */
    gfc_offset logical_offset;	/* Current logical file offset */
    gfc_offset dirty_offset;	/* Start of modified bytes in buffer */
!   gfc_offset file_length;		/* Length of the file, -1 if not seekable. */
  
    char *buffer;
    int len;			/* Physical length of the current buffer */
--- 90,96 ----
    gfc_offset physical_offset;	/* Current physical file offset */
    gfc_offset logical_offset;	/* Current logical file offset */
    gfc_offset dirty_offset;	/* Start of modified bytes in buffer */
!   gfc_offset file_length;	/* Length of the file, -1 if not seekable. */
  
    char *buffer;
    int len;			/* Physical length of the current buffer */
*************** fd_flush (unix_stream * s)
*** 280,287 ****
      return FAILURE;
  
    s->physical_offset = s->dirty_offset + s->ndirty;
!   if (s->physical_offset > s->file_length)
!     s->file_length = s->physical_offset;
    s->ndirty = 0;
  
    return SUCCESS;
--- 280,290 ----
      return FAILURE;
  
    s->physical_offset = s->dirty_offset + s->ndirty;
! 
!   /* don't increment file_length if the file is non-seekable */
!   if (s->file_length != -1 )
!     if (s->physical_offset > s->file_length)
!       s->file_length = s->physical_offset;
    s->ndirty = 0;
  
    return SUCCESS;
*************** fd_alloc_w_at (unix_stream * s, int *len
*** 406,423 ****
      }
  
    /* Return a position within the current buffer */
! 
!   if (s->ndirty == 0)
!     {				/* First write into a clean buffer */
!       s->dirty_offset = where;
!       s->ndirty = *len;
      }
    else
!     {
!       if (s->dirty_offset + s->ndirty == where)
! 	s->ndirty += *len;
!       else
! 	fd_flush (s);		/* Can't combine two dirty blocks */
      }
  
    s->logical_offset = where + *len;
--- 409,436 ----
      }
  
    /* Return a position within the current buffer */
!   if (s->ndirty == 0 
!       || where > s->dirty_offset + s->ndirty    
!       || s->dirty_offset > where + *len)
!     {  /* Discontiguous blocks, start with a clean buffer.  */  
!         /* Flush the buffer.  */  
!        if (s->ndirty != 0)    
!          fd_flush (s);  
!        s->dirty_offset = where;  
!        s->ndirty = *len;
      }
    else
!     {  
!       gfc_offset start;  /* Merge with the existing data.  */  
!       if (where < s->dirty_offset)    
!         start = where;  
!       else    
!         start = s->dirty_offset;  
!       if (where + *len > s->dirty_offset + s->ndirty)    
!         s->ndirty = where + *len - start;  
!       else    
!         s->ndirty = s->dirty_offset + s->ndirty - start;  
!         s->dirty_offset = start;
      }
  
    s->logical_offset = where + *len;
*************** static try
*** 461,473 ****
  fd_truncate (unix_stream * s)
  {
  
!   if (ftruncate (s->fd, s->logical_offset))
      return FAILURE;
  
!   s->physical_offset = s->file_length = s->logical_offset;
  
!   if (lseek (s->fd, s->file_length, SEEK_SET) == -1)
      return FAILURE;
  
    return SUCCESS;
  }
--- 474,491 ----
  fd_truncate (unix_stream * s)
  {
  
!   if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
      return FAILURE;
  
!   /* non-seekable files, like terminals and fifo's fail the lseek.
!      the fd is a regular file at this point */
  
!   if (ftruncate (s->fd, s->logical_offset))
!    {
      return FAILURE;
+    }
+ 
+   s->physical_offset = s->file_length = s->logical_offset;
  
    return SUCCESS;
  }
*************** file_position (stream * s)
*** 1390,1397 ****
  int
  is_seekable (stream * s)
  {
! 
!   return ((unix_stream *) s)->mmaped;
  }
  
  try
--- 1408,1417 ----
  int
  is_seekable (stream * s)
  {
!   /* by convention, if file_length == -1, the file is not seekable
!      note that a mmapped file is always seekable, an fd_ file may
!      or may not be. */
!   return ((unix_stream *) s)->file_length!=-1;
  }
  
  try




More information about the Fortran mailing list