re PR libfortran/30162 (Document when sequential I/O with named pipes works)
authorJerry DeLisle <jvdelisle@gcc.gnu.org>
Sat, 6 Jan 2007 00:14:38 +0000 (00:14 +0000)
committerJerry DeLisle <jvdelisle@gcc.gnu.org>
Sat, 6 Jan 2007 00:14:38 +0000 (00:14 +0000)
2007-01-05  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

PR libgfortran/30162
* io/unix.c (fd_flush): Don't seek if file is not seekable, defined as
s->file_length == -1.
(fd_alloc_w_at): Do not adjust file_length if file is not seekable.
(fd_seek): If not seekable, just return success.
(fd_truncate): If not seekable, no need to truncate.  Return failure if
seek fails and the stream is not a pipe.
(fd_to_stream): Make test for non-seekable file more robust.

From-SVN: r120512

libgfortran/ChangeLog
libgfortran/io/unix.c

index 75476ca1002b0132e4970aa00605b616dc733404..5053e04e8a27a5df30658e8f956f26c621d27ed1 100644 (file)
@@ -1,3 +1,14 @@
+2007-01-05  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
+
+       PR libgfortran/30162
+       * io/unix.c (fd_flush): Don't seek if file is not seekable, defined as
+       s->file_length == -1.
+       (fd_alloc_w_at): Do not adjust file_length if file is not seekable.
+       (fd_seek): If not seekable, just return success.
+       (fd_truncate): If not seekable, no need to truncate.  Return failure if
+       seek fails and the stream is not a pipe.
+       (fd_to_stream): Make test for non-seekable file more robust.
+
 2007-01-01  Steven G. Kargl  <kargls@comcast.net>
 
        * ChangeLog: Copied to ...
index 57883e0f4e3964aa4a7f8f5237ac4a9aa6deba37..3419d72d75a3f4be6339b9fbb6131348a7c7bd8f 100644 (file)
@@ -349,9 +349,9 @@ fd_flush (unix_stream * s)
   size_t writelen;
 
   if (s->ndirty == 0)
-    return SUCCESS;;
-
-  if (s->physical_offset != s->dirty_offset &&
+    return SUCCESS;
+  
+  if (s->file_length != -1 && s->physical_offset != s->dirty_offset &&
       lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
     return FAILURE;
 
@@ -536,8 +536,10 @@ fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
 
   s->logical_offset = where + *len;
 
-  if (where + *len > s->file_length)
-    s->file_length = where + *len;
+  /* Don't increment file_length if the file is non-seekable.  */
+
+  if (s->file_length != -1 && s->logical_offset > s->file_length)
+     s->file_length = s->logical_offset;
 
   n = s->logical_offset - s->buffer_offset;
   if (n > s->active)
@@ -562,6 +564,10 @@ fd_sfree (unix_stream * s)
 static try
 fd_seek (unix_stream * s, gfc_offset offset)
 {
+
+  if (s->file_length == -1)
+    return SUCCESS;
+
   if (s->physical_offset == offset) /* Are we lucky and avoid syscall?  */
     {
       s->logical_offset = offset;
@@ -582,13 +588,19 @@ fd_seek (unix_stream * s, gfc_offset offset)
 static try
 fd_truncate (unix_stream * s)
 {
+  /* Non-seekable files, like terminals and fifo's fail the lseek so just
+     return success, there is nothing to truncate.  If its not a pipe there
+     is a real problem.  */
   if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
-    return FAILURE;
+    {
+      if (errno == ESPIPE)
+       return SUCCESS;
+      else
+       return FAILURE;
+    }
 
-  /* 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.
-  */
+  /* 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))
 #else
@@ -1009,7 +1021,12 @@ fd_to_stream (int fd, int prot)
   /* Get the current length of the file. */
 
   fstat (fd, &statbuf);
-  s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
+
+  if (lseek (fd, 0, SEEK_CUR) == (off_t) -1)
+    s->file_length = -1;
+  else
+    s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
+
   s->special_file = !S_ISREG (statbuf.st_mode);
 
   fd_open (s);