diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 75476ca1002..5053e04e8a2 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,14 @@ +2007-01-05 Jerry DeLisle + + 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 * ChangeLog: Copied to ... diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index 57883e0f4e3..3419d72d75a 100644 --- a/libgfortran/io/unix.c +++ b/libgfortran/io/unix.c @@ -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);