OSDN Git Service

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