OSDN Git Service

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