OSDN Git Service

2011-04-04 Tobias Burnus <burnus@net-b.de>
[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   if (s != NULL)
854     free (s);
855
856   return 0;
857 }
858
859
860 /*********************************************************************
861   Public functions -- A reimplementation of this module needs to
862   define functional equivalents of the following.
863 *********************************************************************/
864
865 /* open_internal()-- Returns a stream structure from a character(kind=1)
866    internal file */
867
868 stream *
869 open_internal (char *base, int length, gfc_offset offset)
870 {
871   unix_stream *s;
872
873   s = get_mem (sizeof (unix_stream));
874   memset (s, '\0', sizeof (unix_stream));
875
876   s->buffer = base;
877   s->buffer_offset = offset;
878
879   s->logical_offset = 0;
880   s->active = s->file_length = length;
881
882   s->st.close = (void *) mem_close;
883   s->st.seek = (void *) mem_seek;
884   s->st.tell = (void *) mem_tell;
885   s->st.trunc = (void *) mem_truncate;
886   s->st.read = (void *) mem_read;
887   s->st.write = (void *) mem_write;
888   s->st.flush = (void *) mem_flush;
889
890   return (stream *) s;
891 }
892
893 /* open_internal4()-- Returns a stream structure from a character(kind=4)
894    internal file */
895
896 stream *
897 open_internal4 (char *base, int length, gfc_offset offset)
898 {
899   unix_stream *s;
900
901   s = get_mem (sizeof (unix_stream));
902   memset (s, '\0', sizeof (unix_stream));
903
904   s->buffer = base;
905   s->buffer_offset = offset;
906
907   s->logical_offset = 0;
908   s->active = s->file_length = length;
909
910   s->st.close = (void *) mem_close;
911   s->st.seek = (void *) mem_seek;
912   s->st.tell = (void *) mem_tell;
913   s->st.trunc = (void *) mem_truncate;
914   s->st.read = (void *) mem_read4;
915   s->st.write = (void *) mem_write4;
916   s->st.flush = (void *) mem_flush;
917
918   return (stream *) s;
919 }
920
921
922 /* fd_to_stream()-- Given an open file descriptor, build a stream
923  * around it. */
924
925 static stream *
926 fd_to_stream (int fd)
927 {
928   struct stat statbuf;
929   unix_stream *s;
930
931   s = get_mem (sizeof (unix_stream));
932   memset (s, '\0', sizeof (unix_stream));
933
934   s->fd = fd;
935   s->buffer_offset = 0;
936   s->physical_offset = 0;
937   s->logical_offset = 0;
938
939   /* Get the current length of the file. */
940
941   fstat (fd, &statbuf);
942
943   s->st_dev = statbuf.st_dev;
944   s->st_ino = statbuf.st_ino;
945   s->special_file = !S_ISREG (statbuf.st_mode);
946
947   if (S_ISREG (statbuf.st_mode))
948     s->file_length = statbuf.st_size;
949   else if (S_ISBLK (statbuf.st_mode))
950     {
951       /* Hopefully more portable than ioctl(fd, BLKGETSIZE64, &size)?  */
952       gfc_offset cur = lseek (fd, 0, SEEK_CUR);
953       s->file_length = lseek (fd, 0, SEEK_END);
954       lseek (fd, cur, SEEK_SET);
955     }
956   else
957     s->file_length = -1;
958
959   if (!(S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
960       || options.all_unbuffered
961       ||(options.unbuffered_preconnected && 
962          (s->fd == STDIN_FILENO 
963           || s->fd == STDOUT_FILENO 
964           || s->fd == STDERR_FILENO))
965       || isatty (s->fd))
966     raw_init (s);
967   else
968     buf_init (s);
969
970   return (stream *) s;
971 }
972
973
974 /* Given the Fortran unit number, convert it to a C file descriptor.  */
975
976 int
977 unit_to_fd (int unit)
978 {
979   gfc_unit *us;
980   int fd;
981
982   us = find_unit (unit);
983   if (us == NULL)
984     return -1;
985
986   fd = ((unix_stream *) us->s)->fd;
987   unlock_unit (us);
988   return fd;
989 }
990
991
992 /* unpack_filename()-- Given a fortran string and a pointer to a
993  * buffer that is PATH_MAX characters, convert the fortran string to a
994  * C string in the buffer.  Returns nonzero if this is not possible.  */
995
996 int
997 unpack_filename (char *cstring, const char *fstring, int len)
998 {
999   if (fstring == NULL)
1000     return 1;
1001   len = fstrlen (fstring, len);
1002   if (len >= PATH_MAX)
1003     return 1;
1004
1005   memmove (cstring, fstring, len);
1006   cstring[len] = '\0';
1007
1008   return 0;
1009 }
1010
1011
1012 /* tempfile()-- Generate a temporary filename for a scratch file and
1013  * open it.  mkstemp() opens the file for reading and writing, but the
1014  * library mode prevents anything that is not allowed.  The descriptor
1015  * is returned, which is -1 on error.  The template is pointed to by 
1016  * opp->file, which is copied into the unit structure
1017  * and freed later. */
1018
1019 static int
1020 tempfile (st_parameter_open *opp)
1021 {
1022   const char *tempdir;
1023   char *template;
1024   const char *slash = "/";
1025   int fd;
1026   size_t tempdirlen;
1027
1028 #ifndef HAVE_MKSTEMP
1029   int count;
1030   size_t slashlen;
1031 #endif
1032
1033   tempdir = getenv ("GFORTRAN_TMPDIR");
1034 #ifdef __MINGW32__
1035   if (tempdir == NULL)
1036     {
1037       char buffer[MAX_PATH + 1];
1038       DWORD ret;
1039       ret = GetTempPath (MAX_PATH, buffer);
1040       /* If we are not able to get a temp-directory, we use
1041          current directory.  */
1042       if (ret > MAX_PATH || !ret)
1043         buffer[0] = 0;
1044       else
1045         buffer[ret] = 0;
1046       tempdir = strdup (buffer);
1047     }
1048 #else
1049   if (tempdir == NULL)
1050     tempdir = getenv ("TMP");
1051   if (tempdir == NULL)
1052     tempdir = getenv ("TEMP");
1053   if (tempdir == NULL)
1054     tempdir = DEFAULT_TEMPDIR;
1055 #endif
1056
1057   /* Check for special case that tempdir contains slash
1058      or backslash at end.  */
1059   tempdirlen = strlen (tempdir);
1060   if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/'
1061 #ifdef __MINGW32__
1062       || tempdir[tempdirlen - 1] == '\\'
1063 #endif
1064      )
1065     slash = "";
1066
1067   // Take care that the template is longer in the mktemp() branch.
1068   template = get_mem (tempdirlen + 23);
1069
1070 #ifdef HAVE_MKSTEMP
1071   sprintf (template, "%s%sgfortrantmpXXXXXX", 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       sprintf (template, "%s%sgfortrantmpaaaXXXXXX", tempdir, slash);
1082       if (count > 0)
1083         {
1084           int c = count;
1085           template[tempdirlen + slashlen + 13] = 'a' + (c% 26);
1086           c /= 26;
1087           template[tempdirlen + slashlen + 12] = 'a' + (c % 26);
1088           c /= 26;
1089           template[tempdirlen + slashlen + 11] = 'a' + (c % 26);
1090           if (c >= 26)
1091             break;
1092         }
1093
1094       if (!mktemp (template))
1095       {
1096         errno = EEXIST;
1097         count++;
1098         continue;
1099       }
1100
1101 #if defined(HAVE_CRLF) && defined(O_BINARY)
1102       fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
1103                  S_IREAD | S_IWRITE);
1104 #else
1105       fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
1106 #endif
1107     }
1108   while (fd == -1 && errno == EEXIST);
1109 #endif /* HAVE_MKSTEMP */
1110
1111   opp->file = template;
1112   opp->file_len = strlen (template);    /* Don't include trailing nul */
1113
1114   return fd;
1115 }
1116
1117
1118 /* regular_file()-- Open a regular file.
1119  * Change flags->action if it is ACTION_UNSPECIFIED on entry,
1120  * unless an error occurs.
1121  * Returns the descriptor, which is less than zero on error. */
1122
1123 static int
1124 regular_file (st_parameter_open *opp, unit_flags *flags)
1125 {
1126   char path[PATH_MAX + 1];
1127   int mode;
1128   int rwflag;
1129   int crflag;
1130   int fd;
1131
1132   if (unpack_filename (path, opp->file, opp->file_len))
1133     {
1134       errno = ENOENT;           /* Fake an OS error */
1135       return -1;
1136     }
1137
1138 #ifdef __CYGWIN__
1139   if (opp->file_len == 7)
1140     {
1141       if (strncmp (path, "CONOUT$", 7) == 0
1142           || strncmp (path, "CONERR$", 7) == 0)
1143         {
1144           fd = open ("/dev/conout", O_WRONLY);
1145           flags->action = ACTION_WRITE;
1146           return fd;
1147         }
1148     }
1149
1150   if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
1151     {
1152       fd = open ("/dev/conin", O_RDONLY);
1153       flags->action = ACTION_READ;
1154       return fd;
1155     }
1156 #endif
1157
1158
1159 #ifdef __MINGW32__
1160   if (opp->file_len == 7)
1161     {
1162       if (strncmp (path, "CONOUT$", 7) == 0
1163           || strncmp (path, "CONERR$", 7) == 0)
1164         {
1165           fd = open ("CONOUT$", O_WRONLY);
1166           flags->action = ACTION_WRITE;
1167           return fd;
1168         }
1169     }
1170
1171   if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
1172     {
1173       fd = open ("CONIN$", O_RDONLY);
1174       flags->action = ACTION_READ;
1175       return fd;
1176     }
1177 #endif
1178
1179   rwflag = 0;
1180
1181   switch (flags->action)
1182     {
1183     case ACTION_READ:
1184       rwflag = O_RDONLY;
1185       break;
1186
1187     case ACTION_WRITE:
1188       rwflag = O_WRONLY;
1189       break;
1190
1191     case ACTION_READWRITE:
1192     case ACTION_UNSPECIFIED:
1193       rwflag = O_RDWR;
1194       break;
1195
1196     default:
1197       internal_error (&opp->common, "regular_file(): Bad action");
1198     }
1199
1200   switch (flags->status)
1201     {
1202     case STATUS_NEW:
1203       crflag = O_CREAT | O_EXCL;
1204       break;
1205
1206     case STATUS_OLD:            /* open will fail if the file does not exist*/
1207       crflag = 0;
1208       break;
1209
1210     case STATUS_UNKNOWN:
1211     case STATUS_SCRATCH:
1212       crflag = O_CREAT;
1213       break;
1214
1215     case STATUS_REPLACE:
1216       crflag = O_CREAT | O_TRUNC;
1217       break;
1218
1219     default:
1220       internal_error (&opp->common, "regular_file(): Bad status");
1221     }
1222
1223   /* rwflag |= O_LARGEFILE; */
1224
1225 #if defined(HAVE_CRLF) && defined(O_BINARY)
1226   crflag |= O_BINARY;
1227 #endif
1228
1229   mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
1230   fd = open (path, rwflag | crflag, mode);
1231   if (flags->action != ACTION_UNSPECIFIED)
1232     return fd;
1233
1234   if (fd >= 0)
1235     {
1236       flags->action = ACTION_READWRITE;
1237       return fd;
1238     }
1239   if (errno != EACCES && errno != EROFS)
1240      return fd;
1241
1242   /* retry for read-only access */
1243   rwflag = O_RDONLY;
1244   fd = open (path, rwflag | crflag, mode);
1245   if (fd >=0)
1246     {
1247       flags->action = ACTION_READ;
1248       return fd;                /* success */
1249     }
1250   
1251   if (errno != EACCES)
1252     return fd;                  /* failure */
1253
1254   /* retry for write-only access */
1255   rwflag = O_WRONLY;
1256   fd = open (path, rwflag | crflag, mode);
1257   if (fd >=0)
1258     {
1259       flags->action = ACTION_WRITE;
1260       return fd;                /* success */
1261     }
1262   return fd;                    /* failure */
1263 }
1264
1265
1266 /* open_external()-- Open an external file, unix specific version.
1267  * Change flags->action if it is ACTION_UNSPECIFIED on entry.
1268  * Returns NULL on operating system error. */
1269
1270 stream *
1271 open_external (st_parameter_open *opp, unit_flags *flags)
1272 {
1273   int fd;
1274
1275   if (flags->status == STATUS_SCRATCH)
1276     {
1277       fd = tempfile (opp);
1278       if (flags->action == ACTION_UNSPECIFIED)
1279         flags->action = ACTION_READWRITE;
1280
1281 #if HAVE_UNLINK_OPEN_FILE
1282       /* We can unlink scratch files now and it will go away when closed. */
1283       if (fd >= 0)
1284         unlink (opp->file);
1285 #endif
1286     }
1287   else
1288     {
1289       /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1290        * if it succeeds */
1291       fd = regular_file (opp, flags);
1292     }
1293
1294   if (fd < 0)
1295     return NULL;
1296   fd = fix_fd (fd);
1297
1298   return fd_to_stream (fd);
1299 }
1300
1301
1302 /* input_stream()-- Return a stream pointer to the default input stream.
1303  * Called on initialization. */
1304
1305 stream *
1306 input_stream (void)
1307 {
1308   return fd_to_stream (STDIN_FILENO);
1309 }
1310
1311
1312 /* output_stream()-- Return a stream pointer to the default output stream.
1313  * Called on initialization. */
1314
1315 stream *
1316 output_stream (void)
1317 {
1318   stream * s;
1319
1320 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1321   setmode (STDOUT_FILENO, O_BINARY);
1322 #endif
1323
1324   s = fd_to_stream (STDOUT_FILENO);
1325   return s;
1326 }
1327
1328
1329 /* error_stream()-- Return a stream pointer to the default error stream.
1330  * Called on initialization. */
1331
1332 stream *
1333 error_stream (void)
1334 {
1335   stream * s;
1336
1337 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1338   setmode (STDERR_FILENO, O_BINARY);
1339 #endif
1340
1341   s = fd_to_stream (STDERR_FILENO);
1342   return s;
1343 }
1344
1345
1346 /* st_vprintf()-- vprintf function for error output.  To avoid buffer
1347    overruns, we limit the length of the buffer to ST_VPRINTF_SIZE.  2k
1348    is big enough to completely fill a 80x25 terminal, so it shuld be
1349    OK.  We use a direct write() because it is simpler and least likely
1350    to be clobbered by memory corruption.  Writing an error message
1351    longer than that is an error.  */
1352
1353 #define ST_VPRINTF_SIZE 2048
1354
1355 int
1356 st_vprintf (const char *format, va_list ap)
1357 {
1358   static char buffer[ST_VPRINTF_SIZE];
1359   int written;
1360   int fd;
1361
1362   fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1363 #ifdef HAVE_VSNPRINTF
1364   written = vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
1365 #else
1366   written = vsprintf(buffer, format, ap);
1367
1368   if (written >= ST_VPRINTF_SIZE-1)
1369     {
1370       /* The error message was longer than our buffer.  Ouch.  Because
1371          we may have messed up things badly, report the error and
1372          quit.  */
1373 #define ERROR_MESSAGE "Internal error: buffer overrun in st_vprintf()\n"
1374       write (fd, buffer, ST_VPRINTF_SIZE-1);
1375       write (fd, ERROR_MESSAGE, strlen(ERROR_MESSAGE));
1376       sys_exit(2);
1377 #undef ERROR_MESSAGE
1378
1379     }
1380 #endif
1381
1382   written = write (fd, buffer, written);
1383   return written;
1384 }
1385
1386 /* st_printf()-- printf() function for error output.  This just calls
1387    st_vprintf() to do the actual work.  */
1388
1389 int
1390 st_printf (const char *format, ...)
1391 {
1392   int written;
1393   va_list ap;
1394   va_start (ap, format);
1395   written = st_vprintf(format, ap);
1396   va_end (ap);
1397   return written;
1398 }
1399
1400
1401 /* compare_file_filename()-- Given an open stream and a fortran string
1402  * that is a filename, figure out if the file is the same as the
1403  * filename. */
1404
1405 int
1406 compare_file_filename (gfc_unit *u, const char *name, int len)
1407 {
1408   char path[PATH_MAX + 1];
1409   struct stat st;
1410 #ifdef HAVE_WORKING_STAT
1411   unix_stream *s;
1412 #else
1413 # ifdef __MINGW32__
1414   uint64_t id1, id2;
1415 # endif
1416 #endif
1417
1418   if (unpack_filename (path, name, len))
1419     return 0;                   /* Can't be the same */
1420
1421   /* If the filename doesn't exist, then there is no match with the
1422    * existing file. */
1423
1424   if (stat (path, &st) < 0)
1425     return 0;
1426
1427 #ifdef HAVE_WORKING_STAT
1428   s = (unix_stream *) (u->s);
1429   return (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
1430 #else
1431
1432 # ifdef __MINGW32__
1433   /* We try to match files by a unique ID.  On some filesystems (network
1434      fs and FAT), we can't generate this unique ID, and will simply compare
1435      filenames.  */
1436   id1 = id_from_path (path);
1437   id2 = id_from_fd (((unix_stream *) (u->s))->fd);
1438   if (id1 || id2)
1439     return (id1 == id2);
1440 # endif
1441
1442   if (len != u->file_len)
1443     return 0;
1444   return (memcmp(path, u->file, len) == 0);
1445 #endif
1446 }
1447
1448
1449 #ifdef HAVE_WORKING_STAT
1450 # define FIND_FILE0_DECL struct stat *st
1451 # define FIND_FILE0_ARGS st
1452 #else
1453 # define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
1454 # define FIND_FILE0_ARGS id, file, file_len
1455 #endif
1456
1457 /* find_file0()-- Recursive work function for find_file() */
1458
1459 static gfc_unit *
1460 find_file0 (gfc_unit *u, FIND_FILE0_DECL)
1461 {
1462   gfc_unit *v;
1463 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1464   uint64_t id1;
1465 #endif
1466
1467   if (u == NULL)
1468     return NULL;
1469
1470 #ifdef HAVE_WORKING_STAT
1471   if (u->s != NULL)
1472     {
1473       unix_stream *s = (unix_stream *) (u->s);
1474       if (st[0].st_dev == s->st_dev && st[0].st_ino == s->st_ino)
1475         return u;
1476     }
1477 #else
1478 # ifdef __MINGW32__ 
1479   if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
1480     {
1481       if (id == id1)
1482         return u;
1483     }
1484   else
1485 # endif
1486     if (compare_string (u->file_len, u->file, file_len, file) == 0)
1487       return u;
1488 #endif
1489
1490   v = find_file0 (u->left, FIND_FILE0_ARGS);
1491   if (v != NULL)
1492     return v;
1493
1494   v = find_file0 (u->right, FIND_FILE0_ARGS);
1495   if (v != NULL)
1496     return v;
1497
1498   return NULL;
1499 }
1500
1501
1502 /* find_file()-- Take the current filename and see if there is a unit
1503  * that has the file already open.  Returns a pointer to the unit if so. */
1504
1505 gfc_unit *
1506 find_file (const char *file, gfc_charlen_type file_len)
1507 {
1508   char path[PATH_MAX + 1];
1509   struct stat st[1];
1510   gfc_unit *u;
1511 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1512   uint64_t id = 0ULL;
1513 #endif
1514
1515   if (unpack_filename (path, file, file_len))
1516     return NULL;
1517
1518   if (stat (path, &st[0]) < 0)
1519     return NULL;
1520
1521 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1522   id = id_from_path (path);
1523 #endif
1524
1525   __gthread_mutex_lock (&unit_lock);
1526 retry:
1527   u = find_file0 (unit_root, FIND_FILE0_ARGS);
1528   if (u != NULL)
1529     {
1530       /* Fast path.  */
1531       if (! __gthread_mutex_trylock (&u->lock))
1532         {
1533           /* assert (u->closed == 0); */
1534           __gthread_mutex_unlock (&unit_lock);
1535           return u;
1536         }
1537
1538       inc_waiting_locked (u);
1539     }
1540   __gthread_mutex_unlock (&unit_lock);
1541   if (u != NULL)
1542     {
1543       __gthread_mutex_lock (&u->lock);
1544       if (u->closed)
1545         {
1546           __gthread_mutex_lock (&unit_lock);
1547           __gthread_mutex_unlock (&u->lock);
1548           if (predec_waiting_locked (u) == 0)
1549             free (u);
1550           goto retry;
1551         }
1552
1553       dec_waiting_unlocked (u);
1554     }
1555   return u;
1556 }
1557
1558 static gfc_unit *
1559 flush_all_units_1 (gfc_unit *u, int min_unit)
1560 {
1561   while (u != NULL)
1562     {
1563       if (u->unit_number > min_unit)
1564         {
1565           gfc_unit *r = flush_all_units_1 (u->left, min_unit);
1566           if (r != NULL)
1567             return r;
1568         }
1569       if (u->unit_number >= min_unit)
1570         {
1571           if (__gthread_mutex_trylock (&u->lock))
1572             return u;
1573           if (u->s)
1574             sflush (u->s);
1575           __gthread_mutex_unlock (&u->lock);
1576         }
1577       u = u->right;
1578     }
1579   return NULL;
1580 }
1581
1582 void
1583 flush_all_units (void)
1584 {
1585   gfc_unit *u;
1586   int min_unit = 0;
1587
1588   __gthread_mutex_lock (&unit_lock);
1589   do
1590     {
1591       u = flush_all_units_1 (unit_root, min_unit);
1592       if (u != NULL)
1593         inc_waiting_locked (u);
1594       __gthread_mutex_unlock (&unit_lock);
1595       if (u == NULL)
1596         return;
1597
1598       __gthread_mutex_lock (&u->lock);
1599
1600       min_unit = u->unit_number + 1;
1601
1602       if (u->closed == 0)
1603         {
1604           sflush (u->s);
1605           __gthread_mutex_lock (&unit_lock);
1606           __gthread_mutex_unlock (&u->lock);
1607           (void) predec_waiting_locked (u);
1608         }
1609       else
1610         {
1611           __gthread_mutex_lock (&unit_lock);
1612           __gthread_mutex_unlock (&u->lock);
1613           if (predec_waiting_locked (u) == 0)
1614             free (u);
1615         }
1616     }
1617   while (1);
1618 }
1619
1620
1621 /* delete_file()-- Given a unit structure, delete the file associated
1622  * with the unit.  Returns nonzero if something went wrong. */
1623
1624 int
1625 delete_file (gfc_unit * u)
1626 {
1627   char path[PATH_MAX + 1];
1628
1629   if (unpack_filename (path, u->file, u->file_len))
1630     {                           /* Shouldn't be possible */
1631       errno = ENOENT;
1632       return 1;
1633     }
1634
1635   return unlink (path);
1636 }
1637
1638
1639 /* file_exists()-- Returns nonzero if the current filename exists on
1640  * the system */
1641
1642 int
1643 file_exists (const char *file, gfc_charlen_type file_len)
1644 {
1645   char path[PATH_MAX + 1];
1646
1647   if (unpack_filename (path, file, file_len))
1648     return 0;
1649
1650   return !(access (path, F_OK));
1651 }
1652
1653
1654 /* file_size()-- Returns the size of the file.  */
1655
1656 GFC_IO_INT
1657 file_size (const char *file, gfc_charlen_type file_len)
1658 {
1659   char path[PATH_MAX + 1];
1660   struct stat statbuf;
1661
1662   if (unpack_filename (path, file, file_len))
1663     return -1;
1664
1665   if (stat (path, &statbuf) < 0)
1666     return -1;
1667
1668   return (GFC_IO_INT) statbuf.st_size;
1669 }
1670
1671 static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
1672
1673 /* inquire_sequential()-- Given a fortran string, determine if the
1674  * file is suitable for sequential access.  Returns a C-style
1675  * string. */
1676
1677 const char *
1678 inquire_sequential (const char *string, int len)
1679 {
1680   char path[PATH_MAX + 1];
1681   struct stat statbuf;
1682
1683   if (string == NULL ||
1684       unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1685     return unknown;
1686
1687   if (S_ISREG (statbuf.st_mode) ||
1688       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1689     return unknown;
1690
1691   if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1692     return no;
1693
1694   return unknown;
1695 }
1696
1697
1698 /* inquire_direct()-- Given a fortran string, determine if the file is
1699  * suitable for direct access.  Returns a C-style string. */
1700
1701 const char *
1702 inquire_direct (const char *string, int len)
1703 {
1704   char path[PATH_MAX + 1];
1705   struct stat statbuf;
1706
1707   if (string == NULL ||
1708       unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1709     return unknown;
1710
1711   if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1712     return unknown;
1713
1714   if (S_ISDIR (statbuf.st_mode) ||
1715       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1716     return no;
1717
1718   return unknown;
1719 }
1720
1721
1722 /* inquire_formatted()-- Given a fortran string, determine if the file
1723  * is suitable for formatted form.  Returns a C-style string. */
1724
1725 const char *
1726 inquire_formatted (const char *string, int len)
1727 {
1728   char path[PATH_MAX + 1];
1729   struct stat statbuf;
1730
1731   if (string == NULL ||
1732       unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1733     return unknown;
1734
1735   if (S_ISREG (statbuf.st_mode) ||
1736       S_ISBLK (statbuf.st_mode) ||
1737       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1738     return unknown;
1739
1740   if (S_ISDIR (statbuf.st_mode))
1741     return no;
1742
1743   return unknown;
1744 }
1745
1746
1747 /* inquire_unformatted()-- Given a fortran string, determine if the file
1748  * is suitable for unformatted form.  Returns a C-style string. */
1749
1750 const char *
1751 inquire_unformatted (const char *string, int len)
1752 {
1753   return inquire_formatted (string, len);
1754 }
1755
1756
1757 /* inquire_access()-- Given a fortran string, determine if the file is
1758  * suitable for access. */
1759
1760 static const char *
1761 inquire_access (const char *string, int len, int mode)
1762 {
1763   char path[PATH_MAX + 1];
1764
1765   if (string == NULL || unpack_filename (path, string, len) ||
1766       access (path, mode) < 0)
1767     return no;
1768
1769   return yes;
1770 }
1771
1772
1773 /* inquire_read()-- Given a fortran string, determine if the file is
1774  * suitable for READ access. */
1775
1776 const char *
1777 inquire_read (const char *string, int len)
1778 {
1779   return inquire_access (string, len, R_OK);
1780 }
1781
1782
1783 /* inquire_write()-- Given a fortran string, determine if the file is
1784  * suitable for READ access. */
1785
1786 const char *
1787 inquire_write (const char *string, int len)
1788 {
1789   return inquire_access (string, len, W_OK);
1790 }
1791
1792
1793 /* inquire_readwrite()-- Given a fortran string, determine if the file is
1794  * suitable for read and write access. */
1795
1796 const char *
1797 inquire_readwrite (const char *string, int len)
1798 {
1799   return inquire_access (string, len, R_OK | W_OK);
1800 }
1801
1802
1803 /* file_length()-- Return the file length in bytes, -1 if unknown */
1804
1805 gfc_offset
1806 file_length (stream * s)
1807 {
1808   gfc_offset curr, end;
1809   if (!is_seekable (s))
1810     return -1;
1811   curr = stell (s);
1812   if (curr == -1)
1813     return curr;
1814   end = sseek (s, 0, SEEK_END);
1815   sseek (s, curr, SEEK_SET);
1816   return end;
1817 }
1818
1819
1820 /* is_seekable()-- Return nonzero if the stream is seekable, zero if
1821  * it is not */
1822
1823 int
1824 is_seekable (stream *s)
1825 {
1826   /* By convention, if file_length == -1, the file is not
1827      seekable.  */
1828   return ((unix_stream *) s)->file_length!=-1;
1829 }
1830
1831
1832 /* is_special()-- Return nonzero if the stream is not a regular file.  */
1833
1834 int
1835 is_special (stream *s)
1836 {
1837   return ((unix_stream *) s)->special_file;
1838 }
1839
1840
1841 int
1842 stream_isatty (stream *s)
1843 {
1844   return isatty (((unix_stream *) s)->fd);
1845 }
1846
1847 int
1848 stream_ttyname (stream *s  __attribute__ ((unused)),
1849                 char * buf  __attribute__ ((unused)),
1850                 size_t buflen  __attribute__ ((unused)))
1851 {
1852 #ifdef HAVE_TTYNAME_R
1853   return ttyname_r (((unix_stream *) s)->fd, buf, buflen);
1854 #elif defined HAVE_TTYNAME
1855   char *p;
1856   size_t plen;
1857   p = ttyname (((unix_stream *) s)->fd);
1858   if (!p)
1859     return errno;
1860   plen = strlen (p);
1861   if (buflen < plen)
1862     plen = buflen;
1863   memcpy (buf, p, plen);
1864   return 0;
1865 #else
1866   return ENOSYS;
1867 #endif
1868 }
1869
1870
1871
1872
1873 /* How files are stored:  This is an operating-system specific issue,
1874    and therefore belongs here.  There are three cases to consider.
1875
1876    Direct Access:
1877       Records are written as block of bytes corresponding to the record
1878       length of the file.  This goes for both formatted and unformatted
1879       records.  Positioning is done explicitly for each data transfer,
1880       so positioning is not much of an issue.
1881
1882    Sequential Formatted:
1883       Records are separated by newline characters.  The newline character
1884       is prohibited from appearing in a string.  If it does, this will be
1885       messed up on the next read.  End of file is also the end of a record.
1886
1887    Sequential Unformatted:
1888       In this case, we are merely copying bytes to and from main storage,
1889       yet we need to keep track of varying record lengths.  We adopt
1890       the solution used by f2c.  Each record contains a pair of length
1891       markers:
1892
1893         Length of record n in bytes
1894         Data of record n
1895         Length of record n in bytes
1896
1897         Length of record n+1 in bytes
1898         Data of record n+1
1899         Length of record n+1 in bytes
1900
1901      The length is stored at the end of a record to allow backspacing to the
1902      previous record.  Between data transfer statements, the file pointer
1903      is left pointing to the first length of the current record.
1904
1905      ENDFILE records are never explicitly stored.
1906
1907 */