-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Andy Vaught
This file is part of the GNU Fortran 95 runtime library (libgfortran).
unix_stream * str = (unix_stream*)st;
if (pos_off < 0)
{
- str->active += pos_off;
- if (str->active < 0)
- str->active = 0;
+ str->logical_offset += pos_off;
- str->logical_offset += pos_off;
-
- if (str->dirty_offset+str->ndirty > str->logical_offset)
+ if (str->dirty_offset + str->ndirty > str->logical_offset)
{
- if (str->ndirty + pos_off > 0)
- str->ndirty += pos_off ;
+ if (str->ndirty + pos_off > 0)
+ str->ndirty += pos_off;
else
{
str->dirty_offset += pos_off + pos_off;
- str->ndirty = 0 ;
+ str->ndirty = 0;
}
}
- return pos_off ;
+ return pos_off;
}
- return 0 ;
+ return 0;
}
* to come next. */
static void
-fd_alloc (unix_stream * s, gfc_offset where, int *len)
+fd_alloc (unix_stream * s, gfc_offset where,
+ int *len __attribute__ ((unused)))
{
char *new_buffer;
int n, read_len;
/* non-seekable files, like terminals and fifo's fail the lseek.
the fd is a regular file at this point */
+#ifdef HAVE_FTRUNCATE
if (ftruncate (s->fd, s->logical_offset))
- return FAILURE;
+#else
+#ifdef HAVE_CHSIZE
+ if (chsize (s->fd, s->logical_offset))
+#endif
+#endif
+ {
+ s->physical_offset = s->file_length = 0;
+ return FAILURE;
+ }
s->physical_offset = s->file_length = s->logical_offset;
if (s->buffer != NULL && s->buffer != s->small_buffer)
free_mem (s->buffer);
- if (close (s->fd) < 0)
- return FAILURE;
+ if (s->fd != STDOUT_FILENO && s->fd != STDERR_FILENO)
+ {
+ if (close (s->fd) < 0)
+ return FAILURE;
+ }
free_mem (s);
* guaranteed to be mappable. */
static try
-mmap_alloc (unix_stream * s, gfc_offset where, int *len)
+mmap_alloc (unix_stream * s, gfc_offset where,
+ int *len __attribute__ ((unused)))
{
gfc_offset offset;
int length;
static try
-mmap_sfree (unix_stream * s)
+mmap_sfree (unix_stream * s __attribute__ ((unused)))
{
return SUCCESS;
}
* mmap()-ed, we fall back to the file descriptor functions. */
static try
-mmap_open (unix_stream * s)
+mmap_open (unix_stream * s __attribute__ ((unused)))
{
char *p;
int i;
static int
-mem_truncate (unix_stream * s)
+mem_truncate (unix_stream * s __attribute__ ((unused)))
{
return SUCCESS;
}
static try
-mem_sfree (unix_stream * s)
+mem_sfree (unix_stream * s __attribute__ ((unused)))
{
return SUCCESS;
}
unix_stream *s;
s = get_mem (sizeof (unix_stream));
+ memset (s, '\0', sizeof (unix_stream));
s->buffer = base;
s->buffer_offset = 0;
* around it. */
static stream *
-fd_to_stream (int fd, int prot)
+fd_to_stream (int fd, int prot, int avoid_mmap)
{
struct stat statbuf;
unix_stream *s;
s = get_mem (sizeof (unix_stream));
+ memset (s, '\0', sizeof (unix_stream));
s->fd = fd;
s->buffer_offset = 0;
s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
#if HAVE_MMAP
- mmap_open (s);
+ if (avoid_mmap)
+ fd_open (s);
+ else
+ mmap_open (s);
#else
fd_open (s);
#endif
/* regular_file()-- Open a regular file.
- * Change flags->action if it is ACTION_UNSPECIFIED on entry.
+ * Change flags->action if it is ACTION_UNSPECIFIED on entry,
+ * unless an error occurs.
* Returns the descriptor, which is less than zero on error. */
static int
regular_file (unit_flags *flags)
{
char path[PATH_MAX + 1];
- struct stat statbuf;
int mode;
int rwflag;
+ int crflag;
int fd;
if (unpack_filename (path, ioparm.file, ioparm.file_len))
switch (flags->status)
{
case STATUS_NEW:
- rwflag |= O_CREAT | O_EXCL;
+ crflag = O_CREAT | O_EXCL;
break;
- case STATUS_OLD: /* file must exist, so check for its existence */
- if (stat (path, &statbuf) < 0)
- return -1;
+ case STATUS_OLD: /* open will fail if the file does not exist*/
+ crflag = 0;
break;
case STATUS_UNKNOWN:
case STATUS_SCRATCH:
- rwflag |= O_CREAT;
+ crflag = O_CREAT;
break;
case STATUS_REPLACE:
- rwflag |= O_CREAT | O_TRUNC;
+ crflag = O_CREAT | O_TRUNC;
break;
default:
/* rwflag |= O_LARGEFILE; */
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
- fd = open (path, rwflag, mode);
- if (flags->action == ACTION_UNSPECIFIED)
+ fd = open (path, rwflag | crflag, mode);
+ if (flags->action != ACTION_UNSPECIFIED)
+ return fd;
+
+ if (fd >= 0)
{
- if (fd < 0)
- {
- rwflag = rwflag & !O_RDWR | O_RDONLY;
- fd = open (path, rwflag, mode);
- if (fd < 0)
- {
- rwflag = rwflag & !O_RDONLY | O_WRONLY;
- fd = open (path, rwflag, mode);
- if (fd < 0)
- flags->action = ACTION_READWRITE; /* Could not open at all. */
- else
- flags->action = ACTION_WRITE;
- }
- else
- flags->action = ACTION_READ;
- }
- else
- flags->action = ACTION_READWRITE;
+ flags->action = ACTION_READWRITE;
+ return fd;
}
- return fd;
+ if (errno != EACCES)
+ return fd;
+
+ /* retry for read-only access */
+ rwflag = O_RDONLY;
+ fd = open (path, rwflag | crflag, mode);
+ if (fd >=0)
+ {
+ flags->action = ACTION_READ;
+ return fd; /* success */
+ }
+
+ if (errno != EACCES)
+ return fd; /* failure */
+
+ /* retry for write-only access */
+ rwflag = O_WRONLY;
+ fd = open (path, rwflag | crflag, mode);
+ if (fd >=0)
+ {
+ flags->action = ACTION_WRITE;
+ return fd; /* success */
+ }
+ return fd; /* failure */
}
}
else
{
- /* regular_file resets flags->action if it is ACTION_UNSPECIFIED. */
+ /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
+ * if it succeeds */
fd = regular_file (flags);
}
internal_error ("open_external(): Bad action");
}
- return fd_to_stream (fd, prot);
+ return fd_to_stream (fd, prot, 0);
}
stream *
input_stream (void)
{
- return fd_to_stream (STDIN_FILENO, PROT_READ);
+ return fd_to_stream (STDIN_FILENO, PROT_READ, 1);
}
-/* output_stream()-- Return a stream pointer to the default input stream.
+/* output_stream()-- Return a stream pointer to the default output stream.
* Called on initialization. */
stream *
output_stream (void)
{
- return fd_to_stream (STDOUT_FILENO, PROT_WRITE);
+ return fd_to_stream (STDOUT_FILENO, PROT_WRITE, 1);
}
+/* error_stream()-- Return a stream pointer to the default error stream.
+ * Called on initialization. */
+
+stream *
+error_stream (void)
+{
+ return fd_to_stream (STDERR_FILENO, PROT_WRITE, 1);
+}
+
/* init_error_stream()-- Return a pointer to the error stream. This
* subroutine is called when the stream is needed, rather than at
* initialization. We want to work even if memory has been seriously
{
unix_stream *us;
- us = (unix_stream *) s;
+ if (!is_seekable (s))
+ return 0;
- if (!us->mmaped)
- return 0; /* File is not seekable */
+ us = (unix_stream *) s;
return us->logical_offset == 0;
}
{
unix_stream *us;
- us = (unix_stream *) s;
+ if (!is_seekable (s))
+ return 0;
- if (!us->mmaped)
- return 0; /* File is not seekable */
+ us = (unix_stream *) s;
return us->logical_offset == us->dirty_offset;
}