OSDN Git Service

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