1 /* Copyright (C) 2002, 2003, 2004, 2005
2 Free Software Foundation, Inc.
3 Contributed by Andy Vaught
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
21 Libgfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with Libgfortran; see the file COPYING. If not, write to
28 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA. */
31 /* Unix stream I/O module */
43 #ifdef HAVE_SYS_MMAN_H
49 #include "libgfortran.h"
57 #define MAP_FAILED ((void *) -1)
68 /* These flags aren't defined on all targets (mingw32), so provide them
86 /* This implementation of stream I/O is based on the paper:
88 * "Exploiting the advantages of mapped files for stream I/O",
89 * O. Krieger, M. Stumm and R. Umrau, "Proceedings of the 1992 Winter
90 * USENIX conference", p. 27-42.
92 * It differs in a number of ways from the version described in the
93 * paper. First of all, threads are not an issue during I/O and we
94 * also don't have to worry about having multiple regions, since
95 * fortran's I/O model only allows you to be one place at a time.
97 * On the other hand, we have to be able to writing at the end of a
98 * stream, read from the start of a stream or read and write blocks of
99 * bytes from an arbitrary position. After opening a file, a pointer
100 * to a stream structure is returned, which is used to handle file
101 * accesses until the file is closed.
103 * salloc_at_r(stream, len, where)-- Given a stream pointer, return a
104 * pointer to a block of memory that mirror the file at position
105 * 'where' that is 'len' bytes long. The len integer is updated to
106 * reflect how many bytes were actually read. The only reason for a
107 * short read is end of file. The file pointer is updated. The
108 * pointer is valid until the next call to salloc_*.
110 * salloc_at_w(stream, len, where)-- Given the stream pointer, returns
111 * a pointer to a block of memory that is updated to reflect the state
112 * of the file. The length of the buffer is always equal to that
113 * requested. The buffer must be completely set by the caller. When
114 * data has been written, the sfree() function must be called to
115 * indicate that the caller is done writing data to the buffer. This
116 * may or may not cause a physical write.
118 * Short forms of these are salloc_r() and salloc_w() which drop the
119 * 'where' parameter and use the current file pointer. */
122 #define BUFFER_SIZE 8192
129 gfc_offset buffer_offset; /* File offset of the start of the buffer */
130 gfc_offset physical_offset; /* Current physical file offset */
131 gfc_offset logical_offset; /* Current logical file offset */
132 gfc_offset dirty_offset; /* Start of modified bytes in buffer */
133 gfc_offset file_length; /* Length of the file, -1 if not seekable. */
136 int len; /* Physical length of the current buffer */
137 int active; /* Length of valid bytes in the buffer */
140 int ndirty; /* Dirty bytes starting at dirty_offset */
142 int special_file; /* =1 if the fd refers to a special file */
144 unsigned unbuffered:1;
146 char small_buffer[BUFFER_SIZE];
151 /*move_pos_offset()-- Move the record pointer right or left
152 *relative to current position */
155 move_pos_offset (stream* st, int pos_off)
157 unix_stream * str = (unix_stream*)st;
160 str->logical_offset += pos_off;
162 if (str->dirty_offset + str->ndirty > str->logical_offset)
164 if (str->ndirty + pos_off > 0)
165 str->ndirty += pos_off;
168 str->dirty_offset += pos_off + pos_off;
179 /* fix_fd()-- Given a file descriptor, make sure it is not one of the
180 * standard descriptors, returning a non-standard descriptor. If the
181 * user specifies that system errors should go to standard output,
182 * then closes standard output, we don't want the system errors to a
183 * file that has been given file descriptor 1 or 0. We want to send
184 * the error to the invalid descriptor. */
189 int input, output, error;
191 input = output = error = 0;
193 /* Unix allocates the lowest descriptors first, so a loop is not
194 required, but this order is. */
196 if (fd == STDIN_FILENO)
201 if (fd == STDOUT_FILENO)
206 if (fd == STDERR_FILENO)
213 close (STDIN_FILENO);
215 close (STDOUT_FILENO);
217 close (STDERR_FILENO);
223 is_preconnected (stream * s)
227 fd = ((unix_stream *) s)->fd;
228 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
234 /* write()-- Write a buffer to a descriptor, allowing for short writes */
237 writen (int fd, char *buffer, int len)
245 n = write (fd, buffer, len);
258 /* readn()-- Read bytes into a buffer, allowing for short reads. If
259 * fewer than len bytes are returned, it is because we've hit the end
263 readn (int fd, char *buffer, int len)
271 n = read (fd, buffer, len);
288 /* get_oserror()-- Get the most recent operating system error. For
289 * unix, this is errno. */
294 return strerror (errno);
298 /* sys_exit()-- Terminate the program with an exit code */
307 /*********************************************************************
308 File descriptor stream functions
309 *********************************************************************/
311 /* fd_flush()-- Write bytes that need to be written */
314 fd_flush (unix_stream * s)
319 if (s->physical_offset != s->dirty_offset &&
320 lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
323 if (writen (s->fd, s->buffer + (s->dirty_offset - s->buffer_offset),
327 s->physical_offset = s->dirty_offset + s->ndirty;
329 /* don't increment file_length if the file is non-seekable */
330 if (s->file_length != -1 && s->physical_offset > s->file_length)
331 s->file_length = s->physical_offset;
338 /* fd_alloc()-- Arrange a buffer such that the salloc() request can be
339 * satisfied. This subroutine gets the buffer ready for whatever is
343 fd_alloc (unix_stream * s, gfc_offset where,
344 int *len __attribute__ ((unused)))
349 if (*len <= BUFFER_SIZE)
351 new_buffer = s->small_buffer;
352 read_len = BUFFER_SIZE;
356 new_buffer = get_mem (*len);
360 /* Salvage bytes currently within the buffer. This is important for
361 * devices that cannot seek. */
363 if (s->buffer != NULL && s->buffer_offset <= where &&
364 where <= s->buffer_offset + s->active)
367 n = s->active - (where - s->buffer_offset);
368 memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
373 { /* new buffer starts off empty */
377 s->buffer_offset = where;
379 /* free the old buffer if necessary */
381 if (s->buffer != NULL && s->buffer != s->small_buffer)
382 free_mem (s->buffer);
384 s->buffer = new_buffer;
389 /* fd_alloc_r_at()-- Allocate a stream buffer for reading. Either
390 * we've already buffered the data or we need to load it. Returns
391 * NULL on I/O error. */
394 fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
400 where = s->logical_offset;
402 if (s->buffer != NULL && s->buffer_offset <= where &&
403 where + *len <= s->buffer_offset + s->active)
406 /* Return a position within the current buffer */
408 s->logical_offset = where + *len;
409 return s->buffer + where - s->buffer_offset;
412 fd_alloc (s, where, len);
414 m = where + s->active;
416 if (s->physical_offset != m && lseek (s->fd, m, SEEK_SET) < 0)
419 n = read (s->fd, s->buffer + s->active, s->len - s->active);
423 s->physical_offset = where + n;
426 if (s->active < *len)
427 *len = s->active; /* Bytes actually available */
429 s->logical_offset = where + *len;
435 /* fd_alloc_w_at()-- Allocate a stream buffer for writing. Either
436 * we've already buffered the data or we need to load it. */
439 fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
444 where = s->logical_offset;
446 if (s->buffer == NULL || s->buffer_offset > where ||
447 where + *len > s->buffer_offset + s->len)
450 if (fd_flush (s) == FAILURE)
452 fd_alloc (s, where, len);
455 /* Return a position within the current buffer */
457 || where > s->dirty_offset + s->ndirty
458 || s->dirty_offset > where + *len)
459 { /* Discontiguous blocks, start with a clean buffer. */
460 /* Flush the buffer. */
463 s->dirty_offset = where;
468 gfc_offset start; /* Merge with the existing data. */
469 if (where < s->dirty_offset)
472 start = s->dirty_offset;
473 if (where + *len > s->dirty_offset + s->ndirty)
474 s->ndirty = where + *len - start;
476 s->ndirty = s->dirty_offset + s->ndirty - start;
477 s->dirty_offset = start;
480 s->logical_offset = where + *len;
482 if (where + *len > s->file_length)
483 s->file_length = where + *len;
485 n = s->logical_offset - s->buffer_offset;
489 return s->buffer + where - s->buffer_offset;
494 fd_sfree (unix_stream * s)
496 if (s->ndirty != 0 &&
497 (s->buffer != s->small_buffer || options.all_unbuffered ||
506 fd_seek (unix_stream * s, gfc_offset offset)
508 s->physical_offset = s->logical_offset = offset;
510 return (lseek (s->fd, offset, SEEK_SET) < 0) ? FAILURE : SUCCESS;
514 /* truncate_file()-- Given a unit, truncate the file at the current
515 * position. Sets the physical location to the new end of the file.
516 * Returns nonzero on error. */
519 fd_truncate (unix_stream * s)
521 if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
524 /* non-seekable files, like terminals and fifo's fail the lseek.
525 Using ftruncate on a seekable special file (like /dev/null)
526 is undefined, so we treat it as if the ftruncate failed.
528 #ifdef HAVE_FTRUNCATE
529 if (s->special_file || ftruncate (s->fd, s->logical_offset))
532 if (s->special_file || chsize (s->fd, s->logical_offset))
536 s->physical_offset = s->file_length = 0;
540 s->physical_offset = s->file_length = s->logical_offset;
547 fd_close (unix_stream * s)
549 if (fd_flush (s) == FAILURE)
552 if (s->buffer != NULL && s->buffer != s->small_buffer)
553 free_mem (s->buffer);
555 if (s->fd != STDOUT_FILENO && s->fd != STDERR_FILENO)
557 if (close (s->fd) < 0)
568 fd_open (unix_stream * s)
573 s->st.alloc_r_at = (void *) fd_alloc_r_at;
574 s->st.alloc_w_at = (void *) fd_alloc_w_at;
575 s->st.sfree = (void *) fd_sfree;
576 s->st.close = (void *) fd_close;
577 s->st.seek = (void *) fd_seek;
578 s->st.truncate = (void *) fd_truncate;
585 /*********************************************************************
586 memory stream functions - These are used for internal files
588 The idea here is that a single stream structure is created and all
589 requests must be satisfied from it. The location and size of the
590 buffer is the character variable supplied to the READ or WRITE
593 *********************************************************************/
597 mem_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
602 where = s->logical_offset;
604 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
607 s->logical_offset = where + *len;
609 n = s->buffer_offset + s->active - where;
613 return s->buffer + (where - s->buffer_offset);
618 mem_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
622 assert (*len >= 0); /* Negative values not allowed. */
625 where = s->logical_offset;
629 if (where < s->buffer_offset)
632 if (m > s->file_length)
634 generate_error (ERROR_END, NULL);
638 s->logical_offset = m;
640 return s->buffer + (where - s->buffer_offset);
645 mem_seek (unix_stream * s, gfc_offset offset)
647 if (offset > s->file_length)
653 s->logical_offset = offset;
659 mem_truncate (unix_stream * s __attribute__ ((unused)))
666 mem_close (unix_stream * s)
675 mem_sfree (unix_stream * s __attribute__ ((unused)))
682 /*********************************************************************
683 Public functions -- A reimplementation of this module needs to
684 define functional equivalents of the following.
685 *********************************************************************/
687 /* empty_internal_buffer()-- Zero the buffer of Internal file */
690 empty_internal_buffer(stream *strm)
692 unix_stream * s = (unix_stream *) strm;
693 memset(s->buffer, ' ', s->file_length);
696 /* open_internal()-- Returns a stream structure from an internal file */
699 open_internal (char *base, int length)
703 s = get_mem (sizeof (unix_stream));
704 memset (s, '\0', sizeof (unix_stream));
707 s->buffer_offset = 0;
709 s->logical_offset = 0;
710 s->active = s->file_length = length;
712 s->st.alloc_r_at = (void *) mem_alloc_r_at;
713 s->st.alloc_w_at = (void *) mem_alloc_w_at;
714 s->st.sfree = (void *) mem_sfree;
715 s->st.close = (void *) mem_close;
716 s->st.seek = (void *) mem_seek;
717 s->st.truncate = (void *) mem_truncate;
723 /* fd_to_stream()-- Given an open file descriptor, build a stream
727 fd_to_stream (int fd, int prot)
732 s = get_mem (sizeof (unix_stream));
733 memset (s, '\0', sizeof (unix_stream));
736 s->buffer_offset = 0;
737 s->physical_offset = 0;
738 s->logical_offset = 0;
741 /* Get the current length of the file. */
743 fstat (fd, &statbuf);
744 s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
745 s->special_file = !S_ISREG (statbuf.st_mode);
753 /* Given the Fortran unit number, convert it to a C file descriptor. */
760 us = find_unit(unit);
764 return ((unix_stream *) us->s)->fd;
768 /* unpack_filename()-- Given a fortran string and a pointer to a
769 * buffer that is PATH_MAX characters, convert the fortran string to a
770 * C string in the buffer. Returns nonzero if this is not possible. */
773 unpack_filename (char *cstring, const char *fstring, int len)
775 len = fstrlen (fstring, len);
779 memmove (cstring, fstring, len);
786 /* tempfile()-- Generate a temporary filename for a scratch file and
787 * open it. mkstemp() opens the file for reading and writing, but the
788 * library mode prevents anything that is not allowed. The descriptor
789 * is returned, which is -1 on error. The template is pointed to by
790 * ioparm.file, which is copied into the unit structure
791 * and freed later. */
800 tempdir = getenv ("GFORTRAN_TMPDIR");
802 tempdir = getenv ("TMP");
804 tempdir = getenv ("TEMP");
806 tempdir = DEFAULT_TEMPDIR;
808 template = get_mem (strlen (tempdir) + 20);
810 st_sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
814 fd = mkstemp (template);
816 #else /* HAVE_MKSTEMP */
818 if (mktemp (template))
821 fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
824 fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
826 while (!(fd == -1 && errno == EEXIST) && mktemp (template));
830 #endif /* HAVE_MKSTEMP */
836 ioparm.file = template;
837 ioparm.file_len = strlen (template); /* Don't include trailing nul */
844 /* regular_file()-- Open a regular file.
845 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
846 * unless an error occurs.
847 * Returns the descriptor, which is less than zero on error. */
850 regular_file (unit_flags *flags)
852 char path[PATH_MAX + 1];
858 if (unpack_filename (path, ioparm.file, ioparm.file_len))
860 errno = ENOENT; /* Fake an OS error */
866 switch (flags->action)
876 case ACTION_READWRITE:
877 case ACTION_UNSPECIFIED:
882 internal_error ("regular_file(): Bad action");
885 switch (flags->status)
888 crflag = O_CREAT | O_EXCL;
891 case STATUS_OLD: /* open will fail if the file does not exist*/
901 crflag = O_CREAT | O_TRUNC;
905 internal_error ("regular_file(): Bad status");
908 /* rwflag |= O_LARGEFILE; */
914 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
915 fd = open (path, rwflag | crflag, mode);
916 if (flags->action != ACTION_UNSPECIFIED)
921 flags->action = ACTION_READWRITE;
927 /* retry for read-only access */
929 fd = open (path, rwflag | crflag, mode);
932 flags->action = ACTION_READ;
933 return fd; /* success */
937 return fd; /* failure */
939 /* retry for write-only access */
941 fd = open (path, rwflag | crflag, mode);
944 flags->action = ACTION_WRITE;
945 return fd; /* success */
947 return fd; /* failure */
951 /* open_external()-- Open an external file, unix specific version.
952 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
953 * Returns NULL on operating system error. */
956 open_external (unit_flags *flags)
960 if (flags->status == STATUS_SCRATCH)
963 if (flags->action == ACTION_UNSPECIFIED)
964 flags->action = ACTION_READWRITE;
966 #if HAVE_UNLINK_OPEN_FILE
967 /* We can unlink scratch files now and it will go away when closed. */
968 unlink (ioparm.file);
973 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
975 fd = regular_file (flags);
982 switch (flags->action)
992 case ACTION_READWRITE:
993 prot = PROT_READ | PROT_WRITE;
997 internal_error ("open_external(): Bad action");
1000 return fd_to_stream (fd, prot);
1004 /* input_stream()-- Return a stream pointer to the default input stream.
1005 * Called on initialization. */
1010 return fd_to_stream (STDIN_FILENO, PROT_READ);
1014 /* output_stream()-- Return a stream pointer to the default output stream.
1015 * Called on initialization. */
1018 output_stream (void)
1020 return fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1024 /* error_stream()-- Return a stream pointer to the default error stream.
1025 * Called on initialization. */
1030 return fd_to_stream (STDERR_FILENO, PROT_WRITE);
1033 /* init_error_stream()-- Return a pointer to the error stream. This
1034 * subroutine is called when the stream is needed, rather than at
1035 * initialization. We want to work even if memory has been seriously
1039 init_error_stream (void)
1041 static unix_stream error;
1043 memset (&error, '\0', sizeof (error));
1045 error.fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1047 error.st.alloc_w_at = (void *) fd_alloc_w_at;
1048 error.st.sfree = (void *) fd_sfree;
1050 error.unbuffered = 1;
1051 error.buffer = error.small_buffer;
1053 return (stream *) & error;
1057 /* compare_file_filename()-- Given an open stream and a fortran string
1058 * that is a filename, figure out if the file is the same as the
1062 compare_file_filename (stream * s, const char *name, int len)
1064 char path[PATH_MAX + 1];
1065 struct stat st1, st2;
1067 if (unpack_filename (path, name, len))
1068 return 0; /* Can't be the same */
1070 /* If the filename doesn't exist, then there is no match with the
1073 if (stat (path, &st1) < 0)
1076 fstat (((unix_stream *) s)->fd, &st2);
1078 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
1082 /* find_file0()-- Recursive work function for find_file() */
1085 find_file0 (gfc_unit * u, struct stat *st1)
1093 if (fstat (((unix_stream *) u->s)->fd, &st2) >= 0 &&
1094 st1->st_dev == st2.st_dev && st1->st_ino == st2.st_ino)
1097 v = find_file0 (u->left, st1);
1101 v = find_file0 (u->right, st1);
1109 /* find_file()-- Take the current filename and see if there is a unit
1110 * that has the file already open. Returns a pointer to the unit if so. */
1115 char path[PATH_MAX + 1];
1116 struct stat statbuf;
1118 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1121 if (stat (path, &statbuf) < 0)
1124 return find_file0 (g.unit_root, &statbuf);
1128 /* stream_at_bof()-- Returns nonzero if the stream is at the beginning
1132 stream_at_bof (stream * s)
1136 if (!is_seekable (s))
1139 us = (unix_stream *) s;
1141 return us->logical_offset == 0;
1145 /* stream_at_eof()-- Returns nonzero if the stream is at the beginning
1149 stream_at_eof (stream * s)
1153 if (!is_seekable (s))
1156 us = (unix_stream *) s;
1158 return us->logical_offset == us->dirty_offset;
1162 /* delete_file()-- Given a unit structure, delete the file associated
1163 * with the unit. Returns nonzero if something went wrong. */
1166 delete_file (gfc_unit * u)
1168 char path[PATH_MAX + 1];
1170 if (unpack_filename (path, u->file, u->file_len))
1171 { /* Shouldn't be possible */
1176 return unlink (path);
1180 /* file_exists()-- Returns nonzero if the current filename exists on
1186 char path[PATH_MAX + 1];
1187 struct stat statbuf;
1189 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1192 if (stat (path, &statbuf) < 0)
1200 static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
1202 /* inquire_sequential()-- Given a fortran string, determine if the
1203 * file is suitable for sequential access. Returns a C-style
1207 inquire_sequential (const char *string, int len)
1209 char path[PATH_MAX + 1];
1210 struct stat statbuf;
1212 if (string == NULL ||
1213 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1216 if (S_ISREG (statbuf.st_mode) ||
1217 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1220 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1227 /* inquire_direct()-- Given a fortran string, determine if the file is
1228 * suitable for direct access. Returns a C-style string. */
1231 inquire_direct (const char *string, int len)
1233 char path[PATH_MAX + 1];
1234 struct stat statbuf;
1236 if (string == NULL ||
1237 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1240 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1243 if (S_ISDIR (statbuf.st_mode) ||
1244 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1251 /* inquire_formatted()-- Given a fortran string, determine if the file
1252 * is suitable for formatted form. Returns a C-style string. */
1255 inquire_formatted (const char *string, int len)
1257 char path[PATH_MAX + 1];
1258 struct stat statbuf;
1260 if (string == NULL ||
1261 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1264 if (S_ISREG (statbuf.st_mode) ||
1265 S_ISBLK (statbuf.st_mode) ||
1266 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1269 if (S_ISDIR (statbuf.st_mode))
1276 /* inquire_unformatted()-- Given a fortran string, determine if the file
1277 * is suitable for unformatted form. Returns a C-style string. */
1280 inquire_unformatted (const char *string, int len)
1282 return inquire_formatted (string, len);
1286 /* inquire_access()-- Given a fortran string, determine if the file is
1287 * suitable for access. */
1290 inquire_access (const char *string, int len, int mode)
1292 char path[PATH_MAX + 1];
1294 if (string == NULL || unpack_filename (path, string, len) ||
1295 access (path, mode) < 0)
1302 /* inquire_read()-- Given a fortran string, determine if the file is
1303 * suitable for READ access. */
1306 inquire_read (const char *string, int len)
1308 return inquire_access (string, len, R_OK);
1312 /* inquire_write()-- Given a fortran string, determine if the file is
1313 * suitable for READ access. */
1316 inquire_write (const char *string, int len)
1318 return inquire_access (string, len, W_OK);
1322 /* inquire_readwrite()-- Given a fortran string, determine if the file is
1323 * suitable for read and write access. */
1326 inquire_readwrite (const char *string, int len)
1328 return inquire_access (string, len, R_OK | W_OK);
1332 /* file_length()-- Return the file length in bytes, -1 if unknown */
1335 file_length (stream * s)
1337 return ((unix_stream *) s)->file_length;
1341 /* file_position()-- Return the current position of the file */
1344 file_position (stream * s)
1346 return ((unix_stream *) s)->logical_offset;
1350 /* is_seekable()-- Return nonzero if the stream is seekable, zero if
1354 is_seekable (stream * s)
1356 /* by convention, if file_length == -1, the file is not seekable
1357 note that a mmapped file is always seekable, an fd_ file may
1359 return ((unix_stream *) s)->file_length!=-1;
1365 return fd_flush( (unix_stream *) s);
1369 stream_isatty (stream *s)
1371 return isatty (((unix_stream *) s)->fd);
1375 stream_ttyname (stream *s)
1378 return ttyname (((unix_stream *) s)->fd);
1385 /* How files are stored: This is an operating-system specific issue,
1386 and therefore belongs here. There are three cases to consider.
1389 Records are written as block of bytes corresponding to the record
1390 length of the file. This goes for both formatted and unformatted
1391 records. Positioning is done explicitly for each data transfer,
1392 so positioning is not much of an issue.
1394 Sequential Formatted:
1395 Records are separated by newline characters. The newline character
1396 is prohibited from appearing in a string. If it does, this will be
1397 messed up on the next read. End of file is also the end of a record.
1399 Sequential Unformatted:
1400 In this case, we are merely copying bytes to and from main storage,
1401 yet we need to keep track of varying record lengths. We adopt
1402 the solution used by f2c. Each record contains a pair of length
1405 Length of record n in bytes
1407 Length of record n in bytes
1409 Length of record n+1 in bytes
1411 Length of record n+1 in bytes
1413 The length is stored at the end of a record to allow backspacing to the
1414 previous record. Between data transfer statements, the file pointer
1415 is left pointing to the first length of the current record.
1417 ENDFILE records are never explicitly stored.