PR libfortran/16805
[official-gcc.git] / libgfortran / io / unix.c
blob377cadd438e1aa2ab51ba7f21c8d597fac9702dc
1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
4 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 Libgfortran is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Libgfortran; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Unix stream I/O module */
23 #include "config.h"
24 #include <stdlib.h>
25 #include <limits.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
31 #include <sys/mman.h>
32 #include <string.h>
33 #include <errno.h>
35 #include "libgfortran.h"
36 #include "io.h"
38 #ifndef PATH_MAX
39 #define PATH_MAX 1024
40 #endif
42 #ifndef MAP_FAILED
43 #define MAP_FAILED ((void *) -1)
44 #endif
46 /* This implementation of stream I/O is based on the paper:
48 * "Exploiting the advantages of mapped files for stream I/O",
49 * O. Krieger, M. Stumm and R. Umrau, "Proceedings of the 1992 Winter
50 * USENIX conference", p. 27-42.
52 * It differs in a number of ways from the version described in the
53 * paper. First of all, threads are not an issue during I/O and we
54 * also don't have to worry about having multiple regions, since
55 * fortran's I/O model only allows you to be one place at a time.
57 * On the other hand, we have to be able to writing at the end of a
58 * stream, read from the start of a stream or read and write blocks of
59 * bytes from an arbitrary position. After opening a file, a pointer
60 * to a stream structure is returned, which is used to handle file
61 * accesses until the file is closed.
63 * salloc_at_r(stream, len, where)-- Given a stream pointer, return a
64 * pointer to a block of memory that mirror the file at position
65 * 'where' that is 'len' bytes long. The len integer is updated to
66 * reflect how many bytes were actually read. The only reason for a
67 * short read is end of file. The file pointer is updated. The
68 * pointer is valid until the next call to salloc_*.
70 * salloc_at_w(stream, len, where)-- Given the stream pointer, returns
71 * a pointer to a block of memory that is updated to reflect the state
72 * of the file. The length of the buffer is always equal to that
73 * requested. The buffer must be completely set by the caller. When
74 * data has been written, the sfree() function must be called to
75 * indicate that the caller is done writing data to the buffer. This
76 * may or may not cause a physical write.
78 * Short forms of these are salloc_r() and salloc_w() which drop the
79 * 'where' parameter and use the current file pointer. */
82 #define BUFFER_SIZE 8192
84 typedef struct
86 stream st;
88 int fd;
89 gfc_offset buffer_offset; /* File offset of the start of the buffer */
90 gfc_offset physical_offset; /* Current physical file offset */
91 gfc_offset logical_offset; /* Current logical file offset */
92 gfc_offset dirty_offset; /* Start of modified bytes in buffer */
93 gfc_offset file_length; /* Length of the file, -1 if not seekable. */
95 char *buffer;
96 int len; /* Physical length of the current buffer */
97 int active; /* Length of valid bytes in the buffer */
99 int prot;
100 int ndirty; /* Dirty bytes starting at dirty_offset */
102 unsigned unbuffered:1, mmaped:1;
104 char small_buffer[BUFFER_SIZE];
107 unix_stream;
109 /*move_pos_offset()-- Move the record pointer right or left
110 *relative to current position */
113 move_pos_offset (stream* st, int pos_off)
115 unix_stream * str = (unix_stream*)st;
116 if (pos_off < 0)
118 str->active += pos_off;
119 if (str->active < 0)
120 str->active = 0;
122 str->logical_offset += pos_off;
124 if (str->dirty_offset+str->ndirty > str->logical_offset)
126 if (str->ndirty + pos_off > 0)
127 str->ndirty += pos_off ;
128 else
130 str->dirty_offset += pos_off + pos_off;
131 str->ndirty = 0 ;
135 return pos_off ;
137 return 0 ;
141 /* fix_fd()-- Given a file descriptor, make sure it is not one of the
142 * standard descriptors, returning a non-standard descriptor. If the
143 * user specifies that system errors should go to standard output,
144 * then closes standard output, we don't want the system errors to a
145 * file that has been given file descriptor 1 or 0. We want to send
146 * the error to the invalid descriptor. */
148 static int
149 fix_fd (int fd)
151 int input, output, error;
153 input = output = error = 0;
155 /* Unix allocates the lowest descriptors first, so a loop is not
156 * required, but this order is. */
158 if (fd == STDIN_FILENO)
160 fd = dup (fd);
161 input = 1;
163 if (fd == STDOUT_FILENO)
165 fd = dup (fd);
166 output = 1;
168 if (fd == STDERR_FILENO)
170 fd = dup (fd);
171 error = 1;
174 if (input)
175 close (STDIN_FILENO);
176 if (output)
177 close (STDOUT_FILENO);
178 if (error)
179 close (STDERR_FILENO);
181 return fd;
185 /* write()-- Write a buffer to a descriptor, allowing for short writes */
187 static int
188 writen (int fd, char *buffer, int len)
190 int n, n0;
192 n0 = len;
194 while (len > 0)
196 n = write (fd, buffer, len);
197 if (n < 0)
198 return n;
200 buffer += n;
201 len -= n;
204 return n0;
208 #if 0
209 /* readn()-- Read bytes into a buffer, allowing for short reads. If
210 * fewer than len bytes are returned, it is because we've hit the end
211 * of file. */
213 static int
214 readn (int fd, char *buffer, int len)
216 int nread, n;
218 nread = 0;
220 while (len > 0)
222 n = read (fd, buffer, len);
223 if (n < 0)
224 return n;
226 if (n == 0)
227 return nread;
229 buffer += n;
230 nread += n;
231 len -= n;
234 return nread;
236 #endif
239 /* get_oserror()-- Get the most recent operating system error. For
240 * unix, this is errno. */
242 const char *
243 get_oserror (void)
246 return strerror (errno);
250 /* sys_exit()-- Terminate the program with an exit code */
252 void
253 sys_exit (int code)
256 exit (code);
261 /*********************************************************************
262 File descriptor stream functions
263 *********************************************************************/
265 /* fd_flush()-- Write bytes that need to be written */
267 static try
268 fd_flush (unix_stream * s)
271 if (s->ndirty == 0)
272 return SUCCESS;;
274 if (s->physical_offset != s->dirty_offset &&
275 lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
276 return FAILURE;
278 if (writen (s->fd, s->buffer + (s->dirty_offset - s->buffer_offset),
279 s->ndirty) < 0)
280 return FAILURE;
282 s->physical_offset = s->dirty_offset + s->ndirty;
284 /* don't increment file_length if the file is non-seekable */
285 if (s->file_length != -1 && s->physical_offset > s->file_length)
286 s->file_length = s->physical_offset;
287 s->ndirty = 0;
289 return SUCCESS;
293 /* fd_alloc()-- Arrange a buffer such that the salloc() request can be
294 * satisfied. This subroutine gets the buffer ready for whatever is
295 * to come next. */
297 static void
298 fd_alloc (unix_stream * s, gfc_offset where, int *len)
300 char *new_buffer;
301 int n, read_len;
303 if (*len <= BUFFER_SIZE)
305 new_buffer = s->small_buffer;
306 read_len = BUFFER_SIZE;
308 else
310 new_buffer = get_mem (*len);
311 read_len = *len;
314 /* Salvage bytes currently within the buffer. This is important for
315 * devices that cannot seek. */
317 if (s->buffer != NULL && s->buffer_offset <= where &&
318 where <= s->buffer_offset + s->active)
321 n = s->active - (where - s->buffer_offset);
322 memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
324 s->active = n;
326 else
327 { /* new buffer starts off empty */
328 s->active = 0;
331 s->buffer_offset = where;
333 /* free the old buffer if necessary */
335 if (s->buffer != NULL && s->buffer != s->small_buffer)
336 free_mem (s->buffer);
338 s->buffer = new_buffer;
339 s->len = read_len;
340 s->mmaped = 0;
344 /* fd_alloc_r_at()-- Allocate a stream buffer for reading. Either
345 * we've already buffered the data or we need to load it. Returns
346 * NULL on I/O error. */
348 static char *
349 fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
351 gfc_offset m;
352 int n;
354 if (where == -1)
355 where = s->logical_offset;
357 if (s->buffer != NULL && s->buffer_offset <= where &&
358 where + *len <= s->buffer_offset + s->active)
361 /* Return a position within the current buffer */
363 s->logical_offset = where + *len;
364 return s->buffer + where - s->buffer_offset;
367 fd_alloc (s, where, len);
369 m = where + s->active;
371 if (s->physical_offset != m && lseek (s->fd, m, SEEK_SET) < 0)
372 return NULL;
374 n = read (s->fd, s->buffer + s->active, s->len - s->active);
375 if (n < 0)
376 return NULL;
378 s->physical_offset = where + n;
380 s->active += n;
381 if (s->active < *len)
382 *len = s->active; /* Bytes actually available */
384 s->logical_offset = where + *len;
386 return s->buffer;
390 /* fd_alloc_w_at()-- Allocate a stream buffer for writing. Either
391 * we've already buffered the data or we need to load it. */
393 static char *
394 fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
396 gfc_offset n;
398 if (where == -1)
399 where = s->logical_offset;
401 if (s->buffer == NULL || s->buffer_offset > where ||
402 where + *len > s->buffer_offset + s->len)
405 if (fd_flush (s) == FAILURE)
406 return NULL;
407 fd_alloc (s, where, len);
410 /* Return a position within the current buffer */
411 if (s->ndirty == 0
412 || where > s->dirty_offset + s->ndirty
413 || s->dirty_offset > where + *len)
414 { /* Discontiguous blocks, start with a clean buffer. */
415 /* Flush the buffer. */
416 if (s->ndirty != 0)
417 fd_flush (s);
418 s->dirty_offset = where;
419 s->ndirty = *len;
421 else
423 gfc_offset start; /* Merge with the existing data. */
424 if (where < s->dirty_offset)
425 start = where;
426 else
427 start = s->dirty_offset;
428 if (where + *len > s->dirty_offset + s->ndirty)
429 s->ndirty = where + *len - start;
430 else
431 s->ndirty = s->dirty_offset + s->ndirty - start;
432 s->dirty_offset = start;
435 s->logical_offset = where + *len;
437 n = s->logical_offset - s->buffer_offset;
438 if (n > s->active)
439 s->active = n;
441 return s->buffer + where - s->buffer_offset;
445 static try
446 fd_sfree (unix_stream * s)
449 if (s->ndirty != 0 &&
450 (s->buffer != s->small_buffer || options.all_unbuffered ||
451 s->unbuffered))
452 return fd_flush (s);
454 return SUCCESS;
458 static int
459 fd_seek (unix_stream * s, gfc_offset offset)
462 s->physical_offset = s->logical_offset = offset;
464 return (lseek (s->fd, offset, SEEK_SET) < 0) ? FAILURE : SUCCESS;
468 /* truncate_file()-- Given a unit, truncate the file at the current
469 * position. Sets the physical location to the new end of the file.
470 * Returns nonzero on error. */
472 static try
473 fd_truncate (unix_stream * s)
476 if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
477 return FAILURE;
479 /* non-seekable files, like terminals and fifo's fail the lseek.
480 the fd is a regular file at this point */
482 if (ftruncate (s->fd, s->logical_offset))
484 return FAILURE;
487 s->physical_offset = s->file_length = s->logical_offset;
489 return SUCCESS;
493 static try
494 fd_close (unix_stream * s)
497 if (fd_flush (s) == FAILURE)
498 return FAILURE;
500 if (s->buffer != NULL && s->buffer != s->small_buffer)
501 free_mem (s->buffer);
503 if (close (s->fd) < 0)
504 return FAILURE;
506 free_mem (s);
508 return SUCCESS;
512 static void
513 fd_open (unix_stream * s)
516 if (isatty (s->fd))
517 s->unbuffered = 1;
519 s->st.alloc_r_at = (void *) fd_alloc_r_at;
520 s->st.alloc_w_at = (void *) fd_alloc_w_at;
521 s->st.sfree = (void *) fd_sfree;
522 s->st.close = (void *) fd_close;
523 s->st.seek = (void *) fd_seek;
524 s->st.truncate = (void *) fd_truncate;
526 s->buffer = NULL;
530 /*********************************************************************
531 mmap stream functions
533 Because mmap() is not capable of extending a file, we have to keep
534 track of how long the file is. We also have to be able to detect end
535 of file conditions. If there are multiple writers to the file (which
536 can only happen outside the current program), things will get
537 confused. Then again, things will get confused anyway.
539 *********************************************************************/
541 #if HAVE_MMAP
543 static int page_size, page_mask;
545 /* mmap_flush()-- Deletes a memory mapping if something is mapped. */
547 static try
548 mmap_flush (unix_stream * s)
551 if (!s->mmaped)
552 return fd_flush (s);
554 if (s->buffer == NULL)
555 return SUCCESS;
557 if (munmap (s->buffer, s->active))
558 return FAILURE;
560 s->buffer = NULL;
561 s->active = 0;
563 return SUCCESS;
567 /* mmap_alloc()-- mmap() a section of the file. The whole section is
568 * guaranteed to be mappable. */
570 static try
571 mmap_alloc (unix_stream * s, gfc_offset where, int *len)
573 gfc_offset offset;
574 int length;
575 char *p;
577 if (mmap_flush (s) == FAILURE)
578 return FAILURE;
580 offset = where & page_mask; /* Round down to the next page */
582 length = ((where - offset) & page_mask) + 2 * page_size;
584 p = mmap (NULL, length, s->prot, MAP_SHARED, s->fd, offset);
585 if (p == (char *) MAP_FAILED)
586 return FAILURE;
588 s->mmaped = 1;
589 s->buffer = p;
590 s->buffer_offset = offset;
591 s->active = length;
593 return SUCCESS;
597 static char *
598 mmap_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
600 gfc_offset m;
602 if (where == -1)
603 where = s->logical_offset;
605 m = where + *len;
607 if ((s->buffer == NULL || s->buffer_offset > where ||
608 m > s->buffer_offset + s->active) &&
609 mmap_alloc (s, where, len) == FAILURE)
610 return NULL;
612 if (m > s->file_length)
614 *len = s->file_length - s->logical_offset;
615 s->logical_offset = s->file_length;
617 else
618 s->logical_offset = m;
620 return s->buffer + (where - s->buffer_offset);
624 static char *
625 mmap_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
627 if (where == -1)
628 where = s->logical_offset;
630 /* If we're extending the file, we have to use file descriptor
631 * methods. */
633 if (where + *len > s->file_length)
635 if (s->mmaped)
636 mmap_flush (s);
637 return fd_alloc_w_at (s, len, where);
640 if ((s->buffer == NULL || s->buffer_offset > where ||
641 where + *len > s->buffer_offset + s->active) &&
642 mmap_alloc (s, where, len) == FAILURE)
643 return NULL;
645 s->logical_offset = where + *len;
647 return s->buffer + where - s->buffer_offset;
651 static int
652 mmap_seek (unix_stream * s, gfc_offset offset)
655 s->logical_offset = offset;
656 return SUCCESS;
660 static try
661 mmap_close (unix_stream * s)
663 try t;
665 t = mmap_flush (s);
667 if (close (s->fd) < 0)
668 t = FAILURE;
669 free_mem (s);
671 return t;
675 static try
676 mmap_sfree (unix_stream * s)
679 return SUCCESS;
683 /* mmap_open()-- mmap_specific open. If the particular file cannot be
684 * mmap()-ed, we fall back to the file descriptor functions. */
686 static try
687 mmap_open (unix_stream * s)
689 char *p;
690 int i;
692 page_size = getpagesize ();
693 page_mask = ~0;
695 p = mmap (0, page_size, s->prot, MAP_SHARED, s->fd, 0);
696 if (p == (char *) MAP_FAILED)
698 fd_open (s);
699 return SUCCESS;
702 munmap (p, page_size);
704 i = page_size >> 1;
705 while (i != 0)
707 page_mask <<= 1;
708 i >>= 1;
711 s->st.alloc_r_at = (void *) mmap_alloc_r_at;
712 s->st.alloc_w_at = (void *) mmap_alloc_w_at;
713 s->st.sfree = (void *) mmap_sfree;
714 s->st.close = (void *) mmap_close;
715 s->st.seek = (void *) mmap_seek;
716 s->st.truncate = (void *) fd_truncate;
718 if (lseek (s->fd, s->file_length, SEEK_SET) < 0)
719 return FAILURE;
721 return SUCCESS;
724 #endif
727 /*********************************************************************
728 memory stream functions - These are used for internal files
730 The idea here is that a single stream structure is created and all
731 requests must be satisfied from it. The location and size of the
732 buffer is the character variable supplied to the READ or WRITE
733 statement.
735 *********************************************************************/
738 static char *
739 mem_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
741 gfc_offset n;
743 if (where == -1)
744 where = s->logical_offset;
746 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
747 return NULL;
749 s->logical_offset = where + *len;
751 n = s->buffer_offset + s->active - where;
752 if (*len > n)
753 *len = n;
755 return s->buffer + (where - s->buffer_offset);
759 static char *
760 mem_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
762 gfc_offset m;
764 if (where == -1)
765 where = s->logical_offset;
767 m = where + *len;
769 if (where < s->buffer_offset || m > s->buffer_offset + s->active)
770 return NULL;
772 s->logical_offset = m;
774 return s->buffer + (where - s->buffer_offset);
778 static int
779 mem_seek (unix_stream * s, gfc_offset offset)
782 if (offset > s->file_length)
784 errno = ESPIPE;
785 return FAILURE;
788 s->logical_offset = offset;
789 return SUCCESS;
793 static int
794 mem_truncate (unix_stream * s)
797 return SUCCESS;
801 static try
802 mem_close (unix_stream * s)
805 return SUCCESS;
809 static try
810 mem_sfree (unix_stream * s)
813 return SUCCESS;
818 /*********************************************************************
819 Public functions -- A reimplementation of this module needs to
820 define functional equivalents of the following.
821 *********************************************************************/
823 /* empty_internal_buffer()-- Zero the buffer of Internal file */
825 void
826 empty_internal_buffer(stream *strm)
828 unix_stream * s = (unix_stream *) strm;
829 memset(s->buffer, ' ', s->file_length);
832 /* open_internal()-- Returns a stream structure from an internal file */
834 stream *
835 open_internal (char *base, int length)
837 unix_stream *s;
839 s = get_mem (sizeof (unix_stream));
841 s->buffer = base;
842 s->buffer_offset = 0;
844 s->logical_offset = 0;
845 s->active = s->file_length = length;
847 s->st.alloc_r_at = (void *) mem_alloc_r_at;
848 s->st.alloc_w_at = (void *) mem_alloc_w_at;
849 s->st.sfree = (void *) mem_sfree;
850 s->st.close = (void *) mem_close;
851 s->st.seek = (void *) mem_seek;
852 s->st.truncate = (void *) mem_truncate;
854 return (stream *) s;
858 /* fd_to_stream()-- Given an open file descriptor, build a stream
859 * around it. */
861 static stream *
862 fd_to_stream (int fd, int prot)
864 struct stat statbuf;
865 unix_stream *s;
867 s = get_mem (sizeof (unix_stream));
869 s->fd = fd;
870 s->buffer_offset = 0;
871 s->physical_offset = 0;
872 s->logical_offset = 0;
873 s->prot = prot;
875 /* Get the current length of the file. */
877 fstat (fd, &statbuf);
878 s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
880 #if HAVE_MMAP
881 mmap_open (s);
882 #else
883 fd_open (s);
884 #endif
886 return (stream *) s;
890 /* unpack_filename()-- Given a fortran string and a pointer to a
891 * buffer that is PATH_MAX characters, convert the fortran string to a
892 * C string in the buffer. Returns nonzero if this is not possible. */
894 static int
895 unpack_filename (char *cstring, const char *fstring, int len)
898 len = fstrlen (fstring, len);
899 if (len >= PATH_MAX)
900 return 1;
902 memmove (cstring, fstring, len);
903 cstring[len] = '\0';
905 return 0;
909 /* tempfile()-- Generate a temporary filename for a scratch file and
910 * open it. mkstemp() opens the file for reading and writing, but the
911 * library mode prevents anything that is not allowed. The descriptor
912 * is returns, which is less than zero on error. The template is
913 * pointed to by ioparm.file, which is copied into the unit structure
914 * and freed later. */
916 static int
917 tempfile (void)
919 const char *tempdir;
920 char *template;
921 int fd;
923 tempdir = getenv ("GFORTRAN_TMPDIR");
924 if (tempdir == NULL)
925 tempdir = getenv ("TMP");
926 if (tempdir == NULL)
927 tempdir = DEFAULT_TEMPDIR;
929 template = get_mem (strlen (tempdir) + 20);
931 st_sprintf (template, "%s/gfortantmpXXXXXX", tempdir);
933 fd = mkstemp (template);
935 if (fd < 0)
936 free_mem (template);
937 else
939 ioparm.file = template;
940 ioparm.file_len = strlen (template); /* Don't include trailing nul */
943 return fd;
947 /* regular_file()-- Open a regular file. Returns the descriptor, which is less than zero on error. */
949 static int
950 regular_file (unit_action action, unit_status status)
952 char path[PATH_MAX + 1];
953 struct stat statbuf;
954 int mode;
956 if (unpack_filename (path, ioparm.file, ioparm.file_len))
958 errno = ENOENT; /* Fake an OS error */
959 return -1;
962 mode = 0;
964 switch (action)
966 case ACTION_READ:
967 mode = O_RDONLY;
968 break;
970 case ACTION_WRITE:
971 mode = O_WRONLY;
972 break;
974 case ACTION_READWRITE:
975 mode = O_RDWR;
976 break;
978 default:
979 internal_error ("regular_file(): Bad action");
982 switch (status)
984 case STATUS_NEW:
985 mode |= O_CREAT | O_EXCL;
986 break;
988 case STATUS_OLD: /* file must exist, so check for its existence */
989 if (stat (path, &statbuf) < 0)
990 return -1;
991 break;
993 case STATUS_UNKNOWN:
994 case STATUS_SCRATCH:
995 mode |= O_CREAT;
996 break;
998 case STATUS_REPLACE:
999 mode |= O_CREAT | O_TRUNC;
1000 break;
1002 default:
1003 internal_error ("regular_file(): Bad status");
1006 // mode |= O_LARGEFILE;
1008 return open (path, mode,
1009 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1013 /* open_external()-- Open an external file, unix specific version.
1014 * Returns NULL on operating system error. */
1016 stream *
1017 open_external (unit_action action, unit_status status)
1019 int fd, prot;
1021 fd =
1022 (status == STATUS_SCRATCH) ? tempfile () : regular_file (action, status);
1024 if (fd < 0)
1025 return NULL;
1026 fd = fix_fd (fd);
1028 switch (action)
1030 case ACTION_READ:
1031 prot = PROT_READ;
1032 break;
1034 case ACTION_WRITE:
1035 prot = PROT_WRITE;
1036 break;
1038 case ACTION_READWRITE:
1039 prot = PROT_READ | PROT_WRITE;
1040 break;
1042 default:
1043 internal_error ("open_external(): Bad action");
1046 /* If this is a scratch file, we can unlink it now and the file will
1047 * go away when it is closed. */
1049 if (status == STATUS_SCRATCH)
1050 unlink (ioparm.file);
1052 return fd_to_stream (fd, prot);
1056 /* input_stream()-- Return a stream pointer to the default input stream.
1057 * Called on initialization. */
1059 stream *
1060 input_stream (void)
1063 return fd_to_stream (STDIN_FILENO, PROT_READ);
1067 /* output_stream()-- Return a stream pointer to the default input stream.
1068 * Called on initialization. */
1070 stream *
1071 output_stream (void)
1074 return fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1078 /* init_error_stream()-- Return a pointer to the error stream. This
1079 * subroutine is called when the stream is needed, rather than at
1080 * initialization. We want to work even if memory has been seriously
1081 * corrupted. */
1083 stream *
1084 init_error_stream (void)
1086 static unix_stream error;
1088 memset (&error, '\0', sizeof (error));
1090 error.fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1092 error.st.alloc_w_at = (void *) fd_alloc_w_at;
1093 error.st.sfree = (void *) fd_sfree;
1095 error.unbuffered = 1;
1096 error.buffer = error.small_buffer;
1098 return (stream *) & error;
1102 /* compare_file_filename()-- Given an open stream and a fortran string
1103 * that is a filename, figure out if the file is the same as the
1104 * filename. */
1107 compare_file_filename (stream * s, const char *name, int len)
1109 char path[PATH_MAX + 1];
1110 struct stat st1, st2;
1112 if (unpack_filename (path, name, len))
1113 return 0; /* Can't be the same */
1115 /* If the filename doesn't exist, then there is no match with the
1116 * existing file. */
1118 if (stat (path, &st1) < 0)
1119 return 0;
1121 fstat (((unix_stream *) s)->fd, &st2);
1123 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
1127 /* find_file0()-- Recursive work function for find_file() */
1129 static gfc_unit *
1130 find_file0 (gfc_unit * u, struct stat *st1)
1132 struct stat st2;
1133 gfc_unit *v;
1135 if (u == NULL)
1136 return NULL;
1138 if (fstat (((unix_stream *) u->s)->fd, &st2) >= 0 &&
1139 st1->st_dev == st2.st_dev && st1->st_ino == st2.st_ino)
1140 return u;
1142 v = find_file0 (u->left, st1);
1143 if (v != NULL)
1144 return v;
1146 v = find_file0 (u->right, st1);
1147 if (v != NULL)
1148 return v;
1150 return NULL;
1154 /* find_file()-- Take the current filename and see if there is a unit
1155 * that has the file already open. Returns a pointer to the unit if so. */
1157 gfc_unit *
1158 find_file (void)
1160 char path[PATH_MAX + 1];
1161 struct stat statbuf;
1163 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1164 return NULL;
1166 if (stat (path, &statbuf) < 0)
1167 return NULL;
1169 return find_file0 (g.unit_root, &statbuf);
1173 /* stream_at_bof()-- Returns nonzero if the stream is at the beginning
1174 * of the file. */
1177 stream_at_bof (stream * s)
1179 unix_stream *us;
1181 us = (unix_stream *) s;
1183 if (!us->mmaped)
1184 return 0; /* File is not seekable */
1186 return us->logical_offset == 0;
1190 /* stream_at_eof()-- Returns nonzero if the stream is at the beginning
1191 * of the file. */
1194 stream_at_eof (stream * s)
1196 unix_stream *us;
1198 us = (unix_stream *) s;
1200 if (!us->mmaped)
1201 return 0; /* File is not seekable */
1203 return us->logical_offset == us->dirty_offset;
1207 /* delete_file()-- Given a unit structure, delete the file associated
1208 * with the unit. Returns nonzero if something went wrong. */
1211 delete_file (gfc_unit * u)
1213 char path[PATH_MAX + 1];
1215 if (unpack_filename (path, u->file, u->file_len))
1216 { /* Shouldn't be possible */
1217 errno = ENOENT;
1218 return 1;
1221 return unlink (path);
1225 /* file_exists()-- Returns nonzero if the current filename exists on
1226 * the system */
1229 file_exists (void)
1231 char path[PATH_MAX + 1];
1232 struct stat statbuf;
1234 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1235 return 0;
1237 if (stat (path, &statbuf) < 0)
1238 return 0;
1240 return 1;
1245 static const char *yes = "YES", *no = "NO", *unknown = "UNKNOWN";
1247 /* inquire_sequential()-- Given a fortran string, determine if the
1248 * file is suitable for sequential access. Returns a C-style
1249 * string. */
1251 const char *
1252 inquire_sequential (const char *string, int len)
1254 char path[PATH_MAX + 1];
1255 struct stat statbuf;
1257 if (string == NULL ||
1258 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1259 return unknown;
1261 if (S_ISREG (statbuf.st_mode) ||
1262 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1263 return yes;
1265 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1266 return no;
1268 return unknown;
1272 /* inquire_direct()-- Given a fortran string, determine if the file is
1273 * suitable for direct access. Returns a C-style string. */
1275 const char *
1276 inquire_direct (const char *string, int len)
1278 char path[PATH_MAX + 1];
1279 struct stat statbuf;
1281 if (string == NULL ||
1282 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1283 return unknown;
1285 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1286 return yes;
1288 if (S_ISDIR (statbuf.st_mode) ||
1289 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1290 return no;
1292 return unknown;
1296 /* inquire_formatted()-- Given a fortran string, determine if the file
1297 * is suitable for formatted form. Returns a C-style string. */
1299 const char *
1300 inquire_formatted (const char *string, int len)
1302 char path[PATH_MAX + 1];
1303 struct stat statbuf;
1305 if (string == NULL ||
1306 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1307 return unknown;
1309 if (S_ISREG (statbuf.st_mode) ||
1310 S_ISBLK (statbuf.st_mode) ||
1311 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1312 return yes;
1314 if (S_ISDIR (statbuf.st_mode))
1315 return no;
1317 return unknown;
1321 /* inquire_unformatted()-- Given a fortran string, determine if the file
1322 * is suitable for unformatted form. Returns a C-style string. */
1324 const char *
1325 inquire_unformatted (const char *string, int len)
1328 return inquire_formatted (string, len);
1332 /* inquire_access()-- Given a fortran string, determine if the file is
1333 * suitable for access. */
1335 static const char *
1336 inquire_access (const char *string, int len, int mode)
1338 char path[PATH_MAX + 1];
1340 if (string == NULL || unpack_filename (path, string, len) ||
1341 access (path, mode) < 0)
1342 return no;
1344 return yes;
1348 /* inquire_read()-- Given a fortran string, determine if the file is
1349 * suitable for READ access. */
1351 const char *
1352 inquire_read (const char *string, int len)
1355 return inquire_access (string, len, R_OK);
1359 /* inquire_write()-- Given a fortran string, determine if the file is
1360 * suitable for READ access. */
1362 const char *
1363 inquire_write (const char *string, int len)
1366 return inquire_access (string, len, W_OK);
1370 /* inquire_readwrite()-- Given a fortran string, determine if the file is
1371 * suitable for read and write access. */
1373 const char *
1374 inquire_readwrite (const char *string, int len)
1377 return inquire_access (string, len, R_OK | W_OK);
1381 /* file_length()-- Return the file length in bytes, -1 if unknown */
1383 gfc_offset
1384 file_length (stream * s)
1387 return ((unix_stream *) s)->file_length;
1391 /* file_position()-- Return the current position of the file */
1393 gfc_offset
1394 file_position (stream * s)
1397 return ((unix_stream *) s)->logical_offset;
1401 /* is_seekable()-- Return nonzero if the stream is seekable, zero if
1402 * it is not */
1405 is_seekable (stream * s)
1407 /* by convention, if file_length == -1, the file is not seekable
1408 note that a mmapped file is always seekable, an fd_ file may
1409 or may not be. */
1410 return ((unix_stream *) s)->file_length!=-1;
1414 flush (stream *s)
1416 return fd_flush( (unix_stream *) s);
1420 /* How files are stored: This is an operating-system specific issue,
1421 and therefore belongs here. There are three cases to consider.
1423 Direct Access:
1424 Records are written as block of bytes corresponding to the record
1425 length of the file. This goes for both formatted and unformatted
1426 records. Positioning is done explicitly for each data transfer,
1427 so positioning is not much of an issue.
1429 Sequential Formatted:
1430 Records are separated by newline characters. The newline character
1431 is prohibited from appearing in a string. If it does, this will be
1432 messed up on the next read. End of file is also the end of a record.
1434 Sequential Unformatted:
1435 In this case, we are merely copying bytes to and from main storage,
1436 yet we need to keep track of varying record lengths. We adopt
1437 the solution used by f2c. Each record contains a pair of length
1438 markers:
1440 Length of record n in bytes
1441 Data of record n
1442 Length of record n in bytes
1444 Length of record n+1 in bytes
1445 Data of record n+1
1446 Length of record n+1 in bytes
1448 The length is stored at the end of a record to allow backspacing to the
1449 previous record. Between data transfer statements, the file pointer
1450 is left pointing to the first length of the current record.
1452 ENDFILE records are never explicitly stored.