OSDN Git Service

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