2004-12-22 Daniel Berlin <dberlin@dberlin.org>
[official-gcc.git] / libgfortran / io / unix.c
bloba21eb47792c682791e1dd9feb5139e66dc24259a
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 <stdio.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
32 #ifdef HAVE_SYS_MMAN_H
33 #include <sys/mman.h>
34 #endif
35 #include <string.h>
36 #include <errno.h>
38 #include "libgfortran.h"
39 #include "io.h"
41 #ifndef PATH_MAX
42 #define PATH_MAX 1024
43 #endif
45 #ifndef MAP_FAILED
46 #define MAP_FAILED ((void *) -1)
47 #endif
49 #ifndef PROT_READ
50 #define PROT_READ 1
51 #endif
53 #ifndef PROT_WRITE
54 #define PROT_WRITE 2
55 #endif
57 /* These flags aren't defined on all targets (mingw32), so provide them
58 here. */
59 #ifndef S_IRGRP
60 #define S_IRGRP 0
61 #endif
63 #ifndef S_IWGRP
64 #define S_IWGRP 0
65 #endif
67 #ifndef S_IROTH
68 #define S_IROTH 0
69 #endif
71 #ifndef S_IWOTH
72 #define S_IWOTH 0
73 #endif
75 /* This implementation of stream I/O is based on the paper:
77 * "Exploiting the advantages of mapped files for stream I/O",
78 * O. Krieger, M. Stumm and R. Umrau, "Proceedings of the 1992 Winter
79 * USENIX conference", p. 27-42.
81 * It differs in a number of ways from the version described in the
82 * paper. First of all, threads are not an issue during I/O and we
83 * also don't have to worry about having multiple regions, since
84 * fortran's I/O model only allows you to be one place at a time.
86 * On the other hand, we have to be able to writing at the end of a
87 * stream, read from the start of a stream or read and write blocks of
88 * bytes from an arbitrary position. After opening a file, a pointer
89 * to a stream structure is returned, which is used to handle file
90 * accesses until the file is closed.
92 * salloc_at_r(stream, len, where)-- Given a stream pointer, return a
93 * pointer to a block of memory that mirror the file at position
94 * 'where' that is 'len' bytes long. The len integer is updated to
95 * reflect how many bytes were actually read. The only reason for a
96 * short read is end of file. The file pointer is updated. The
97 * pointer is valid until the next call to salloc_*.
99 * salloc_at_w(stream, len, where)-- Given the stream pointer, returns
100 * a pointer to a block of memory that is updated to reflect the state
101 * of the file. The length of the buffer is always equal to that
102 * requested. The buffer must be completely set by the caller. When
103 * data has been written, the sfree() function must be called to
104 * indicate that the caller is done writing data to the buffer. This
105 * may or may not cause a physical write.
107 * Short forms of these are salloc_r() and salloc_w() which drop the
108 * 'where' parameter and use the current file pointer. */
111 #define BUFFER_SIZE 8192
113 typedef struct
115 stream st;
117 int fd;
118 gfc_offset buffer_offset; /* File offset of the start of the buffer */
119 gfc_offset physical_offset; /* Current physical file offset */
120 gfc_offset logical_offset; /* Current logical file offset */
121 gfc_offset dirty_offset; /* Start of modified bytes in buffer */
122 gfc_offset file_length; /* Length of the file, -1 if not seekable. */
124 char *buffer;
125 int len; /* Physical length of the current buffer */
126 int active; /* Length of valid bytes in the buffer */
128 int prot;
129 int ndirty; /* Dirty bytes starting at dirty_offset */
131 unsigned unbuffered:1, mmaped:1;
133 char small_buffer[BUFFER_SIZE];
136 unix_stream;
138 /*move_pos_offset()-- Move the record pointer right or left
139 *relative to current position */
142 move_pos_offset (stream* st, int pos_off)
144 unix_stream * str = (unix_stream*)st;
145 if (pos_off < 0)
147 str->active += pos_off;
148 if (str->active < 0)
149 str->active = 0;
151 str->logical_offset += pos_off;
153 if (str->dirty_offset+str->ndirty > str->logical_offset)
155 if (str->ndirty + pos_off > 0)
156 str->ndirty += pos_off ;
157 else
159 str->dirty_offset += pos_off + pos_off;
160 str->ndirty = 0 ;
164 return pos_off ;
166 return 0 ;
170 /* fix_fd()-- Given a file descriptor, make sure it is not one of the
171 * standard descriptors, returning a non-standard descriptor. If the
172 * user specifies that system errors should go to standard output,
173 * then closes standard output, we don't want the system errors to a
174 * file that has been given file descriptor 1 or 0. We want to send
175 * the error to the invalid descriptor. */
177 static int
178 fix_fd (int fd)
180 int input, output, error;
182 input = output = error = 0;
184 /* Unix allocates the lowest descriptors first, so a loop is not
185 required, but this order is. */
187 if (fd == STDIN_FILENO)
189 fd = dup (fd);
190 input = 1;
192 if (fd == STDOUT_FILENO)
194 fd = dup (fd);
195 output = 1;
197 if (fd == STDERR_FILENO)
199 fd = dup (fd);
200 error = 1;
203 if (input)
204 close (STDIN_FILENO);
205 if (output)
206 close (STDOUT_FILENO);
207 if (error)
208 close (STDERR_FILENO);
210 return fd;
214 /* write()-- Write a buffer to a descriptor, allowing for short writes */
216 static int
217 writen (int fd, char *buffer, int len)
219 int n, n0;
221 n0 = len;
223 while (len > 0)
225 n = write (fd, buffer, len);
226 if (n < 0)
227 return n;
229 buffer += n;
230 len -= n;
233 return n0;
237 #if 0
238 /* readn()-- Read bytes into a buffer, allowing for short reads. If
239 * fewer than len bytes are returned, it is because we've hit the end
240 * of file. */
242 static int
243 readn (int fd, char *buffer, int len)
245 int nread, n;
247 nread = 0;
249 while (len > 0)
251 n = read (fd, buffer, len);
252 if (n < 0)
253 return n;
255 if (n == 0)
256 return nread;
258 buffer += n;
259 nread += n;
260 len -= n;
263 return nread;
265 #endif
268 /* get_oserror()-- Get the most recent operating system error. For
269 * unix, this is errno. */
271 const char *
272 get_oserror (void)
274 return strerror (errno);
278 /* sys_exit()-- Terminate the program with an exit code */
280 void
281 sys_exit (int code)
283 exit (code);
287 /*********************************************************************
288 File descriptor stream functions
289 *********************************************************************/
291 /* fd_flush()-- Write bytes that need to be written */
293 static try
294 fd_flush (unix_stream * s)
296 if (s->ndirty == 0)
297 return SUCCESS;;
299 if (s->physical_offset != s->dirty_offset &&
300 lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
301 return FAILURE;
303 if (writen (s->fd, s->buffer + (s->dirty_offset - s->buffer_offset),
304 s->ndirty) < 0)
305 return FAILURE;
307 s->physical_offset = s->dirty_offset + s->ndirty;
309 /* don't increment file_length if the file is non-seekable */
310 if (s->file_length != -1 && s->physical_offset > s->file_length)
311 s->file_length = s->physical_offset;
312 s->ndirty = 0;
314 return SUCCESS;
318 /* fd_alloc()-- Arrange a buffer such that the salloc() request can be
319 * satisfied. This subroutine gets the buffer ready for whatever is
320 * to come next. */
322 static void
323 fd_alloc (unix_stream * s, gfc_offset where, int *len)
325 char *new_buffer;
326 int n, read_len;
328 if (*len <= BUFFER_SIZE)
330 new_buffer = s->small_buffer;
331 read_len = BUFFER_SIZE;
333 else
335 new_buffer = get_mem (*len);
336 read_len = *len;
339 /* Salvage bytes currently within the buffer. This is important for
340 * devices that cannot seek. */
342 if (s->buffer != NULL && s->buffer_offset <= where &&
343 where <= s->buffer_offset + s->active)
346 n = s->active - (where - s->buffer_offset);
347 memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
349 s->active = n;
351 else
352 { /* new buffer starts off empty */
353 s->active = 0;
356 s->buffer_offset = where;
358 /* free the old buffer if necessary */
360 if (s->buffer != NULL && s->buffer != s->small_buffer)
361 free_mem (s->buffer);
363 s->buffer = new_buffer;
364 s->len = read_len;
365 s->mmaped = 0;
369 /* fd_alloc_r_at()-- Allocate a stream buffer for reading. Either
370 * we've already buffered the data or we need to load it. Returns
371 * NULL on I/O error. */
373 static char *
374 fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
376 gfc_offset m;
377 int n;
379 if (where == -1)
380 where = s->logical_offset;
382 if (s->buffer != NULL && s->buffer_offset <= where &&
383 where + *len <= s->buffer_offset + s->active)
386 /* Return a position within the current buffer */
388 s->logical_offset = where + *len;
389 return s->buffer + where - s->buffer_offset;
392 fd_alloc (s, where, len);
394 m = where + s->active;
396 if (s->physical_offset != m && lseek (s->fd, m, SEEK_SET) < 0)
397 return NULL;
399 n = read (s->fd, s->buffer + s->active, s->len - s->active);
400 if (n < 0)
401 return NULL;
403 s->physical_offset = where + n;
405 s->active += n;
406 if (s->active < *len)
407 *len = s->active; /* Bytes actually available */
409 s->logical_offset = where + *len;
411 return s->buffer;
415 /* fd_alloc_w_at()-- Allocate a stream buffer for writing. Either
416 * we've already buffered the data or we need to load it. */
418 static char *
419 fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
421 gfc_offset n;
423 if (where == -1)
424 where = s->logical_offset;
426 if (s->buffer == NULL || s->buffer_offset > where ||
427 where + *len > s->buffer_offset + s->len)
430 if (fd_flush (s) == FAILURE)
431 return NULL;
432 fd_alloc (s, where, len);
435 /* Return a position within the current buffer */
436 if (s->ndirty == 0
437 || where > s->dirty_offset + s->ndirty
438 || s->dirty_offset > where + *len)
439 { /* Discontiguous blocks, start with a clean buffer. */
440 /* Flush the buffer. */
441 if (s->ndirty != 0)
442 fd_flush (s);
443 s->dirty_offset = where;
444 s->ndirty = *len;
446 else
448 gfc_offset start; /* Merge with the existing data. */
449 if (where < s->dirty_offset)
450 start = where;
451 else
452 start = s->dirty_offset;
453 if (where + *len > s->dirty_offset + s->ndirty)
454 s->ndirty = where + *len - start;
455 else
456 s->ndirty = s->dirty_offset + s->ndirty - start;
457 s->dirty_offset = start;
460 s->logical_offset = where + *len;
462 if (where + *len > s->file_length)
463 s->file_length = where + *len;
465 n = s->logical_offset - s->buffer_offset;
466 if (n > s->active)
467 s->active = n;
469 return s->buffer + where - s->buffer_offset;
473 static try
474 fd_sfree (unix_stream * s)
476 if (s->ndirty != 0 &&
477 (s->buffer != s->small_buffer || options.all_unbuffered ||
478 s->unbuffered))
479 return fd_flush (s);
481 return SUCCESS;
485 static int
486 fd_seek (unix_stream * s, gfc_offset offset)
488 s->physical_offset = s->logical_offset = offset;
490 return (lseek (s->fd, offset, SEEK_SET) < 0) ? FAILURE : SUCCESS;
494 /* truncate_file()-- Given a unit, truncate the file at the current
495 * position. Sets the physical location to the new end of the file.
496 * Returns nonzero on error. */
498 static try
499 fd_truncate (unix_stream * s)
501 if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
502 return FAILURE;
504 /* non-seekable files, like terminals and fifo's fail the lseek.
505 the fd is a regular file at this point */
507 if (ftruncate (s->fd, s->logical_offset))
508 return FAILURE;
510 s->physical_offset = s->file_length = s->logical_offset;
512 return SUCCESS;
516 static try
517 fd_close (unix_stream * s)
519 if (fd_flush (s) == FAILURE)
520 return FAILURE;
522 if (s->buffer != NULL && s->buffer != s->small_buffer)
523 free_mem (s->buffer);
525 if (close (s->fd) < 0)
526 return FAILURE;
528 free_mem (s);
530 return SUCCESS;
534 static void
535 fd_open (unix_stream * s)
537 if (isatty (s->fd))
538 s->unbuffered = 1;
540 s->st.alloc_r_at = (void *) fd_alloc_r_at;
541 s->st.alloc_w_at = (void *) fd_alloc_w_at;
542 s->st.sfree = (void *) fd_sfree;
543 s->st.close = (void *) fd_close;
544 s->st.seek = (void *) fd_seek;
545 s->st.truncate = (void *) fd_truncate;
547 s->buffer = NULL;
551 /*********************************************************************
552 mmap stream functions
554 Because mmap() is not capable of extending a file, we have to keep
555 track of how long the file is. We also have to be able to detect end
556 of file conditions. If there are multiple writers to the file (which
557 can only happen outside the current program), things will get
558 confused. Then again, things will get confused anyway.
560 *********************************************************************/
562 #if HAVE_MMAP
564 static int page_size, page_mask;
566 /* mmap_flush()-- Deletes a memory mapping if something is mapped. */
568 static try
569 mmap_flush (unix_stream * s)
571 if (!s->mmaped)
572 return fd_flush (s);
574 if (s->buffer == NULL)
575 return SUCCESS;
577 if (munmap (s->buffer, s->active))
578 return FAILURE;
580 s->buffer = NULL;
581 s->active = 0;
583 return SUCCESS;
587 /* mmap_alloc()-- mmap() a section of the file. The whole section is
588 * guaranteed to be mappable. */
590 static try
591 mmap_alloc (unix_stream * s, gfc_offset where, int *len)
593 gfc_offset offset;
594 int length;
595 char *p;
597 if (mmap_flush (s) == FAILURE)
598 return FAILURE;
600 offset = where & page_mask; /* Round down to the next page */
602 length = ((where - offset) & page_mask) + 2 * page_size;
604 p = mmap (NULL, length, s->prot, MAP_SHARED, s->fd, offset);
605 if (p == (char *) MAP_FAILED)
606 return FAILURE;
608 s->mmaped = 1;
609 s->buffer = p;
610 s->buffer_offset = offset;
611 s->active = length;
613 return SUCCESS;
617 static char *
618 mmap_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
620 gfc_offset m;
622 if (where == -1)
623 where = s->logical_offset;
625 m = where + *len;
627 if ((s->buffer == NULL || s->buffer_offset > where ||
628 m > s->buffer_offset + s->active) &&
629 mmap_alloc (s, where, len) == FAILURE)
630 return NULL;
632 if (m > s->file_length)
634 *len = s->file_length - s->logical_offset;
635 s->logical_offset = s->file_length;
637 else
638 s->logical_offset = m;
640 return s->buffer + (where - s->buffer_offset);
644 static char *
645 mmap_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
647 if (where == -1)
648 where = s->logical_offset;
650 /* If we're extending the file, we have to use file descriptor
651 * methods. */
653 if (where + *len > s->file_length)
655 if (s->mmaped)
656 mmap_flush (s);
657 return fd_alloc_w_at (s, len, where);
660 if ((s->buffer == NULL || s->buffer_offset > where ||
661 where + *len > s->buffer_offset + s->active ||
662 where < s->buffer_offset + s->active) &&
663 mmap_alloc (s, where, len) == FAILURE)
664 return NULL;
666 s->logical_offset = where + *len;
668 return s->buffer + where - s->buffer_offset;
672 static int
673 mmap_seek (unix_stream * s, gfc_offset offset)
675 s->logical_offset = offset;
676 return SUCCESS;
680 static try
681 mmap_close (unix_stream * s)
683 try t;
685 t = mmap_flush (s);
687 if (close (s->fd) < 0)
688 t = FAILURE;
689 free_mem (s);
691 return t;
695 static try
696 mmap_sfree (unix_stream * s)
698 return SUCCESS;
702 /* mmap_open()-- mmap_specific open. If the particular file cannot be
703 * mmap()-ed, we fall back to the file descriptor functions. */
705 static try
706 mmap_open (unix_stream * s)
708 char *p;
709 int i;
711 page_size = getpagesize ();
712 page_mask = ~0;
714 p = mmap (0, page_size, s->prot, MAP_SHARED, s->fd, 0);
715 if (p == (char *) MAP_FAILED)
717 fd_open (s);
718 return SUCCESS;
721 munmap (p, page_size);
723 i = page_size >> 1;
724 while (i != 0)
726 page_mask <<= 1;
727 i >>= 1;
730 s->st.alloc_r_at = (void *) mmap_alloc_r_at;
731 s->st.alloc_w_at = (void *) mmap_alloc_w_at;
732 s->st.sfree = (void *) mmap_sfree;
733 s->st.close = (void *) mmap_close;
734 s->st.seek = (void *) mmap_seek;
735 s->st.truncate = (void *) fd_truncate;
737 if (lseek (s->fd, s->file_length, SEEK_SET) < 0)
738 return FAILURE;
740 return SUCCESS;
743 #endif
746 /*********************************************************************
747 memory stream functions - These are used for internal files
749 The idea here is that a single stream structure is created and all
750 requests must be satisfied from it. The location and size of the
751 buffer is the character variable supplied to the READ or WRITE
752 statement.
754 *********************************************************************/
757 static char *
758 mem_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
760 gfc_offset n;
762 if (where == -1)
763 where = s->logical_offset;
765 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
766 return NULL;
768 s->logical_offset = where + *len;
770 n = s->buffer_offset + s->active - where;
771 if (*len > n)
772 *len = n;
774 return s->buffer + (where - s->buffer_offset);
778 static char *
779 mem_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
781 gfc_offset m;
783 if (where == -1)
784 where = s->logical_offset;
786 m = where + *len;
788 if (where < s->buffer_offset || m > s->buffer_offset + s->active)
789 return NULL;
791 s->logical_offset = m;
793 return s->buffer + (where - s->buffer_offset);
797 static int
798 mem_seek (unix_stream * s, gfc_offset offset)
800 if (offset > s->file_length)
802 errno = ESPIPE;
803 return FAILURE;
806 s->logical_offset = offset;
807 return SUCCESS;
811 static int
812 mem_truncate (unix_stream * s)
814 return SUCCESS;
818 static try
819 mem_close (unix_stream * s)
821 free_mem (s);
823 return SUCCESS;
827 static try
828 mem_sfree (unix_stream * s)
830 return SUCCESS;
835 /*********************************************************************
836 Public functions -- A reimplementation of this module needs to
837 define functional equivalents of the following.
838 *********************************************************************/
840 /* empty_internal_buffer()-- Zero the buffer of Internal file */
842 void
843 empty_internal_buffer(stream *strm)
845 unix_stream * s = (unix_stream *) strm;
846 memset(s->buffer, ' ', s->file_length);
849 /* open_internal()-- Returns a stream structure from an internal file */
851 stream *
852 open_internal (char *base, int length)
854 unix_stream *s;
856 s = get_mem (sizeof (unix_stream));
858 s->buffer = base;
859 s->buffer_offset = 0;
861 s->logical_offset = 0;
862 s->active = s->file_length = length;
864 s->st.alloc_r_at = (void *) mem_alloc_r_at;
865 s->st.alloc_w_at = (void *) mem_alloc_w_at;
866 s->st.sfree = (void *) mem_sfree;
867 s->st.close = (void *) mem_close;
868 s->st.seek = (void *) mem_seek;
869 s->st.truncate = (void *) mem_truncate;
871 return (stream *) s;
875 /* fd_to_stream()-- Given an open file descriptor, build a stream
876 * around it. */
878 static stream *
879 fd_to_stream (int fd, int prot)
881 struct stat statbuf;
882 unix_stream *s;
884 s = get_mem (sizeof (unix_stream));
886 s->fd = fd;
887 s->buffer_offset = 0;
888 s->physical_offset = 0;
889 s->logical_offset = 0;
890 s->prot = prot;
892 /* Get the current length of the file. */
894 fstat (fd, &statbuf);
895 s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
897 #if HAVE_MMAP
898 mmap_open (s);
899 #else
900 fd_open (s);
901 #endif
903 return (stream *) s;
907 /* Given the Fortran unit number, convert it to a C file descriptor. */
910 unit_to_fd(int unit)
912 gfc_unit *us;
914 us = find_unit(unit);
915 if (us == NULL)
916 return -1;
918 return ((unix_stream *) us->s)->fd;
922 /* unpack_filename()-- Given a fortran string and a pointer to a
923 * buffer that is PATH_MAX characters, convert the fortran string to a
924 * C string in the buffer. Returns nonzero if this is not possible. */
926 static int
927 unpack_filename (char *cstring, const char *fstring, int len)
929 len = fstrlen (fstring, len);
930 if (len >= PATH_MAX)
931 return 1;
933 memmove (cstring, fstring, len);
934 cstring[len] = '\0';
936 return 0;
940 /* tempfile()-- Generate a temporary filename for a scratch file and
941 * open it. mkstemp() opens the file for reading and writing, but the
942 * library mode prevents anything that is not allowed. The descriptor
943 * is returned, which is -1 on error. The template is pointed to by
944 * ioparm.file, which is copied into the unit structure
945 * and freed later. */
947 static int
948 tempfile (void)
950 const char *tempdir;
951 char *template;
952 int fd;
954 tempdir = getenv ("GFORTRAN_TMPDIR");
955 if (tempdir == NULL)
956 tempdir = getenv ("TMP");
957 if (tempdir == NULL)
958 tempdir = DEFAULT_TEMPDIR;
960 template = get_mem (strlen (tempdir) + 20);
962 st_sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
964 #ifdef HAVE_MKSTEMP
966 fd = mkstemp (template);
968 #else /* HAVE_MKSTEMP */
970 if (mktemp (template))
972 fd = open (template, O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
973 while (!(fd == -1 && errno == EEXIST) && mktemp (template));
974 else
975 fd = -1;
977 #endif /* HAVE_MKSTEMP */
979 if (fd < 0)
980 free_mem (template);
981 else
983 ioparm.file = template;
984 ioparm.file_len = strlen (template); /* Don't include trailing nul */
987 return fd;
991 /* regular_file()-- Open a regular file.
992 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
993 * Returns the descriptor, which is less than zero on error. */
995 static int
996 regular_file (unit_flags *flags)
998 char path[PATH_MAX + 1];
999 struct stat statbuf;
1000 int mode;
1001 int rwflag;
1002 int fd;
1004 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1006 errno = ENOENT; /* Fake an OS error */
1007 return -1;
1010 rwflag = 0;
1012 switch (flags->action)
1014 case ACTION_READ:
1015 rwflag = O_RDONLY;
1016 break;
1018 case ACTION_WRITE:
1019 rwflag = O_WRONLY;
1020 break;
1022 case ACTION_READWRITE:
1023 case ACTION_UNSPECIFIED:
1024 rwflag = O_RDWR;
1025 break;
1027 default:
1028 internal_error ("regular_file(): Bad action");
1031 switch (flags->status)
1033 case STATUS_NEW:
1034 rwflag |= O_CREAT | O_EXCL;
1035 break;
1037 case STATUS_OLD: /* file must exist, so check for its existence */
1038 if (stat (path, &statbuf) < 0)
1039 return -1;
1040 break;
1042 case STATUS_UNKNOWN:
1043 case STATUS_SCRATCH:
1044 rwflag |= O_CREAT;
1045 break;
1047 case STATUS_REPLACE:
1048 rwflag |= O_CREAT | O_TRUNC;
1049 break;
1051 default:
1052 internal_error ("regular_file(): Bad status");
1055 /* rwflag |= O_LARGEFILE; */
1057 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
1058 fd = open (path, rwflag, mode);
1059 if (flags->action == ACTION_UNSPECIFIED)
1061 if (fd < 0)
1063 rwflag = rwflag & !O_RDWR | O_RDONLY;
1064 fd = open (path, rwflag, mode);
1065 if (fd < 0)
1067 rwflag = rwflag & !O_RDONLY | O_WRONLY;
1068 fd = open (path, rwflag, mode);
1069 if (fd < 0)
1070 flags->action = ACTION_READWRITE; /* Could not open at all. */
1071 else
1072 flags->action = ACTION_WRITE;
1074 else
1075 flags->action = ACTION_READ;
1077 else
1078 flags->action = ACTION_READWRITE;
1080 return fd;
1084 /* open_external()-- Open an external file, unix specific version.
1085 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
1086 * Returns NULL on operating system error. */
1088 stream *
1089 open_external (unit_flags *flags)
1091 int fd, prot;
1093 if (flags->status == STATUS_SCRATCH)
1095 fd = tempfile ();
1096 if (flags->action == ACTION_UNSPECIFIED)
1097 flags->action = ACTION_READWRITE;
1098 /* We can unlink scratch files now and it will go away when closed. */
1099 unlink (ioparm.file);
1101 else
1103 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED. */
1104 fd = regular_file (flags);
1107 if (fd < 0)
1108 return NULL;
1109 fd = fix_fd (fd);
1111 switch (flags->action)
1113 case ACTION_READ:
1114 prot = PROT_READ;
1115 break;
1117 case ACTION_WRITE:
1118 prot = PROT_WRITE;
1119 break;
1121 case ACTION_READWRITE:
1122 prot = PROT_READ | PROT_WRITE;
1123 break;
1125 default:
1126 internal_error ("open_external(): Bad action");
1129 return fd_to_stream (fd, prot);
1133 /* input_stream()-- Return a stream pointer to the default input stream.
1134 * Called on initialization. */
1136 stream *
1137 input_stream (void)
1139 return fd_to_stream (STDIN_FILENO, PROT_READ);
1143 /* output_stream()-- Return a stream pointer to the default input stream.
1144 * Called on initialization. */
1146 stream *
1147 output_stream (void)
1149 return fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1153 /* init_error_stream()-- Return a pointer to the error stream. This
1154 * subroutine is called when the stream is needed, rather than at
1155 * initialization. We want to work even if memory has been seriously
1156 * corrupted. */
1158 stream *
1159 init_error_stream (void)
1161 static unix_stream error;
1163 memset (&error, '\0', sizeof (error));
1165 error.fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1167 error.st.alloc_w_at = (void *) fd_alloc_w_at;
1168 error.st.sfree = (void *) fd_sfree;
1170 error.unbuffered = 1;
1171 error.buffer = error.small_buffer;
1173 return (stream *) & error;
1177 /* compare_file_filename()-- Given an open stream and a fortran string
1178 * that is a filename, figure out if the file is the same as the
1179 * filename. */
1182 compare_file_filename (stream * s, const char *name, int len)
1184 char path[PATH_MAX + 1];
1185 struct stat st1, st2;
1187 if (unpack_filename (path, name, len))
1188 return 0; /* Can't be the same */
1190 /* If the filename doesn't exist, then there is no match with the
1191 * existing file. */
1193 if (stat (path, &st1) < 0)
1194 return 0;
1196 fstat (((unix_stream *) s)->fd, &st2);
1198 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
1202 /* find_file0()-- Recursive work function for find_file() */
1204 static gfc_unit *
1205 find_file0 (gfc_unit * u, struct stat *st1)
1207 struct stat st2;
1208 gfc_unit *v;
1210 if (u == NULL)
1211 return NULL;
1213 if (fstat (((unix_stream *) u->s)->fd, &st2) >= 0 &&
1214 st1->st_dev == st2.st_dev && st1->st_ino == st2.st_ino)
1215 return u;
1217 v = find_file0 (u->left, st1);
1218 if (v != NULL)
1219 return v;
1221 v = find_file0 (u->right, st1);
1222 if (v != NULL)
1223 return v;
1225 return NULL;
1229 /* find_file()-- Take the current filename and see if there is a unit
1230 * that has the file already open. Returns a pointer to the unit if so. */
1232 gfc_unit *
1233 find_file (void)
1235 char path[PATH_MAX + 1];
1236 struct stat statbuf;
1238 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1239 return NULL;
1241 if (stat (path, &statbuf) < 0)
1242 return NULL;
1244 return find_file0 (g.unit_root, &statbuf);
1248 /* stream_at_bof()-- Returns nonzero if the stream is at the beginning
1249 * of the file. */
1252 stream_at_bof (stream * s)
1254 unix_stream *us;
1256 us = (unix_stream *) s;
1258 if (!us->mmaped)
1259 return 0; /* File is not seekable */
1261 return us->logical_offset == 0;
1265 /* stream_at_eof()-- Returns nonzero if the stream is at the beginning
1266 * of the file. */
1269 stream_at_eof (stream * s)
1271 unix_stream *us;
1273 us = (unix_stream *) s;
1275 if (!us->mmaped)
1276 return 0; /* File is not seekable */
1278 return us->logical_offset == us->dirty_offset;
1282 /* delete_file()-- Given a unit structure, delete the file associated
1283 * with the unit. Returns nonzero if something went wrong. */
1286 delete_file (gfc_unit * u)
1288 char path[PATH_MAX + 1];
1290 if (unpack_filename (path, u->file, u->file_len))
1291 { /* Shouldn't be possible */
1292 errno = ENOENT;
1293 return 1;
1296 return unlink (path);
1300 /* file_exists()-- Returns nonzero if the current filename exists on
1301 * the system */
1304 file_exists (void)
1306 char path[PATH_MAX + 1];
1307 struct stat statbuf;
1309 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1310 return 0;
1312 if (stat (path, &statbuf) < 0)
1313 return 0;
1315 return 1;
1320 static const char *yes = "YES", *no = "NO", *unknown = "UNKNOWN";
1322 /* inquire_sequential()-- Given a fortran string, determine if the
1323 * file is suitable for sequential access. Returns a C-style
1324 * string. */
1326 const char *
1327 inquire_sequential (const char *string, int len)
1329 char path[PATH_MAX + 1];
1330 struct stat statbuf;
1332 if (string == NULL ||
1333 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1334 return unknown;
1336 if (S_ISREG (statbuf.st_mode) ||
1337 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1338 return yes;
1340 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1341 return no;
1343 return unknown;
1347 /* inquire_direct()-- Given a fortran string, determine if the file is
1348 * suitable for direct access. Returns a C-style string. */
1350 const char *
1351 inquire_direct (const char *string, int len)
1353 char path[PATH_MAX + 1];
1354 struct stat statbuf;
1356 if (string == NULL ||
1357 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1358 return unknown;
1360 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1361 return yes;
1363 if (S_ISDIR (statbuf.st_mode) ||
1364 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1365 return no;
1367 return unknown;
1371 /* inquire_formatted()-- Given a fortran string, determine if the file
1372 * is suitable for formatted form. Returns a C-style string. */
1374 const char *
1375 inquire_formatted (const char *string, int len)
1377 char path[PATH_MAX + 1];
1378 struct stat statbuf;
1380 if (string == NULL ||
1381 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1382 return unknown;
1384 if (S_ISREG (statbuf.st_mode) ||
1385 S_ISBLK (statbuf.st_mode) ||
1386 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1387 return yes;
1389 if (S_ISDIR (statbuf.st_mode))
1390 return no;
1392 return unknown;
1396 /* inquire_unformatted()-- Given a fortran string, determine if the file
1397 * is suitable for unformatted form. Returns a C-style string. */
1399 const char *
1400 inquire_unformatted (const char *string, int len)
1402 return inquire_formatted (string, len);
1406 /* inquire_access()-- Given a fortran string, determine if the file is
1407 * suitable for access. */
1409 static const char *
1410 inquire_access (const char *string, int len, int mode)
1412 char path[PATH_MAX + 1];
1414 if (string == NULL || unpack_filename (path, string, len) ||
1415 access (path, mode) < 0)
1416 return no;
1418 return yes;
1422 /* inquire_read()-- Given a fortran string, determine if the file is
1423 * suitable for READ access. */
1425 const char *
1426 inquire_read (const char *string, int len)
1428 return inquire_access (string, len, R_OK);
1432 /* inquire_write()-- Given a fortran string, determine if the file is
1433 * suitable for READ access. */
1435 const char *
1436 inquire_write (const char *string, int len)
1438 return inquire_access (string, len, W_OK);
1442 /* inquire_readwrite()-- Given a fortran string, determine if the file is
1443 * suitable for read and write access. */
1445 const char *
1446 inquire_readwrite (const char *string, int len)
1448 return inquire_access (string, len, R_OK | W_OK);
1452 /* file_length()-- Return the file length in bytes, -1 if unknown */
1454 gfc_offset
1455 file_length (stream * s)
1457 return ((unix_stream *) s)->file_length;
1461 /* file_position()-- Return the current position of the file */
1463 gfc_offset
1464 file_position (stream * s)
1466 return ((unix_stream *) s)->logical_offset;
1470 /* is_seekable()-- Return nonzero if the stream is seekable, zero if
1471 * it is not */
1474 is_seekable (stream * s)
1476 /* by convention, if file_length == -1, the file is not seekable
1477 note that a mmapped file is always seekable, an fd_ file may
1478 or may not be. */
1479 return ((unix_stream *) s)->file_length!=-1;
1483 flush (stream *s)
1485 return fd_flush( (unix_stream *) s);
1489 /* How files are stored: This is an operating-system specific issue,
1490 and therefore belongs here. There are three cases to consider.
1492 Direct Access:
1493 Records are written as block of bytes corresponding to the record
1494 length of the file. This goes for both formatted and unformatted
1495 records. Positioning is done explicitly for each data transfer,
1496 so positioning is not much of an issue.
1498 Sequential Formatted:
1499 Records are separated by newline characters. The newline character
1500 is prohibited from appearing in a string. If it does, this will be
1501 messed up on the next read. End of file is also the end of a record.
1503 Sequential Unformatted:
1504 In this case, we are merely copying bytes to and from main storage,
1505 yet we need to keep track of varying record lengths. We adopt
1506 the solution used by f2c. Each record contains a pair of length
1507 markers:
1509 Length of record n in bytes
1510 Data of record n
1511 Length of record n in bytes
1513 Length of record n+1 in bytes
1514 Data of record n+1
1515 Length of record n+1 in bytes
1517 The length is stored at the end of a record to allow backspacing to the
1518 previous record. Between data transfer statements, the file pointer
1519 is left pointing to the first length of the current record.
1521 ENDFILE records are never explicitly stored.