OSDN Git Service

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