OSDN Git Service

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