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