OSDN Git Service

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