OSDN Git Service

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