mirror of git://gcc.gnu.org/git/gcc.git
Simplify handling of special files.
2011-10-31 Janne Blomqvist <jb@gcc.gnu.org> * io/file_pos.c (st_rewind): Handle regular and special files identically. * io/intrinsics.c (fseek_sub): Don't check whether we think the file is seekable, just do what the caller says. * io/transfer.c (skip_record): First try to seek, then fallback to reading and throwing away what we read. * io/unit.c (update_position): Don't check whether file is seekable, just try to do what we're told. (unit_truncate): Likewise. * io/unix.c (struct unix_stream): Remove special_file flag. (buf_flush): Remove code for handling unseekable files. (buf_seek): Likewise. (fd_to_stream): Use buffered IO only for regular files. (file_length): Remove is_seekable() call. (is_seekable): Remove function. (is_special): Likewise. * io/unix.h: Remove prototypes for is_seekable and is_special. From-SVN: r180701
This commit is contained in:
parent
2062f77b8b
commit
7d5ee21935
|
@ -1,3 +1,23 @@
|
||||||
|
2011-10-31 Janne Blomqvist <jb@gcc.gnu.org>
|
||||||
|
|
||||||
|
* io/file_pos.c (st_rewind): Handle regular and special files
|
||||||
|
identically.
|
||||||
|
* io/intrinsics.c (fseek_sub): Don't check whether we think the
|
||||||
|
file is seekable, just do what the caller says.
|
||||||
|
* io/transfer.c (skip_record): First try to seek, then fallback to
|
||||||
|
reading and throwing away what we read.
|
||||||
|
* io/unit.c (update_position): Don't check whether file is
|
||||||
|
seekable, just try to do what we're told.
|
||||||
|
(unit_truncate): Likewise.
|
||||||
|
* io/unix.c (struct unix_stream): Remove special_file flag.
|
||||||
|
(buf_flush): Remove code for handling unseekable files.
|
||||||
|
(buf_seek): Likewise.
|
||||||
|
(fd_to_stream): Use buffered IO only for regular files.
|
||||||
|
(file_length): Remove is_seekable() call.
|
||||||
|
(is_seekable): Remove function.
|
||||||
|
(is_special): Likewise.
|
||||||
|
* io/unix.h: Remove prototypes for is_seekable and is_special.
|
||||||
|
|
||||||
2011-09-10 Thomas Koenig <tkoenig@gcc.gnu.org>
|
2011-09-10 Thomas Koenig <tkoenig@gcc.gnu.org>
|
||||||
|
|
||||||
PR fortran/49479
|
PR fortran/49479
|
||||||
|
|
|
@ -407,19 +407,14 @@ st_rewind (st_parameter_filepos *fpp)
|
||||||
if (sseek (u->s, 0, SEEK_SET) < 0)
|
if (sseek (u->s, 0, SEEK_SET) < 0)
|
||||||
generate_error (&fpp->common, LIBERROR_OS, NULL);
|
generate_error (&fpp->common, LIBERROR_OS, NULL);
|
||||||
|
|
||||||
/* Handle special files like /dev/null differently. */
|
/* Set this for compatibilty with g77 for /dev/null. */
|
||||||
if (!is_special (u->s))
|
if (file_length (u->s) == 0)
|
||||||
|
u->endfile = AT_ENDFILE;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* We are rewinding so we are not at the end. */
|
/* We are rewinding so we are not at the end. */
|
||||||
u->endfile = NO_ENDFILE;
|
u->endfile = NO_ENDFILE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set this for compatibilty with g77 for /dev/null. */
|
|
||||||
if (file_length (u->s) == 0 && stell (u->s) == 0)
|
|
||||||
u->endfile = AT_ENDFILE;
|
|
||||||
/* Future refinements on special files can go here. */
|
|
||||||
}
|
|
||||||
|
|
||||||
u->current_record = 0;
|
u->current_record = 0;
|
||||||
u->strm_pos = 1;
|
u->strm_pos = 1;
|
||||||
|
|
|
@ -246,7 +246,7 @@ fseek_sub (int * unit, GFC_IO_INT * offset, int * whence, int * status)
|
||||||
gfc_unit * u = find_unit (*unit);
|
gfc_unit * u = find_unit (*unit);
|
||||||
ssize_t result = -1;
|
ssize_t result = -1;
|
||||||
|
|
||||||
if (u != NULL && is_seekable(u->s))
|
if (u != NULL)
|
||||||
{
|
{
|
||||||
result = sseek(u->s, *offset, *whence);
|
result = sseek(u->s, *offset, *whence);
|
||||||
|
|
||||||
|
|
|
@ -2823,18 +2823,12 @@ skip_record (st_parameter_dt *dtp, ssize_t bytes)
|
||||||
if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
|
if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (is_seekable (dtp->u.p.current_unit->s))
|
|
||||||
{
|
|
||||||
/* Direct access files do not generate END conditions,
|
/* Direct access files do not generate END conditions,
|
||||||
only I/O errors. */
|
only I/O errors. */
|
||||||
if (sseek (dtp->u.p.current_unit->s,
|
if (sseek (dtp->u.p.current_unit->s,
|
||||||
dtp->u.p.current_unit->bytes_left_subrecord, SEEK_CUR) < 0)
|
dtp->u.p.current_unit->bytes_left_subrecord, SEEK_CUR) < 0)
|
||||||
generate_error (&dtp->common, LIBERROR_OS, NULL);
|
{
|
||||||
|
/* Seeking failed, fall back to seeking by reading data. */
|
||||||
dtp->u.p.current_unit->bytes_left_subrecord = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* Seek by reading data. */
|
|
||||||
while (dtp->u.p.current_unit->bytes_left_subrecord > 0)
|
while (dtp->u.p.current_unit->bytes_left_subrecord > 0)
|
||||||
{
|
{
|
||||||
rlength =
|
rlength =
|
||||||
|
@ -2850,8 +2844,9 @@ skip_record (st_parameter_dt *dtp, ssize_t bytes)
|
||||||
|
|
||||||
dtp->u.p.current_unit->bytes_left_subrecord -= readb;
|
dtp->u.p.current_unit->bytes_left_subrecord -= readb;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
dtp->u.p.current_unit->bytes_left_subrecord = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -714,23 +714,21 @@ update_position (gfc_unit *u)
|
||||||
/* If unit is not seekable, this makes no sense (and the standard is
|
/* If unit is not seekable, this makes no sense (and the standard is
|
||||||
silent on this matter), and thus we don't change the position for
|
silent on this matter), and thus we don't change the position for
|
||||||
a non-seekable file. */
|
a non-seekable file. */
|
||||||
if (is_seekable (u->s))
|
|
||||||
{
|
|
||||||
gfc_offset cur = stell (u->s);
|
gfc_offset cur = stell (u->s);
|
||||||
if (cur == 0)
|
if (cur == -1)
|
||||||
|
return;
|
||||||
|
else if (cur == 0)
|
||||||
u->flags.position = POSITION_REWIND;
|
u->flags.position = POSITION_REWIND;
|
||||||
else if (cur != -1 && (file_length (u->s) == cur))
|
else if (file_length (u->s) == cur)
|
||||||
u->flags.position = POSITION_APPEND;
|
u->flags.position = POSITION_APPEND;
|
||||||
else
|
else
|
||||||
u->flags.position = POSITION_ASIS;
|
u->flags.position = POSITION_ASIS;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* High level interface to truncate a file safely, i.e. flush format
|
/* High level interface to truncate a file, i.e. flush format buffers,
|
||||||
buffers, check that it's a regular file, and generate error if that
|
and generate an error or set some flags. Just like POSIX
|
||||||
occurs. Just like POSIX ftruncate, returns 0 on success, -1 on
|
ftruncate, returns 0 on success, -1 on failure. */
|
||||||
failure. */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
|
unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
|
||||||
|
@ -746,24 +744,12 @@ unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
|
||||||
fbuf_flush (u, u->mode);
|
fbuf_flush (u, u->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't try to truncate a special file, just pretend that it
|
|
||||||
succeeds. */
|
|
||||||
if (is_special (u->s) || !is_seekable (u->s))
|
|
||||||
{
|
|
||||||
sflush (u->s);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* struncate() should flush the stream buffer if necessary, so don't
|
/* struncate() should flush the stream buffer if necessary, so don't
|
||||||
bother calling sflush() here. */
|
bother calling sflush() here. */
|
||||||
ret = struncate (u->s, pos);
|
ret = struncate (u->s, pos);
|
||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
|
||||||
generate_error (common, LIBERROR_OS, NULL);
|
generate_error (common, LIBERROR_OS, NULL);
|
||||||
u->endfile = NO_ENDFILE;
|
|
||||||
u->flags.position = POSITION_ASIS;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u->endfile = AT_ENDFILE;
|
u->endfile = AT_ENDFILE;
|
||||||
|
|
|
@ -187,7 +187,7 @@ typedef struct
|
||||||
gfc_offset buffer_offset; /* File offset of the start of the buffer */
|
gfc_offset buffer_offset; /* File offset of the start of the buffer */
|
||||||
gfc_offset physical_offset; /* Current physical file offset */
|
gfc_offset physical_offset; /* Current physical file offset */
|
||||||
gfc_offset logical_offset; /* Current logical file offset */
|
gfc_offset logical_offset; /* Current logical file offset */
|
||||||
gfc_offset file_length; /* Length of the file, -1 if not seekable. */
|
gfc_offset file_length; /* Length of the file. */
|
||||||
|
|
||||||
char *buffer; /* Pointer to the buffer. */
|
char *buffer; /* Pointer to the buffer. */
|
||||||
int fd; /* The POSIX file descriptor. */
|
int fd; /* The POSIX file descriptor. */
|
||||||
|
@ -196,8 +196,6 @@ typedef struct
|
||||||
|
|
||||||
int ndirty; /* Dirty bytes starting at buffer_offset */
|
int ndirty; /* Dirty bytes starting at buffer_offset */
|
||||||
|
|
||||||
int special_file; /* =1 if the fd refers to a special file */
|
|
||||||
|
|
||||||
/* Cached stat(2) values. */
|
/* Cached stat(2) values. */
|
||||||
dev_t st_dev;
|
dev_t st_dev;
|
||||||
ino_t st_ino;
|
ino_t st_ino;
|
||||||
|
@ -413,7 +411,7 @@ raw_init (unix_stream * s)
|
||||||
Buffered I/O functions. These functions have the same semantics as the
|
Buffered I/O functions. These functions have the same semantics as the
|
||||||
raw I/O functions above, except that they are buffered in order to
|
raw I/O functions above, except that they are buffered in order to
|
||||||
improve performance. The buffer must be flushed when switching from
|
improve performance. The buffer must be flushed when switching from
|
||||||
reading to writing and vice versa.
|
reading to writing and vice versa. Only supported for regular files.
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -427,7 +425,7 @@ buf_flush (unix_stream * s)
|
||||||
if (s->ndirty == 0)
|
if (s->ndirty == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (s->file_length != -1 && s->physical_offset != s->buffer_offset
|
if (s->physical_offset != s->buffer_offset
|
||||||
&& lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
|
&& lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -435,8 +433,7 @@ buf_flush (unix_stream * s)
|
||||||
|
|
||||||
s->physical_offset = s->buffer_offset + writelen;
|
s->physical_offset = s->buffer_offset + writelen;
|
||||||
|
|
||||||
/* Don't increment file_length if the file is non-seekable. */
|
if (s->physical_offset > s->file_length)
|
||||||
if (s->file_length != -1 && s->physical_offset > s->file_length)
|
|
||||||
s->file_length = s->physical_offset;
|
s->file_length = s->physical_offset;
|
||||||
|
|
||||||
s->ndirty -= writelen;
|
s->ndirty -= writelen;
|
||||||
|
@ -481,7 +478,7 @@ buf_read (unix_stream * s, void * buf, ssize_t nbyte)
|
||||||
/* At this point we consider all bytes in the buffer discarded. */
|
/* At this point we consider all bytes in the buffer discarded. */
|
||||||
to_read = nbyte - nread;
|
to_read = nbyte - nread;
|
||||||
new_logical = s->logical_offset + nread;
|
new_logical = s->logical_offset + nread;
|
||||||
if (s->file_length != -1 && s->physical_offset != new_logical
|
if (s->physical_offset != new_logical
|
||||||
&& lseek (s->fd, new_logical, SEEK_SET) < 0)
|
&& lseek (s->fd, new_logical, SEEK_SET) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
s->buffer_offset = s->physical_offset = new_logical;
|
s->buffer_offset = s->physical_offset = new_logical;
|
||||||
|
@ -539,7 +536,7 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (s->file_length != -1 && s->physical_offset != s->logical_offset)
|
if (s->physical_offset != s->logical_offset)
|
||||||
{
|
{
|
||||||
if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
|
if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -551,8 +548,7 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->logical_offset += nbyte;
|
s->logical_offset += nbyte;
|
||||||
/* Don't increment file_length if the file is non-seekable. */
|
if (s->logical_offset > s->file_length)
|
||||||
if (s->file_length != -1 && s->logical_offset > s->file_length)
|
|
||||||
s->file_length = s->logical_offset;
|
s->file_length = s->logical_offset;
|
||||||
return nbyte;
|
return nbyte;
|
||||||
}
|
}
|
||||||
|
@ -560,11 +556,6 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
|
||||||
static gfc_offset
|
static gfc_offset
|
||||||
buf_seek (unix_stream * s, gfc_offset offset, int whence)
|
buf_seek (unix_stream * s, gfc_offset offset, int whence)
|
||||||
{
|
{
|
||||||
if (s->file_length == -1)
|
|
||||||
{
|
|
||||||
errno = ESPIPE;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
switch (whence)
|
switch (whence)
|
||||||
{
|
{
|
||||||
case SEEK_SET:
|
case SEEK_SET:
|
||||||
|
@ -953,30 +944,18 @@ fd_to_stream (int fd)
|
||||||
|
|
||||||
s->st_dev = statbuf.st_dev;
|
s->st_dev = statbuf.st_dev;
|
||||||
s->st_ino = statbuf.st_ino;
|
s->st_ino = statbuf.st_ino;
|
||||||
s->special_file = !S_ISREG (statbuf.st_mode);
|
|
||||||
|
|
||||||
if (S_ISREG (statbuf.st_mode))
|
|
||||||
s->file_length = statbuf.st_size;
|
s->file_length = statbuf.st_size;
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Some character special files are seekable but most are not,
|
|
||||||
so figure it out by trying to seek. On Linux, /dev/null is
|
|
||||||
an example of such a special file. */
|
|
||||||
s->file_length = lseek (fd, 0, SEEK_END);
|
|
||||||
if (s->file_length > 0)
|
|
||||||
lseek (fd, 0, SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
|
/* Only use buffered IO for regular files. */
|
||||||
|| options.all_unbuffered
|
if (S_ISREG (statbuf.st_mode)
|
||||||
||(options.unbuffered_preconnected &&
|
&& !options.all_unbuffered
|
||||||
|
&& !(options.unbuffered_preconnected &&
|
||||||
(s->fd == STDIN_FILENO
|
(s->fd == STDIN_FILENO
|
||||||
|| s->fd == STDOUT_FILENO
|
|| s->fd == STDOUT_FILENO
|
||||||
|| s->fd == STDERR_FILENO))
|
|| s->fd == STDERR_FILENO)))
|
||||||
|| isatty (s->fd))
|
|
||||||
raw_init (s);
|
|
||||||
else
|
|
||||||
buf_init (s);
|
buf_init (s);
|
||||||
|
else
|
||||||
|
raw_init (s);
|
||||||
|
|
||||||
return (stream *) s;
|
return (stream *) s;
|
||||||
}
|
}
|
||||||
|
@ -1767,8 +1746,6 @@ gfc_offset
|
||||||
file_length (stream * s)
|
file_length (stream * s)
|
||||||
{
|
{
|
||||||
gfc_offset curr, end;
|
gfc_offset curr, end;
|
||||||
if (!is_seekable (s))
|
|
||||||
return -1;
|
|
||||||
curr = stell (s);
|
curr = stell (s);
|
||||||
if (curr == -1)
|
if (curr == -1)
|
||||||
return curr;
|
return curr;
|
||||||
|
@ -1778,27 +1755,6 @@ file_length (stream * s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* is_seekable()-- Return nonzero if the stream is seekable, zero if
|
|
||||||
* it is not */
|
|
||||||
|
|
||||||
int
|
|
||||||
is_seekable (stream *s)
|
|
||||||
{
|
|
||||||
/* By convention, if file_length == -1, the file is not
|
|
||||||
seekable. */
|
|
||||||
return ((unix_stream *) s)->file_length!=-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* is_special()-- Return nonzero if the stream is not a regular file. */
|
|
||||||
|
|
||||||
int
|
|
||||||
is_special (stream *s)
|
|
||||||
{
|
|
||||||
return ((unix_stream *) s)->special_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
stream_isatty (stream *s)
|
stream_isatty (stream *s)
|
||||||
{
|
{
|
||||||
|
|
|
@ -158,12 +158,6 @@ internal_proto(inquire_readwrite);
|
||||||
extern gfc_offset file_length (stream *);
|
extern gfc_offset file_length (stream *);
|
||||||
internal_proto(file_length);
|
internal_proto(file_length);
|
||||||
|
|
||||||
extern int is_seekable (stream *);
|
|
||||||
internal_proto(is_seekable);
|
|
||||||
|
|
||||||
extern int is_special (stream *);
|
|
||||||
internal_proto(is_special);
|
|
||||||
|
|
||||||
extern void flush_if_preconnected (stream *);
|
extern void flush_if_preconnected (stream *);
|
||||||
internal_proto(flush_if_preconnected);
|
internal_proto(flush_if_preconnected);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue