OSDN Git Service

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