OSDN Git Service

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