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 */
42 #ifdef HAVE_SYS_MMAN_H
48 #include "libgfortran.h"
56 #define MAP_FAILED ((void *) -1)
67 /* These flags aren't defined on all targets (mingw32), so provide them
85 /* This implementation of stream I/O is based on the paper:
87 * "Exploiting the advantages of mapped files for stream I/O",
88 * O. Krieger, M. Stumm and R. Umrau, "Proceedings of the 1992 Winter
89 * USENIX conference", p. 27-42.
91 * It differs in a number of ways from the version described in the
92 * paper. First of all, threads are not an issue during I/O and we
93 * also don't have to worry about having multiple regions, since
94 * fortran's I/O model only allows you to be one place at a time.
96 * On the other hand, we have to be able to writing at the end of a
97 * stream, read from the start of a stream or read and write blocks of
98 * bytes from an arbitrary position. After opening a file, a pointer
99 * to a stream structure is returned, which is used to handle file
100 * accesses until the file is closed.
102 * salloc_at_r(stream, len, where)-- Given a stream pointer, return a
103 * pointer to a block of memory that mirror the file at position
104 * 'where' that is 'len' bytes long. The len integer is updated to
105 * reflect how many bytes were actually read. The only reason for a
106 * short read is end of file. The file pointer is updated. The
107 * pointer is valid until the next call to salloc_*.
109 * salloc_at_w(stream, len, where)-- Given the stream pointer, returns
110 * a pointer to a block of memory that is updated to reflect the state
111 * of the file. The length of the buffer is always equal to that
112 * requested. The buffer must be completely set by the caller. When
113 * data has been written, the sfree() function must be called to
114 * indicate that the caller is done writing data to the buffer. This
115 * may or may not cause a physical write.
117 * Short forms of these are salloc_r() and salloc_w() which drop the
118 * 'where' parameter and use the current file pointer. */
121 #define BUFFER_SIZE 8192
128 gfc_offset buffer_offset; /* File offset of the start of the buffer */
129 gfc_offset physical_offset; /* Current physical file offset */
130 gfc_offset logical_offset; /* Current logical file offset */
131 gfc_offset dirty_offset; /* Start of modified bytes in buffer */
132 gfc_offset file_length; /* Length of the file, -1 if not seekable. */
135 int len; /* Physical length of the current buffer */
136 int active; /* Length of valid bytes in the buffer */
139 int ndirty; /* Dirty bytes starting at dirty_offset */
141 int special_file; /* =1 if the fd refers to a special file */
143 unsigned unbuffered:1;
145 char small_buffer[BUFFER_SIZE];
150 /*move_pos_offset()-- Move the record pointer right or left
151 *relative to current position */
154 move_pos_offset (stream* st, int pos_off)
156 unix_stream * str = (unix_stream*)st;
159 str->logical_offset += pos_off;
161 if (str->dirty_offset + str->ndirty > str->logical_offset)
163 if (str->ndirty + pos_off > 0)
164 str->ndirty += pos_off;
167 str->dirty_offset += pos_off + pos_off;
178 /* fix_fd()-- Given a file descriptor, make sure it is not one of the
179 * standard descriptors, returning a non-standard descriptor. If the
180 * user specifies that system errors should go to standard output,
181 * then closes standard output, we don't want the system errors to a
182 * file that has been given file descriptor 1 or 0. We want to send
183 * the error to the invalid descriptor. */
188 int input, output, error;
190 input = output = error = 0;
192 /* Unix allocates the lowest descriptors first, so a loop is not
193 required, but this order is. */
195 if (fd == STDIN_FILENO)
200 if (fd == STDOUT_FILENO)
205 if (fd == STDERR_FILENO)
212 close (STDIN_FILENO);
214 close (STDOUT_FILENO);
216 close (STDERR_FILENO);
222 is_preconnected (stream * s)
226 fd = ((unix_stream *) s)->fd;
227 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
233 /* write()-- Write a buffer to a descriptor, allowing for short writes */
236 writen (int fd, char *buffer, int len)
244 n = write (fd, buffer, len);
257 /* readn()-- Read bytes into a buffer, allowing for short reads. If
258 * fewer than len bytes are returned, it is because we've hit the end
262 readn (int fd, char *buffer, int len)
270 n = read (fd, buffer, len);
287 /* get_oserror()-- Get the most recent operating system error. For
288 * unix, this is errno. */
293 return strerror (errno);
297 /* sys_exit()-- Terminate the program with an exit code */
306 /*********************************************************************
307 File descriptor stream functions
308 *********************************************************************/
310 /* fd_flush()-- Write bytes that need to be written */
313 fd_flush (unix_stream * s)
318 if (s->physical_offset != s->dirty_offset &&
319 lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
322 if (writen (s->fd, s->buffer + (s->dirty_offset - s->buffer_offset),
326 s->physical_offset = s->dirty_offset + s->ndirty;
328 /* don't increment file_length if the file is non-seekable */
329 if (s->file_length != -1 && s->physical_offset > s->file_length)
330 s->file_length = s->physical_offset;
337 /* fd_alloc()-- Arrange a buffer such that the salloc() request can be
338 * satisfied. This subroutine gets the buffer ready for whatever is
342 fd_alloc (unix_stream * s, gfc_offset where,
343 int *len __attribute__ ((unused)))
348 if (*len <= BUFFER_SIZE)
350 new_buffer = s->small_buffer;
351 read_len = BUFFER_SIZE;
355 new_buffer = get_mem (*len);
359 /* Salvage bytes currently within the buffer. This is important for
360 * devices that cannot seek. */
362 if (s->buffer != NULL && s->buffer_offset <= where &&
363 where <= s->buffer_offset + s->active)
366 n = s->active - (where - s->buffer_offset);
367 memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
372 { /* new buffer starts off empty */
376 s->buffer_offset = where;
378 /* free the old buffer if necessary */
380 if (s->buffer != NULL && s->buffer != s->small_buffer)
381 free_mem (s->buffer);
383 s->buffer = new_buffer;
388 /* fd_alloc_r_at()-- Allocate a stream buffer for reading. Either
389 * we've already buffered the data or we need to load it. Returns
390 * NULL on I/O error. */
393 fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
399 where = s->logical_offset;
401 if (s->buffer != NULL && s->buffer_offset <= where &&
402 where + *len <= s->buffer_offset + s->active)
405 /* Return a position within the current buffer */
407 s->logical_offset = where + *len;
408 return s->buffer + where - s->buffer_offset;
411 fd_alloc (s, where, len);
413 m = where + s->active;
415 if (s->physical_offset != m && lseek (s->fd, m, SEEK_SET) < 0)
418 n = read (s->fd, s->buffer + s->active, s->len - s->active);
422 s->physical_offset = where + n;
425 if (s->active < *len)
426 *len = s->active; /* Bytes actually available */
428 s->logical_offset = where + *len;
434 /* fd_alloc_w_at()-- Allocate a stream buffer for writing. Either
435 * we've already buffered the data or we need to load it. */
438 fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
443 where = s->logical_offset;
445 if (s->buffer == NULL || s->buffer_offset > where ||
446 where + *len > s->buffer_offset + s->len)
449 if (fd_flush (s) == FAILURE)
451 fd_alloc (s, where, len);
454 /* Return a position within the current buffer */
456 || where > s->dirty_offset + s->ndirty
457 || s->dirty_offset > where + *len)
458 { /* Discontiguous blocks, start with a clean buffer. */
459 /* Flush the buffer. */
462 s->dirty_offset = where;
467 gfc_offset start; /* Merge with the existing data. */
468 if (where < s->dirty_offset)
471 start = s->dirty_offset;
472 if (where + *len > s->dirty_offset + s->ndirty)
473 s->ndirty = where + *len - start;
475 s->ndirty = s->dirty_offset + s->ndirty - start;
476 s->dirty_offset = start;
479 s->logical_offset = where + *len;
481 if (where + *len > s->file_length)
482 s->file_length = where + *len;
484 n = s->logical_offset - s->buffer_offset;
488 return s->buffer + where - s->buffer_offset;
493 fd_sfree (unix_stream * s)
495 if (s->ndirty != 0 &&
496 (s->buffer != s->small_buffer || options.all_unbuffered ||
505 fd_seek (unix_stream * s, gfc_offset offset)
507 s->physical_offset = s->logical_offset = offset;
509 return (lseek (s->fd, offset, SEEK_SET) < 0) ? FAILURE : SUCCESS;
513 /* truncate_file()-- Given a unit, truncate the file at the current
514 * position. Sets the physical location to the new end of the file.
515 * Returns nonzero on error. */
518 fd_truncate (unix_stream * s)
520 if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
523 /* non-seekable files, like terminals and fifo's fail the lseek.
524 Using ftruncate on a seekable special file (like /dev/null)
525 is undefined, so we treat it as if the ftruncate failed.
527 #ifdef HAVE_FTRUNCATE
528 if (s->special_file || ftruncate (s->fd, s->logical_offset))
531 if (s->special_file || chsize (s->fd, s->logical_offset))
535 s->physical_offset = s->file_length = 0;
539 s->physical_offset = s->file_length = s->logical_offset;
546 fd_close (unix_stream * s)
548 if (fd_flush (s) == FAILURE)
551 if (s->buffer != NULL && s->buffer != s->small_buffer)
552 free_mem (s->buffer);
554 if (s->fd != STDOUT_FILENO && s->fd != STDERR_FILENO)
556 if (close (s->fd) < 0)
567 fd_open (unix_stream * s)
572 s->st.alloc_r_at = (void *) fd_alloc_r_at;
573 s->st.alloc_w_at = (void *) fd_alloc_w_at;
574 s->st.sfree = (void *) fd_sfree;
575 s->st.close = (void *) fd_close;
576 s->st.seek = (void *) fd_seek;
577 s->st.truncate = (void *) fd_truncate;
584 /*********************************************************************
585 memory stream functions - These are used for internal files
587 The idea here is that a single stream structure is created and all
588 requests must be satisfied from it. The location and size of the
589 buffer is the character variable supplied to the READ or WRITE
592 *********************************************************************/
596 mem_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
601 where = s->logical_offset;
603 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
606 s->logical_offset = where + *len;
608 n = s->buffer_offset + s->active - where;
612 return s->buffer + (where - s->buffer_offset);
617 mem_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
622 where = s->logical_offset;
626 if (where < s->buffer_offset || m > s->buffer_offset + s->active)
629 s->logical_offset = m;
631 return s->buffer + (where - s->buffer_offset);
636 mem_seek (unix_stream * s, gfc_offset offset)
638 if (offset > s->file_length)
644 s->logical_offset = offset;
650 mem_truncate (unix_stream * s __attribute__ ((unused)))
657 mem_close (unix_stream * s)
666 mem_sfree (unix_stream * s __attribute__ ((unused)))
673 /*********************************************************************
674 Public functions -- A reimplementation of this module needs to
675 define functional equivalents of the following.
676 *********************************************************************/
678 /* empty_internal_buffer()-- Zero the buffer of Internal file */
681 empty_internal_buffer(stream *strm)
683 unix_stream * s = (unix_stream *) strm;
684 memset(s->buffer, ' ', s->file_length);
687 /* open_internal()-- Returns a stream structure from an internal file */
690 open_internal (char *base, int length)
694 s = get_mem (sizeof (unix_stream));
695 memset (s, '\0', sizeof (unix_stream));
698 s->buffer_offset = 0;
700 s->logical_offset = 0;
701 s->active = s->file_length = length;
703 s->st.alloc_r_at = (void *) mem_alloc_r_at;
704 s->st.alloc_w_at = (void *) mem_alloc_w_at;
705 s->st.sfree = (void *) mem_sfree;
706 s->st.close = (void *) mem_close;
707 s->st.seek = (void *) mem_seek;
708 s->st.truncate = (void *) mem_truncate;
714 /* fd_to_stream()-- Given an open file descriptor, build a stream
718 fd_to_stream (int fd, int prot)
723 s = get_mem (sizeof (unix_stream));
724 memset (s, '\0', sizeof (unix_stream));
727 s->buffer_offset = 0;
728 s->physical_offset = 0;
729 s->logical_offset = 0;
732 /* Get the current length of the file. */
734 fstat (fd, &statbuf);
735 s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
736 s->special_file = !S_ISREG (statbuf.st_mode);
744 /* Given the Fortran unit number, convert it to a C file descriptor. */
751 us = find_unit(unit);
755 return ((unix_stream *) us->s)->fd;
759 /* unpack_filename()-- Given a fortran string and a pointer to a
760 * buffer that is PATH_MAX characters, convert the fortran string to a
761 * C string in the buffer. Returns nonzero if this is not possible. */
764 unpack_filename (char *cstring, const char *fstring, int len)
766 len = fstrlen (fstring, len);
770 memmove (cstring, fstring, len);
777 /* tempfile()-- Generate a temporary filename for a scratch file and
778 * open it. mkstemp() opens the file for reading and writing, but the
779 * library mode prevents anything that is not allowed. The descriptor
780 * is returned, which is -1 on error. The template is pointed to by
781 * ioparm.file, which is copied into the unit structure
782 * and freed later. */
791 tempdir = getenv ("GFORTRAN_TMPDIR");
793 tempdir = getenv ("TMP");
795 tempdir = getenv ("TEMP");
797 tempdir = DEFAULT_TEMPDIR;
799 template = get_mem (strlen (tempdir) + 20);
801 st_sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
805 fd = mkstemp (template);
807 #else /* HAVE_MKSTEMP */
809 if (mktemp (template))
812 fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
815 fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
817 while (!(fd == -1 && errno == EEXIST) && mktemp (template));
821 #endif /* HAVE_MKSTEMP */
827 ioparm.file = template;
828 ioparm.file_len = strlen (template); /* Don't include trailing nul */
835 /* regular_file()-- Open a regular file.
836 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
837 * unless an error occurs.
838 * Returns the descriptor, which is less than zero on error. */
841 regular_file (unit_flags *flags)
843 char path[PATH_MAX + 1];
849 if (unpack_filename (path, ioparm.file, ioparm.file_len))
851 errno = ENOENT; /* Fake an OS error */
857 switch (flags->action)
867 case ACTION_READWRITE:
868 case ACTION_UNSPECIFIED:
873 internal_error ("regular_file(): Bad action");
876 switch (flags->status)
879 crflag = O_CREAT | O_EXCL;
882 case STATUS_OLD: /* open will fail if the file does not exist*/
892 crflag = O_CREAT | O_TRUNC;
896 internal_error ("regular_file(): Bad status");
899 /* rwflag |= O_LARGEFILE; */
905 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
906 fd = open (path, rwflag | crflag, mode);
907 if (flags->action != ACTION_UNSPECIFIED)
912 flags->action = ACTION_READWRITE;
918 /* retry for read-only access */
920 fd = open (path, rwflag | crflag, mode);
923 flags->action = ACTION_READ;
924 return fd; /* success */
928 return fd; /* failure */
930 /* retry for write-only access */
932 fd = open (path, rwflag | crflag, mode);
935 flags->action = ACTION_WRITE;
936 return fd; /* success */
938 return fd; /* failure */
942 /* open_external()-- Open an external file, unix specific version.
943 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
944 * Returns NULL on operating system error. */
947 open_external (unit_flags *flags)
951 if (flags->status == STATUS_SCRATCH)
954 if (flags->action == ACTION_UNSPECIFIED)
955 flags->action = ACTION_READWRITE;
957 #if HAVE_UNLINK_OPEN_FILE
958 /* We can unlink scratch files now and it will go away when closed. */
959 unlink (ioparm.file);
964 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
966 fd = regular_file (flags);
973 switch (flags->action)
983 case ACTION_READWRITE:
984 prot = PROT_READ | PROT_WRITE;
988 internal_error ("open_external(): Bad action");
991 return fd_to_stream (fd, prot);
995 /* input_stream()-- Return a stream pointer to the default input stream.
996 * Called on initialization. */
1001 return fd_to_stream (STDIN_FILENO, PROT_READ);
1005 /* output_stream()-- Return a stream pointer to the default output stream.
1006 * Called on initialization. */
1009 output_stream (void)
1011 return fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1015 /* error_stream()-- Return a stream pointer to the default error stream.
1016 * Called on initialization. */
1021 return fd_to_stream (STDERR_FILENO, PROT_WRITE);
1024 /* init_error_stream()-- Return a pointer to the error stream. This
1025 * subroutine is called when the stream is needed, rather than at
1026 * initialization. We want to work even if memory has been seriously
1030 init_error_stream (void)
1032 static unix_stream error;
1034 memset (&error, '\0', sizeof (error));
1036 error.fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1038 error.st.alloc_w_at = (void *) fd_alloc_w_at;
1039 error.st.sfree = (void *) fd_sfree;
1041 error.unbuffered = 1;
1042 error.buffer = error.small_buffer;
1044 return (stream *) & error;
1048 /* compare_file_filename()-- Given an open stream and a fortran string
1049 * that is a filename, figure out if the file is the same as the
1053 compare_file_filename (stream * s, const char *name, int len)
1055 char path[PATH_MAX + 1];
1056 struct stat st1, st2;
1058 if (unpack_filename (path, name, len))
1059 return 0; /* Can't be the same */
1061 /* If the filename doesn't exist, then there is no match with the
1064 if (stat (path, &st1) < 0)
1067 fstat (((unix_stream *) s)->fd, &st2);
1069 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
1073 /* find_file0()-- Recursive work function for find_file() */
1076 find_file0 (gfc_unit * u, struct stat *st1)
1084 if (fstat (((unix_stream *) u->s)->fd, &st2) >= 0 &&
1085 st1->st_dev == st2.st_dev && st1->st_ino == st2.st_ino)
1088 v = find_file0 (u->left, st1);
1092 v = find_file0 (u->right, st1);
1100 /* find_file()-- Take the current filename and see if there is a unit
1101 * that has the file already open. Returns a pointer to the unit if so. */
1106 char path[PATH_MAX + 1];
1107 struct stat statbuf;
1109 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1112 if (stat (path, &statbuf) < 0)
1115 return find_file0 (g.unit_root, &statbuf);
1119 /* stream_at_bof()-- Returns nonzero if the stream is at the beginning
1123 stream_at_bof (stream * s)
1127 if (!is_seekable (s))
1130 us = (unix_stream *) s;
1132 return us->logical_offset == 0;
1136 /* stream_at_eof()-- Returns nonzero if the stream is at the beginning
1140 stream_at_eof (stream * s)
1144 if (!is_seekable (s))
1147 us = (unix_stream *) s;
1149 return us->logical_offset == us->dirty_offset;
1153 /* delete_file()-- Given a unit structure, delete the file associated
1154 * with the unit. Returns nonzero if something went wrong. */
1157 delete_file (gfc_unit * u)
1159 char path[PATH_MAX + 1];
1161 if (unpack_filename (path, u->file, u->file_len))
1162 { /* Shouldn't be possible */
1167 return unlink (path);
1171 /* file_exists()-- Returns nonzero if the current filename exists on
1177 char path[PATH_MAX + 1];
1178 struct stat statbuf;
1180 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1183 if (stat (path, &statbuf) < 0)
1191 static const char *yes = "YES", *no = "NO", *unknown = "UNKNOWN";
1193 /* inquire_sequential()-- Given a fortran string, determine if the
1194 * file is suitable for sequential access. Returns a C-style
1198 inquire_sequential (const char *string, int len)
1200 char path[PATH_MAX + 1];
1201 struct stat statbuf;
1203 if (string == NULL ||
1204 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1207 if (S_ISREG (statbuf.st_mode) ||
1208 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1211 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1218 /* inquire_direct()-- Given a fortran string, determine if the file is
1219 * suitable for direct access. Returns a C-style string. */
1222 inquire_direct (const char *string, int len)
1224 char path[PATH_MAX + 1];
1225 struct stat statbuf;
1227 if (string == NULL ||
1228 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1231 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1234 if (S_ISDIR (statbuf.st_mode) ||
1235 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1242 /* inquire_formatted()-- Given a fortran string, determine if the file
1243 * is suitable for formatted form. Returns a C-style string. */
1246 inquire_formatted (const char *string, int len)
1248 char path[PATH_MAX + 1];
1249 struct stat statbuf;
1251 if (string == NULL ||
1252 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1255 if (S_ISREG (statbuf.st_mode) ||
1256 S_ISBLK (statbuf.st_mode) ||
1257 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1260 if (S_ISDIR (statbuf.st_mode))
1267 /* inquire_unformatted()-- Given a fortran string, determine if the file
1268 * is suitable for unformatted form. Returns a C-style string. */
1271 inquire_unformatted (const char *string, int len)
1273 return inquire_formatted (string, len);
1277 /* inquire_access()-- Given a fortran string, determine if the file is
1278 * suitable for access. */
1281 inquire_access (const char *string, int len, int mode)
1283 char path[PATH_MAX + 1];
1285 if (string == NULL || unpack_filename (path, string, len) ||
1286 access (path, mode) < 0)
1293 /* inquire_read()-- Given a fortran string, determine if the file is
1294 * suitable for READ access. */
1297 inquire_read (const char *string, int len)
1299 return inquire_access (string, len, R_OK);
1303 /* inquire_write()-- Given a fortran string, determine if the file is
1304 * suitable for READ access. */
1307 inquire_write (const char *string, int len)
1309 return inquire_access (string, len, W_OK);
1313 /* inquire_readwrite()-- Given a fortran string, determine if the file is
1314 * suitable for read and write access. */
1317 inquire_readwrite (const char *string, int len)
1319 return inquire_access (string, len, R_OK | W_OK);
1323 /* file_length()-- Return the file length in bytes, -1 if unknown */
1326 file_length (stream * s)
1328 return ((unix_stream *) s)->file_length;
1332 /* file_position()-- Return the current position of the file */
1335 file_position (stream * s)
1337 return ((unix_stream *) s)->logical_offset;
1341 /* is_seekable()-- Return nonzero if the stream is seekable, zero if
1345 is_seekable (stream * s)
1347 /* by convention, if file_length == -1, the file is not seekable
1348 note that a mmapped file is always seekable, an fd_ file may
1350 return ((unix_stream *) s)->file_length!=-1;
1356 return fd_flush( (unix_stream *) s);
1360 stream_isatty (stream *s)
1362 return isatty (((unix_stream *) s)->fd);
1366 stream_ttyname (stream *s)
1369 return ttyname (((unix_stream *) s)->fd);
1376 /* How files are stored: This is an operating-system specific issue,
1377 and therefore belongs here. There are three cases to consider.
1380 Records are written as block of bytes corresponding to the record
1381 length of the file. This goes for both formatted and unformatted
1382 records. Positioning is done explicitly for each data transfer,
1383 so positioning is not much of an issue.
1385 Sequential Formatted:
1386 Records are separated by newline characters. The newline character
1387 is prohibited from appearing in a string. If it does, this will be
1388 messed up on the next read. End of file is also the end of a record.
1390 Sequential Unformatted:
1391 In this case, we are merely copying bytes to and from main storage,
1392 yet we need to keep track of varying record lengths. We adopt
1393 the solution used by f2c. Each record contains a pair of length
1396 Length of record n in bytes
1398 Length of record n in bytes
1400 Length of record n+1 in bytes
1402 Length of record n+1 in bytes
1404 The length is stored at the end of a record to allow backspacing to the
1405 previous record. Between data transfer statements, the file pointer
1406 is left pointing to the first length of the current record.
1408 ENDFILE records are never explicitly stored.