]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/io/unix.c
environ.c: Include unistd.h.
[thirdparty/gcc.git] / libgfortran / io / unix.c
1 /* Copyright (C) 2002-2013 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3 F2003 I/O support contributed by Jerry DeLisle
4
5 This file is part of the GNU Fortran runtime library (libgfortran).
6
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.
11
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.
16
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.
20
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/>. */
25
26 /* Unix stream I/O module */
27
28 #include "io.h"
29 #include "unix.h"
30 #include <stdlib.h>
31 #include <limits.h>
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <assert.h>
40
41 #include <string.h>
42 #include <errno.h>
43
44
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__
48
49 #define WIN32_LEAN_AND_MEAN
50 #include <windows.h>
51
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
60
61 #ifndef HAVE_WORKING_STAT
62 static uint64_t
63 id_from_handle (HANDLE hFile)
64 {
65 BY_HANDLE_FILE_INFORMATION FileInformation;
66
67 if (hFile == INVALID_HANDLE_VALUE)
68 return 0;
69
70 memset (&FileInformation, 0, sizeof(FileInformation));
71 if (!GetFileInformationByHandle (hFile, &FileInformation))
72 return 0;
73
74 return ((uint64_t) FileInformation.nFileIndexLow)
75 | (((uint64_t) FileInformation.nFileIndexHigh) << 32);
76 }
77
78
79 static uint64_t
80 id_from_path (const char *path)
81 {
82 HANDLE hFile;
83 uint64_t res;
84
85 if (!path || !*path || access (path, F_OK))
86 return (uint64_t) -1;
87
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;
94 }
95
96
97 static uint64_t
98 id_from_fd (const int fd)
99 {
100 return id_from_handle ((HANDLE) _get_osfhandle (fd));
101 }
102
103 #endif /* HAVE_WORKING_STAT */
104 #endif /* __MINGW32__ */
105
106
107 /* min macro that evaluates its arguments only once. */
108 #ifdef min
109 #undef min
110 #endif
111
112 #define min(a,b) \
113 ({ typeof (a) _a = (a); \
114 typeof (b) _b = (b); \
115 _a < _b ? _a : _b; })
116
117 #ifndef PATH_MAX
118 #define PATH_MAX 1024
119 #endif
120
121 /* These flags aren't defined on all targets (mingw32), so provide them
122 here. */
123 #ifndef S_IRGRP
124 #define S_IRGRP 0
125 #endif
126
127 #ifndef S_IWGRP
128 #define S_IWGRP 0
129 #endif
130
131 #ifndef S_IROTH
132 #define S_IROTH 0
133 #endif
134
135 #ifndef S_IWOTH
136 #define S_IWOTH 0
137 #endif
138
139
140 #ifndef HAVE_ACCESS
141
142 #ifndef W_OK
143 #define W_OK 2
144 #endif
145
146 #ifndef R_OK
147 #define R_OK 4
148 #endif
149
150 #ifndef F_OK
151 #define F_OK 0
152 #endif
153
154 /* Fallback implementation of access() on systems that don't have it.
155 Only modes R_OK, W_OK and F_OK are used in this file. */
156
157 static int
158 fallback_access (const char *path, int mode)
159 {
160 int fd;
161
162 if ((mode & R_OK) && (fd = open (path, O_RDONLY)) < 0)
163 return -1;
164 close (fd);
165
166 if ((mode & W_OK) && (fd = open (path, O_WRONLY)) < 0)
167 return -1;
168 close (fd);
169
170 if (mode == F_OK)
171 {
172 struct stat st;
173 return stat (path, &st);
174 }
175
176 return 0;
177 }
178
179 #undef access
180 #define access fallback_access
181 #endif
182
183
184 /* Fallback directory for creating temporary files. P_tmpdir is
185 defined on many POSIX platforms. */
186 #ifndef P_tmpdir
187 #ifdef _P_tmpdir
188 #define P_tmpdir _P_tmpdir /* MinGW */
189 #else
190 #define P_tmpdir "/tmp"
191 #endif
192 #endif
193
194
195 /* Unix and internal stream I/O module */
196
197 static const int BUFFER_SIZE = 8192;
198
199 typedef struct
200 {
201 stream st;
202
203 gfc_offset buffer_offset; /* File offset of the start of the buffer */
204 gfc_offset physical_offset; /* Current physical file offset */
205 gfc_offset logical_offset; /* Current logical file offset */
206 gfc_offset file_length; /* Length of the file. */
207
208 char *buffer; /* Pointer to the buffer. */
209 int fd; /* The POSIX file descriptor. */
210
211 int active; /* Length of valid bytes in the buffer */
212
213 int ndirty; /* Dirty bytes starting at buffer_offset */
214
215 /* Cached stat(2) values. */
216 dev_t st_dev;
217 ino_t st_ino;
218
219 bool unbuffered; /* Buffer should be flushed after each I/O statement. */
220 }
221 unix_stream;
222
223
224 /* fix_fd()-- Given a file descriptor, make sure it is not one of the
225 * standard descriptors, returning a non-standard descriptor. If the
226 * user specifies that system errors should go to standard output,
227 * then closes standard output, we don't want the system errors to a
228 * file that has been given file descriptor 1 or 0. We want to send
229 * the error to the invalid descriptor. */
230
231 static int
232 fix_fd (int fd)
233 {
234 #ifdef HAVE_DUP
235 int input, output, error;
236
237 input = output = error = 0;
238
239 /* Unix allocates the lowest descriptors first, so a loop is not
240 required, but this order is. */
241 if (fd == STDIN_FILENO)
242 {
243 fd = dup (fd);
244 input = 1;
245 }
246 if (fd == STDOUT_FILENO)
247 {
248 fd = dup (fd);
249 output = 1;
250 }
251 if (fd == STDERR_FILENO)
252 {
253 fd = dup (fd);
254 error = 1;
255 }
256
257 if (input)
258 close (STDIN_FILENO);
259 if (output)
260 close (STDOUT_FILENO);
261 if (error)
262 close (STDERR_FILENO);
263 #endif
264
265 return fd;
266 }
267
268
269 /* If the stream corresponds to a preconnected unit, we flush the
270 corresponding C stream. This is bugware for mixed C-Fortran codes
271 where the C code doesn't flush I/O before returning. */
272 void
273 flush_if_preconnected (stream * s)
274 {
275 int fd;
276
277 fd = ((unix_stream *) s)->fd;
278 if (fd == STDIN_FILENO)
279 fflush (stdin);
280 else if (fd == STDOUT_FILENO)
281 fflush (stdout);
282 else if (fd == STDERR_FILENO)
283 fflush (stderr);
284 }
285
286
287 /********************************************************************
288 Raw I/O functions (read, write, seek, tell, truncate, close).
289
290 These functions wrap the basic POSIX I/O syscalls. Any deviation in
291 semantics is a bug, except the following: write restarts in case
292 of being interrupted by a signal, and as the first argument the
293 functions take the unix_stream struct rather than an integer file
294 descriptor. Also, for POSIX read() and write() a nbyte argument larger
295 than SSIZE_MAX is undefined; here the type of nbyte is ssize_t rather
296 than size_t as for POSIX read/write.
297 *********************************************************************/
298
299 static int
300 raw_flush (unix_stream * s __attribute__ ((unused)))
301 {
302 return 0;
303 }
304
305 static ssize_t
306 raw_read (unix_stream * s, void * buf, ssize_t nbyte)
307 {
308 /* For read we can't do I/O in a loop like raw_write does, because
309 that will break applications that wait for interactive I/O. */
310 return read (s->fd, buf, nbyte);
311 }
312
313 static ssize_t
314 raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
315 {
316 ssize_t trans, bytes_left;
317 char *buf_st;
318
319 bytes_left = nbyte;
320 buf_st = (char *) buf;
321
322 /* We must write in a loop since some systems don't restart system
323 calls in case of a signal. */
324 while (bytes_left > 0)
325 {
326 trans = write (s->fd, buf_st, bytes_left);
327 if (trans < 0)
328 {
329 if (errno == EINTR)
330 continue;
331 else
332 return trans;
333 }
334 buf_st += trans;
335 bytes_left -= trans;
336 }
337
338 return nbyte - bytes_left;
339 }
340
341 static gfc_offset
342 raw_seek (unix_stream * s, gfc_offset offset, int whence)
343 {
344 return lseek (s->fd, offset, whence);
345 }
346
347 static gfc_offset
348 raw_tell (unix_stream * s)
349 {
350 return lseek (s->fd, 0, SEEK_CUR);
351 }
352
353 static gfc_offset
354 raw_size (unix_stream * s)
355 {
356 struct stat statbuf;
357 int ret = fstat (s->fd, &statbuf);
358 if (ret == -1)
359 return ret;
360 if (S_ISREG (statbuf.st_mode))
361 return statbuf.st_size;
362 else
363 return 0;
364 }
365
366 static int
367 raw_truncate (unix_stream * s, gfc_offset length)
368 {
369 #ifdef __MINGW32__
370 HANDLE h;
371 gfc_offset cur;
372
373 if (isatty (s->fd))
374 {
375 errno = EBADF;
376 return -1;
377 }
378 h = (HANDLE) _get_osfhandle (s->fd);
379 if (h == INVALID_HANDLE_VALUE)
380 {
381 errno = EBADF;
382 return -1;
383 }
384 cur = lseek (s->fd, 0, SEEK_CUR);
385 if (cur == -1)
386 return -1;
387 if (lseek (s->fd, length, SEEK_SET) == -1)
388 goto error;
389 if (!SetEndOfFile (h))
390 {
391 errno = EBADF;
392 goto error;
393 }
394 if (lseek (s->fd, cur, SEEK_SET) == -1)
395 return -1;
396 return 0;
397 error:
398 lseek (s->fd, cur, SEEK_SET);
399 return -1;
400 #elif defined HAVE_FTRUNCATE
401 return ftruncate (s->fd, length);
402 #elif defined HAVE_CHSIZE
403 return chsize (s->fd, length);
404 #else
405 runtime_error ("required ftruncate or chsize support not present");
406 return -1;
407 #endif
408 }
409
410 static int
411 raw_close (unix_stream * s)
412 {
413 int retval;
414
415 if (s->fd != STDOUT_FILENO
416 && s->fd != STDERR_FILENO
417 && s->fd != STDIN_FILENO)
418 retval = close (s->fd);
419 else
420 retval = 0;
421 free (s);
422 return retval;
423 }
424
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 };
435
436 static int
437 raw_init (unix_stream * s)
438 {
439 s->st.vptr = &raw_vtable;
440
441 s->buffer = NULL;
442 return 0;
443 }
444
445
446 /*********************************************************************
447 Buffered I/O functions. These functions have the same semantics as the
448 raw I/O functions above, except that they are buffered in order to
449 improve performance. The buffer must be flushed when switching from
450 reading to writing and vice versa.
451 *********************************************************************/
452
453 static int
454 buf_flush (unix_stream * s)
455 {
456 int writelen;
457
458 /* Flushing in read mode means discarding read bytes. */
459 s->active = 0;
460
461 if (s->ndirty == 0)
462 return 0;
463
464 if (s->physical_offset != s->buffer_offset
465 && lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
466 return -1;
467
468 writelen = raw_write (s, s->buffer, s->ndirty);
469
470 s->physical_offset = s->buffer_offset + writelen;
471
472 if (s->physical_offset > s->file_length)
473 s->file_length = s->physical_offset;
474
475 s->ndirty -= writelen;
476 if (s->ndirty != 0)
477 return -1;
478
479 return 0;
480 }
481
482 static ssize_t
483 buf_read (unix_stream * s, void * buf, ssize_t nbyte)
484 {
485 if (s->active == 0)
486 s->buffer_offset = s->logical_offset;
487
488 /* Is the data we want in the buffer? */
489 if (s->logical_offset + nbyte <= s->buffer_offset + s->active
490 && s->buffer_offset <= s->logical_offset)
491 memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset), nbyte);
492 else
493 {
494 /* First copy the active bytes if applicable, then read the rest
495 either directly or filling the buffer. */
496 char *p;
497 int nread = 0;
498 ssize_t to_read, did_read;
499 gfc_offset new_logical;
500
501 p = (char *) buf;
502 if (s->logical_offset >= s->buffer_offset
503 && s->buffer_offset + s->active >= s->logical_offset)
504 {
505 nread = s->active - (s->logical_offset - s->buffer_offset);
506 memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset),
507 nread);
508 p += nread;
509 }
510 /* At this point we consider all bytes in the buffer discarded. */
511 to_read = nbyte - nread;
512 new_logical = s->logical_offset + nread;
513 if (s->physical_offset != new_logical
514 && lseek (s->fd, new_logical, SEEK_SET) < 0)
515 return -1;
516 s->buffer_offset = s->physical_offset = new_logical;
517 if (to_read <= BUFFER_SIZE/2)
518 {
519 did_read = raw_read (s, s->buffer, BUFFER_SIZE);
520 s->physical_offset += did_read;
521 s->active = did_read;
522 did_read = (did_read > to_read) ? to_read : did_read;
523 memcpy (p, s->buffer, did_read);
524 }
525 else
526 {
527 did_read = raw_read (s, p, to_read);
528 s->physical_offset += did_read;
529 s->active = 0;
530 }
531 nbyte = did_read + nread;
532 }
533 s->logical_offset += nbyte;
534 return nbyte;
535 }
536
537 static ssize_t
538 buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
539 {
540 if (s->ndirty == 0)
541 s->buffer_offset = s->logical_offset;
542
543 /* Does the data fit into the buffer? As a special case, if the
544 buffer is empty and the request is bigger than BUFFER_SIZE/2,
545 write directly. This avoids the case where the buffer would have
546 to be flushed at every write. */
547 if (!(s->ndirty == 0 && nbyte > BUFFER_SIZE/2)
548 && s->logical_offset + nbyte <= s->buffer_offset + BUFFER_SIZE
549 && s->buffer_offset <= s->logical_offset
550 && s->buffer_offset + s->ndirty >= s->logical_offset)
551 {
552 memcpy (s->buffer + (s->logical_offset - s->buffer_offset), buf, nbyte);
553 int nd = (s->logical_offset - s->buffer_offset) + nbyte;
554 if (nd > s->ndirty)
555 s->ndirty = nd;
556 }
557 else
558 {
559 /* Flush, and either fill the buffer with the new data, or if
560 the request is bigger than the buffer size, write directly
561 bypassing the buffer. */
562 buf_flush (s);
563 if (nbyte <= BUFFER_SIZE/2)
564 {
565 memcpy (s->buffer, buf, nbyte);
566 s->buffer_offset = s->logical_offset;
567 s->ndirty += nbyte;
568 }
569 else
570 {
571 if (s->physical_offset != s->logical_offset)
572 {
573 if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
574 return -1;
575 s->physical_offset = s->logical_offset;
576 }
577
578 nbyte = raw_write (s, buf, nbyte);
579 s->physical_offset += nbyte;
580 }
581 }
582 s->logical_offset += nbyte;
583 if (s->logical_offset > s->file_length)
584 s->file_length = s->logical_offset;
585 return nbyte;
586 }
587
588 static gfc_offset
589 buf_seek (unix_stream * s, gfc_offset offset, int whence)
590 {
591 switch (whence)
592 {
593 case SEEK_SET:
594 break;
595 case SEEK_CUR:
596 offset += s->logical_offset;
597 break;
598 case SEEK_END:
599 offset += s->file_length;
600 break;
601 default:
602 return -1;
603 }
604 if (offset < 0)
605 {
606 errno = EINVAL;
607 return -1;
608 }
609 s->logical_offset = offset;
610 return offset;
611 }
612
613 static gfc_offset
614 buf_tell (unix_stream * s)
615 {
616 return buf_seek (s, 0, SEEK_CUR);
617 }
618
619 static gfc_offset
620 buf_size (unix_stream * s)
621 {
622 return s->file_length;
623 }
624
625 static int
626 buf_truncate (unix_stream * s, gfc_offset length)
627 {
628 int r;
629
630 if (buf_flush (s) != 0)
631 return -1;
632 r = raw_truncate (s, length);
633 if (r == 0)
634 s->file_length = length;
635 return r;
636 }
637
638 static int
639 buf_close (unix_stream * s)
640 {
641 if (buf_flush (s) != 0)
642 return -1;
643 free (s->buffer);
644 return raw_close (s);
645 }
646
647 static const struct stream_vtable buf_vtable = {
648 .read = (void *) buf_read,
649 .write = (void *) buf_write,
650 .seek = (void *) buf_seek,
651 .tell = (void *) buf_tell,
652 .size = (void *) buf_size,
653 .trunc = (void *) buf_truncate,
654 .close = (void *) buf_close,
655 .flush = (void *) buf_flush
656 };
657
658 static int
659 buf_init (unix_stream * s)
660 {
661 s->st.vptr = &buf_vtable;
662
663 s->buffer = xmalloc (BUFFER_SIZE);
664 return 0;
665 }
666
667
668 /*********************************************************************
669 memory stream functions - These are used for internal files
670
671 The idea here is that a single stream structure is created and all
672 requests must be satisfied from it. The location and size of the
673 buffer is the character variable supplied to the READ or WRITE
674 statement.
675
676 *********************************************************************/
677
678 char *
679 mem_alloc_r (stream * strm, int * len)
680 {
681 unix_stream * s = (unix_stream *) strm;
682 gfc_offset n;
683 gfc_offset where = s->logical_offset;
684
685 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
686 return NULL;
687
688 n = s->buffer_offset + s->active - where;
689 if (*len > n)
690 *len = n;
691
692 s->logical_offset = where + *len;
693
694 return s->buffer + (where - s->buffer_offset);
695 }
696
697
698 char *
699 mem_alloc_r4 (stream * strm, int * len)
700 {
701 unix_stream * s = (unix_stream *) strm;
702 gfc_offset n;
703 gfc_offset where = s->logical_offset;
704
705 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
706 return NULL;
707
708 n = s->buffer_offset + s->active - where;
709 if (*len > n)
710 *len = n;
711
712 s->logical_offset = where + *len;
713
714 return s->buffer + (where - s->buffer_offset) * 4;
715 }
716
717
718 char *
719 mem_alloc_w (stream * strm, int * len)
720 {
721 unix_stream * s = (unix_stream *) strm;
722 gfc_offset m;
723 gfc_offset where = s->logical_offset;
724
725 m = where + *len;
726
727 if (where < s->buffer_offset)
728 return NULL;
729
730 if (m > s->file_length)
731 return NULL;
732
733 s->logical_offset = m;
734
735 return s->buffer + (where - s->buffer_offset);
736 }
737
738
739 gfc_char4_t *
740 mem_alloc_w4 (stream * strm, int * len)
741 {
742 unix_stream * s = (unix_stream *) strm;
743 gfc_offset m;
744 gfc_offset where = s->logical_offset;
745 gfc_char4_t *result = (gfc_char4_t *) s->buffer;
746
747 m = where + *len;
748
749 if (where < s->buffer_offset)
750 return NULL;
751
752 if (m > s->file_length)
753 return NULL;
754
755 s->logical_offset = m;
756 return &result[where - s->buffer_offset];
757 }
758
759
760 /* Stream read function for character(kind=1) internal units. */
761
762 static ssize_t
763 mem_read (stream * s, void * buf, ssize_t nbytes)
764 {
765 void *p;
766 int nb = nbytes;
767
768 p = mem_alloc_r (s, &nb);
769 if (p)
770 {
771 memcpy (buf, p, nb);
772 return (ssize_t) nb;
773 }
774 else
775 return 0;
776 }
777
778
779 /* Stream read function for chracter(kind=4) internal units. */
780
781 static ssize_t
782 mem_read4 (stream * s, void * buf, ssize_t nbytes)
783 {
784 void *p;
785 int nb = nbytes;
786
787 p = mem_alloc_r (s, &nb);
788 if (p)
789 {
790 memcpy (buf, p, nb);
791 return (ssize_t) nb;
792 }
793 else
794 return 0;
795 }
796
797
798 /* Stream write function for character(kind=1) internal units. */
799
800 static ssize_t
801 mem_write (stream * s, const void * buf, ssize_t nbytes)
802 {
803 void *p;
804 int nb = nbytes;
805
806 p = mem_alloc_w (s, &nb);
807 if (p)
808 {
809 memcpy (p, buf, nb);
810 return (ssize_t) nb;
811 }
812 else
813 return 0;
814 }
815
816
817 /* Stream write function for character(kind=4) internal units. */
818
819 static ssize_t
820 mem_write4 (stream * s, const void * buf, ssize_t nwords)
821 {
822 gfc_char4_t *p;
823 int nw = nwords;
824
825 p = mem_alloc_w4 (s, &nw);
826 if (p)
827 {
828 while (nw--)
829 *p++ = (gfc_char4_t) *((char *) buf);
830 return nwords;
831 }
832 else
833 return 0;
834 }
835
836
837 static gfc_offset
838 mem_seek (stream * strm, gfc_offset offset, int whence)
839 {
840 unix_stream * s = (unix_stream *) strm;
841 switch (whence)
842 {
843 case SEEK_SET:
844 break;
845 case SEEK_CUR:
846 offset += s->logical_offset;
847 break;
848 case SEEK_END:
849 offset += s->file_length;
850 break;
851 default:
852 return -1;
853 }
854
855 /* Note that for internal array I/O it's actually possible to have a
856 negative offset, so don't check for that. */
857 if (offset > s->file_length)
858 {
859 errno = EINVAL;
860 return -1;
861 }
862
863 s->logical_offset = offset;
864
865 /* Returning < 0 is the error indicator for sseek(), so return 0 if
866 offset is negative. Thus if the return value is 0, the caller
867 has to use stell() to get the real value of logical_offset. */
868 if (offset >= 0)
869 return offset;
870 return 0;
871 }
872
873
874 static gfc_offset
875 mem_tell (stream * s)
876 {
877 return ((unix_stream *)s)->logical_offset;
878 }
879
880
881 static int
882 mem_truncate (unix_stream * s __attribute__ ((unused)),
883 gfc_offset length __attribute__ ((unused)))
884 {
885 return 0;
886 }
887
888
889 static int
890 mem_flush (unix_stream * s __attribute__ ((unused)))
891 {
892 return 0;
893 }
894
895
896 static int
897 mem_close (unix_stream * s)
898 {
899 free (s);
900
901 return 0;
902 }
903
904 static const struct stream_vtable mem_vtable = {
905 .read = (void *) mem_read,
906 .write = (void *) mem_write,
907 .seek = (void *) mem_seek,
908 .tell = (void *) mem_tell,
909 /* buf_size is not a typo, we just reuse an identical
910 implementation. */
911 .size = (void *) buf_size,
912 .trunc = (void *) mem_truncate,
913 .close = (void *) mem_close,
914 .flush = (void *) mem_flush
915 };
916
917 static const struct stream_vtable mem4_vtable = {
918 .read = (void *) mem_read4,
919 .write = (void *) mem_write4,
920 .seek = (void *) mem_seek,
921 .tell = (void *) mem_tell,
922 /* buf_size is not a typo, we just reuse an identical
923 implementation. */
924 .size = (void *) buf_size,
925 .trunc = (void *) mem_truncate,
926 .close = (void *) mem_close,
927 .flush = (void *) mem_flush
928 };
929
930 /*********************************************************************
931 Public functions -- A reimplementation of this module needs to
932 define functional equivalents of the following.
933 *********************************************************************/
934
935 /* open_internal()-- Returns a stream structure from a character(kind=1)
936 internal file */
937
938 stream *
939 open_internal (char *base, int length, gfc_offset offset)
940 {
941 unix_stream *s;
942
943 s = xcalloc (1, sizeof (unix_stream));
944
945 s->buffer = base;
946 s->buffer_offset = offset;
947
948 s->active = s->file_length = length;
949
950 s->st.vptr = &mem_vtable;
951
952 return (stream *) s;
953 }
954
955 /* open_internal4()-- Returns a stream structure from a character(kind=4)
956 internal file */
957
958 stream *
959 open_internal4 (char *base, int length, gfc_offset offset)
960 {
961 unix_stream *s;
962
963 s = xcalloc (1, sizeof (unix_stream));
964
965 s->buffer = base;
966 s->buffer_offset = offset;
967
968 s->active = s->file_length = length * sizeof (gfc_char4_t);
969
970 s->st.vptr = &mem4_vtable;
971
972 return (stream *) s;
973 }
974
975
976 /* "Unbuffered" really means I/O statement buffering. For formatted
977 I/O, the fbuf manages this, and then uses raw I/O. For unformatted
978 I/O, buffered I/O is used, and the buffer is flushed at the end of
979 each I/O statement, where this function is called. */
980
981 int
982 flush_if_unbuffered (stream* s)
983 {
984 unix_stream* us = (unix_stream*) s;
985 if (us->unbuffered)
986 return sflush (s);
987 return 0;
988 }
989
990
991 /* fd_to_stream()-- Given an open file descriptor, build a stream
992 * around it. */
993
994 static stream *
995 fd_to_stream (int fd, bool unformatted)
996 {
997 struct stat statbuf;
998 unix_stream *s;
999
1000 s = xcalloc (1, sizeof (unix_stream));
1001
1002 s->fd = fd;
1003
1004 /* Get the current length of the file. */
1005
1006 fstat (fd, &statbuf);
1007
1008 s->st_dev = statbuf.st_dev;
1009 s->st_ino = statbuf.st_ino;
1010 s->file_length = statbuf.st_size;
1011
1012 /* Only use buffered IO for regular files. */
1013 if (S_ISREG (statbuf.st_mode)
1014 && !options.all_unbuffered
1015 && !(options.unbuffered_preconnected &&
1016 (s->fd == STDIN_FILENO
1017 || s->fd == STDOUT_FILENO
1018 || s->fd == STDERR_FILENO)))
1019 buf_init (s);
1020 else
1021 {
1022 if (unformatted)
1023 {
1024 s->unbuffered = true;
1025 buf_init (s);
1026 }
1027 else
1028 raw_init (s);
1029 }
1030
1031 return (stream *) s;
1032 }
1033
1034
1035 /* Given the Fortran unit number, convert it to a C file descriptor. */
1036
1037 int
1038 unit_to_fd (int unit)
1039 {
1040 gfc_unit *us;
1041 int fd;
1042
1043 us = find_unit (unit);
1044 if (us == NULL)
1045 return -1;
1046
1047 fd = ((unix_stream *) us->s)->fd;
1048 unlock_unit (us);
1049 return fd;
1050 }
1051
1052
1053 /* unpack_filename()-- Given a fortran string and a pointer to a
1054 * buffer that is PATH_MAX characters, convert the fortran string to a
1055 * C string in the buffer. Returns nonzero if this is not possible. */
1056
1057 int
1058 unpack_filename (char *cstring, const char *fstring, int len)
1059 {
1060 if (fstring == NULL)
1061 return EFAULT;
1062 len = fstrlen (fstring, len);
1063 if (len >= PATH_MAX)
1064 return ENAMETOOLONG;
1065
1066 memmove (cstring, fstring, len);
1067 cstring[len] = '\0';
1068
1069 return 0;
1070 }
1071
1072
1073 /* Helper function for tempfile(). Tries to open a temporary file in
1074 the directory specified by tempdir. If successful, the file name is
1075 stored in fname and the descriptor returned. Returns -1 on
1076 failure. */
1077
1078 static int
1079 tempfile_open (const char *tempdir, char **fname)
1080 {
1081 int fd;
1082 const char *slash = "/";
1083 #if defined(HAVE_UMASK) && defined(HAVE_MKSTEMP)
1084 mode_t mode_mask;
1085 #endif
1086
1087 if (!tempdir)
1088 return -1;
1089
1090 /* Check for the special case that tempdir ends with a slash or
1091 backslash. */
1092 size_t tempdirlen = strlen (tempdir);
1093 if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/'
1094 #ifdef __MINGW32__
1095 || tempdir[tempdirlen - 1] == '\\'
1096 #endif
1097 )
1098 slash = "";
1099
1100 // Take care that the template is longer in the mktemp() branch.
1101 char * template = xmalloc (tempdirlen + 23);
1102
1103 #ifdef HAVE_MKSTEMP
1104 snprintf (template, tempdirlen + 23, "%s%sgfortrantmpXXXXXX",
1105 tempdir, slash);
1106
1107 #ifdef HAVE_UMASK
1108 /* Temporarily set the umask such that the file has 0600 permissions. */
1109 mode_mask = umask (S_IXUSR | S_IRWXG | S_IRWXO);
1110 #endif
1111
1112 fd = mkstemp (template);
1113
1114 #ifdef HAVE_UMASK
1115 (void) umask (mode_mask);
1116 #endif
1117
1118 #else /* HAVE_MKSTEMP */
1119 fd = -1;
1120 int count = 0;
1121 size_t slashlen = strlen (slash);
1122 do
1123 {
1124 snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX",
1125 tempdir, slash);
1126 if (count > 0)
1127 {
1128 int c = count;
1129 template[tempdirlen + slashlen + 13] = 'a' + (c% 26);
1130 c /= 26;
1131 template[tempdirlen + slashlen + 12] = 'a' + (c % 26);
1132 c /= 26;
1133 template[tempdirlen + slashlen + 11] = 'a' + (c % 26);
1134 if (c >= 26)
1135 break;
1136 }
1137
1138 if (!mktemp (template))
1139 {
1140 errno = EEXIST;
1141 count++;
1142 continue;
1143 }
1144
1145 #if defined(HAVE_CRLF) && defined(O_BINARY)
1146 fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
1147 S_IRUSR | S_IWUSR);
1148 #else
1149 fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
1150 #endif
1151 }
1152 while (fd == -1 && errno == EEXIST);
1153 #endif /* HAVE_MKSTEMP */
1154
1155 *fname = template;
1156 return fd;
1157 }
1158
1159
1160 /* tempfile()-- Generate a temporary filename for a scratch file and
1161 * open it. mkstemp() opens the file for reading and writing, but the
1162 * library mode prevents anything that is not allowed. The descriptor
1163 * is returned, which is -1 on error. The template is pointed to by
1164 * opp->file, which is copied into the unit structure
1165 * and freed later. */
1166
1167 static int
1168 tempfile (st_parameter_open *opp)
1169 {
1170 const char *tempdir;
1171 char *fname;
1172 int fd = -1;
1173
1174 tempdir = secure_getenv ("TMPDIR");
1175 fd = tempfile_open (tempdir, &fname);
1176 #ifdef __MINGW32__
1177 if (fd == -1)
1178 {
1179 char buffer[MAX_PATH + 1];
1180 DWORD ret;
1181 ret = GetTempPath (MAX_PATH, buffer);
1182 /* If we are not able to get a temp-directory, we use
1183 current directory. */
1184 if (ret > MAX_PATH || !ret)
1185 buffer[0] = 0;
1186 else
1187 buffer[ret] = 0;
1188 tempdir = strdup (buffer);
1189 fd = tempfile_open (tempdir, &fname);
1190 }
1191 #elif defined(__CYGWIN__)
1192 if (fd == -1)
1193 {
1194 tempdir = secure_getenv ("TMP");
1195 fd = tempfile_open (tempdir, &fname);
1196 }
1197 if (fd == -1)
1198 {
1199 tempdir = secure_getenv ("TEMP");
1200 fd = tempfile_open (tempdir, &fname);
1201 }
1202 #endif
1203 if (fd == -1)
1204 fd = tempfile_open (P_tmpdir, &fname);
1205
1206 opp->file = fname;
1207 opp->file_len = strlen (fname); /* Don't include trailing nul */
1208
1209 return fd;
1210 }
1211
1212
1213 /* regular_file()-- Open a regular file.
1214 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
1215 * unless an error occurs.
1216 * Returns the descriptor, which is less than zero on error. */
1217
1218 static int
1219 regular_file (st_parameter_open *opp, unit_flags *flags)
1220 {
1221 char path[min(PATH_MAX, opp->file_len + 1)];
1222 int mode;
1223 int rwflag;
1224 int crflag;
1225 int fd;
1226 int err;
1227
1228 err = unpack_filename (path, opp->file, opp->file_len);
1229 if (err)
1230 {
1231 errno = err; /* Fake an OS error */
1232 return -1;
1233 }
1234
1235 #ifdef __CYGWIN__
1236 if (opp->file_len == 7)
1237 {
1238 if (strncmp (path, "CONOUT$", 7) == 0
1239 || strncmp (path, "CONERR$", 7) == 0)
1240 {
1241 fd = open ("/dev/conout", O_WRONLY);
1242 flags->action = ACTION_WRITE;
1243 return fd;
1244 }
1245 }
1246
1247 if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
1248 {
1249 fd = open ("/dev/conin", O_RDONLY);
1250 flags->action = ACTION_READ;
1251 return fd;
1252 }
1253 #endif
1254
1255
1256 #ifdef __MINGW32__
1257 if (opp->file_len == 7)
1258 {
1259 if (strncmp (path, "CONOUT$", 7) == 0
1260 || strncmp (path, "CONERR$", 7) == 0)
1261 {
1262 fd = open ("CONOUT$", O_WRONLY);
1263 flags->action = ACTION_WRITE;
1264 return fd;
1265 }
1266 }
1267
1268 if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
1269 {
1270 fd = open ("CONIN$", O_RDONLY);
1271 flags->action = ACTION_READ;
1272 return fd;
1273 }
1274 #endif
1275
1276 rwflag = 0;
1277
1278 switch (flags->action)
1279 {
1280 case ACTION_READ:
1281 rwflag = O_RDONLY;
1282 break;
1283
1284 case ACTION_WRITE:
1285 rwflag = O_WRONLY;
1286 break;
1287
1288 case ACTION_READWRITE:
1289 case ACTION_UNSPECIFIED:
1290 rwflag = O_RDWR;
1291 break;
1292
1293 default:
1294 internal_error (&opp->common, "regular_file(): Bad action");
1295 }
1296
1297 switch (flags->status)
1298 {
1299 case STATUS_NEW:
1300 crflag = O_CREAT | O_EXCL;
1301 break;
1302
1303 case STATUS_OLD: /* open will fail if the file does not exist*/
1304 crflag = 0;
1305 break;
1306
1307 case STATUS_UNKNOWN:
1308 case STATUS_SCRATCH:
1309 crflag = O_CREAT;
1310 break;
1311
1312 case STATUS_REPLACE:
1313 crflag = O_CREAT | O_TRUNC;
1314 break;
1315
1316 default:
1317 internal_error (&opp->common, "regular_file(): Bad status");
1318 }
1319
1320 /* rwflag |= O_LARGEFILE; */
1321
1322 #if defined(HAVE_CRLF) && defined(O_BINARY)
1323 crflag |= O_BINARY;
1324 #endif
1325
1326 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
1327 fd = open (path, rwflag | crflag, mode);
1328 if (flags->action != ACTION_UNSPECIFIED)
1329 return fd;
1330
1331 if (fd >= 0)
1332 {
1333 flags->action = ACTION_READWRITE;
1334 return fd;
1335 }
1336 if (errno != EACCES && errno != EROFS)
1337 return fd;
1338
1339 /* retry for read-only access */
1340 rwflag = O_RDONLY;
1341 fd = open (path, rwflag | crflag, mode);
1342 if (fd >=0)
1343 {
1344 flags->action = ACTION_READ;
1345 return fd; /* success */
1346 }
1347
1348 if (errno != EACCES)
1349 return fd; /* failure */
1350
1351 /* retry for write-only access */
1352 rwflag = O_WRONLY;
1353 fd = open (path, rwflag | crflag, mode);
1354 if (fd >=0)
1355 {
1356 flags->action = ACTION_WRITE;
1357 return fd; /* success */
1358 }
1359 return fd; /* failure */
1360 }
1361
1362
1363 /* open_external()-- Open an external file, unix specific version.
1364 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
1365 * Returns NULL on operating system error. */
1366
1367 stream *
1368 open_external (st_parameter_open *opp, unit_flags *flags)
1369 {
1370 int fd;
1371
1372 if (flags->status == STATUS_SCRATCH)
1373 {
1374 fd = tempfile (opp);
1375 if (flags->action == ACTION_UNSPECIFIED)
1376 flags->action = ACTION_READWRITE;
1377
1378 #if HAVE_UNLINK_OPEN_FILE
1379 /* We can unlink scratch files now and it will go away when closed. */
1380 if (fd >= 0)
1381 unlink (opp->file);
1382 #endif
1383 }
1384 else
1385 {
1386 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1387 * if it succeeds */
1388 fd = regular_file (opp, flags);
1389 }
1390
1391 if (fd < 0)
1392 return NULL;
1393 fd = fix_fd (fd);
1394
1395 return fd_to_stream (fd, flags->form == FORM_UNFORMATTED);
1396 }
1397
1398
1399 /* input_stream()-- Return a stream pointer to the default input stream.
1400 * Called on initialization. */
1401
1402 stream *
1403 input_stream (void)
1404 {
1405 return fd_to_stream (STDIN_FILENO, false);
1406 }
1407
1408
1409 /* output_stream()-- Return a stream pointer to the default output stream.
1410 * Called on initialization. */
1411
1412 stream *
1413 output_stream (void)
1414 {
1415 stream * s;
1416
1417 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1418 setmode (STDOUT_FILENO, O_BINARY);
1419 #endif
1420
1421 s = fd_to_stream (STDOUT_FILENO, false);
1422 return s;
1423 }
1424
1425
1426 /* error_stream()-- Return a stream pointer to the default error stream.
1427 * Called on initialization. */
1428
1429 stream *
1430 error_stream (void)
1431 {
1432 stream * s;
1433
1434 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1435 setmode (STDERR_FILENO, O_BINARY);
1436 #endif
1437
1438 s = fd_to_stream (STDERR_FILENO, false);
1439 return s;
1440 }
1441
1442
1443 /* compare_file_filename()-- Given an open stream and a fortran string
1444 * that is a filename, figure out if the file is the same as the
1445 * filename. */
1446
1447 int
1448 compare_file_filename (gfc_unit *u, const char *name, int len)
1449 {
1450 char path[min(PATH_MAX, len + 1)];
1451 struct stat st;
1452 #ifdef HAVE_WORKING_STAT
1453 unix_stream *s;
1454 #else
1455 # ifdef __MINGW32__
1456 uint64_t id1, id2;
1457 # endif
1458 #endif
1459
1460 if (unpack_filename (path, name, len))
1461 return 0; /* Can't be the same */
1462
1463 /* If the filename doesn't exist, then there is no match with the
1464 * existing file. */
1465
1466 if (stat (path, &st) < 0)
1467 return 0;
1468
1469 #ifdef HAVE_WORKING_STAT
1470 s = (unix_stream *) (u->s);
1471 return (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
1472 #else
1473
1474 # ifdef __MINGW32__
1475 /* We try to match files by a unique ID. On some filesystems (network
1476 fs and FAT), we can't generate this unique ID, and will simply compare
1477 filenames. */
1478 id1 = id_from_path (path);
1479 id2 = id_from_fd (((unix_stream *) (u->s))->fd);
1480 if (id1 || id2)
1481 return (id1 == id2);
1482 # endif
1483
1484 if (len != u->file_len)
1485 return 0;
1486 return (memcmp(path, u->file, len) == 0);
1487 #endif
1488 }
1489
1490
1491 #ifdef HAVE_WORKING_STAT
1492 # define FIND_FILE0_DECL struct stat *st
1493 # define FIND_FILE0_ARGS st
1494 #else
1495 # define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
1496 # define FIND_FILE0_ARGS id, file, file_len
1497 #endif
1498
1499 /* find_file0()-- Recursive work function for find_file() */
1500
1501 static gfc_unit *
1502 find_file0 (gfc_unit *u, FIND_FILE0_DECL)
1503 {
1504 gfc_unit *v;
1505 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1506 uint64_t id1;
1507 #endif
1508
1509 if (u == NULL)
1510 return NULL;
1511
1512 #ifdef HAVE_WORKING_STAT
1513 if (u->s != NULL)
1514 {
1515 unix_stream *s = (unix_stream *) (u->s);
1516 if (st[0].st_dev == s->st_dev && st[0].st_ino == s->st_ino)
1517 return u;
1518 }
1519 #else
1520 # ifdef __MINGW32__
1521 if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
1522 {
1523 if (id == id1)
1524 return u;
1525 }
1526 else
1527 # endif
1528 if (compare_string (u->file_len, u->file, file_len, file) == 0)
1529 return u;
1530 #endif
1531
1532 v = find_file0 (u->left, FIND_FILE0_ARGS);
1533 if (v != NULL)
1534 return v;
1535
1536 v = find_file0 (u->right, FIND_FILE0_ARGS);
1537 if (v != NULL)
1538 return v;
1539
1540 return NULL;
1541 }
1542
1543
1544 /* find_file()-- Take the current filename and see if there is a unit
1545 * that has the file already open. Returns a pointer to the unit if so. */
1546
1547 gfc_unit *
1548 find_file (const char *file, gfc_charlen_type file_len)
1549 {
1550 char path[min(PATH_MAX, file_len + 1)];
1551 struct stat st[1];
1552 gfc_unit *u;
1553 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1554 uint64_t id = 0ULL;
1555 #endif
1556
1557 if (unpack_filename (path, file, file_len))
1558 return NULL;
1559
1560 if (stat (path, &st[0]) < 0)
1561 return NULL;
1562
1563 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1564 id = id_from_path (path);
1565 #endif
1566
1567 __gthread_mutex_lock (&unit_lock);
1568 retry:
1569 u = find_file0 (unit_root, FIND_FILE0_ARGS);
1570 if (u != NULL)
1571 {
1572 /* Fast path. */
1573 if (! __gthread_mutex_trylock (&u->lock))
1574 {
1575 /* assert (u->closed == 0); */
1576 __gthread_mutex_unlock (&unit_lock);
1577 return u;
1578 }
1579
1580 inc_waiting_locked (u);
1581 }
1582 __gthread_mutex_unlock (&unit_lock);
1583 if (u != NULL)
1584 {
1585 __gthread_mutex_lock (&u->lock);
1586 if (u->closed)
1587 {
1588 __gthread_mutex_lock (&unit_lock);
1589 __gthread_mutex_unlock (&u->lock);
1590 if (predec_waiting_locked (u) == 0)
1591 free (u);
1592 goto retry;
1593 }
1594
1595 dec_waiting_unlocked (u);
1596 }
1597 return u;
1598 }
1599
1600 static gfc_unit *
1601 flush_all_units_1 (gfc_unit *u, int min_unit)
1602 {
1603 while (u != NULL)
1604 {
1605 if (u->unit_number > min_unit)
1606 {
1607 gfc_unit *r = flush_all_units_1 (u->left, min_unit);
1608 if (r != NULL)
1609 return r;
1610 }
1611 if (u->unit_number >= min_unit)
1612 {
1613 if (__gthread_mutex_trylock (&u->lock))
1614 return u;
1615 if (u->s)
1616 sflush (u->s);
1617 __gthread_mutex_unlock (&u->lock);
1618 }
1619 u = u->right;
1620 }
1621 return NULL;
1622 }
1623
1624 void
1625 flush_all_units (void)
1626 {
1627 gfc_unit *u;
1628 int min_unit = 0;
1629
1630 __gthread_mutex_lock (&unit_lock);
1631 do
1632 {
1633 u = flush_all_units_1 (unit_root, min_unit);
1634 if (u != NULL)
1635 inc_waiting_locked (u);
1636 __gthread_mutex_unlock (&unit_lock);
1637 if (u == NULL)
1638 return;
1639
1640 __gthread_mutex_lock (&u->lock);
1641
1642 min_unit = u->unit_number + 1;
1643
1644 if (u->closed == 0)
1645 {
1646 sflush (u->s);
1647 __gthread_mutex_lock (&unit_lock);
1648 __gthread_mutex_unlock (&u->lock);
1649 (void) predec_waiting_locked (u);
1650 }
1651 else
1652 {
1653 __gthread_mutex_lock (&unit_lock);
1654 __gthread_mutex_unlock (&u->lock);
1655 if (predec_waiting_locked (u) == 0)
1656 free (u);
1657 }
1658 }
1659 while (1);
1660 }
1661
1662
1663 /* delete_file()-- Given a unit structure, delete the file associated
1664 * with the unit. Returns nonzero if something went wrong. */
1665
1666 int
1667 delete_file (gfc_unit * u)
1668 {
1669 char path[min(PATH_MAX, u->file_len + 1)];
1670 int err = unpack_filename (path, u->file, u->file_len);
1671
1672 if (err)
1673 { /* Shouldn't be possible */
1674 errno = err;
1675 return 1;
1676 }
1677
1678 return unlink (path);
1679 }
1680
1681
1682 /* file_exists()-- Returns nonzero if the current filename exists on
1683 * the system */
1684
1685 int
1686 file_exists (const char *file, gfc_charlen_type file_len)
1687 {
1688 char path[min(PATH_MAX, file_len + 1)];
1689
1690 if (unpack_filename (path, file, file_len))
1691 return 0;
1692
1693 return !(access (path, F_OK));
1694 }
1695
1696
1697 /* file_size()-- Returns the size of the file. */
1698
1699 GFC_IO_INT
1700 file_size (const char *file, gfc_charlen_type file_len)
1701 {
1702 char path[min(PATH_MAX, file_len + 1)];
1703 struct stat statbuf;
1704
1705 if (unpack_filename (path, file, file_len))
1706 return -1;
1707
1708 if (stat (path, &statbuf) < 0)
1709 return -1;
1710
1711 return (GFC_IO_INT) statbuf.st_size;
1712 }
1713
1714 static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
1715
1716 /* inquire_sequential()-- Given a fortran string, determine if the
1717 * file is suitable for sequential access. Returns a C-style
1718 * string. */
1719
1720 const char *
1721 inquire_sequential (const char *string, int len)
1722 {
1723 char path[min(PATH_MAX, len + 1)];
1724 struct stat statbuf;
1725
1726 if (string == NULL ||
1727 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1728 return unknown;
1729
1730 if (S_ISREG (statbuf.st_mode) ||
1731 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1732 return unknown;
1733
1734 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1735 return no;
1736
1737 return unknown;
1738 }
1739
1740
1741 /* inquire_direct()-- Given a fortran string, determine if the file is
1742 * suitable for direct access. Returns a C-style string. */
1743
1744 const char *
1745 inquire_direct (const char *string, int len)
1746 {
1747 char path[min(PATH_MAX, len + 1)];
1748 struct stat statbuf;
1749
1750 if (string == NULL ||
1751 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1752 return unknown;
1753
1754 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1755 return unknown;
1756
1757 if (S_ISDIR (statbuf.st_mode) ||
1758 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1759 return no;
1760
1761 return unknown;
1762 }
1763
1764
1765 /* inquire_formatted()-- Given a fortran string, determine if the file
1766 * is suitable for formatted form. Returns a C-style string. */
1767
1768 const char *
1769 inquire_formatted (const char *string, int len)
1770 {
1771 char path[min(PATH_MAX, len + 1)];
1772 struct stat statbuf;
1773
1774 if (string == NULL ||
1775 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1776 return unknown;
1777
1778 if (S_ISREG (statbuf.st_mode) ||
1779 S_ISBLK (statbuf.st_mode) ||
1780 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1781 return unknown;
1782
1783 if (S_ISDIR (statbuf.st_mode))
1784 return no;
1785
1786 return unknown;
1787 }
1788
1789
1790 /* inquire_unformatted()-- Given a fortran string, determine if the file
1791 * is suitable for unformatted form. Returns a C-style string. */
1792
1793 const char *
1794 inquire_unformatted (const char *string, int len)
1795 {
1796 return inquire_formatted (string, len);
1797 }
1798
1799
1800 /* inquire_access()-- Given a fortran string, determine if the file is
1801 * suitable for access. */
1802
1803 static const char *
1804 inquire_access (const char *string, int len, int mode)
1805 {
1806 char path[min(PATH_MAX, len + 1)];
1807
1808 if (string == NULL || unpack_filename (path, string, len) ||
1809 access (path, mode) < 0)
1810 return no;
1811
1812 return yes;
1813 }
1814
1815
1816 /* inquire_read()-- Given a fortran string, determine if the file is
1817 * suitable for READ access. */
1818
1819 const char *
1820 inquire_read (const char *string, int len)
1821 {
1822 return inquire_access (string, len, R_OK);
1823 }
1824
1825
1826 /* inquire_write()-- Given a fortran string, determine if the file is
1827 * suitable for READ access. */
1828
1829 const char *
1830 inquire_write (const char *string, int len)
1831 {
1832 return inquire_access (string, len, W_OK);
1833 }
1834
1835
1836 /* inquire_readwrite()-- Given a fortran string, determine if the file is
1837 * suitable for read and write access. */
1838
1839 const char *
1840 inquire_readwrite (const char *string, int len)
1841 {
1842 return inquire_access (string, len, R_OK | W_OK);
1843 }
1844
1845
1846 int
1847 stream_isatty (stream *s)
1848 {
1849 return isatty (((unix_stream *) s)->fd);
1850 }
1851
1852 int
1853 stream_ttyname (stream *s __attribute__ ((unused)),
1854 char * buf __attribute__ ((unused)),
1855 size_t buflen __attribute__ ((unused)))
1856 {
1857 #ifdef HAVE_TTYNAME_R
1858 return ttyname_r (((unix_stream *) s)->fd, buf, buflen);
1859 #elif defined HAVE_TTYNAME
1860 char *p;
1861 size_t plen;
1862 p = ttyname (((unix_stream *) s)->fd);
1863 if (!p)
1864 return errno;
1865 plen = strlen (p);
1866 if (buflen < plen)
1867 plen = buflen;
1868 memcpy (buf, p, plen);
1869 return 0;
1870 #else
1871 return ENOSYS;
1872 #endif
1873 }
1874
1875
1876
1877
1878 /* How files are stored: This is an operating-system specific issue,
1879 and therefore belongs here. There are three cases to consider.
1880
1881 Direct Access:
1882 Records are written as block of bytes corresponding to the record
1883 length of the file. This goes for both formatted and unformatted
1884 records. Positioning is done explicitly for each data transfer,
1885 so positioning is not much of an issue.
1886
1887 Sequential Formatted:
1888 Records are separated by newline characters. The newline character
1889 is prohibited from appearing in a string. If it does, this will be
1890 messed up on the next read. End of file is also the end of a record.
1891
1892 Sequential Unformatted:
1893 In this case, we are merely copying bytes to and from main storage,
1894 yet we need to keep track of varying record lengths. We adopt
1895 the solution used by f2c. Each record contains a pair of length
1896 markers:
1897
1898 Length of record n in bytes
1899 Data of record n
1900 Length of record n in bytes
1901
1902 Length of record n+1 in bytes
1903 Data of record n+1
1904 Length of record n+1 in bytes
1905
1906 The length is stored at the end of a record to allow backspacing to the
1907 previous record. Between data transfer statements, the file pointer
1908 is left pointing to the first length of the current record.
1909
1910 ENDFILE records are never explicitly stored.
1911
1912 */