OSDN Git Service

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