OSDN Git Service

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