OSDN Git Service

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