2016-09-25 François Dumont <fdumont@gcc.gnu.org>
[official-gcc.git] / libgfortran / io / unix.c
blob29818cd7a1401557fb5c697946ba00375e43286b
1 /* Copyright (C) 2002-2016 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3 F2003 I/O support contributed by Jerry DeLisle
5 This file is part of the GNU Fortran 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 3, or (at your option)
10 any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 /* Unix stream I/O module */
28 #include "io.h"
29 #include "unix.h"
30 #include <stdlib.h>
31 #include <limits.h>
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <assert.h>
41 #include <string.h>
42 #include <errno.h>
45 /* For mingw, we don't identify files by their inode number, but by a
46 64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
47 #ifdef __MINGW32__
49 #define WIN32_LEAN_AND_MEAN
50 #include <windows.h>
52 #if !defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
53 #undef lseek
54 #define lseek _lseeki64
55 #undef fstat
56 #define fstat _fstati64
57 #undef stat
58 #define stat _stati64
59 #endif
61 #ifndef HAVE_WORKING_STAT
62 static uint64_t
63 id_from_handle (HANDLE hFile)
65 BY_HANDLE_FILE_INFORMATION FileInformation;
67 if (hFile == INVALID_HANDLE_VALUE)
68 return 0;
70 memset (&FileInformation, 0, sizeof(FileInformation));
71 if (!GetFileInformationByHandle (hFile, &FileInformation))
72 return 0;
74 return ((uint64_t) FileInformation.nFileIndexLow)
75 | (((uint64_t) FileInformation.nFileIndexHigh) << 32);
79 static uint64_t
80 id_from_path (const char *path)
82 HANDLE hFile;
83 uint64_t res;
85 if (!path || !*path || access (path, F_OK))
86 return (uint64_t) -1;
88 hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
89 FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
90 NULL);
91 res = id_from_handle (hFile);
92 CloseHandle (hFile);
93 return res;
97 static uint64_t
98 id_from_fd (const int fd)
100 return id_from_handle ((HANDLE) _get_osfhandle (fd));
103 #endif /* HAVE_WORKING_STAT */
106 /* On mingw, we don't use umask in tempfile_open(), because it
107 doesn't support the user/group/other-based permissions. */
108 #undef HAVE_UMASK
110 #endif /* __MINGW32__ */
113 /* These flags aren't defined on all targets (mingw32), so provide them
114 here. */
115 #ifndef S_IRGRP
116 #define S_IRGRP 0
117 #endif
119 #ifndef S_IWGRP
120 #define S_IWGRP 0
121 #endif
123 #ifndef S_IROTH
124 #define S_IROTH 0
125 #endif
127 #ifndef S_IWOTH
128 #define S_IWOTH 0
129 #endif
132 #ifndef HAVE_ACCESS
134 #ifndef W_OK
135 #define W_OK 2
136 #endif
138 #ifndef R_OK
139 #define R_OK 4
140 #endif
142 #ifndef F_OK
143 #define F_OK 0
144 #endif
146 /* Fallback implementation of access() on systems that don't have it.
147 Only modes R_OK, W_OK and F_OK are used in this file. */
149 static int
150 fallback_access (const char *path, int mode)
152 int fd;
154 if ((mode & R_OK) && (fd = open (path, O_RDONLY)) < 0)
155 return -1;
156 close (fd);
158 if ((mode & W_OK) && (fd = open (path, O_WRONLY)) < 0)
159 return -1;
160 close (fd);
162 if (mode == F_OK)
164 struct stat st;
165 return stat (path, &st);
168 return 0;
171 #undef access
172 #define access fallback_access
173 #endif
176 /* Fallback directory for creating temporary files. P_tmpdir is
177 defined on many POSIX platforms. */
178 #ifndef P_tmpdir
179 #ifdef _P_tmpdir
180 #define P_tmpdir _P_tmpdir /* MinGW */
181 #else
182 #define P_tmpdir "/tmp"
183 #endif
184 #endif
187 /* Unix and internal stream I/O module */
189 static const int BUFFER_SIZE = 8192;
191 typedef struct
193 stream st;
195 gfc_offset buffer_offset; /* File offset of the start of the buffer */
196 gfc_offset physical_offset; /* Current physical file offset */
197 gfc_offset logical_offset; /* Current logical file offset */
198 gfc_offset file_length; /* Length of the file. */
200 char *buffer; /* Pointer to the buffer. */
201 int fd; /* The POSIX file descriptor. */
203 int active; /* Length of valid bytes in the buffer */
205 int ndirty; /* Dirty bytes starting at buffer_offset */
207 /* Cached stat(2) values. */
208 dev_t st_dev;
209 ino_t st_ino;
211 bool unbuffered; /* Buffer should be flushed after each I/O statement. */
213 unix_stream;
216 /* fix_fd()-- Given a file descriptor, make sure it is not one of the
217 * standard descriptors, returning a non-standard descriptor. If the
218 * user specifies that system errors should go to standard output,
219 * then closes standard output, we don't want the system errors to a
220 * file that has been given file descriptor 1 or 0. We want to send
221 * the error to the invalid descriptor. */
223 static int
224 fix_fd (int fd)
226 #ifdef HAVE_DUP
227 int input, output, error;
229 input = output = error = 0;
231 /* Unix allocates the lowest descriptors first, so a loop is not
232 required, but this order is. */
233 if (fd == STDIN_FILENO)
235 fd = dup (fd);
236 input = 1;
238 if (fd == STDOUT_FILENO)
240 fd = dup (fd);
241 output = 1;
243 if (fd == STDERR_FILENO)
245 fd = dup (fd);
246 error = 1;
249 if (input)
250 close (STDIN_FILENO);
251 if (output)
252 close (STDOUT_FILENO);
253 if (error)
254 close (STDERR_FILENO);
255 #endif
257 return fd;
261 /* If the stream corresponds to a preconnected unit, we flush the
262 corresponding C stream. This is bugware for mixed C-Fortran codes
263 where the C code doesn't flush I/O before returning. */
264 void
265 flush_if_preconnected (stream * s)
267 int fd;
269 fd = ((unix_stream *) s)->fd;
270 if (fd == STDIN_FILENO)
271 fflush (stdin);
272 else if (fd == STDOUT_FILENO)
273 fflush (stdout);
274 else if (fd == STDERR_FILENO)
275 fflush (stderr);
279 /********************************************************************
280 Raw I/O functions (read, write, seek, tell, truncate, close).
282 These functions wrap the basic POSIX I/O syscalls. Any deviation in
283 semantics is a bug, except the following: write restarts in case
284 of being interrupted by a signal, and as the first argument the
285 functions take the unix_stream struct rather than an integer file
286 descriptor. Also, for POSIX read() and write() a nbyte argument larger
287 than SSIZE_MAX is undefined; here the type of nbyte is ssize_t rather
288 than size_t as for POSIX read/write.
289 *********************************************************************/
291 static int
292 raw_flush (unix_stream * s __attribute__ ((unused)))
294 return 0;
297 static ssize_t
298 raw_read (unix_stream * s, void * buf, ssize_t nbyte)
300 /* For read we can't do I/O in a loop like raw_write does, because
301 that will break applications that wait for interactive I/O. */
302 return read (s->fd, buf, nbyte);
305 static ssize_t
306 raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
308 ssize_t trans, bytes_left;
309 char *buf_st;
311 bytes_left = nbyte;
312 buf_st = (char *) buf;
314 /* We must write in a loop since some systems don't restart system
315 calls in case of a signal. */
316 while (bytes_left > 0)
318 trans = write (s->fd, buf_st, bytes_left);
319 if (trans < 0)
321 if (errno == EINTR)
322 continue;
323 else
324 return trans;
326 buf_st += trans;
327 bytes_left -= trans;
330 return nbyte - bytes_left;
333 static gfc_offset
334 raw_seek (unix_stream * s, gfc_offset offset, int whence)
336 return lseek (s->fd, offset, whence);
339 static gfc_offset
340 raw_tell (unix_stream * s)
342 return lseek (s->fd, 0, SEEK_CUR);
345 static gfc_offset
346 raw_size (unix_stream * s)
348 struct stat statbuf;
349 int ret = fstat (s->fd, &statbuf);
350 if (ret == -1)
351 return ret;
352 if (S_ISREG (statbuf.st_mode))
353 return statbuf.st_size;
354 else
355 return 0;
358 static int
359 raw_truncate (unix_stream * s, gfc_offset length)
361 #ifdef __MINGW32__
362 HANDLE h;
363 gfc_offset cur;
365 if (isatty (s->fd))
367 errno = EBADF;
368 return -1;
370 h = (HANDLE) _get_osfhandle (s->fd);
371 if (h == INVALID_HANDLE_VALUE)
373 errno = EBADF;
374 return -1;
376 cur = lseek (s->fd, 0, SEEK_CUR);
377 if (cur == -1)
378 return -1;
379 if (lseek (s->fd, length, SEEK_SET) == -1)
380 goto error;
381 if (!SetEndOfFile (h))
383 errno = EBADF;
384 goto error;
386 if (lseek (s->fd, cur, SEEK_SET) == -1)
387 return -1;
388 return 0;
389 error:
390 lseek (s->fd, cur, SEEK_SET);
391 return -1;
392 #elif defined HAVE_FTRUNCATE
393 return ftruncate (s->fd, length);
394 #elif defined HAVE_CHSIZE
395 return chsize (s->fd, length);
396 #else
397 runtime_error ("required ftruncate or chsize support not present");
398 return -1;
399 #endif
402 static int
403 raw_close (unix_stream * s)
405 int retval;
407 if (s->fd == -1)
408 retval = -1;
409 else if (s->fd != STDOUT_FILENO
410 && s->fd != STDERR_FILENO
411 && s->fd != STDIN_FILENO)
412 retval = close (s->fd);
413 else
414 retval = 0;
415 free (s);
416 return retval;
419 static int
420 raw_markeor (unix_stream * s __attribute__ ((unused)))
422 return 0;
425 static const struct stream_vtable raw_vtable = {
426 .read = (void *) raw_read,
427 .write = (void *) raw_write,
428 .seek = (void *) raw_seek,
429 .tell = (void *) raw_tell,
430 .size = (void *) raw_size,
431 .trunc = (void *) raw_truncate,
432 .close = (void *) raw_close,
433 .flush = (void *) raw_flush,
434 .markeor = (void *) raw_markeor
437 static int
438 raw_init (unix_stream * s)
440 s->st.vptr = &raw_vtable;
442 s->buffer = NULL;
443 return 0;
447 /*********************************************************************
448 Buffered I/O functions. These functions have the same semantics as the
449 raw I/O functions above, except that they are buffered in order to
450 improve performance. The buffer must be flushed when switching from
451 reading to writing and vice versa.
452 *********************************************************************/
454 static int
455 buf_flush (unix_stream * s)
457 int writelen;
459 /* Flushing in read mode means discarding read bytes. */
460 s->active = 0;
462 if (s->ndirty == 0)
463 return 0;
465 if (s->physical_offset != s->buffer_offset
466 && lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
467 return -1;
469 writelen = raw_write (s, s->buffer, s->ndirty);
471 s->physical_offset = s->buffer_offset + writelen;
473 if (s->physical_offset > s->file_length)
474 s->file_length = s->physical_offset;
476 s->ndirty -= writelen;
477 if (s->ndirty != 0)
478 return -1;
480 return 0;
483 static ssize_t
484 buf_read (unix_stream * s, void * buf, ssize_t nbyte)
486 if (s->active == 0)
487 s->buffer_offset = s->logical_offset;
489 /* Is the data we want in the buffer? */
490 if (s->logical_offset + nbyte <= s->buffer_offset + s->active
491 && s->buffer_offset <= s->logical_offset)
493 /* When nbyte == 0, buf can be NULL which would lead to undefined
494 behavior if we called memcpy(). */
495 if (nbyte != 0)
496 memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset),
497 nbyte);
499 else
501 /* First copy the active bytes if applicable, then read the rest
502 either directly or filling the buffer. */
503 char *p;
504 int nread = 0;
505 ssize_t to_read, did_read;
506 gfc_offset new_logical;
508 p = (char *) buf;
509 if (s->logical_offset >= s->buffer_offset
510 && s->buffer_offset + s->active >= s->logical_offset)
512 nread = s->active - (s->logical_offset - s->buffer_offset);
513 memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset),
514 nread);
515 p += nread;
517 /* At this point we consider all bytes in the buffer discarded. */
518 to_read = nbyte - nread;
519 new_logical = s->logical_offset + nread;
520 if (s->physical_offset != new_logical
521 && lseek (s->fd, new_logical, SEEK_SET) < 0)
522 return -1;
523 s->buffer_offset = s->physical_offset = new_logical;
524 if (to_read <= BUFFER_SIZE/2)
526 did_read = raw_read (s, s->buffer, BUFFER_SIZE);
527 if (likely (did_read >= 0))
529 s->physical_offset += did_read;
530 s->active = did_read;
531 did_read = (did_read > to_read) ? to_read : did_read;
532 memcpy (p, s->buffer, did_read);
534 else
535 return did_read;
537 else
539 did_read = raw_read (s, p, to_read);
540 if (likely (did_read >= 0))
542 s->physical_offset += did_read;
543 s->active = 0;
545 else
546 return did_read;
548 nbyte = did_read + nread;
550 s->logical_offset += nbyte;
551 return nbyte;
554 static ssize_t
555 buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
557 if (s->ndirty == 0)
558 s->buffer_offset = s->logical_offset;
560 /* Does the data fit into the buffer? As a special case, if the
561 buffer is empty and the request is bigger than BUFFER_SIZE/2,
562 write directly. This avoids the case where the buffer would have
563 to be flushed at every write. */
564 if (!(s->ndirty == 0 && nbyte > BUFFER_SIZE/2)
565 && s->logical_offset + nbyte <= s->buffer_offset + BUFFER_SIZE
566 && s->buffer_offset <= s->logical_offset
567 && s->buffer_offset + s->ndirty >= s->logical_offset)
569 memcpy (s->buffer + (s->logical_offset - s->buffer_offset), buf, nbyte);
570 int nd = (s->logical_offset - s->buffer_offset) + nbyte;
571 if (nd > s->ndirty)
572 s->ndirty = nd;
574 else
576 /* Flush, and either fill the buffer with the new data, or if
577 the request is bigger than the buffer size, write directly
578 bypassing the buffer. */
579 buf_flush (s);
580 if (nbyte <= BUFFER_SIZE/2)
582 memcpy (s->buffer, buf, nbyte);
583 s->buffer_offset = s->logical_offset;
584 s->ndirty += nbyte;
586 else
588 if (s->physical_offset != s->logical_offset)
590 if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
591 return -1;
592 s->physical_offset = s->logical_offset;
595 nbyte = raw_write (s, buf, nbyte);
596 s->physical_offset += nbyte;
599 s->logical_offset += nbyte;
600 if (s->logical_offset > s->file_length)
601 s->file_length = s->logical_offset;
602 return nbyte;
606 /* "Unbuffered" really means I/O statement buffering. For formatted
607 I/O, the fbuf manages this, and then uses raw I/O. For unformatted
608 I/O, buffered I/O is used, and the buffer is flushed at the end of
609 each I/O statement, where this function is called. Alternatively,
610 the buffer is flushed at the end of the record if the buffer is
611 more than half full; this prevents needless seeking back and forth
612 when writing sequential unformatted. */
614 static int
615 buf_markeor (unix_stream * s)
617 if (s->unbuffered || s->ndirty >= BUFFER_SIZE / 2)
618 return buf_flush (s);
619 return 0;
622 static gfc_offset
623 buf_seek (unix_stream * s, gfc_offset offset, int whence)
625 switch (whence)
627 case SEEK_SET:
628 break;
629 case SEEK_CUR:
630 offset += s->logical_offset;
631 break;
632 case SEEK_END:
633 offset += s->file_length;
634 break;
635 default:
636 return -1;
638 if (offset < 0)
640 errno = EINVAL;
641 return -1;
643 s->logical_offset = offset;
644 return offset;
647 static gfc_offset
648 buf_tell (unix_stream * s)
650 return buf_seek (s, 0, SEEK_CUR);
653 static gfc_offset
654 buf_size (unix_stream * s)
656 return s->file_length;
659 static int
660 buf_truncate (unix_stream * s, gfc_offset length)
662 int r;
664 if (buf_flush (s) != 0)
665 return -1;
666 r = raw_truncate (s, length);
667 if (r == 0)
668 s->file_length = length;
669 return r;
672 static int
673 buf_close (unix_stream * s)
675 if (buf_flush (s) != 0)
676 return -1;
677 free (s->buffer);
678 return raw_close (s);
681 static const struct stream_vtable buf_vtable = {
682 .read = (void *) buf_read,
683 .write = (void *) buf_write,
684 .seek = (void *) buf_seek,
685 .tell = (void *) buf_tell,
686 .size = (void *) buf_size,
687 .trunc = (void *) buf_truncate,
688 .close = (void *) buf_close,
689 .flush = (void *) buf_flush,
690 .markeor = (void *) buf_markeor
693 static int
694 buf_init (unix_stream * s)
696 s->st.vptr = &buf_vtable;
698 s->buffer = xmalloc (BUFFER_SIZE);
699 return 0;
703 /*********************************************************************
704 memory stream functions - These are used for internal files
706 The idea here is that a single stream structure is created and all
707 requests must be satisfied from it. The location and size of the
708 buffer is the character variable supplied to the READ or WRITE
709 statement.
711 *********************************************************************/
713 char *
714 mem_alloc_r (stream * strm, int * len)
716 unix_stream * s = (unix_stream *) strm;
717 gfc_offset n;
718 gfc_offset where = s->logical_offset;
720 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
721 return NULL;
723 n = s->buffer_offset + s->active - where;
724 if (*len > n)
725 *len = n;
727 s->logical_offset = where + *len;
729 return s->buffer + (where - s->buffer_offset);
733 char *
734 mem_alloc_r4 (stream * strm, int * len)
736 unix_stream * s = (unix_stream *) strm;
737 gfc_offset n;
738 gfc_offset where = s->logical_offset;
740 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
741 return NULL;
743 n = s->buffer_offset + s->active - where;
744 if (*len > n)
745 *len = n;
747 s->logical_offset = where + *len;
749 return s->buffer + (where - s->buffer_offset) * 4;
753 char *
754 mem_alloc_w (stream * strm, int * len)
756 unix_stream * s = (unix_stream *) strm;
757 gfc_offset m;
758 gfc_offset where = s->logical_offset;
760 m = where + *len;
762 if (where < s->buffer_offset)
763 return NULL;
765 if (m > s->file_length)
766 return NULL;
768 s->logical_offset = m;
770 return s->buffer + (where - s->buffer_offset);
774 gfc_char4_t *
775 mem_alloc_w4 (stream * strm, int * len)
777 unix_stream * s = (unix_stream *) strm;
778 gfc_offset m;
779 gfc_offset where = s->logical_offset;
780 gfc_char4_t *result = (gfc_char4_t *) s->buffer;
782 m = where + *len;
784 if (where < s->buffer_offset)
785 return NULL;
787 if (m > s->file_length)
788 return NULL;
790 s->logical_offset = m;
791 return &result[where - s->buffer_offset];
795 /* Stream read function for character(kind=1) internal units. */
797 static ssize_t
798 mem_read (stream * s, void * buf, ssize_t nbytes)
800 void *p;
801 int nb = nbytes;
803 p = mem_alloc_r (s, &nb);
804 if (p)
806 memcpy (buf, p, nb);
807 return (ssize_t) nb;
809 else
810 return 0;
814 /* Stream read function for chracter(kind=4) internal units. */
816 static ssize_t
817 mem_read4 (stream * s, void * buf, ssize_t nbytes)
819 void *p;
820 int nb = nbytes;
822 p = mem_alloc_r4 (s, &nb);
823 if (p)
825 memcpy (buf, p, nb * 4);
826 return (ssize_t) nb;
828 else
829 return 0;
833 /* Stream write function for character(kind=1) internal units. */
835 static ssize_t
836 mem_write (stream * s, const void * buf, ssize_t nbytes)
838 void *p;
839 int nb = nbytes;
841 p = mem_alloc_w (s, &nb);
842 if (p)
844 memcpy (p, buf, nb);
845 return (ssize_t) nb;
847 else
848 return 0;
852 /* Stream write function for character(kind=4) internal units. */
854 static ssize_t
855 mem_write4 (stream * s, const void * buf, ssize_t nwords)
857 gfc_char4_t *p;
858 int nw = nwords;
860 p = mem_alloc_w4 (s, &nw);
861 if (p)
863 while (nw--)
864 *p++ = (gfc_char4_t) *((char *) buf);
865 return nwords;
867 else
868 return 0;
872 static gfc_offset
873 mem_seek (stream * strm, gfc_offset offset, int whence)
875 unix_stream * s = (unix_stream *) strm;
876 switch (whence)
878 case SEEK_SET:
879 break;
880 case SEEK_CUR:
881 offset += s->logical_offset;
882 break;
883 case SEEK_END:
884 offset += s->file_length;
885 break;
886 default:
887 return -1;
890 /* Note that for internal array I/O it's actually possible to have a
891 negative offset, so don't check for that. */
892 if (offset > s->file_length)
894 errno = EINVAL;
895 return -1;
898 s->logical_offset = offset;
900 /* Returning < 0 is the error indicator for sseek(), so return 0 if
901 offset is negative. Thus if the return value is 0, the caller
902 has to use stell() to get the real value of logical_offset. */
903 if (offset >= 0)
904 return offset;
905 return 0;
909 static gfc_offset
910 mem_tell (stream * s)
912 return ((unix_stream *)s)->logical_offset;
916 static int
917 mem_truncate (unix_stream * s __attribute__ ((unused)),
918 gfc_offset length __attribute__ ((unused)))
920 return 0;
924 static int
925 mem_flush (unix_stream * s __attribute__ ((unused)))
927 return 0;
931 static int
932 mem_close (unix_stream * s)
934 free (s);
936 return 0;
939 static const struct stream_vtable mem_vtable = {
940 .read = (void *) mem_read,
941 .write = (void *) mem_write,
942 .seek = (void *) mem_seek,
943 .tell = (void *) mem_tell,
944 /* buf_size is not a typo, we just reuse an identical
945 implementation. */
946 .size = (void *) buf_size,
947 .trunc = (void *) mem_truncate,
948 .close = (void *) mem_close,
949 .flush = (void *) mem_flush,
950 .markeor = (void *) raw_markeor
953 static const struct stream_vtable mem4_vtable = {
954 .read = (void *) mem_read4,
955 .write = (void *) mem_write4,
956 .seek = (void *) mem_seek,
957 .tell = (void *) mem_tell,
958 /* buf_size is not a typo, we just reuse an identical
959 implementation. */
960 .size = (void *) buf_size,
961 .trunc = (void *) mem_truncate,
962 .close = (void *) mem_close,
963 .flush = (void *) mem_flush,
964 .markeor = (void *) raw_markeor
967 /*********************************************************************
968 Public functions -- A reimplementation of this module needs to
969 define functional equivalents of the following.
970 *********************************************************************/
972 /* open_internal()-- Returns a stream structure from a character(kind=1)
973 internal file */
975 stream *
976 open_internal (char *base, int length, gfc_offset offset)
978 unix_stream *s;
980 s = xcalloc (1, sizeof (unix_stream));
982 s->buffer = base;
983 s->buffer_offset = offset;
985 s->active = s->file_length = length;
987 s->st.vptr = &mem_vtable;
989 return (stream *) s;
992 /* open_internal4()-- Returns a stream structure from a character(kind=4)
993 internal file */
995 stream *
996 open_internal4 (char *base, int length, gfc_offset offset)
998 unix_stream *s;
1000 s = xcalloc (1, sizeof (unix_stream));
1002 s->buffer = base;
1003 s->buffer_offset = offset;
1005 s->active = s->file_length = length * sizeof (gfc_char4_t);
1007 s->st.vptr = &mem4_vtable;
1009 return (stream *) s;
1013 /* fd_to_stream()-- Given an open file descriptor, build a stream
1014 * around it. */
1016 static stream *
1017 fd_to_stream (int fd, bool unformatted)
1019 struct stat statbuf;
1020 unix_stream *s;
1022 s = xcalloc (1, sizeof (unix_stream));
1024 s->fd = fd;
1026 /* Get the current length of the file. */
1028 if (fstat (fd, &statbuf) == -1)
1030 s->st_dev = s->st_ino = -1;
1031 s->file_length = 0;
1032 if (errno == EBADF)
1033 s->fd = -1;
1034 raw_init (s);
1035 return (stream *) s;
1038 s->st_dev = statbuf.st_dev;
1039 s->st_ino = statbuf.st_ino;
1040 s->file_length = statbuf.st_size;
1042 /* Only use buffered IO for regular files. */
1043 if (S_ISREG (statbuf.st_mode)
1044 && !options.all_unbuffered
1045 && !(options.unbuffered_preconnected &&
1046 (s->fd == STDIN_FILENO
1047 || s->fd == STDOUT_FILENO
1048 || s->fd == STDERR_FILENO)))
1049 buf_init (s);
1050 else
1052 if (unformatted)
1054 s->unbuffered = true;
1055 buf_init (s);
1057 else
1058 raw_init (s);
1061 return (stream *) s;
1065 /* Given the Fortran unit number, convert it to a C file descriptor. */
1068 unit_to_fd (int unit)
1070 gfc_unit *us;
1071 int fd;
1073 us = find_unit (unit);
1074 if (us == NULL)
1075 return -1;
1077 fd = ((unix_stream *) us->s)->fd;
1078 unlock_unit (us);
1079 return fd;
1083 /* Set the close-on-exec flag for an existing fd, if the system
1084 supports such. */
1086 static void __attribute__ ((unused))
1087 set_close_on_exec (int fd __attribute__ ((unused)))
1089 /* Mingw does not define F_SETFD. */
1090 #if defined(HAVE_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC)
1091 if (fd >= 0)
1092 fcntl(fd, F_SETFD, FD_CLOEXEC);
1093 #endif
1097 /* Helper function for tempfile(). Tries to open a temporary file in
1098 the directory specified by tempdir. If successful, the file name is
1099 stored in fname and the descriptor returned. Returns -1 on
1100 failure. */
1102 static int
1103 tempfile_open (const char *tempdir, char **fname)
1105 int fd;
1106 const char *slash = "/";
1107 #if defined(HAVE_UMASK) && defined(HAVE_MKSTEMP)
1108 mode_t mode_mask;
1109 #endif
1111 if (!tempdir)
1112 return -1;
1114 /* Check for the special case that tempdir ends with a slash or
1115 backslash. */
1116 size_t tempdirlen = strlen (tempdir);
1117 if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/'
1118 #ifdef __MINGW32__
1119 || tempdir[tempdirlen - 1] == '\\'
1120 #endif
1122 slash = "";
1124 /* Take care that the template is longer in the mktemp() branch. */
1125 char * template = xmalloc (tempdirlen + 23);
1127 #ifdef HAVE_MKSTEMP
1128 snprintf (template, tempdirlen + 23, "%s%sgfortrantmpXXXXXX",
1129 tempdir, slash);
1131 #ifdef HAVE_UMASK
1132 /* Temporarily set the umask such that the file has 0600 permissions. */
1133 mode_mask = umask (S_IXUSR | S_IRWXG | S_IRWXO);
1134 #endif
1136 #if defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
1137 fd = mkostemp (template, O_CLOEXEC);
1138 #else
1139 fd = mkstemp (template);
1140 set_close_on_exec (fd);
1141 #endif
1143 #ifdef HAVE_UMASK
1144 (void) umask (mode_mask);
1145 #endif
1147 #else /* HAVE_MKSTEMP */
1148 fd = -1;
1149 int count = 0;
1150 size_t slashlen = strlen (slash);
1151 int flags = O_RDWR | O_CREAT | O_EXCL;
1152 #if defined(HAVE_CRLF) && defined(O_BINARY)
1153 flags |= O_BINARY;
1154 #endif
1155 #ifdef O_CLOEXEC
1156 flags |= O_CLOEXEC;
1157 #endif
1160 snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX",
1161 tempdir, slash);
1162 if (count > 0)
1164 int c = count;
1165 template[tempdirlen + slashlen + 13] = 'a' + (c% 26);
1166 c /= 26;
1167 template[tempdirlen + slashlen + 12] = 'a' + (c % 26);
1168 c /= 26;
1169 template[tempdirlen + slashlen + 11] = 'a' + (c % 26);
1170 if (c >= 26)
1171 break;
1174 if (!mktemp (template))
1176 errno = EEXIST;
1177 count++;
1178 continue;
1181 fd = open (template, flags, S_IRUSR | S_IWUSR);
1183 while (fd == -1 && errno == EEXIST);
1184 #ifndef O_CLOEXEC
1185 set_close_on_exec (fd);
1186 #endif
1187 #endif /* HAVE_MKSTEMP */
1189 *fname = template;
1190 return fd;
1194 /* tempfile()-- Generate a temporary filename for a scratch file and
1195 * open it. mkstemp() opens the file for reading and writing, but the
1196 * library mode prevents anything that is not allowed. The descriptor
1197 * is returned, which is -1 on error. The template is pointed to by
1198 * opp->file, which is copied into the unit structure
1199 * and freed later. */
1201 static int
1202 tempfile (st_parameter_open *opp)
1204 const char *tempdir;
1205 char *fname;
1206 int fd = -1;
1208 tempdir = secure_getenv ("TMPDIR");
1209 fd = tempfile_open (tempdir, &fname);
1210 #ifdef __MINGW32__
1211 if (fd == -1)
1213 char buffer[MAX_PATH + 1];
1214 DWORD ret;
1215 ret = GetTempPath (MAX_PATH, buffer);
1216 /* If we are not able to get a temp-directory, we use
1217 current directory. */
1218 if (ret > MAX_PATH || !ret)
1219 buffer[0] = 0;
1220 else
1221 buffer[ret] = 0;
1222 tempdir = strdup (buffer);
1223 fd = tempfile_open (tempdir, &fname);
1225 #elif defined(__CYGWIN__)
1226 if (fd == -1)
1228 tempdir = secure_getenv ("TMP");
1229 fd = tempfile_open (tempdir, &fname);
1231 if (fd == -1)
1233 tempdir = secure_getenv ("TEMP");
1234 fd = tempfile_open (tempdir, &fname);
1236 #endif
1237 if (fd == -1)
1238 fd = tempfile_open (P_tmpdir, &fname);
1240 opp->file = fname;
1241 opp->file_len = strlen (fname); /* Don't include trailing nul */
1243 return fd;
1247 /* regular_file2()-- Open a regular file.
1248 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
1249 * unless an error occurs.
1250 * Returns the descriptor, which is less than zero on error. */
1252 static int
1253 regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
1255 int mode;
1256 int rwflag;
1257 int crflag, crflag2;
1258 int fd;
1260 #ifdef __CYGWIN__
1261 if (opp->file_len == 7)
1263 if (strncmp (path, "CONOUT$", 7) == 0
1264 || strncmp (path, "CONERR$", 7) == 0)
1266 fd = open ("/dev/conout", O_WRONLY);
1267 flags->action = ACTION_WRITE;
1268 return fd;
1272 if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
1274 fd = open ("/dev/conin", O_RDONLY);
1275 flags->action = ACTION_READ;
1276 return fd;
1278 #endif
1281 #ifdef __MINGW32__
1282 if (opp->file_len == 7)
1284 if (strncmp (path, "CONOUT$", 7) == 0
1285 || strncmp (path, "CONERR$", 7) == 0)
1287 fd = open ("CONOUT$", O_WRONLY);
1288 flags->action = ACTION_WRITE;
1289 return fd;
1293 if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
1295 fd = open ("CONIN$", O_RDONLY);
1296 flags->action = ACTION_READ;
1297 return fd;
1299 #endif
1301 switch (flags->action)
1303 case ACTION_READ:
1304 rwflag = O_RDONLY;
1305 break;
1307 case ACTION_WRITE:
1308 rwflag = O_WRONLY;
1309 break;
1311 case ACTION_READWRITE:
1312 case ACTION_UNSPECIFIED:
1313 rwflag = O_RDWR;
1314 break;
1316 default:
1317 internal_error (&opp->common, "regular_file(): Bad action");
1320 switch (flags->status)
1322 case STATUS_NEW:
1323 crflag = O_CREAT | O_EXCL;
1324 break;
1326 case STATUS_OLD: /* open will fail if the file does not exist*/
1327 crflag = 0;
1328 break;
1330 case STATUS_UNKNOWN:
1331 if (rwflag == O_RDONLY)
1332 crflag = 0;
1333 else
1334 crflag = O_CREAT;
1335 break;
1337 case STATUS_REPLACE:
1338 crflag = O_CREAT | O_TRUNC;
1339 break;
1341 default:
1342 /* Note: STATUS_SCRATCH is handled by tempfile () and should
1343 never be seen here. */
1344 internal_error (&opp->common, "regular_file(): Bad status");
1347 /* rwflag |= O_LARGEFILE; */
1349 #if defined(HAVE_CRLF) && defined(O_BINARY)
1350 crflag |= O_BINARY;
1351 #endif
1353 #ifdef O_CLOEXEC
1354 crflag |= O_CLOEXEC;
1355 #endif
1357 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
1358 fd = open (path, rwflag | crflag, mode);
1359 if (flags->action != ACTION_UNSPECIFIED)
1360 return fd;
1362 if (fd >= 0)
1364 flags->action = ACTION_READWRITE;
1365 return fd;
1367 if (errno != EACCES && errno != EPERM && errno != EROFS)
1368 return fd;
1370 /* retry for read-only access */
1371 rwflag = O_RDONLY;
1372 if (flags->status == STATUS_UNKNOWN)
1373 crflag2 = crflag & ~(O_CREAT);
1374 else
1375 crflag2 = crflag;
1376 fd = open (path, rwflag | crflag2, mode);
1377 if (fd >=0)
1379 flags->action = ACTION_READ;
1380 return fd; /* success */
1383 if (errno != EACCES && errno != EPERM && errno != ENOENT)
1384 return fd; /* failure */
1386 /* retry for write-only access */
1387 rwflag = O_WRONLY;
1388 fd = open (path, rwflag | crflag, mode);
1389 if (fd >=0)
1391 flags->action = ACTION_WRITE;
1392 return fd; /* success */
1394 return fd; /* failure */
1398 /* Wrapper around regular_file2, to make sure we free the path after
1399 we're done. */
1401 static int
1402 regular_file (st_parameter_open *opp, unit_flags *flags)
1404 char *path = fc_strdup (opp->file, opp->file_len);
1405 int fd = regular_file2 (path, opp, flags);
1406 free (path);
1407 return fd;
1410 /* open_external()-- Open an external file, unix specific version.
1411 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
1412 * Returns NULL on operating system error. */
1414 stream *
1415 open_external (st_parameter_open *opp, unit_flags *flags)
1417 int fd;
1419 if (flags->status == STATUS_SCRATCH)
1421 fd = tempfile (opp);
1422 if (flags->action == ACTION_UNSPECIFIED)
1423 flags->action = ACTION_READWRITE;
1425 #if HAVE_UNLINK_OPEN_FILE
1426 /* We can unlink scratch files now and it will go away when closed. */
1427 if (fd >= 0)
1428 unlink (opp->file);
1429 #endif
1431 else
1433 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1434 * if it succeeds */
1435 fd = regular_file (opp, flags);
1436 #ifndef O_CLOEXEC
1437 set_close_on_exec (fd);
1438 #endif
1441 if (fd < 0)
1442 return NULL;
1443 fd = fix_fd (fd);
1445 return fd_to_stream (fd, flags->form == FORM_UNFORMATTED);
1449 /* input_stream()-- Return a stream pointer to the default input stream.
1450 * Called on initialization. */
1452 stream *
1453 input_stream (void)
1455 return fd_to_stream (STDIN_FILENO, false);
1459 /* output_stream()-- Return a stream pointer to the default output stream.
1460 * Called on initialization. */
1462 stream *
1463 output_stream (void)
1465 stream * s;
1467 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1468 setmode (STDOUT_FILENO, O_BINARY);
1469 #endif
1471 s = fd_to_stream (STDOUT_FILENO, false);
1472 return s;
1476 /* error_stream()-- Return a stream pointer to the default error stream.
1477 * Called on initialization. */
1479 stream *
1480 error_stream (void)
1482 stream * s;
1484 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1485 setmode (STDERR_FILENO, O_BINARY);
1486 #endif
1488 s = fd_to_stream (STDERR_FILENO, false);
1489 return s;
1493 /* compare_file_filename()-- Given an open stream and a fortran string
1494 * that is a filename, figure out if the file is the same as the
1495 * filename. */
1498 compare_file_filename (gfc_unit *u, const char *name, int len)
1500 struct stat st;
1501 int ret;
1502 #ifdef HAVE_WORKING_STAT
1503 unix_stream *s;
1504 #else
1505 # ifdef __MINGW32__
1506 uint64_t id1, id2;
1507 # endif
1508 #endif
1510 char *path = fc_strdup (name, len);
1512 /* If the filename doesn't exist, then there is no match with the
1513 * existing file. */
1515 if (stat (path, &st) < 0)
1517 ret = 0;
1518 goto done;
1521 #ifdef HAVE_WORKING_STAT
1522 s = (unix_stream *) (u->s);
1523 ret = (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
1524 goto done;
1525 #else
1527 # ifdef __MINGW32__
1528 /* We try to match files by a unique ID. On some filesystems (network
1529 fs and FAT), we can't generate this unique ID, and will simply compare
1530 filenames. */
1531 id1 = id_from_path (path);
1532 id2 = id_from_fd (((unix_stream *) (u->s))->fd);
1533 if (id1 || id2)
1535 ret = (id1 == id2);
1536 goto done;
1538 # endif
1539 if (u->filename)
1540 ret = (strcmp(path, u->filename) == 0);
1541 else
1542 ret = 0;
1543 #endif
1544 done:
1545 free (path);
1546 return ret;
1550 #ifdef HAVE_WORKING_STAT
1551 # define FIND_FILE0_DECL struct stat *st
1552 # define FIND_FILE0_ARGS st
1553 #else
1554 # define FIND_FILE0_DECL uint64_t id, const char *path
1555 # define FIND_FILE0_ARGS id, path
1556 #endif
1558 /* find_file0()-- Recursive work function for find_file() */
1560 static gfc_unit *
1561 find_file0 (gfc_unit *u, FIND_FILE0_DECL)
1563 gfc_unit *v;
1564 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1565 uint64_t id1;
1566 #endif
1568 if (u == NULL)
1569 return NULL;
1571 #ifdef HAVE_WORKING_STAT
1572 if (u->s != NULL)
1574 unix_stream *s = (unix_stream *) (u->s);
1575 if (st[0].st_dev == s->st_dev && st[0].st_ino == s->st_ino)
1576 return u;
1578 #else
1579 # ifdef __MINGW32__
1580 if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
1582 if (id == id1)
1583 return u;
1585 else
1586 # endif
1587 if (u->filename && strcmp (u->filename, path) == 0)
1588 return u;
1589 #endif
1591 v = find_file0 (u->left, FIND_FILE0_ARGS);
1592 if (v != NULL)
1593 return v;
1595 v = find_file0 (u->right, FIND_FILE0_ARGS);
1596 if (v != NULL)
1597 return v;
1599 return NULL;
1603 /* find_file()-- Take the current filename and see if there is a unit
1604 * that has the file already open. Returns a pointer to the unit if so. */
1606 gfc_unit *
1607 find_file (const char *file, gfc_charlen_type file_len)
1609 struct stat st[1];
1610 gfc_unit *u;
1611 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1612 uint64_t id = 0ULL;
1613 #endif
1615 char *path = fc_strdup (file, file_len);
1617 if (stat (path, &st[0]) < 0)
1619 u = NULL;
1620 goto done;
1623 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1624 id = id_from_path (path);
1625 #endif
1627 __gthread_mutex_lock (&unit_lock);
1628 retry:
1629 u = find_file0 (unit_root, FIND_FILE0_ARGS);
1630 if (u != NULL)
1632 /* Fast path. */
1633 if (! __gthread_mutex_trylock (&u->lock))
1635 /* assert (u->closed == 0); */
1636 __gthread_mutex_unlock (&unit_lock);
1637 goto done;
1640 inc_waiting_locked (u);
1642 __gthread_mutex_unlock (&unit_lock);
1643 if (u != NULL)
1645 __gthread_mutex_lock (&u->lock);
1646 if (u->closed)
1648 __gthread_mutex_lock (&unit_lock);
1649 __gthread_mutex_unlock (&u->lock);
1650 if (predec_waiting_locked (u) == 0)
1651 free (u);
1652 goto retry;
1655 dec_waiting_unlocked (u);
1657 done:
1658 free (path);
1659 return u;
1662 static gfc_unit *
1663 flush_all_units_1 (gfc_unit *u, int min_unit)
1665 while (u != NULL)
1667 if (u->unit_number > min_unit)
1669 gfc_unit *r = flush_all_units_1 (u->left, min_unit);
1670 if (r != NULL)
1671 return r;
1673 if (u->unit_number >= min_unit)
1675 if (__gthread_mutex_trylock (&u->lock))
1676 return u;
1677 if (u->s)
1678 sflush (u->s);
1679 __gthread_mutex_unlock (&u->lock);
1681 u = u->right;
1683 return NULL;
1686 void
1687 flush_all_units (void)
1689 gfc_unit *u;
1690 int min_unit = 0;
1692 __gthread_mutex_lock (&unit_lock);
1695 u = flush_all_units_1 (unit_root, min_unit);
1696 if (u != NULL)
1697 inc_waiting_locked (u);
1698 __gthread_mutex_unlock (&unit_lock);
1699 if (u == NULL)
1700 return;
1702 __gthread_mutex_lock (&u->lock);
1704 min_unit = u->unit_number + 1;
1706 if (u->closed == 0)
1708 sflush (u->s);
1709 __gthread_mutex_lock (&unit_lock);
1710 __gthread_mutex_unlock (&u->lock);
1711 (void) predec_waiting_locked (u);
1713 else
1715 __gthread_mutex_lock (&unit_lock);
1716 __gthread_mutex_unlock (&u->lock);
1717 if (predec_waiting_locked (u) == 0)
1718 free (u);
1721 while (1);
1725 /* file_exists()-- Returns nonzero if the current filename exists on
1726 * the system */
1729 file_exists (const char *file, gfc_charlen_type file_len)
1731 char *path = fc_strdup (file, file_len);
1732 int res = !(access (path, F_OK));
1733 free (path);
1734 return res;
1738 /* file_size()-- Returns the size of the file. */
1740 GFC_IO_INT
1741 file_size (const char *file, gfc_charlen_type file_len)
1743 char *path = fc_strdup (file, file_len);
1744 struct stat statbuf;
1745 int err = stat (path, &statbuf);
1746 free (path);
1747 if (err == -1)
1748 return -1;
1749 return (GFC_IO_INT) statbuf.st_size;
1752 static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
1754 /* inquire_sequential()-- Given a fortran string, determine if the
1755 * file is suitable for sequential access. Returns a C-style
1756 * string. */
1758 const char *
1759 inquire_sequential (const char *string, int len)
1761 struct stat statbuf;
1763 if (string == NULL)
1764 return unknown;
1766 char *path = fc_strdup (string, len);
1767 int err = stat (path, &statbuf);
1768 free (path);
1769 if (err == -1)
1770 return unknown;
1772 if (S_ISREG (statbuf.st_mode) ||
1773 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1774 return unknown;
1776 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1777 return no;
1779 return unknown;
1783 /* inquire_direct()-- Given a fortran string, determine if the file is
1784 * suitable for direct access. Returns a C-style string. */
1786 const char *
1787 inquire_direct (const char *string, int len)
1789 struct stat statbuf;
1791 if (string == NULL)
1792 return unknown;
1794 char *path = fc_strdup (string, len);
1795 int err = stat (path, &statbuf);
1796 free (path);
1797 if (err == -1)
1798 return unknown;
1800 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1801 return unknown;
1803 if (S_ISDIR (statbuf.st_mode) ||
1804 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1805 return no;
1807 return unknown;
1811 /* inquire_formatted()-- Given a fortran string, determine if the file
1812 * is suitable for formatted form. Returns a C-style string. */
1814 const char *
1815 inquire_formatted (const char *string, int len)
1817 struct stat statbuf;
1819 if (string == NULL)
1820 return unknown;
1822 char *path = fc_strdup (string, len);
1823 int err = stat (path, &statbuf);
1824 free (path);
1825 if (err == -1)
1826 return unknown;
1828 if (S_ISREG (statbuf.st_mode) ||
1829 S_ISBLK (statbuf.st_mode) ||
1830 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1831 return unknown;
1833 if (S_ISDIR (statbuf.st_mode))
1834 return no;
1836 return unknown;
1840 /* inquire_unformatted()-- Given a fortran string, determine if the file
1841 * is suitable for unformatted form. Returns a C-style string. */
1843 const char *
1844 inquire_unformatted (const char *string, int len)
1846 return inquire_formatted (string, len);
1850 /* inquire_access()-- Given a fortran string, determine if the file is
1851 * suitable for access. */
1853 static const char *
1854 inquire_access (const char *string, int len, int mode)
1856 if (string == NULL)
1857 return no;
1858 char *path = fc_strdup (string, len);
1859 int res = access (path, mode);
1860 free (path);
1861 if (res == -1)
1862 return no;
1864 return yes;
1868 /* inquire_read()-- Given a fortran string, determine if the file is
1869 * suitable for READ access. */
1871 const char *
1872 inquire_read (const char *string, int len)
1874 return inquire_access (string, len, R_OK);
1878 /* inquire_write()-- Given a fortran string, determine if the file is
1879 * suitable for READ access. */
1881 const char *
1882 inquire_write (const char *string, int len)
1884 return inquire_access (string, len, W_OK);
1888 /* inquire_readwrite()-- Given a fortran string, determine if the file is
1889 * suitable for read and write access. */
1891 const char *
1892 inquire_readwrite (const char *string, int len)
1894 return inquire_access (string, len, R_OK | W_OK);
1899 stream_isatty (stream *s)
1901 return isatty (((unix_stream *) s)->fd);
1905 stream_ttyname (stream *s __attribute__ ((unused)),
1906 char * buf __attribute__ ((unused)),
1907 size_t buflen __attribute__ ((unused)))
1909 #ifdef HAVE_TTYNAME_R
1910 return ttyname_r (((unix_stream *) s)->fd, buf, buflen);
1911 #elif defined HAVE_TTYNAME
1912 char *p;
1913 size_t plen;
1914 p = ttyname (((unix_stream *) s)->fd);
1915 if (!p)
1916 return errno;
1917 plen = strlen (p);
1918 if (buflen < plen)
1919 plen = buflen;
1920 memcpy (buf, p, plen);
1921 return 0;
1922 #else
1923 return ENOSYS;
1924 #endif
1930 /* How files are stored: This is an operating-system specific issue,
1931 and therefore belongs here. There are three cases to consider.
1933 Direct Access:
1934 Records are written as block of bytes corresponding to the record
1935 length of the file. This goes for both formatted and unformatted
1936 records. Positioning is done explicitly for each data transfer,
1937 so positioning is not much of an issue.
1939 Sequential Formatted:
1940 Records are separated by newline characters. The newline character
1941 is prohibited from appearing in a string. If it does, this will be
1942 messed up on the next read. End of file is also the end of a record.
1944 Sequential Unformatted:
1945 In this case, we are merely copying bytes to and from main storage,
1946 yet we need to keep track of varying record lengths. We adopt
1947 the solution used by f2c. Each record contains a pair of length
1948 markers:
1950 Length of record n in bytes
1951 Data of record n
1952 Length of record n in bytes
1954 Length of record n+1 in bytes
1955 Data of record n+1
1956 Length of record n+1 in bytes
1958 The length is stored at the end of a record to allow backspacing to the
1959 previous record. Between data transfer statements, the file pointer
1960 is left pointing to the first length of the current record.
1962 ENDFILE records are never explicitly stored.