aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io/unix.c
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2006-02-12 21:59:32 +0200
committerJanne Blomqvist <jb@gcc.gnu.org>2006-02-12 21:59:32 +0200
commit82b8244c51cbf71e28f53a0e7e998aff924c36e7 (patch)
treeca366a0096c08065ac811e843aec247485318297 /libgfortran/io/unix.c
parent5b0b72518b76d75ad93ac95e6e05e772124085df (diff)
downloadgcc-82b8244c51cbf71e28f53a0e7e998aff924c36e7.zip
gcc-82b8244c51cbf71e28f53a0e7e998aff924c36e7.tar.gz
gcc-82b8244c51cbf71e28f53a0e7e998aff924c36e7.tar.bz2
re PR libfortran/25949 (Unbounded I/O buffer memory usage for formatted IO)
2006-02-12 Janne Blomqvist <jb@gcc.gnu.org> PR libgfortran/25949 * io/io.h: Add set function pointer to struct stream. * io/unix.c (fd_seek): Only update offset, don't seek. (fd_sset): New function. (fd_read): Call lseek directly if necessary. (fd_write): Likewise. (fd_open): Set pointer to fd_sset. (mem_set): New function. (open_internal): Set pointer to mem_set. * io/transfer.c (write_block_direct): Rename to write_buf, add error return, non-pointer length argument. (unformatted_write): Update to use write_buf. (us_write): Simplify by using swrite instead of salloc_w. (write_us_marker): New function. (new_record_w): Use sset instead of memset, use write_us_marker, simplify by using swrite instead of salloc_w. From-SVN: r110895
Diffstat (limited to 'libgfortran/io/unix.c')
-rw-r--r--libgfortran/io/unix.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 237f09e..40ad2d8 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -562,15 +562,9 @@ fd_sfree (unix_stream * s)
static try
fd_seek (unix_stream * s, gfc_offset offset)
{
- if (s->physical_offset == offset) /* Are we lucky and avoid syscall? */
- {
- s->logical_offset = offset;
- return SUCCESS;
- }
-
- s->physical_offset = s->logical_offset = offset;
+ s->logical_offset = offset;
- return (lseek (s->fd, offset, SEEK_SET) < 0) ? FAILURE : SUCCESS;
+ return SUCCESS;
}
@@ -606,6 +600,34 @@ fd_truncate (unix_stream * s)
}
+/* Similar to memset(), but operating on a stream instead of a string.
+ Takes care of not using too much memory. */
+
+static try
+fd_sset (unix_stream * s, int c, size_t n)
+{
+ size_t bytes_left;
+ int trans;
+ void *p;
+
+ bytes_left = n;
+
+ while (bytes_left > 0)
+ {
+ /* memset() in chunks of BUFFER_SIZE. */
+ trans = (bytes_left < BUFFER_SIZE) ? bytes_left : BUFFER_SIZE;
+
+ p = fd_alloc_w_at (s, &trans, -1);
+ if (p)
+ memset (p, c, trans);
+ else
+ return FAILURE;
+
+ bytes_left -= trans;
+ }
+
+ return SUCCESS;
+}
/* Stream read function. Avoids using a buffer for big reads. The
@@ -644,7 +666,8 @@ fd_read (unix_stream * s, void * buf, size_t * nbytes)
return errno;
}
- if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
+ if (is_seekable ((stream *) s) && s->physical_offset != s->logical_offset
+ && lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
{
*nbytes = 0;
return errno;
@@ -692,7 +715,8 @@ fd_write (unix_stream * s, const void * buf, size_t * nbytes)
return errno;
}
- if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
+ if (is_seekable ((stream *) s) && s->physical_offset != s->logical_offset
+ && lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
{
*nbytes = 0;
return errno;
@@ -739,6 +763,7 @@ fd_open (unix_stream * s)
s->st.truncate = (void *) fd_truncate;
s->st.read = (void *) fd_read;
s->st.write = (void *) fd_write;
+ s->st.set = (void *) fd_sset;
s->buffer = NULL;
}
@@ -870,6 +895,25 @@ mem_seek (unix_stream * s, gfc_offset offset)
}
+static try
+mem_set (unix_stream * s, int c, size_t n)
+{
+ void *p;
+ int len;
+
+ len = n;
+
+ p = mem_alloc_w_at (s, &len, -1);
+ if (p)
+ {
+ memset (p, c, len);
+ return SUCCESS;
+ }
+ else
+ return FAILURE;
+}
+
+
static int
mem_truncate (unix_stream * s __attribute__ ((unused)))
{
@@ -932,6 +976,7 @@ open_internal (char *base, int length)
s->st.truncate = (void *) mem_truncate;
s->st.read = (void *) mem_read;
s->st.write = (void *) mem_write;
+ s->st.set = (void *) mem_set;
return (stream *) s;
}