OSDN Git Service

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