OSDN Git Service

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