OSDN Git Service

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