OSDN Git Service

2008-04-05 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libgfortran / io / unix.c
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
2    Free Software Foundation, Inc.
3    Contributed by Andy Vaught
4    F2003 I/O support contributed by Jerry DeLisle
5
6 This file is part of the GNU Fortran 95 runtime library (libgfortran).
7
8 Libgfortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file.  (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combine
20 executable.)
21
22 Libgfortran is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 GNU General Public License for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with Libgfortran; see the file COPYING.  If not, write to
29 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
30 Boston, MA 02110-1301, USA.  */
31
32 /* Unix stream I/O module */
33
34 #include "io.h"
35 #include <stdlib.h>
36 #include <limits.h>
37
38 #include <unistd.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <assert.h>
42
43 #include <string.h>
44 #include <errno.h>
45
46
47 /* For mingw, we don't identify files by their inode number, but by a
48    64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
49 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
50
51 #define WIN32_LEAN_AND_MEAN
52 #include <windows.h>
53
54 static uint64_t
55 id_from_handle (HANDLE hFile)
56 {
57   BY_HANDLE_FILE_INFORMATION FileInformation;
58
59   if (hFile == INVALID_HANDLE_VALUE)
60       return 0;
61
62   memset (&FileInformation, 0, sizeof(FileInformation));
63   if (!GetFileInformationByHandle (hFile, &FileInformation))
64     return 0;
65
66   return ((uint64_t) FileInformation.nFileIndexLow)
67          | (((uint64_t) FileInformation.nFileIndexHigh) << 32);
68 }
69
70
71 static uint64_t
72 id_from_path (const char *path)
73 {
74   HANDLE hFile;
75   uint64_t res;
76
77   if (!path || !*path || access (path, F_OK))
78     return (uint64_t) -1;
79
80   hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
81                       FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
82                       NULL);
83   res = id_from_handle (hFile);
84   CloseHandle (hFile);
85   return res;
86 }
87
88
89 static uint64_t
90 id_from_fd (const int fd)
91 {
92   return id_from_handle ((HANDLE) _get_osfhandle (fd));
93 }
94
95 #endif
96
97 #ifndef SSIZE_MAX
98 #define SSIZE_MAX SHRT_MAX
99 #endif
100
101 #ifndef PATH_MAX
102 #define PATH_MAX 1024
103 #endif
104
105 #ifndef PROT_READ
106 #define PROT_READ 1
107 #endif
108
109 #ifndef PROT_WRITE
110 #define PROT_WRITE 2
111 #endif
112
113 /* These flags aren't defined on all targets (mingw32), so provide them
114    here.  */
115 #ifndef S_IRGRP
116 #define S_IRGRP 0
117 #endif
118
119 #ifndef S_IWGRP
120 #define S_IWGRP 0
121 #endif
122
123 #ifndef S_IROTH
124 #define S_IROTH 0
125 #endif
126
127 #ifndef S_IWOTH
128 #define S_IWOTH 0
129 #endif
130
131
132 /* Unix stream I/O module */
133
134 #define BUFFER_SIZE 8192
135
136 typedef struct
137 {
138   stream st;
139
140   int fd;
141   gfc_offset buffer_offset;     /* File offset of the start of the buffer */
142   gfc_offset physical_offset;   /* Current physical file offset */
143   gfc_offset logical_offset;    /* Current logical file offset */
144   gfc_offset dirty_offset;      /* Start of modified bytes in buffer */
145   gfc_offset file_length;       /* Length of the file, -1 if not seekable. */
146
147   int len;                      /* Physical length of the current buffer */
148   int active;                   /* Length of valid bytes in the buffer */
149
150   int prot;
151   int ndirty;                   /* Dirty bytes starting at dirty_offset */
152
153   int special_file;             /* =1 if the fd refers to a special file */
154
155   io_mode method;               /* Method of stream I/O being used */
156
157   char *buffer;
158   char small_buffer[BUFFER_SIZE];
159 }
160 unix_stream;
161
162
163 /* Stream structure for internal files. Fields must be kept in sync
164    with unix_stream above, except for the buffer. For internal files
165    we point the buffer pointer directly at the destination memory.  */
166
167 typedef struct
168 {
169   stream st;
170
171   int fd;
172   gfc_offset buffer_offset;     /* File offset of the start of the buffer */
173   gfc_offset physical_offset;   /* Current physical file offset */
174   gfc_offset logical_offset;    /* Current logical file offset */
175   gfc_offset dirty_offset;      /* Start of modified bytes in buffer */
176   gfc_offset file_length;       /* Length of the file, -1 if not seekable. */
177
178   int len;                      /* Physical length of the current buffer */
179   int active;                   /* Length of valid bytes in the buffer */
180
181   int prot;
182   int ndirty;                   /* Dirty bytes starting at dirty_offset */
183
184   int special_file;             /* =1 if the fd refers to a special file */
185
186   io_mode method;               /* Method of stream I/O being used */
187
188   char *buffer;
189 }
190 int_stream;
191
192 /* This implementation of stream I/O is based on the paper:
193  *
194  *  "Exploiting the advantages of mapped files for stream I/O",
195  *  O. Krieger, M. Stumm and R. Umrau, "Proceedings of the 1992 Winter
196  *  USENIX conference", p. 27-42.
197  *
198  * It differs in a number of ways from the version described in the
199  * paper.  First of all, threads are not an issue during I/O and we
200  * also don't have to worry about having multiple regions, since
201  * fortran's I/O model only allows you to be one place at a time.
202  *
203  * On the other hand, we have to be able to writing at the end of a
204  * stream, read from the start of a stream or read and write blocks of
205  * bytes from an arbitrary position.  After opening a file, a pointer
206  * to a stream structure is returned, which is used to handle file
207  * accesses until the file is closed.
208  *
209  * salloc_at_r(stream, len, where)-- Given a stream pointer, return a
210  * pointer to a block of memory that mirror the file at position
211  * 'where' that is 'len' bytes long.  The len integer is updated to
212  * reflect how many bytes were actually read.  The only reason for a
213  * short read is end of file.  The file pointer is updated.  The
214  * pointer is valid until the next call to salloc_*.
215  *
216  * salloc_at_w(stream, len, where)-- Given the stream pointer, returns
217  * a pointer to a block of memory that is updated to reflect the state
218  * of the file.  The length of the buffer is always equal to that
219  * requested.  The buffer must be completely set by the caller.  When
220  * data has been written, the sfree() function must be called to
221  * indicate that the caller is done writing data to the buffer.  This
222  * may or may not cause a physical write.
223  *
224  * Short forms of these are salloc_r() and salloc_w() which drop the
225  * 'where' parameter and use the current file pointer. */
226
227
228 /*move_pos_offset()--  Move the record pointer right or left
229  *relative to current position */
230
231 int
232 move_pos_offset (stream* st, int pos_off)
233 {
234   unix_stream * str = (unix_stream*)st;
235   if (pos_off < 0)
236     {
237       str->logical_offset += pos_off;
238
239       if (str->dirty_offset + str->ndirty > str->logical_offset)
240         {
241           if (str->ndirty + pos_off > 0)
242             str->ndirty += pos_off;
243           else
244             {
245               str->dirty_offset +=  pos_off + pos_off;
246               str->ndirty = 0;
247             }
248         }
249
250     return pos_off;
251   }
252   return 0;
253 }
254
255
256 /* fix_fd()-- Given a file descriptor, make sure it is not one of the
257  * standard descriptors, returning a non-standard descriptor.  If the
258  * user specifies that system errors should go to standard output,
259  * then closes standard output, we don't want the system errors to a
260  * file that has been given file descriptor 1 or 0.  We want to send
261  * the error to the invalid descriptor. */
262
263 static int
264 fix_fd (int fd)
265 {
266 #ifdef HAVE_DUP
267   int input, output, error;
268
269   input = output = error = 0;
270
271   /* Unix allocates the lowest descriptors first, so a loop is not
272      required, but this order is. */
273   if (fd == STDIN_FILENO)
274     {
275       fd = dup (fd);
276       input = 1;
277     }
278   if (fd == STDOUT_FILENO)
279     {
280       fd = dup (fd);
281       output = 1;
282     }
283   if (fd == STDERR_FILENO)
284     {
285       fd = dup (fd);
286       error = 1;
287     }
288
289   if (input)
290     close (STDIN_FILENO);
291   if (output)
292     close (STDOUT_FILENO);
293   if (error)
294     close (STDERR_FILENO);
295 #endif
296
297   return fd;
298 }
299
300 int
301 is_preconnected (stream * s)
302 {
303   int fd;
304
305   fd = ((unix_stream *) s)->fd;
306   if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
307     return 1;
308   else
309     return 0;
310 }
311
312 /* If the stream corresponds to a preconnected unit, we flush the
313    corresponding C stream.  This is bugware for mixed C-Fortran codes
314    where the C code doesn't flush I/O before returning.  */
315 void
316 flush_if_preconnected (stream * s)
317 {
318   int fd;
319
320   fd = ((unix_stream *) s)->fd;
321   if (fd == STDIN_FILENO)
322     fflush (stdin);
323   else if (fd == STDOUT_FILENO)
324     fflush (stdout);
325   else if (fd == STDERR_FILENO)
326     fflush (stderr);
327 }
328
329
330 /* Reset a stream after reading/writing. Assumes that the buffers have
331    been flushed.  */
332
333 inline static void
334 reset_stream (unix_stream * s, size_t bytes_rw)
335 {
336   s->physical_offset += bytes_rw;
337   s->logical_offset = s->physical_offset;
338   if (s->file_length != -1 && s->physical_offset > s->file_length)
339     s->file_length = s->physical_offset;
340 }
341
342
343 /* Read bytes into a buffer, allowing for short reads.  If the nbytes
344  * argument is less on return than on entry, it is because we've hit
345  * the end of file. */
346
347 static int
348 do_read (unix_stream * s, void * buf, size_t * nbytes)
349 {
350   ssize_t trans;
351   size_t bytes_left;
352   char *buf_st;
353   int status;
354
355   status = 0;
356   bytes_left = *nbytes;
357   buf_st = (char *) buf;
358
359   /* We must read in a loop since some systems don't restart system
360      calls in case of a signal.  */
361   while (bytes_left > 0)
362     {
363       /* Requests between SSIZE_MAX and SIZE_MAX are undefined by SUSv3,
364          so we must read in chunks smaller than SSIZE_MAX.  */
365       trans = (bytes_left < SSIZE_MAX) ? bytes_left : SSIZE_MAX;
366       trans = read (s->fd, buf_st, trans);
367       if (trans < 0)
368         {
369           if (errno == EINTR)
370             continue;
371           else
372             {
373               status = errno;
374               break;
375             }
376         }
377       else if (trans == 0) /* We hit EOF.  */
378         break;
379       buf_st += trans;
380       bytes_left -= trans;
381     }
382
383   *nbytes -= bytes_left;
384   return status;
385 }
386
387
388 /* Write a buffer to a stream, allowing for short writes.  */
389
390 static int
391 do_write (unix_stream * s, const void * buf, size_t * nbytes)
392 {
393   ssize_t trans;
394   size_t bytes_left;
395   char *buf_st;
396   int status;
397
398   status = 0;
399   bytes_left = *nbytes;
400   buf_st = (char *) buf;
401
402   /* We must write in a loop since some systems don't restart system
403      calls in case of a signal.  */
404   while (bytes_left > 0)
405     {
406       /* Requests between SSIZE_MAX and SIZE_MAX are undefined by SUSv3,
407          so we must write in chunks smaller than SSIZE_MAX.  */
408       trans = (bytes_left < SSIZE_MAX) ? bytes_left : SSIZE_MAX;
409       trans = write (s->fd, buf_st, trans);
410       if (trans < 0)
411         {
412           if (errno == EINTR)
413             continue;
414           else
415             {
416               status = errno;
417               break;
418             }
419         }
420       buf_st += trans;
421       bytes_left -= trans;
422     }
423
424   *nbytes -= bytes_left;
425   return status;
426 }
427
428
429 /* get_oserror()-- Get the most recent operating system error.  For
430  * unix, this is errno. */
431
432 const char *
433 get_oserror (void)
434 {
435   return strerror (errno);
436 }
437
438
439 /*********************************************************************
440     File descriptor stream functions
441 *********************************************************************/
442
443
444 /* fd_flush()-- Write bytes that need to be written */
445
446 static try
447 fd_flush (unix_stream * s)
448 {
449   size_t writelen;
450
451   if (s->ndirty == 0)
452     return SUCCESS;
453   
454   if (s->file_length != -1 && s->physical_offset != s->dirty_offset &&
455       lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
456     return FAILURE;
457
458   writelen = s->ndirty;
459   if (do_write (s, s->buffer + (s->dirty_offset - s->buffer_offset),
460                 &writelen) != 0)
461     return FAILURE;
462
463   s->physical_offset = s->dirty_offset + writelen;
464
465   /* don't increment file_length if the file is non-seekable */
466   if (s->file_length != -1 && s->physical_offset > s->file_length)
467       s->file_length = s->physical_offset; 
468
469   s->ndirty -= writelen;
470   if (s->ndirty != 0)
471     return FAILURE;
472
473   return SUCCESS;
474 }
475
476
477 /* fd_alloc()-- Arrange a buffer such that the salloc() request can be
478  * satisfied.  This subroutine gets the buffer ready for whatever is
479  * to come next. */
480
481 static void
482 fd_alloc (unix_stream * s, gfc_offset where,
483           int *len __attribute__ ((unused)))
484 {
485   char *new_buffer;
486   int n, read_len;
487
488   if (*len <= BUFFER_SIZE)
489     {
490       new_buffer = s->small_buffer;
491       read_len = BUFFER_SIZE;
492     }
493   else
494     {
495       new_buffer = get_mem (*len);
496       read_len = *len;
497     }
498
499   /* Salvage bytes currently within the buffer.  This is important for
500    * devices that cannot seek. */
501
502   if (s->buffer != NULL && s->buffer_offset <= where &&
503       where <= s->buffer_offset + s->active)
504     {
505
506       n = s->active - (where - s->buffer_offset);
507       memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
508
509       s->active = n;
510     }
511   else
512     {                           /* new buffer starts off empty */
513       s->active = 0;
514     }
515
516   s->buffer_offset = where;
517
518   /* free the old buffer if necessary */
519
520   if (s->buffer != NULL && s->buffer != s->small_buffer)
521     free_mem (s->buffer);
522
523   s->buffer = new_buffer;
524   s->len = read_len;
525 }
526
527
528 /* fd_alloc_r_at()-- Allocate a stream buffer for reading.  Either
529  * we've already buffered the data or we need to load it.  Returns
530  * NULL on I/O error. */
531
532 static char *
533 fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
534 {
535   gfc_offset m;
536
537   if (where == -1)
538     where = s->logical_offset;
539
540   if (s->buffer != NULL && s->buffer_offset <= where &&
541       where + *len <= s->buffer_offset + s->active)
542     {
543
544       /* Return a position within the current buffer */
545
546       s->logical_offset = where + *len;
547       return s->buffer + where - s->buffer_offset;
548     }
549
550   fd_alloc (s, where, len);
551
552   m = where + s->active;
553
554   if (s->physical_offset != m && lseek (s->fd, m, SEEK_SET) < 0)
555     return NULL;
556
557   /* do_read() hangs on read from terminals for *BSD-systems.  Only
558      use read() in that case.  */
559
560   if (s->special_file)
561     {
562       ssize_t n;
563
564       n = read (s->fd, s->buffer + s->active, s->len - s->active);
565       if (n < 0)
566         return NULL;
567
568       s->physical_offset = m + n;
569       s->active += n;
570     }
571   else
572     {
573       size_t n;
574
575       n = s->len - s->active;
576       if (do_read (s, s->buffer + s->active, &n) != 0)
577         return NULL;
578
579       s->physical_offset = m + n;
580       s->active += n;
581     }
582
583   if (s->active < *len)
584     *len = s->active;           /* Bytes actually available */
585
586   s->logical_offset = where + *len;
587
588   return s->buffer;
589 }
590
591
592 /* fd_alloc_w_at()-- Allocate a stream buffer for writing.  Either
593  * we've already buffered the data or we need to load it. */
594
595 static char *
596 fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
597 {
598   gfc_offset n;
599
600   if (where == -1)
601     where = s->logical_offset;
602
603   if (s->buffer == NULL || s->buffer_offset > where ||
604       where + *len > s->buffer_offset + s->len)
605     {
606
607       if (fd_flush (s) == FAILURE)
608         return NULL;
609       fd_alloc (s, where, len);
610     }
611
612   /* Return a position within the current buffer */
613   if (s->ndirty == 0 
614       || where > s->dirty_offset + s->ndirty    
615       || s->dirty_offset > where + *len)
616     {  /* Discontiguous blocks, start with a clean buffer.  */  
617         /* Flush the buffer.  */  
618       if (s->ndirty != 0)    
619         fd_flush (s);  
620       s->dirty_offset = where;  
621       s->ndirty = *len;
622     }
623   else
624     {  
625       gfc_offset start;  /* Merge with the existing data.  */  
626       if (where < s->dirty_offset)    
627         start = where;  
628       else    
629         start = s->dirty_offset;  
630       if (where + *len > s->dirty_offset + s->ndirty)    
631         s->ndirty = where + *len - start;  
632       else    
633         s->ndirty = s->dirty_offset + s->ndirty - start;  
634       s->dirty_offset = start;
635     }
636
637   s->logical_offset = where + *len;
638
639   /* Don't increment file_length if the file is non-seekable.  */
640
641   if (s->file_length != -1 && s->logical_offset > s->file_length)
642      s->file_length = s->logical_offset;
643
644   n = s->logical_offset - s->buffer_offset;
645   if (n > s->active)
646     s->active = n;
647
648   return s->buffer + where - s->buffer_offset;
649 }
650
651
652 static try
653 fd_sfree (unix_stream * s)
654 {
655   if (s->ndirty != 0 &&
656       (s->buffer != s->small_buffer || options.all_unbuffered ||
657        s->method == SYNC_UNBUFFERED))
658     return fd_flush (s);
659
660   return SUCCESS;
661 }
662
663
664 static try
665 fd_seek (unix_stream * s, gfc_offset offset)
666 {
667
668   if (s->file_length == -1)
669     return SUCCESS;
670
671   if (s->physical_offset == offset) /* Are we lucky and avoid syscall?  */
672     {
673       s->logical_offset = offset;
674       return SUCCESS;
675     }
676
677   if (lseek (s->fd, offset, SEEK_SET) >= 0)
678     {
679       s->physical_offset = s->logical_offset = offset;
680       s->active = 0;
681       return SUCCESS;
682     }
683
684   return FAILURE;
685 }
686
687
688 /* truncate_file()-- Given a unit, truncate the file at the current
689  * position.  Sets the physical location to the new end of the file.
690  * Returns nonzero on error. */
691
692 static try
693 fd_truncate (unix_stream * s)
694 {
695   /* Non-seekable files, like terminals and fifo's fail the lseek so just
696      return success, there is nothing to truncate.  If its not a pipe there
697      is a real problem.  */
698   if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
699     {
700       if (errno == ESPIPE)
701         return SUCCESS;
702       else
703         return FAILURE;
704     }
705
706   /* Using ftruncate on a seekable special file (like /dev/null)
707      is undefined, so we treat it as if the ftruncate succeeded.  */
708   if (!s->special_file
709       && (
710 #ifdef HAVE_FTRUNCATE
711           ftruncate (s->fd, s->logical_offset) != 0
712 #elif defined HAVE_CHSIZE
713           chsize (s->fd, s->logical_offset) != 0
714 #else
715           /* If we have neither, always fail and exit, noisily.  */
716           runtime_error ("required ftruncate or chsize support not present"), 1
717 #endif
718           ))
719     {
720       /* The truncation failed and we need to handle this gracefully.
721          The file length remains the same, but the file-descriptor
722          offset needs adjustment per the successful lseek above.
723          (Similarly, the contents of the buffer isn't valid anymore.)
724          A ftruncate call does not affect the physical (file-descriptor)
725          offset, according to the ftruncate manual, so neither should a
726          failed call.  */
727       s->physical_offset = s->logical_offset;
728       s->active = 0;
729       return FAILURE;
730     }
731
732   s->physical_offset = s->file_length = s->logical_offset;
733   s->active = 0;
734   return SUCCESS;
735 }
736
737
738 /* Similar to memset(), but operating on a stream instead of a string.
739    Takes care of not using too much memory.  */
740
741 static try
742 fd_sset (unix_stream * s, int c, size_t n)
743 {
744   size_t bytes_left;
745   int trans;
746   void *p;
747
748   bytes_left = n;
749
750   while (bytes_left > 0)
751     {
752       /* memset() in chunks of BUFFER_SIZE.  */
753       trans = (bytes_left < BUFFER_SIZE) ? bytes_left : BUFFER_SIZE;
754
755       p = fd_alloc_w_at (s, &trans, -1);
756       if (p)
757           memset (p, c, trans);
758       else
759         return FAILURE;
760
761       bytes_left -= trans;
762     }
763
764   return SUCCESS;
765 }
766
767
768 /* Stream read function. Avoids using a buffer for big reads. The
769    interface is like POSIX read(), but the nbytes argument is a
770    pointer; on return it contains the number of bytes written. The
771    function return value is the status indicator (0 for success).  */
772
773 static int
774 fd_read (unix_stream * s, void * buf, size_t * nbytes)
775 {
776   void *p;
777   int tmp, status;
778
779   if (*nbytes < BUFFER_SIZE && s->method == SYNC_BUFFERED)
780     {
781       tmp = *nbytes;
782       p = fd_alloc_r_at (s, &tmp, -1);
783       if (p)
784         {
785           *nbytes = tmp;
786           memcpy (buf, p, *nbytes);
787           return 0;
788         }
789       else
790         {
791           *nbytes = 0;
792           return errno;
793         }
794     }
795
796   /* If the request is bigger than BUFFER_SIZE we flush the buffers
797      and read directly.  */
798   if (fd_flush (s) == FAILURE)
799     {
800       *nbytes = 0;
801       return errno;
802     }
803
804   if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
805     {
806       *nbytes = 0;
807       return errno;
808     }
809
810   status = do_read (s, buf, nbytes);
811   reset_stream (s, *nbytes);
812   return status;
813 }
814
815
816 /* Stream write function. Avoids using a buffer for big writes. The
817    interface is like POSIX write(), but the nbytes argument is a
818    pointer; on return it contains the number of bytes written. The
819    function return value is the status indicator (0 for success).  */
820
821 static int
822 fd_write (unix_stream * s, const void * buf, size_t * nbytes)
823 {
824   void *p;
825   int tmp, status;
826
827   if (*nbytes < BUFFER_SIZE && s->method == SYNC_BUFFERED)
828     {
829       tmp = *nbytes;
830       p = fd_alloc_w_at (s, &tmp, -1);
831       if (p)
832         {
833           *nbytes = tmp;
834           memcpy (p, buf, *nbytes);
835           return 0;
836         }
837       else
838         {
839           *nbytes = 0;
840           return errno;
841         }
842     }
843
844   /* If the request is bigger than BUFFER_SIZE we flush the buffers
845      and write directly.  */
846   if (fd_flush (s) == FAILURE)
847     {
848       *nbytes = 0;
849       return errno;
850     }
851
852   if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
853     {
854       *nbytes = 0;
855       return errno;
856     }
857
858   status =  do_write (s, buf, nbytes);
859   reset_stream (s, *nbytes);
860   return status;
861 }
862
863
864 static try
865 fd_close (unix_stream * s)
866 {
867   if (fd_flush (s) == FAILURE)
868     return FAILURE;
869
870   if (s->buffer != NULL && s->buffer != s->small_buffer)
871     free_mem (s->buffer);
872
873   if (s->fd != STDOUT_FILENO && s->fd != STDERR_FILENO && s->fd != STDIN_FILENO)
874     {
875       if (close (s->fd) < 0)
876         return FAILURE;
877     }
878
879   free_mem (s);
880
881   return SUCCESS;
882 }
883
884
885 static void
886 fd_open (unix_stream * s)
887 {
888   if (isatty (s->fd))
889     s->method = SYNC_UNBUFFERED;
890   else
891     s->method = SYNC_BUFFERED;
892
893   s->st.alloc_r_at = (void *) fd_alloc_r_at;
894   s->st.alloc_w_at = (void *) fd_alloc_w_at;
895   s->st.sfree = (void *) fd_sfree;
896   s->st.close = (void *) fd_close;
897   s->st.seek = (void *) fd_seek;
898   s->st.trunc = (void *) fd_truncate;
899   s->st.read = (void *) fd_read;
900   s->st.write = (void *) fd_write;
901   s->st.set = (void *) fd_sset;
902
903   s->buffer = NULL;
904 }
905
906
907
908
909 /*********************************************************************
910   memory stream functions - These are used for internal files
911
912   The idea here is that a single stream structure is created and all
913   requests must be satisfied from it.  The location and size of the
914   buffer is the character variable supplied to the READ or WRITE
915   statement.
916
917 *********************************************************************/
918
919
920 static char *
921 mem_alloc_r_at (int_stream * s, int *len, gfc_offset where)
922 {
923   gfc_offset n;
924
925   if (where == -1)
926     where = s->logical_offset;
927
928   if (where < s->buffer_offset || where > s->buffer_offset + s->active)
929     return NULL;
930
931   s->logical_offset = where + *len;
932
933   n = s->buffer_offset + s->active - where;
934   if (*len > n)
935     *len = n;
936
937   return s->buffer + (where - s->buffer_offset);
938 }
939
940
941 static char *
942 mem_alloc_w_at (int_stream * s, int *len, gfc_offset where)
943 {
944   gfc_offset m;
945
946   assert (*len >= 0);  /* Negative values not allowed. */
947   
948   if (where == -1)
949     where = s->logical_offset;
950
951   m = where + *len;
952
953   if (where < s->buffer_offset)
954     return NULL;
955
956   if (m > s->file_length)
957     return NULL;
958
959   s->logical_offset = m;
960
961   return s->buffer + (where - s->buffer_offset);
962 }
963
964
965 /* Stream read function for internal units. This is not actually used
966    at the moment, as all internal IO is formatted and the formatted IO
967    routines use mem_alloc_r_at.  */
968
969 static int
970 mem_read (int_stream * s, void * buf, size_t * nbytes)
971 {
972   void *p;
973   int tmp;
974
975   tmp = *nbytes;
976   p = mem_alloc_r_at (s, &tmp, -1);
977   if (p)
978     {
979       *nbytes = tmp;
980       memcpy (buf, p, *nbytes);
981       return 0;
982     }
983   else
984     {
985       *nbytes = 0;
986       return errno;
987     }
988 }
989
990
991 /* Stream write function for internal units. This is not actually used
992    at the moment, as all internal IO is formatted and the formatted IO
993    routines use mem_alloc_w_at.  */
994
995 static int
996 mem_write (int_stream * s, const void * buf, size_t * nbytes)
997 {
998   void *p;
999   int tmp;
1000
1001   errno = 0;
1002
1003   tmp = *nbytes;
1004   p = mem_alloc_w_at (s, &tmp, -1);
1005   if (p)
1006     {
1007       *nbytes = tmp;
1008       memcpy (p, buf, *nbytes);
1009       return 0;
1010     }
1011   else
1012     {
1013       *nbytes = 0;
1014       return errno;
1015     }
1016 }
1017
1018
1019 static int
1020 mem_seek (int_stream * s, gfc_offset offset)
1021 {
1022   if (offset > s->file_length)
1023     {
1024       errno = ESPIPE;
1025       return FAILURE;
1026     }
1027
1028   s->logical_offset = offset;
1029   return SUCCESS;
1030 }
1031
1032
1033 static try
1034 mem_set (int_stream * s, int c, size_t n)
1035 {
1036   void *p;
1037   int len;
1038
1039   len = n;
1040   
1041   p = mem_alloc_w_at (s, &len, -1);
1042   if (p)
1043     {
1044       memset (p, c, len);
1045       return SUCCESS;
1046     }
1047   else
1048     return FAILURE;
1049 }
1050
1051
1052 static int
1053 mem_truncate (int_stream * s __attribute__ ((unused)))
1054 {
1055   return SUCCESS;
1056 }
1057
1058
1059 static try
1060 mem_close (int_stream * s)
1061 {
1062   if (s != NULL)
1063     free_mem (s);
1064
1065   return SUCCESS;
1066 }
1067
1068
1069 static try
1070 mem_sfree (int_stream * s __attribute__ ((unused)))
1071 {
1072   return SUCCESS;
1073 }
1074
1075
1076
1077 /*********************************************************************
1078   Public functions -- A reimplementation of this module needs to
1079   define functional equivalents of the following.
1080 *********************************************************************/
1081
1082 /* empty_internal_buffer()-- Zero the buffer of Internal file */
1083
1084 void
1085 empty_internal_buffer(stream *strm)
1086 {
1087   int_stream * s = (int_stream *) strm;
1088   memset(s->buffer, ' ', s->file_length);
1089 }
1090
1091 /* open_internal()-- Returns a stream structure from an internal file */
1092
1093 stream *
1094 open_internal (char *base, int length, gfc_offset offset)
1095 {
1096   int_stream *s;
1097
1098   s = get_mem (sizeof (int_stream));
1099   memset (s, '\0', sizeof (int_stream));
1100
1101   s->buffer = base;
1102   s->buffer_offset = offset;
1103
1104   s->logical_offset = 0;
1105   s->active = s->file_length = length;
1106
1107   s->st.alloc_r_at = (void *) mem_alloc_r_at;
1108   s->st.alloc_w_at = (void *) mem_alloc_w_at;
1109   s->st.sfree = (void *) mem_sfree;
1110   s->st.close = (void *) mem_close;
1111   s->st.seek = (void *) mem_seek;
1112   s->st.trunc = (void *) mem_truncate;
1113   s->st.read = (void *) mem_read;
1114   s->st.write = (void *) mem_write;
1115   s->st.set = (void *) mem_set;
1116
1117   return (stream *) s;
1118 }
1119
1120
1121 /* fd_to_stream()-- Given an open file descriptor, build a stream
1122  * around it. */
1123
1124 static stream *
1125 fd_to_stream (int fd, int prot)
1126 {
1127   struct stat statbuf;
1128   unix_stream *s;
1129
1130   s = get_mem (sizeof (unix_stream));
1131   memset (s, '\0', sizeof (unix_stream));
1132
1133   s->fd = fd;
1134   s->buffer_offset = 0;
1135   s->physical_offset = 0;
1136   s->logical_offset = 0;
1137   s->prot = prot;
1138
1139   /* Get the current length of the file. */
1140
1141   fstat (fd, &statbuf);
1142
1143   if (lseek (fd, 0, SEEK_CUR) == (off_t) -1)
1144     s->file_length = -1;
1145   else
1146     s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
1147
1148   s->special_file = !S_ISREG (statbuf.st_mode);
1149
1150   fd_open (s);
1151
1152   return (stream *) s;
1153 }
1154
1155
1156 /* Given the Fortran unit number, convert it to a C file descriptor.  */
1157
1158 int
1159 unit_to_fd (int unit)
1160 {
1161   gfc_unit *us;
1162   int fd;
1163
1164   us = find_unit (unit);
1165   if (us == NULL)
1166     return -1;
1167
1168   fd = ((unix_stream *) us->s)->fd;
1169   unlock_unit (us);
1170   return fd;
1171 }
1172
1173
1174 /* unpack_filename()-- Given a fortran string and a pointer to a
1175  * buffer that is PATH_MAX characters, convert the fortran string to a
1176  * C string in the buffer.  Returns nonzero if this is not possible.  */
1177
1178 int
1179 unpack_filename (char *cstring, const char *fstring, int len)
1180 {
1181   len = fstrlen (fstring, len);
1182   if (len >= PATH_MAX)
1183     return 1;
1184
1185   memmove (cstring, fstring, len);
1186   cstring[len] = '\0';
1187
1188   return 0;
1189 }
1190
1191
1192 /* tempfile()-- Generate a temporary filename for a scratch file and
1193  * open it.  mkstemp() opens the file for reading and writing, but the
1194  * library mode prevents anything that is not allowed.  The descriptor
1195  * is returned, which is -1 on error.  The template is pointed to by 
1196  * opp->file, which is copied into the unit structure
1197  * and freed later. */
1198
1199 static int
1200 tempfile (st_parameter_open *opp)
1201 {
1202   const char *tempdir;
1203   char *template;
1204   int fd;
1205
1206   tempdir = getenv ("GFORTRAN_TMPDIR");
1207   if (tempdir == NULL)
1208     tempdir = getenv ("TMP");
1209   if (tempdir == NULL)
1210     tempdir = getenv ("TEMP");
1211   if (tempdir == NULL)
1212     tempdir = DEFAULT_TEMPDIR;
1213
1214   template = get_mem (strlen (tempdir) + 20);
1215
1216   sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
1217
1218 #ifdef HAVE_MKSTEMP
1219
1220   fd = mkstemp (template);
1221
1222 #else /* HAVE_MKSTEMP */
1223
1224   if (mktemp (template))
1225     do
1226 #if defined(HAVE_CRLF) && defined(O_BINARY)
1227       fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
1228                  S_IREAD | S_IWRITE);
1229 #else
1230       fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
1231 #endif
1232     while (!(fd == -1 && errno == EEXIST) && mktemp (template));
1233   else
1234     fd = -1;
1235
1236 #endif /* HAVE_MKSTEMP */
1237
1238   if (fd < 0)
1239     free_mem (template);
1240   else
1241     {
1242       opp->file = template;
1243       opp->file_len = strlen (template);        /* Don't include trailing nul */
1244     }
1245
1246   return fd;
1247 }
1248
1249
1250 /* regular_file()-- Open a regular file.
1251  * Change flags->action if it is ACTION_UNSPECIFIED on entry,
1252  * unless an error occurs.
1253  * Returns the descriptor, which is less than zero on error. */
1254
1255 static int
1256 regular_file (st_parameter_open *opp, unit_flags *flags)
1257 {
1258   char path[PATH_MAX + 1];
1259   int mode;
1260   int rwflag;
1261   int crflag;
1262   int fd;
1263
1264   if (unpack_filename (path, opp->file, opp->file_len))
1265     {
1266       errno = ENOENT;           /* Fake an OS error */
1267       return -1;
1268     }
1269
1270   rwflag = 0;
1271
1272   switch (flags->action)
1273     {
1274     case ACTION_READ:
1275       rwflag = O_RDONLY;
1276       break;
1277
1278     case ACTION_WRITE:
1279       rwflag = O_WRONLY;
1280       break;
1281
1282     case ACTION_READWRITE:
1283     case ACTION_UNSPECIFIED:
1284       rwflag = O_RDWR;
1285       break;
1286
1287     default:
1288       internal_error (&opp->common, "regular_file(): Bad action");
1289     }
1290
1291   switch (flags->status)
1292     {
1293     case STATUS_NEW:
1294       crflag = O_CREAT | O_EXCL;
1295       break;
1296
1297     case STATUS_OLD:            /* open will fail if the file does not exist*/
1298       crflag = 0;
1299       break;
1300
1301     case STATUS_UNKNOWN:
1302     case STATUS_SCRATCH:
1303       crflag = O_CREAT;
1304       break;
1305
1306     case STATUS_REPLACE:
1307       crflag = O_CREAT | O_TRUNC;
1308       break;
1309
1310     default:
1311       internal_error (&opp->common, "regular_file(): Bad status");
1312     }
1313
1314   /* rwflag |= O_LARGEFILE; */
1315
1316 #if defined(HAVE_CRLF) && defined(O_BINARY)
1317   crflag |= O_BINARY;
1318 #endif
1319
1320   mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
1321   fd = open (path, rwflag | crflag, mode);
1322   if (flags->action != ACTION_UNSPECIFIED)
1323     return fd;
1324
1325   if (fd >= 0)
1326     {
1327       flags->action = ACTION_READWRITE;
1328       return fd;
1329     }
1330   if (errno != EACCES && errno != EROFS)
1331      return fd;
1332
1333   /* retry for read-only access */
1334   rwflag = O_RDONLY;
1335   fd = open (path, rwflag | crflag, mode);
1336   if (fd >=0)
1337     {
1338       flags->action = ACTION_READ;
1339       return fd;                /* success */
1340     }
1341   
1342   if (errno != EACCES)
1343     return fd;                  /* failure */
1344
1345   /* retry for write-only access */
1346   rwflag = O_WRONLY;
1347   fd = open (path, rwflag | crflag, mode);
1348   if (fd >=0)
1349     {
1350       flags->action = ACTION_WRITE;
1351       return fd;                /* success */
1352     }
1353   return fd;                    /* failure */
1354 }
1355
1356
1357 /* open_external()-- Open an external file, unix specific version.
1358  * Change flags->action if it is ACTION_UNSPECIFIED on entry.
1359  * Returns NULL on operating system error. */
1360
1361 stream *
1362 open_external (st_parameter_open *opp, unit_flags *flags)
1363 {
1364   int fd, prot;
1365
1366   if (flags->status == STATUS_SCRATCH)
1367     {
1368       fd = tempfile (opp);
1369       if (flags->action == ACTION_UNSPECIFIED)
1370         flags->action = ACTION_READWRITE;
1371
1372 #if HAVE_UNLINK_OPEN_FILE
1373       /* We can unlink scratch files now and it will go away when closed. */
1374       if (fd >= 0)
1375         unlink (opp->file);
1376 #endif
1377     }
1378   else
1379     {
1380       /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1381        * if it succeeds */
1382       fd = regular_file (opp, flags);
1383     }
1384
1385   if (fd < 0)
1386     return NULL;
1387   fd = fix_fd (fd);
1388
1389   switch (flags->action)
1390     {
1391     case ACTION_READ:
1392       prot = PROT_READ;
1393       break;
1394
1395     case ACTION_WRITE:
1396       prot = PROT_WRITE;
1397       break;
1398
1399     case ACTION_READWRITE:
1400       prot = PROT_READ | PROT_WRITE;
1401       break;
1402
1403     default:
1404       internal_error (&opp->common, "open_external(): Bad action");
1405     }
1406
1407   return fd_to_stream (fd, prot);
1408 }
1409
1410
1411 /* input_stream()-- Return a stream pointer to the default input stream.
1412  * Called on initialization. */
1413
1414 stream *
1415 input_stream (void)
1416 {
1417   return fd_to_stream (STDIN_FILENO, PROT_READ);
1418 }
1419
1420
1421 /* output_stream()-- Return a stream pointer to the default output stream.
1422  * Called on initialization. */
1423
1424 stream *
1425 output_stream (void)
1426 {
1427   stream * s;
1428
1429 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1430   setmode (STDOUT_FILENO, O_BINARY);
1431 #endif
1432
1433   s = fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1434   if (options.unbuffered_preconnected)
1435     ((unix_stream *) s)->method = SYNC_UNBUFFERED;
1436   return s;
1437 }
1438
1439
1440 /* error_stream()-- Return a stream pointer to the default error stream.
1441  * Called on initialization. */
1442
1443 stream *
1444 error_stream (void)
1445 {
1446   stream * s;
1447
1448 #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1449   setmode (STDERR_FILENO, O_BINARY);
1450 #endif
1451
1452   s = fd_to_stream (STDERR_FILENO, PROT_WRITE);
1453   if (options.unbuffered_preconnected)
1454     ((unix_stream *) s)->method = SYNC_UNBUFFERED;
1455   return s;
1456 }
1457
1458
1459 /* st_vprintf()-- vprintf function for error output.  To avoid buffer
1460    overruns, we limit the length of the buffer to ST_VPRINTF_SIZE.  2k
1461    is big enough to completely fill a 80x25 terminal, so it shuld be
1462    OK.  We use a direct write() because it is simpler and least likely
1463    to be clobbered by memory corruption.  Writing an error message
1464    longer than that is an error.  */
1465
1466 #define ST_VPRINTF_SIZE 2048
1467
1468 int
1469 st_vprintf (const char *format, va_list ap)
1470 {
1471   static char buffer[ST_VPRINTF_SIZE];
1472   int written;
1473   int fd;
1474
1475   fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1476 #ifdef HAVE_VSNPRINTF
1477   written = vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
1478 #else
1479   written = vsprintf(buffer, format, ap);
1480
1481   if (written >= ST_VPRINTF_SIZE-1)
1482     {
1483       /* The error message was longer than our buffer.  Ouch.  Because
1484          we may have messed up things badly, report the error and
1485          quit.  */
1486 #define ERROR_MESSAGE "Internal error: buffer overrun in st_vprintf()\n"
1487       write (fd, buffer, ST_VPRINTF_SIZE-1);
1488       write (fd, ERROR_MESSAGE, strlen(ERROR_MESSAGE));
1489       sys_exit(2);
1490 #undef ERROR_MESSAGE
1491
1492     }
1493 #endif
1494
1495   written = write (fd, buffer, written);
1496   return written;
1497 }
1498
1499 /* st_printf()-- printf() function for error output.  This just calls
1500    st_vprintf() to do the actual work.  */
1501
1502 int
1503 st_printf (const char *format, ...)
1504 {
1505   int written;
1506   va_list ap;
1507   va_start (ap, format);
1508   written = st_vprintf(format, ap);
1509   va_end (ap);
1510   return written;
1511 }
1512
1513
1514 /* compare_file_filename()-- Given an open stream and a fortran string
1515  * that is a filename, figure out if the file is the same as the
1516  * filename. */
1517
1518 int
1519 compare_file_filename (gfc_unit *u, const char *name, int len)
1520 {
1521   char path[PATH_MAX + 1];
1522   struct stat st1;
1523 #ifdef HAVE_WORKING_STAT
1524   struct stat st2;
1525 #else
1526 # ifdef __MINGW32__
1527   uint64_t id1, id2;
1528 # endif
1529 #endif
1530
1531   if (unpack_filename (path, name, len))
1532     return 0;                   /* Can't be the same */
1533
1534   /* If the filename doesn't exist, then there is no match with the
1535    * existing file. */
1536
1537   if (stat (path, &st1) < 0)
1538     return 0;
1539
1540 #ifdef HAVE_WORKING_STAT
1541   fstat (((unix_stream *) (u->s))->fd, &st2);
1542   return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
1543 #else
1544
1545 # ifdef __MINGW32__
1546   /* We try to match files by a unique ID.  On some filesystems (network
1547      fs and FAT), we can't generate this unique ID, and will simply compare
1548      filenames.  */
1549   id1 = id_from_path (path);
1550   id2 = id_from_fd (((unix_stream *) (u->s))->fd);
1551   if (id1 || id2)
1552     return (id1 == id2);
1553 # endif
1554
1555   if (len != u->file_len)
1556     return 0;
1557   return (memcmp(path, u->file, len) == 0);
1558 #endif
1559 }
1560
1561
1562 #ifdef HAVE_WORKING_STAT
1563 # define FIND_FILE0_DECL struct stat *st
1564 # define FIND_FILE0_ARGS st
1565 #else
1566 # define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
1567 # define FIND_FILE0_ARGS id, file, file_len
1568 #endif
1569
1570 /* find_file0()-- Recursive work function for find_file() */
1571
1572 static gfc_unit *
1573 find_file0 (gfc_unit *u, FIND_FILE0_DECL)
1574 {
1575   gfc_unit *v;
1576 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1577   uint64_t id1;
1578 #endif
1579
1580   if (u == NULL)
1581     return NULL;
1582
1583 #ifdef HAVE_WORKING_STAT
1584   if (u->s != NULL
1585       && fstat (((unix_stream *) u->s)->fd, &st[1]) >= 0 &&
1586       st[0].st_dev == st[1].st_dev && st[0].st_ino == st[1].st_ino)
1587     return u;
1588 #else
1589 # ifdef __MINGW32__ 
1590   if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
1591     {
1592       if (id == id1)
1593         return u;
1594     }
1595   else
1596 # endif
1597     if (compare_string (u->file_len, u->file, file_len, file) == 0)
1598       return u;
1599 #endif
1600
1601   v = find_file0 (u->left, FIND_FILE0_ARGS);
1602   if (v != NULL)
1603     return v;
1604
1605   v = find_file0 (u->right, FIND_FILE0_ARGS);
1606   if (v != NULL)
1607     return v;
1608
1609   return NULL;
1610 }
1611
1612
1613 /* find_file()-- Take the current filename and see if there is a unit
1614  * that has the file already open.  Returns a pointer to the unit if so. */
1615
1616 gfc_unit *
1617 find_file (const char *file, gfc_charlen_type file_len)
1618 {
1619   char path[PATH_MAX + 1];
1620   struct stat st[2];
1621   gfc_unit *u;
1622   uint64_t id;
1623
1624   if (unpack_filename (path, file, file_len))
1625     return NULL;
1626
1627   if (stat (path, &st[0]) < 0)
1628     return NULL;
1629
1630 #if defined(__MINGW32__) && !HAVE_WORKING_STAT
1631   id = id_from_path (path);
1632 #else
1633   id = 0;
1634 #endif
1635
1636   __gthread_mutex_lock (&unit_lock);
1637 retry:
1638   u = find_file0 (unit_root, FIND_FILE0_ARGS);
1639   if (u != NULL)
1640     {
1641       /* Fast path.  */
1642       if (! __gthread_mutex_trylock (&u->lock))
1643         {
1644           /* assert (u->closed == 0); */
1645           __gthread_mutex_unlock (&unit_lock);
1646           return u;
1647         }
1648
1649       inc_waiting_locked (u);
1650     }
1651   __gthread_mutex_unlock (&unit_lock);
1652   if (u != NULL)
1653     {
1654       __gthread_mutex_lock (&u->lock);
1655       if (u->closed)
1656         {
1657           __gthread_mutex_lock (&unit_lock);
1658           __gthread_mutex_unlock (&u->lock);
1659           if (predec_waiting_locked (u) == 0)
1660             free_mem (u);
1661           goto retry;
1662         }
1663
1664       dec_waiting_unlocked (u);
1665     }
1666   return u;
1667 }
1668
1669 static gfc_unit *
1670 flush_all_units_1 (gfc_unit *u, int min_unit)
1671 {
1672   while (u != NULL)
1673     {
1674       if (u->unit_number > min_unit)
1675         {
1676           gfc_unit *r = flush_all_units_1 (u->left, min_unit);
1677           if (r != NULL)
1678             return r;
1679         }
1680       if (u->unit_number >= min_unit)
1681         {
1682           if (__gthread_mutex_trylock (&u->lock))
1683             return u;
1684           if (u->s)
1685             flush (u->s);
1686           __gthread_mutex_unlock (&u->lock);
1687         }
1688       u = u->right;
1689     }
1690   return NULL;
1691 }
1692
1693 void
1694 flush_all_units (void)
1695 {
1696   gfc_unit *u;
1697   int min_unit = 0;
1698
1699   __gthread_mutex_lock (&unit_lock);
1700   do
1701     {
1702       u = flush_all_units_1 (unit_root, min_unit);
1703       if (u != NULL)
1704         inc_waiting_locked (u);
1705       __gthread_mutex_unlock (&unit_lock);
1706       if (u == NULL)
1707         return;
1708
1709       __gthread_mutex_lock (&u->lock);
1710
1711       min_unit = u->unit_number + 1;
1712
1713       if (u->closed == 0)
1714         {
1715           flush (u->s);
1716           __gthread_mutex_lock (&unit_lock);
1717           __gthread_mutex_unlock (&u->lock);
1718           (void) predec_waiting_locked (u);
1719         }
1720       else
1721         {
1722           __gthread_mutex_lock (&unit_lock);
1723           __gthread_mutex_unlock (&u->lock);
1724           if (predec_waiting_locked (u) == 0)
1725             free_mem (u);
1726         }
1727     }
1728   while (1);
1729 }
1730
1731
1732 /* stream_at_bof()-- Returns nonzero if the stream is at the beginning
1733  * of the file. */
1734
1735 int
1736 stream_at_bof (stream * s)
1737 {
1738   unix_stream *us;
1739
1740   if (!is_seekable (s))
1741     return 0;
1742
1743   us = (unix_stream *) s;
1744
1745   return us->logical_offset == 0;
1746 }
1747
1748
1749 /* stream_at_eof()-- Returns nonzero if the stream is at the end
1750  * of the file. */
1751
1752 int
1753 stream_at_eof (stream * s)
1754 {
1755   unix_stream *us;
1756
1757   if (!is_seekable (s))
1758     return 0;
1759
1760   us = (unix_stream *) s;
1761
1762   return us->logical_offset == us->dirty_offset;
1763 }
1764
1765
1766 /* delete_file()-- Given a unit structure, delete the file associated
1767  * with the unit.  Returns nonzero if something went wrong. */
1768
1769 int
1770 delete_file (gfc_unit * u)
1771 {
1772   char path[PATH_MAX + 1];
1773
1774   if (unpack_filename (path, u->file, u->file_len))
1775     {                           /* Shouldn't be possible */
1776       errno = ENOENT;
1777       return 1;
1778     }
1779
1780   return unlink (path);
1781 }
1782
1783
1784 /* file_exists()-- Returns nonzero if the current filename exists on
1785  * the system */
1786
1787 int
1788 file_exists (const char *file, gfc_charlen_type file_len)
1789 {
1790   char path[PATH_MAX + 1];
1791   struct stat statbuf;
1792
1793   if (unpack_filename (path, file, file_len))
1794     return 0;
1795
1796   if (stat (path, &statbuf) < 0)
1797     return 0;
1798
1799   return 1;
1800 }
1801
1802
1803
1804 static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
1805
1806 /* inquire_sequential()-- Given a fortran string, determine if the
1807  * file is suitable for sequential access.  Returns a C-style
1808  * string. */
1809
1810 const char *
1811 inquire_sequential (const char *string, int len)
1812 {
1813   char path[PATH_MAX + 1];
1814   struct stat statbuf;
1815
1816   if (string == NULL ||
1817       unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1818     return unknown;
1819
1820   if (S_ISREG (statbuf.st_mode) ||
1821       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1822     return unknown;
1823
1824   if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1825     return no;
1826
1827   return unknown;
1828 }
1829
1830
1831 /* inquire_direct()-- Given a fortran string, determine if the file is
1832  * suitable for direct access.  Returns a C-style string. */
1833
1834 const char *
1835 inquire_direct (const char *string, int len)
1836 {
1837   char path[PATH_MAX + 1];
1838   struct stat statbuf;
1839
1840   if (string == NULL ||
1841       unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1842     return unknown;
1843
1844   if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1845     return unknown;
1846
1847   if (S_ISDIR (statbuf.st_mode) ||
1848       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1849     return no;
1850
1851   return unknown;
1852 }
1853
1854
1855 /* inquire_formatted()-- Given a fortran string, determine if the file
1856  * is suitable for formatted form.  Returns a C-style string. */
1857
1858 const char *
1859 inquire_formatted (const char *string, int len)
1860 {
1861   char path[PATH_MAX + 1];
1862   struct stat statbuf;
1863
1864   if (string == NULL ||
1865       unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1866     return unknown;
1867
1868   if (S_ISREG (statbuf.st_mode) ||
1869       S_ISBLK (statbuf.st_mode) ||
1870       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1871     return unknown;
1872
1873   if (S_ISDIR (statbuf.st_mode))
1874     return no;
1875
1876   return unknown;
1877 }
1878
1879
1880 /* inquire_unformatted()-- Given a fortran string, determine if the file
1881  * is suitable for unformatted form.  Returns a C-style string. */
1882
1883 const char *
1884 inquire_unformatted (const char *string, int len)
1885 {
1886   return inquire_formatted (string, len);
1887 }
1888
1889
1890 #ifndef HAVE_ACCESS
1891
1892 #ifndef W_OK
1893 #define W_OK 2
1894 #endif
1895
1896 #ifndef R_OK
1897 #define R_OK 4
1898 #endif
1899
1900 /* Fallback implementation of access() on systems that don't have it.
1901    Only modes R_OK and W_OK are used in this file.  */
1902
1903 static int
1904 fallback_access (const char *path, int mode)
1905 {
1906   if ((mode & R_OK) && open (path, O_RDONLY) < 0)
1907     return -1;
1908
1909   if ((mode & W_OK) && open (path, O_WRONLY) < 0)
1910     return -1;
1911
1912   return 0;
1913 }
1914
1915 #undef access
1916 #define access fallback_access
1917 #endif
1918
1919
1920 /* inquire_access()-- Given a fortran string, determine if the file is
1921  * suitable for access. */
1922
1923 static const char *
1924 inquire_access (const char *string, int len, int mode)
1925 {
1926   char path[PATH_MAX + 1];
1927
1928   if (string == NULL || unpack_filename (path, string, len) ||
1929       access (path, mode) < 0)
1930     return no;
1931
1932   return yes;
1933 }
1934
1935
1936 /* inquire_read()-- Given a fortran string, determine if the file is
1937  * suitable for READ access. */
1938
1939 const char *
1940 inquire_read (const char *string, int len)
1941 {
1942   return inquire_access (string, len, R_OK);
1943 }
1944
1945
1946 /* inquire_write()-- Given a fortran string, determine if the file is
1947  * suitable for READ access. */
1948
1949 const char *
1950 inquire_write (const char *string, int len)
1951 {
1952   return inquire_access (string, len, W_OK);
1953 }
1954
1955
1956 /* inquire_readwrite()-- Given a fortran string, determine if the file is
1957  * suitable for read and write access. */
1958
1959 const char *
1960 inquire_readwrite (const char *string, int len)
1961 {
1962   return inquire_access (string, len, R_OK | W_OK);
1963 }
1964
1965
1966 /* file_length()-- Return the file length in bytes, -1 if unknown */
1967
1968 gfc_offset
1969 file_length (stream * s)
1970 {
1971   return ((unix_stream *) s)->file_length;
1972 }
1973
1974
1975 /* file_position()-- Return the current position of the file */
1976
1977 gfc_offset
1978 file_position (stream *s)
1979 {
1980   return ((unix_stream *) s)->logical_offset;
1981 }
1982
1983
1984 /* is_seekable()-- Return nonzero if the stream is seekable, zero if
1985  * it is not */
1986
1987 int
1988 is_seekable (stream *s)
1989 {
1990   /* By convention, if file_length == -1, the file is not
1991      seekable.  */
1992   return ((unix_stream *) s)->file_length!=-1;
1993 }
1994
1995
1996 /* is_special()-- Return nonzero if the stream is not a regular file.  */
1997
1998 int
1999 is_special (stream *s)
2000 {
2001   return ((unix_stream *) s)->special_file;
2002 }
2003
2004
2005 try
2006 flush (stream *s)
2007 {
2008   return fd_flush( (unix_stream *) s);
2009 }
2010
2011 int
2012 stream_isatty (stream *s)
2013 {
2014   return isatty (((unix_stream *) s)->fd);
2015 }
2016
2017 char *
2018 stream_ttyname (stream *s __attribute__ ((unused)))
2019 {
2020 #ifdef HAVE_TTYNAME
2021   return ttyname (((unix_stream *) s)->fd);
2022 #else
2023   return NULL;
2024 #endif
2025 }
2026
2027 gfc_offset
2028 stream_offset (stream *s)
2029 {
2030   return (((unix_stream *) s)->logical_offset);
2031 }
2032
2033
2034 /* How files are stored:  This is an operating-system specific issue,
2035    and therefore belongs here.  There are three cases to consider.
2036
2037    Direct Access:
2038       Records are written as block of bytes corresponding to the record
2039       length of the file.  This goes for both formatted and unformatted
2040       records.  Positioning is done explicitly for each data transfer,
2041       so positioning is not much of an issue.
2042
2043    Sequential Formatted:
2044       Records are separated by newline characters.  The newline character
2045       is prohibited from appearing in a string.  If it does, this will be
2046       messed up on the next read.  End of file is also the end of a record.
2047
2048    Sequential Unformatted:
2049       In this case, we are merely copying bytes to and from main storage,
2050       yet we need to keep track of varying record lengths.  We adopt
2051       the solution used by f2c.  Each record contains a pair of length
2052       markers:
2053
2054         Length of record n in bytes
2055         Data of record n
2056         Length of record n in bytes
2057
2058         Length of record n+1 in bytes
2059         Data of record n+1
2060         Length of record n+1 in bytes
2061
2062      The length is stored at the end of a record to allow backspacing to the
2063      previous record.  Between data transfer statements, the file pointer
2064      is left pointing to the first length of the current record.
2065
2066      ENDFILE records are never explicitly stored.
2067
2068 */