Home | History | Annotate | Line # | Download | only in io
unix.c revision 1.1
      1  1.1  mrg /* Copyright (C) 2002-2019 Free Software Foundation, Inc.
      2  1.1  mrg    Contributed by Andy Vaught
      3  1.1  mrg    F2003 I/O support contributed by Jerry DeLisle
      4  1.1  mrg 
      5  1.1  mrg This file is part of the GNU Fortran runtime library (libgfortran).
      6  1.1  mrg 
      7  1.1  mrg Libgfortran is free software; you can redistribute it and/or modify
      8  1.1  mrg it under the terms of the GNU General Public License as published by
      9  1.1  mrg the Free Software Foundation; either version 3, or (at your option)
     10  1.1  mrg any later version.
     11  1.1  mrg 
     12  1.1  mrg Libgfortran is distributed in the hope that it will be useful,
     13  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  mrg GNU General Public License for more details.
     16  1.1  mrg 
     17  1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18  1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19  1.1  mrg 3.1, as published by the Free Software Foundation.
     20  1.1  mrg 
     21  1.1  mrg You should have received a copy of the GNU General Public License and
     22  1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23  1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24  1.1  mrg <http://www.gnu.org/licenses/>.  */
     25  1.1  mrg 
     26  1.1  mrg /* Unix stream I/O module */
     27  1.1  mrg 
     28  1.1  mrg #include "io.h"
     29  1.1  mrg #include "unix.h"
     30  1.1  mrg #include "async.h"
     31  1.1  mrg #include <limits.h>
     32  1.1  mrg 
     33  1.1  mrg #ifdef HAVE_UNISTD_H
     34  1.1  mrg #include <unistd.h>
     35  1.1  mrg #endif
     36  1.1  mrg 
     37  1.1  mrg #include <sys/stat.h>
     38  1.1  mrg #include <fcntl.h>
     39  1.1  mrg 
     40  1.1  mrg #include <string.h>
     41  1.1  mrg #include <errno.h>
     42  1.1  mrg 
     43  1.1  mrg 
     44  1.1  mrg /* For mingw, we don't identify files by their inode number, but by a
     45  1.1  mrg    64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
     46  1.1  mrg #ifdef __MINGW32__
     47  1.1  mrg 
     48  1.1  mrg #define WIN32_LEAN_AND_MEAN
     49  1.1  mrg #include <windows.h>
     50  1.1  mrg 
     51  1.1  mrg #if !defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64
     52  1.1  mrg #undef lseek
     53  1.1  mrg #define lseek _lseeki64
     54  1.1  mrg #undef fstat
     55  1.1  mrg #define fstat _fstati64
     56  1.1  mrg #undef stat
     57  1.1  mrg #define stat _stati64
     58  1.1  mrg #endif
     59  1.1  mrg 
     60  1.1  mrg #ifndef HAVE_WORKING_STAT
     61  1.1  mrg static uint64_t
     62  1.1  mrg id_from_handle (HANDLE hFile)
     63  1.1  mrg {
     64  1.1  mrg   BY_HANDLE_FILE_INFORMATION FileInformation;
     65  1.1  mrg 
     66  1.1  mrg   if (hFile == INVALID_HANDLE_VALUE)
     67  1.1  mrg       return 0;
     68  1.1  mrg 
     69  1.1  mrg   memset (&FileInformation, 0, sizeof(FileInformation));
     70  1.1  mrg   if (!GetFileInformationByHandle (hFile, &FileInformation))
     71  1.1  mrg     return 0;
     72  1.1  mrg 
     73  1.1  mrg   return ((uint64_t) FileInformation.nFileIndexLow)
     74  1.1  mrg 	 | (((uint64_t) FileInformation.nFileIndexHigh) << 32);
     75  1.1  mrg }
     76  1.1  mrg 
     77  1.1  mrg 
     78  1.1  mrg static uint64_t
     79  1.1  mrg id_from_path (const char *path)
     80  1.1  mrg {
     81  1.1  mrg   HANDLE hFile;
     82  1.1  mrg   uint64_t res;
     83  1.1  mrg 
     84  1.1  mrg   if (!path || !*path || access (path, F_OK))
     85  1.1  mrg     return (uint64_t) -1;
     86  1.1  mrg 
     87  1.1  mrg   hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
     88  1.1  mrg 		      FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
     89  1.1  mrg 		      NULL);
     90  1.1  mrg   res = id_from_handle (hFile);
     91  1.1  mrg   CloseHandle (hFile);
     92  1.1  mrg   return res;
     93  1.1  mrg }
     94  1.1  mrg 
     95  1.1  mrg 
     96  1.1  mrg static uint64_t
     97  1.1  mrg id_from_fd (const int fd)
     98  1.1  mrg {
     99  1.1  mrg   return id_from_handle ((HANDLE) _get_osfhandle (fd));
    100  1.1  mrg }
    101  1.1  mrg 
    102  1.1  mrg #endif /* HAVE_WORKING_STAT */
    103  1.1  mrg 
    104  1.1  mrg 
    105  1.1  mrg /* On mingw, we don't use umask in tempfile_open(), because it
    106  1.1  mrg    doesn't support the user/group/other-based permissions.  */
    107  1.1  mrg #undef HAVE_UMASK
    108  1.1  mrg 
    109  1.1  mrg #endif /* __MINGW32__ */
    110  1.1  mrg 
    111  1.1  mrg 
    112  1.1  mrg /* These flags aren't defined on all targets (mingw32), so provide them
    113  1.1  mrg    here.  */
    114  1.1  mrg #ifndef S_IRGRP
    115  1.1  mrg #define S_IRGRP 0
    116  1.1  mrg #endif
    117  1.1  mrg 
    118  1.1  mrg #ifndef S_IWGRP
    119  1.1  mrg #define S_IWGRP 0
    120  1.1  mrg #endif
    121  1.1  mrg 
    122  1.1  mrg #ifndef S_IROTH
    123  1.1  mrg #define S_IROTH 0
    124  1.1  mrg #endif
    125  1.1  mrg 
    126  1.1  mrg #ifndef S_IWOTH
    127  1.1  mrg #define S_IWOTH 0
    128  1.1  mrg #endif
    129  1.1  mrg 
    130  1.1  mrg 
    131  1.1  mrg #ifndef HAVE_ACCESS
    132  1.1  mrg 
    133  1.1  mrg #ifndef W_OK
    134  1.1  mrg #define W_OK 2
    135  1.1  mrg #endif
    136  1.1  mrg 
    137  1.1  mrg #ifndef R_OK
    138  1.1  mrg #define R_OK 4
    139  1.1  mrg #endif
    140  1.1  mrg 
    141  1.1  mrg #ifndef F_OK
    142  1.1  mrg #define F_OK 0
    143  1.1  mrg #endif
    144  1.1  mrg 
    145  1.1  mrg /* Fallback implementation of access() on systems that don't have it.
    146  1.1  mrg    Only modes R_OK, W_OK and F_OK are used in this file.  */
    147  1.1  mrg 
    148  1.1  mrg static int
    149  1.1  mrg fallback_access (const char *path, int mode)
    150  1.1  mrg {
    151  1.1  mrg   int fd;
    152  1.1  mrg 
    153  1.1  mrg   if (mode & R_OK)
    154  1.1  mrg     {
    155  1.1  mrg       if ((fd = open (path, O_RDONLY)) < 0)
    156  1.1  mrg 	return -1;
    157  1.1  mrg       else
    158  1.1  mrg 	close (fd);
    159  1.1  mrg     }
    160  1.1  mrg 
    161  1.1  mrg   if (mode & W_OK)
    162  1.1  mrg     {
    163  1.1  mrg       if ((fd = open (path, O_WRONLY)) < 0)
    164  1.1  mrg 	return -1;
    165  1.1  mrg       else
    166  1.1  mrg 	close (fd);
    167  1.1  mrg     }
    168  1.1  mrg 
    169  1.1  mrg   if (mode == F_OK)
    170  1.1  mrg     {
    171  1.1  mrg       struct stat st;
    172  1.1  mrg       return stat (path, &st);
    173  1.1  mrg     }
    174  1.1  mrg 
    175  1.1  mrg   return 0;
    176  1.1  mrg }
    177  1.1  mrg 
    178  1.1  mrg #undef access
    179  1.1  mrg #define access fallback_access
    180  1.1  mrg #endif
    181  1.1  mrg 
    182  1.1  mrg 
    183  1.1  mrg /* Fallback directory for creating temporary files.  P_tmpdir is
    184  1.1  mrg    defined on many POSIX platforms.  */
    185  1.1  mrg #ifndef P_tmpdir
    186  1.1  mrg #ifdef _P_tmpdir
    187  1.1  mrg #define P_tmpdir _P_tmpdir  /* MinGW */
    188  1.1  mrg #else
    189  1.1  mrg #define P_tmpdir "/tmp"
    190  1.1  mrg #endif
    191  1.1  mrg #endif
    192  1.1  mrg 
    193  1.1  mrg 
    194  1.1  mrg /* Unix and internal stream I/O module */
    195  1.1  mrg 
    196  1.1  mrg static const int FORMATTED_BUFFER_SIZE_DEFAULT = 8192;
    197  1.1  mrg static const int UNFORMATTED_BUFFER_SIZE_DEFAULT = 128*1024;
    198  1.1  mrg 
    199  1.1  mrg typedef struct
    200  1.1  mrg {
    201  1.1  mrg   stream st;
    202  1.1  mrg 
    203  1.1  mrg   gfc_offset buffer_offset;	/* File offset of the start of the buffer */
    204  1.1  mrg   gfc_offset physical_offset;	/* Current physical file offset */
    205  1.1  mrg   gfc_offset logical_offset;	/* Current logical file offset */
    206  1.1  mrg   gfc_offset file_length;	/* Length of the file. */
    207  1.1  mrg 
    208  1.1  mrg   char *buffer;                 /* Pointer to the buffer.  */
    209  1.1  mrg   ssize_t buffer_size;           /* Length of the buffer.  */
    210  1.1  mrg   int fd;                       /* The POSIX file descriptor.  */
    211  1.1  mrg 
    212  1.1  mrg   int active;			/* Length of valid bytes in the buffer */
    213  1.1  mrg 
    214  1.1  mrg   int ndirty;			/* Dirty bytes starting at buffer_offset */
    215  1.1  mrg 
    216  1.1  mrg   /* Cached stat(2) values.  */
    217  1.1  mrg   dev_t st_dev;
    218  1.1  mrg   ino_t st_ino;
    219  1.1  mrg 
    220  1.1  mrg   bool unbuffered;  /* Buffer should be flushed after each I/O statement.  */
    221  1.1  mrg }
    222  1.1  mrg unix_stream;
    223  1.1  mrg 
    224  1.1  mrg 
    225  1.1  mrg /* fix_fd()-- Given a file descriptor, make sure it is not one of the
    226  1.1  mrg    standard descriptors, returning a non-standard descriptor.  If the
    227  1.1  mrg    user specifies that system errors should go to standard output,
    228  1.1  mrg    then closes standard output, we don't want the system errors to a
    229  1.1  mrg    file that has been given file descriptor 1 or 0.  We want to send
    230  1.1  mrg    the error to the invalid descriptor. */
    231  1.1  mrg 
    232  1.1  mrg static int
    233  1.1  mrg fix_fd (int fd)
    234  1.1  mrg {
    235  1.1  mrg #ifdef HAVE_DUP
    236  1.1  mrg   int input, output, error;
    237  1.1  mrg 
    238  1.1  mrg   input = output = error = 0;
    239  1.1  mrg 
    240  1.1  mrg   /* Unix allocates the lowest descriptors first, so a loop is not
    241  1.1  mrg      required, but this order is. */
    242  1.1  mrg   if (fd == STDIN_FILENO)
    243  1.1  mrg     {
    244  1.1  mrg       fd = dup (fd);
    245  1.1  mrg       input = 1;
    246  1.1  mrg     }
    247  1.1  mrg   if (fd == STDOUT_FILENO)
    248  1.1  mrg     {
    249  1.1  mrg       fd = dup (fd);
    250  1.1  mrg       output = 1;
    251  1.1  mrg     }
    252  1.1  mrg   if (fd == STDERR_FILENO)
    253  1.1  mrg     {
    254  1.1  mrg       fd = dup (fd);
    255  1.1  mrg       error = 1;
    256  1.1  mrg     }
    257  1.1  mrg 
    258  1.1  mrg   if (input)
    259  1.1  mrg     close (STDIN_FILENO);
    260  1.1  mrg   if (output)
    261  1.1  mrg     close (STDOUT_FILENO);
    262  1.1  mrg   if (error)
    263  1.1  mrg     close (STDERR_FILENO);
    264  1.1  mrg #endif
    265  1.1  mrg 
    266  1.1  mrg   return fd;
    267  1.1  mrg }
    268  1.1  mrg 
    269  1.1  mrg 
    270  1.1  mrg /* If the stream corresponds to a preconnected unit, we flush the
    271  1.1  mrg    corresponding C stream.  This is bugware for mixed C-Fortran codes
    272  1.1  mrg    where the C code doesn't flush I/O before returning.  */
    273  1.1  mrg void
    274  1.1  mrg flush_if_preconnected (stream *s)
    275  1.1  mrg {
    276  1.1  mrg   int fd;
    277  1.1  mrg 
    278  1.1  mrg   fd = ((unix_stream *) s)->fd;
    279  1.1  mrg   if (fd == STDIN_FILENO)
    280  1.1  mrg     fflush (stdin);
    281  1.1  mrg   else if (fd == STDOUT_FILENO)
    282  1.1  mrg     fflush (stdout);
    283  1.1  mrg   else if (fd == STDERR_FILENO)
    284  1.1  mrg     fflush (stderr);
    285  1.1  mrg }
    286  1.1  mrg 
    287  1.1  mrg 
    288  1.1  mrg /********************************************************************
    289  1.1  mrg Raw I/O functions (read, write, seek, tell, truncate, close).
    290  1.1  mrg 
    291  1.1  mrg These functions wrap the basic POSIX I/O syscalls. Any deviation in
    292  1.1  mrg semantics is a bug, except the following: write restarts in case
    293  1.1  mrg of being interrupted by a signal, and as the first argument the
    294  1.1  mrg functions take the unix_stream struct rather than an integer file
    295  1.1  mrg descriptor. Also, for POSIX read() and write() a nbyte argument larger
    296  1.1  mrg than SSIZE_MAX is undefined; here the type of nbyte is ssize_t rather
    297  1.1  mrg than size_t as for POSIX read/write.
    298  1.1  mrg *********************************************************************/
    299  1.1  mrg 
    300  1.1  mrg static int
    301  1.1  mrg raw_flush (unix_stream *s  __attribute__ ((unused)))
    302  1.1  mrg {
    303  1.1  mrg   return 0;
    304  1.1  mrg }
    305  1.1  mrg 
    306  1.1  mrg /* Write/read at most 2 GB - 4k chunks at a time. Linux never reads or
    307  1.1  mrg    writes more than this, and there are reports that macOS fails for
    308  1.1  mrg    larger than 2 GB as well.  */
    309  1.1  mrg #define MAX_CHUNK 2147479552
    310  1.1  mrg 
    311  1.1  mrg static ssize_t
    312  1.1  mrg raw_read (unix_stream *s, void *buf, ssize_t nbyte)
    313  1.1  mrg {
    314  1.1  mrg   /* For read we can't do I/O in a loop like raw_write does, because
    315  1.1  mrg      that will break applications that wait for interactive I/O.  We
    316  1.1  mrg      still can loop around EINTR, though.  This however causes a
    317  1.1  mrg      problem for large reads which must be chunked, see comment above.
    318  1.1  mrg      So assume that if the size is larger than the chunk size, we're
    319  1.1  mrg      reading from a file and not the terminal.  */
    320  1.1  mrg   if (nbyte <= MAX_CHUNK)
    321  1.1  mrg     {
    322  1.1  mrg       while (true)
    323  1.1  mrg 	{
    324  1.1  mrg 	  ssize_t trans = read (s->fd, buf, nbyte);
    325  1.1  mrg 	  if (trans == -1 && errno == EINTR)
    326  1.1  mrg 	    continue;
    327  1.1  mrg 	  return trans;
    328  1.1  mrg 	}
    329  1.1  mrg     }
    330  1.1  mrg   else
    331  1.1  mrg     {
    332  1.1  mrg       ssize_t bytes_left = nbyte;
    333  1.1  mrg       char *buf_st = buf;
    334  1.1  mrg       while (bytes_left > 0)
    335  1.1  mrg 	{
    336  1.1  mrg 	  ssize_t to_read = bytes_left < MAX_CHUNK ? bytes_left: MAX_CHUNK;
    337  1.1  mrg 	  ssize_t trans = read (s->fd, buf_st, to_read);
    338  1.1  mrg 	  if (trans == -1)
    339  1.1  mrg 	    {
    340  1.1  mrg 	      if (errno == EINTR)
    341  1.1  mrg 		continue;
    342  1.1  mrg 	      else
    343  1.1  mrg 		return trans;
    344  1.1  mrg 	    }
    345  1.1  mrg 	  buf_st += trans;
    346  1.1  mrg 	  bytes_left -= trans;
    347  1.1  mrg 	}
    348  1.1  mrg       return nbyte - bytes_left;
    349  1.1  mrg     }
    350  1.1  mrg }
    351  1.1  mrg 
    352  1.1  mrg static ssize_t
    353  1.1  mrg raw_write (unix_stream *s, const void *buf, ssize_t nbyte)
    354  1.1  mrg {
    355  1.1  mrg   ssize_t trans, bytes_left;
    356  1.1  mrg   char *buf_st;
    357  1.1  mrg 
    358  1.1  mrg   bytes_left = nbyte;
    359  1.1  mrg   buf_st = (char *) buf;
    360  1.1  mrg 
    361  1.1  mrg   /* We must write in a loop since some systems don't restart system
    362  1.1  mrg      calls in case of a signal.  Also some systems might fail outright
    363  1.1  mrg      if we try to write more than 2 GB in a single syscall, so chunk
    364  1.1  mrg      up large writes.  */
    365  1.1  mrg   while (bytes_left > 0)
    366  1.1  mrg     {
    367  1.1  mrg       ssize_t to_write = bytes_left < MAX_CHUNK ? bytes_left: MAX_CHUNK;
    368  1.1  mrg       trans = write (s->fd, buf_st, to_write);
    369  1.1  mrg       if (trans == -1)
    370  1.1  mrg 	{
    371  1.1  mrg 	  if (errno == EINTR)
    372  1.1  mrg 	    continue;
    373  1.1  mrg 	  else
    374  1.1  mrg 	    return trans;
    375  1.1  mrg 	}
    376  1.1  mrg       buf_st += trans;
    377  1.1  mrg       bytes_left -= trans;
    378  1.1  mrg     }
    379  1.1  mrg 
    380  1.1  mrg   return nbyte - bytes_left;
    381  1.1  mrg }
    382  1.1  mrg 
    383  1.1  mrg static gfc_offset
    384  1.1  mrg raw_seek (unix_stream *s, gfc_offset offset, int whence)
    385  1.1  mrg {
    386  1.1  mrg   while (true)
    387  1.1  mrg     {
    388  1.1  mrg       gfc_offset off = lseek (s->fd, offset, whence);
    389  1.1  mrg       if (off == (gfc_offset) -1 && errno == EINTR)
    390  1.1  mrg 	continue;
    391  1.1  mrg       return off;
    392  1.1  mrg     }
    393  1.1  mrg }
    394  1.1  mrg 
    395  1.1  mrg static gfc_offset
    396  1.1  mrg raw_tell (unix_stream *s)
    397  1.1  mrg {
    398  1.1  mrg   while (true)
    399  1.1  mrg     {
    400  1.1  mrg       gfc_offset off = lseek (s->fd, 0, SEEK_CUR);
    401  1.1  mrg       if (off == (gfc_offset) -1 && errno == EINTR)
    402  1.1  mrg 	continue;
    403  1.1  mrg       return off;
    404  1.1  mrg     }
    405  1.1  mrg }
    406  1.1  mrg 
    407  1.1  mrg static gfc_offset
    408  1.1  mrg raw_size (unix_stream *s)
    409  1.1  mrg {
    410  1.1  mrg   struct stat statbuf;
    411  1.1  mrg   if (TEMP_FAILURE_RETRY (fstat (s->fd, &statbuf)) == -1)
    412  1.1  mrg     return -1;
    413  1.1  mrg   if (S_ISREG (statbuf.st_mode))
    414  1.1  mrg     return statbuf.st_size;
    415  1.1  mrg   else
    416  1.1  mrg     return 0;
    417  1.1  mrg }
    418  1.1  mrg 
    419  1.1  mrg static int
    420  1.1  mrg raw_truncate (unix_stream *s, gfc_offset length)
    421  1.1  mrg {
    422  1.1  mrg #ifdef __MINGW32__
    423  1.1  mrg   HANDLE h;
    424  1.1  mrg   gfc_offset cur;
    425  1.1  mrg 
    426  1.1  mrg   if (isatty (s->fd))
    427  1.1  mrg     {
    428  1.1  mrg       errno = EBADF;
    429  1.1  mrg       return -1;
    430  1.1  mrg     }
    431  1.1  mrg   h = (HANDLE) _get_osfhandle (s->fd);
    432  1.1  mrg   if (h == INVALID_HANDLE_VALUE)
    433  1.1  mrg     {
    434  1.1  mrg       errno = EBADF;
    435  1.1  mrg       return -1;
    436  1.1  mrg     }
    437  1.1  mrg   cur = lseek (s->fd, 0, SEEK_CUR);
    438  1.1  mrg   if (cur == -1)
    439  1.1  mrg     return -1;
    440  1.1  mrg   if (lseek (s->fd, length, SEEK_SET) == -1)
    441  1.1  mrg     goto error;
    442  1.1  mrg   if (!SetEndOfFile (h))
    443  1.1  mrg     {
    444  1.1  mrg       errno = EBADF;
    445  1.1  mrg       goto error;
    446  1.1  mrg     }
    447  1.1  mrg   if (lseek (s->fd, cur, SEEK_SET) == -1)
    448  1.1  mrg     return -1;
    449  1.1  mrg   return 0;
    450  1.1  mrg  error:
    451  1.1  mrg   lseek (s->fd, cur, SEEK_SET);
    452  1.1  mrg   return -1;
    453  1.1  mrg #elif defined HAVE_FTRUNCATE
    454  1.1  mrg   if (TEMP_FAILURE_RETRY (ftruncate (s->fd, length)) == -1)
    455  1.1  mrg     return -1;
    456  1.1  mrg   return 0;
    457  1.1  mrg #elif defined HAVE_CHSIZE
    458  1.1  mrg   return chsize (s->fd, length);
    459  1.1  mrg #else
    460  1.1  mrg   runtime_error ("required ftruncate or chsize support not present");
    461  1.1  mrg   return -1;
    462  1.1  mrg #endif
    463  1.1  mrg }
    464  1.1  mrg 
    465  1.1  mrg static int
    466  1.1  mrg raw_close (unix_stream *s)
    467  1.1  mrg {
    468  1.1  mrg   int retval;
    469  1.1  mrg 
    470  1.1  mrg   if (s->fd == -1)
    471  1.1  mrg     retval = -1;
    472  1.1  mrg   else if (s->fd != STDOUT_FILENO
    473  1.1  mrg       && s->fd != STDERR_FILENO
    474  1.1  mrg       && s->fd != STDIN_FILENO)
    475  1.1  mrg     {
    476  1.1  mrg       retval = close (s->fd);
    477  1.1  mrg       /* close() and EINTR is special, as the file descriptor is
    478  1.1  mrg 	 deallocated before doing anything that might cause the
    479  1.1  mrg 	 operation to be interrupted. Thus if we get EINTR the best we
    480  1.1  mrg 	 can do is ignore it and continue (otherwise if we try again
    481  1.1  mrg 	 the file descriptor may have been allocated again to some
    482  1.1  mrg 	 other file).  */
    483  1.1  mrg       if (retval == -1 && errno == EINTR)
    484  1.1  mrg 	retval = errno = 0;
    485  1.1  mrg     }
    486  1.1  mrg   else
    487  1.1  mrg     retval = 0;
    488  1.1  mrg   free (s);
    489  1.1  mrg   return retval;
    490  1.1  mrg }
    491  1.1  mrg 
    492  1.1  mrg static int
    493  1.1  mrg raw_markeor (unix_stream *s __attribute__ ((unused)))
    494  1.1  mrg {
    495  1.1  mrg   return 0;
    496  1.1  mrg }
    497  1.1  mrg 
    498  1.1  mrg static const struct stream_vtable raw_vtable = {
    499  1.1  mrg   .read = (void *) raw_read,
    500  1.1  mrg   .write = (void *) raw_write,
    501  1.1  mrg   .seek = (void *) raw_seek,
    502  1.1  mrg   .tell = (void *) raw_tell,
    503  1.1  mrg   .size = (void *) raw_size,
    504  1.1  mrg   .trunc = (void *) raw_truncate,
    505  1.1  mrg   .close = (void *) raw_close,
    506  1.1  mrg   .flush = (void *) raw_flush,
    507  1.1  mrg   .markeor = (void *) raw_markeor
    508  1.1  mrg };
    509  1.1  mrg 
    510  1.1  mrg static int
    511  1.1  mrg raw_init (unix_stream *s)
    512  1.1  mrg {
    513  1.1  mrg   s->st.vptr = &raw_vtable;
    514  1.1  mrg 
    515  1.1  mrg   s->buffer = NULL;
    516  1.1  mrg   return 0;
    517  1.1  mrg }
    518  1.1  mrg 
    519  1.1  mrg 
    520  1.1  mrg /*********************************************************************
    521  1.1  mrg Buffered I/O functions. These functions have the same semantics as the
    522  1.1  mrg raw I/O functions above, except that they are buffered in order to
    523  1.1  mrg improve performance. The buffer must be flushed when switching from
    524  1.1  mrg reading to writing and vice versa.
    525  1.1  mrg *********************************************************************/
    526  1.1  mrg 
    527  1.1  mrg static int
    528  1.1  mrg buf_flush (unix_stream *s)
    529  1.1  mrg {
    530  1.1  mrg   int writelen;
    531  1.1  mrg 
    532  1.1  mrg   /* Flushing in read mode means discarding read bytes.  */
    533  1.1  mrg   s->active = 0;
    534  1.1  mrg 
    535  1.1  mrg   if (s->ndirty == 0)
    536  1.1  mrg     return 0;
    537  1.1  mrg 
    538  1.1  mrg   if (s->physical_offset != s->buffer_offset
    539  1.1  mrg       && raw_seek (s, s->buffer_offset, SEEK_SET) < 0)
    540  1.1  mrg     return -1;
    541  1.1  mrg 
    542  1.1  mrg   writelen = raw_write (s, s->buffer, s->ndirty);
    543  1.1  mrg 
    544  1.1  mrg   s->physical_offset = s->buffer_offset + writelen;
    545  1.1  mrg 
    546  1.1  mrg   if (s->physical_offset > s->file_length)
    547  1.1  mrg       s->file_length = s->physical_offset;
    548  1.1  mrg 
    549  1.1  mrg   s->ndirty -= writelen;
    550  1.1  mrg   if (s->ndirty != 0)
    551  1.1  mrg     return -1;
    552  1.1  mrg 
    553  1.1  mrg   return 0;
    554  1.1  mrg }
    555  1.1  mrg 
    556  1.1  mrg static ssize_t
    557  1.1  mrg buf_read (unix_stream *s, void *buf, ssize_t nbyte)
    558  1.1  mrg {
    559  1.1  mrg   if (s->active == 0)
    560  1.1  mrg     s->buffer_offset = s->logical_offset;
    561  1.1  mrg 
    562  1.1  mrg   /* Is the data we want in the buffer?  */
    563  1.1  mrg   if (s->logical_offset + nbyte <= s->buffer_offset + s->active
    564  1.1  mrg       && s->buffer_offset <= s->logical_offset)
    565  1.1  mrg     {
    566  1.1  mrg       /* When nbyte == 0, buf can be NULL which would lead to undefined
    567  1.1  mrg 	 behavior if we called memcpy().  */
    568  1.1  mrg       if (nbyte != 0)
    569  1.1  mrg 	memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset),
    570  1.1  mrg 		nbyte);
    571  1.1  mrg     }
    572  1.1  mrg   else
    573  1.1  mrg     {
    574  1.1  mrg       /* First copy the active bytes if applicable, then read the rest
    575  1.1  mrg          either directly or filling the buffer.  */
    576  1.1  mrg       char *p;
    577  1.1  mrg       int nread = 0;
    578  1.1  mrg       ssize_t to_read, did_read;
    579  1.1  mrg       gfc_offset new_logical;
    580  1.1  mrg 
    581  1.1  mrg       p = (char *) buf;
    582  1.1  mrg       if (s->logical_offset >= s->buffer_offset
    583  1.1  mrg           && s->buffer_offset + s->active >= s->logical_offset)
    584  1.1  mrg         {
    585  1.1  mrg           nread = s->active - (s->logical_offset - s->buffer_offset);
    586  1.1  mrg           memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset),
    587  1.1  mrg                   nread);
    588  1.1  mrg           p += nread;
    589  1.1  mrg         }
    590  1.1  mrg       /* At this point we consider all bytes in the buffer discarded.  */
    591  1.1  mrg       to_read = nbyte - nread;
    592  1.1  mrg       new_logical = s->logical_offset + nread;
    593  1.1  mrg       if (s->physical_offset != new_logical
    594  1.1  mrg           && raw_seek (s, new_logical, SEEK_SET) < 0)
    595  1.1  mrg         return -1;
    596  1.1  mrg       s->buffer_offset = s->physical_offset = new_logical;
    597  1.1  mrg       if (to_read <= s->buffer_size/2)
    598  1.1  mrg         {
    599  1.1  mrg           did_read = raw_read (s, s->buffer, s->buffer_size);
    600  1.1  mrg 	  if (likely (did_read >= 0))
    601  1.1  mrg 	    {
    602  1.1  mrg 	      s->physical_offset += did_read;
    603  1.1  mrg 	      s->active = did_read;
    604  1.1  mrg 	      did_read = (did_read > to_read) ? to_read : did_read;
    605  1.1  mrg 	      memcpy (p, s->buffer, did_read);
    606  1.1  mrg 	    }
    607  1.1  mrg 	  else
    608  1.1  mrg 	    return did_read;
    609  1.1  mrg         }
    610  1.1  mrg       else
    611  1.1  mrg         {
    612  1.1  mrg           did_read = raw_read (s, p, to_read);
    613  1.1  mrg 	  if (likely (did_read >= 0))
    614  1.1  mrg 	    {
    615  1.1  mrg 	      s->physical_offset += did_read;
    616  1.1  mrg 	      s->active = 0;
    617  1.1  mrg 	    }
    618  1.1  mrg 	  else
    619  1.1  mrg 	    return did_read;
    620  1.1  mrg         }
    621  1.1  mrg       nbyte = did_read + nread;
    622  1.1  mrg     }
    623  1.1  mrg   s->logical_offset += nbyte;
    624  1.1  mrg   return nbyte;
    625  1.1  mrg }
    626  1.1  mrg 
    627  1.1  mrg static ssize_t
    628  1.1  mrg buf_write (unix_stream *s, const void *buf, ssize_t nbyte)
    629  1.1  mrg {
    630  1.1  mrg   if (nbyte == 0)
    631  1.1  mrg     return 0;
    632  1.1  mrg 
    633  1.1  mrg   if (s->ndirty == 0)
    634  1.1  mrg     s->buffer_offset = s->logical_offset;
    635  1.1  mrg 
    636  1.1  mrg   /* Does the data fit into the buffer?  As a special case, if the
    637  1.1  mrg      buffer is empty and the request is bigger than s->buffer_size/2,
    638  1.1  mrg      write directly. This avoids the case where the buffer would have
    639  1.1  mrg      to be flushed at every write.  */
    640  1.1  mrg   if (!(s->ndirty == 0 && nbyte > s->buffer_size/2)
    641  1.1  mrg       && s->logical_offset + nbyte <= s->buffer_offset + s->buffer_size
    642  1.1  mrg       && s->buffer_offset <= s->logical_offset
    643  1.1  mrg       && s->buffer_offset + s->ndirty >= s->logical_offset)
    644  1.1  mrg     {
    645  1.1  mrg       memcpy (s->buffer + (s->logical_offset - s->buffer_offset), buf, nbyte);
    646  1.1  mrg       int nd = (s->logical_offset - s->buffer_offset) + nbyte;
    647  1.1  mrg       if (nd > s->ndirty)
    648  1.1  mrg         s->ndirty = nd;
    649  1.1  mrg     }
    650  1.1  mrg   else
    651  1.1  mrg     {
    652  1.1  mrg       /* Flush, and either fill the buffer with the new data, or if
    653  1.1  mrg          the request is bigger than the buffer size, write directly
    654  1.1  mrg          bypassing the buffer.  */
    655  1.1  mrg       buf_flush (s);
    656  1.1  mrg       if (nbyte <= s->buffer_size/2)
    657  1.1  mrg         {
    658  1.1  mrg           memcpy (s->buffer, buf, nbyte);
    659  1.1  mrg           s->buffer_offset = s->logical_offset;
    660  1.1  mrg           s->ndirty += nbyte;
    661  1.1  mrg         }
    662  1.1  mrg       else
    663  1.1  mrg 	{
    664  1.1  mrg 	  if (s->physical_offset != s->logical_offset)
    665  1.1  mrg 	    {
    666  1.1  mrg 	      if (raw_seek (s, s->logical_offset, SEEK_SET) < 0)
    667  1.1  mrg 		return -1;
    668  1.1  mrg 	      s->physical_offset = s->logical_offset;
    669  1.1  mrg 	    }
    670  1.1  mrg 
    671  1.1  mrg 	  nbyte = raw_write (s, buf, nbyte);
    672  1.1  mrg 	  s->physical_offset += nbyte;
    673  1.1  mrg 	}
    674  1.1  mrg     }
    675  1.1  mrg   s->logical_offset += nbyte;
    676  1.1  mrg   if (s->logical_offset > s->file_length)
    677  1.1  mrg     s->file_length = s->logical_offset;
    678  1.1  mrg   return nbyte;
    679  1.1  mrg }
    680  1.1  mrg 
    681  1.1  mrg 
    682  1.1  mrg /* "Unbuffered" really means I/O statement buffering. For formatted
    683  1.1  mrg    I/O, the fbuf manages this, and then uses raw I/O. For unformatted
    684  1.1  mrg    I/O, buffered I/O is used, and the buffer is flushed at the end of
    685  1.1  mrg    each I/O statement, where this function is called.  Alternatively,
    686  1.1  mrg    the buffer is flushed at the end of the record if the buffer is
    687  1.1  mrg    more than half full; this prevents needless seeking back and forth
    688  1.1  mrg    when writing sequential unformatted.  */
    689  1.1  mrg 
    690  1.1  mrg static int
    691  1.1  mrg buf_markeor (unix_stream *s)
    692  1.1  mrg {
    693  1.1  mrg   if (s->unbuffered || s->ndirty >= s->buffer_size / 2)
    694  1.1  mrg     return buf_flush (s);
    695  1.1  mrg   return 0;
    696  1.1  mrg }
    697  1.1  mrg 
    698  1.1  mrg static gfc_offset
    699  1.1  mrg buf_seek (unix_stream *s, gfc_offset offset, int whence)
    700  1.1  mrg {
    701  1.1  mrg   switch (whence)
    702  1.1  mrg     {
    703  1.1  mrg     case SEEK_SET:
    704  1.1  mrg       break;
    705  1.1  mrg     case SEEK_CUR:
    706  1.1  mrg       offset += s->logical_offset;
    707  1.1  mrg       break;
    708  1.1  mrg     case SEEK_END:
    709  1.1  mrg       offset += s->file_length;
    710  1.1  mrg       break;
    711  1.1  mrg     default:
    712  1.1  mrg       return -1;
    713  1.1  mrg     }
    714  1.1  mrg   if (offset < 0)
    715  1.1  mrg     {
    716  1.1  mrg       errno = EINVAL;
    717  1.1  mrg       return -1;
    718  1.1  mrg     }
    719  1.1  mrg   s->logical_offset = offset;
    720  1.1  mrg   return offset;
    721  1.1  mrg }
    722  1.1  mrg 
    723  1.1  mrg static gfc_offset
    724  1.1  mrg buf_tell (unix_stream *s)
    725  1.1  mrg {
    726  1.1  mrg   return buf_seek (s, 0, SEEK_CUR);
    727  1.1  mrg }
    728  1.1  mrg 
    729  1.1  mrg static gfc_offset
    730  1.1  mrg buf_size (unix_stream *s)
    731  1.1  mrg {
    732  1.1  mrg   return s->file_length;
    733  1.1  mrg }
    734  1.1  mrg 
    735  1.1  mrg static int
    736  1.1  mrg buf_truncate (unix_stream *s, gfc_offset length)
    737  1.1  mrg {
    738  1.1  mrg   int r;
    739  1.1  mrg 
    740  1.1  mrg   if (buf_flush (s) != 0)
    741  1.1  mrg     return -1;
    742  1.1  mrg   r = raw_truncate (s, length);
    743  1.1  mrg   if (r == 0)
    744  1.1  mrg     s->file_length = length;
    745  1.1  mrg   return r;
    746  1.1  mrg }
    747  1.1  mrg 
    748  1.1  mrg static int
    749  1.1  mrg buf_close (unix_stream *s)
    750  1.1  mrg {
    751  1.1  mrg   if (buf_flush (s) != 0)
    752  1.1  mrg     return -1;
    753  1.1  mrg   free (s->buffer);
    754  1.1  mrg   return raw_close (s);
    755  1.1  mrg }
    756  1.1  mrg 
    757  1.1  mrg static const struct stream_vtable buf_vtable = {
    758  1.1  mrg   .read = (void *) buf_read,
    759  1.1  mrg   .write = (void *) buf_write,
    760  1.1  mrg   .seek = (void *) buf_seek,
    761  1.1  mrg   .tell = (void *) buf_tell,
    762  1.1  mrg   .size = (void *) buf_size,
    763  1.1  mrg   .trunc = (void *) buf_truncate,
    764  1.1  mrg   .close = (void *) buf_close,
    765  1.1  mrg   .flush = (void *) buf_flush,
    766  1.1  mrg   .markeor = (void *) buf_markeor
    767  1.1  mrg };
    768  1.1  mrg 
    769  1.1  mrg static int
    770  1.1  mrg buf_init (unix_stream *s, bool unformatted)
    771  1.1  mrg {
    772  1.1  mrg   s->st.vptr = &buf_vtable;
    773  1.1  mrg 
    774  1.1  mrg   /* Try to guess a good value for the buffer size.  For formatted
    775  1.1  mrg      I/O, we use so many CPU cycles converting the data that there is
    776  1.1  mrg      more sense in converving memory and especially cache.  For
    777  1.1  mrg      unformatted, a bigger block can have a large impact in some
    778  1.1  mrg      environments.  */
    779  1.1  mrg 
    780  1.1  mrg   if (unformatted)
    781  1.1  mrg     {
    782  1.1  mrg       if (options.unformatted_buffer_size > 0)
    783  1.1  mrg 	s->buffer_size = options.unformatted_buffer_size;
    784  1.1  mrg       else
    785  1.1  mrg 	s->buffer_size = UNFORMATTED_BUFFER_SIZE_DEFAULT;
    786  1.1  mrg     }
    787  1.1  mrg   else
    788  1.1  mrg     {
    789  1.1  mrg       if (options.formatted_buffer_size > 0)
    790  1.1  mrg 	s->buffer_size = options.formatted_buffer_size;
    791  1.1  mrg       else
    792  1.1  mrg 	s->buffer_size = FORMATTED_BUFFER_SIZE_DEFAULT;
    793  1.1  mrg     }
    794  1.1  mrg 
    795  1.1  mrg   s->buffer = xmalloc (s->buffer_size);
    796  1.1  mrg   return 0;
    797  1.1  mrg }
    798  1.1  mrg 
    799  1.1  mrg 
    800  1.1  mrg /*********************************************************************
    801  1.1  mrg   memory stream functions - These are used for internal files
    802  1.1  mrg 
    803  1.1  mrg   The idea here is that a single stream structure is created and all
    804  1.1  mrg   requests must be satisfied from it.  The location and size of the
    805  1.1  mrg   buffer is the character variable supplied to the READ or WRITE
    806  1.1  mrg   statement.
    807  1.1  mrg 
    808  1.1  mrg *********************************************************************/
    809  1.1  mrg 
    810  1.1  mrg char *
    811  1.1  mrg mem_alloc_r (stream *strm, size_t *len)
    812  1.1  mrg {
    813  1.1  mrg   unix_stream *s = (unix_stream *) strm;
    814  1.1  mrg   gfc_offset n;
    815  1.1  mrg   gfc_offset where = s->logical_offset;
    816  1.1  mrg 
    817  1.1  mrg   if (where < s->buffer_offset || where > s->buffer_offset + s->active)
    818  1.1  mrg     return NULL;
    819  1.1  mrg 
    820  1.1  mrg   n = s->buffer_offset + s->active - where;
    821  1.1  mrg   if ((gfc_offset) *len > n)
    822  1.1  mrg     *len = n;
    823  1.1  mrg 
    824  1.1  mrg   s->logical_offset = where + *len;
    825  1.1  mrg 
    826  1.1  mrg   return s->buffer + (where - s->buffer_offset);
    827  1.1  mrg }
    828  1.1  mrg 
    829  1.1  mrg 
    830  1.1  mrg char *
    831  1.1  mrg mem_alloc_r4 (stream *strm, size_t *len)
    832  1.1  mrg {
    833  1.1  mrg   unix_stream *s = (unix_stream *) strm;
    834  1.1  mrg   gfc_offset n;
    835  1.1  mrg   gfc_offset where = s->logical_offset;
    836  1.1  mrg 
    837  1.1  mrg   if (where < s->buffer_offset || where > s->buffer_offset + s->active)
    838  1.1  mrg     return NULL;
    839  1.1  mrg 
    840  1.1  mrg   n = s->buffer_offset + s->active - where;
    841  1.1  mrg   if ((gfc_offset) *len > n)
    842  1.1  mrg     *len = n;
    843  1.1  mrg 
    844  1.1  mrg   s->logical_offset = where + *len;
    845  1.1  mrg 
    846  1.1  mrg   return s->buffer + (where - s->buffer_offset) * 4;
    847  1.1  mrg }
    848  1.1  mrg 
    849  1.1  mrg 
    850  1.1  mrg char *
    851  1.1  mrg mem_alloc_w (stream *strm, size_t *len)
    852  1.1  mrg {
    853  1.1  mrg   unix_stream *s = (unix_stream *)strm;
    854  1.1  mrg   gfc_offset m;
    855  1.1  mrg   gfc_offset where = s->logical_offset;
    856  1.1  mrg 
    857  1.1  mrg   m = where + *len;
    858  1.1  mrg 
    859  1.1  mrg   if (where < s->buffer_offset)
    860  1.1  mrg     return NULL;
    861  1.1  mrg 
    862  1.1  mrg   if (m > s->file_length)
    863  1.1  mrg     return NULL;
    864  1.1  mrg 
    865  1.1  mrg   s->logical_offset = m;
    866  1.1  mrg 
    867  1.1  mrg   return s->buffer + (where - s->buffer_offset);
    868  1.1  mrg }
    869  1.1  mrg 
    870  1.1  mrg 
    871  1.1  mrg gfc_char4_t *
    872  1.1  mrg mem_alloc_w4 (stream *strm, size_t *len)
    873  1.1  mrg {
    874  1.1  mrg   unix_stream *s = (unix_stream *)strm;
    875  1.1  mrg   gfc_offset m;
    876  1.1  mrg   gfc_offset where = s->logical_offset;
    877  1.1  mrg   gfc_char4_t *result = (gfc_char4_t *) s->buffer;
    878  1.1  mrg 
    879  1.1  mrg   m = where + *len;
    880  1.1  mrg 
    881  1.1  mrg   if (where < s->buffer_offset)
    882  1.1  mrg     return NULL;
    883  1.1  mrg 
    884  1.1  mrg   if (m > s->file_length)
    885  1.1  mrg     return NULL;
    886  1.1  mrg 
    887  1.1  mrg   s->logical_offset = m;
    888  1.1  mrg   return &result[where - s->buffer_offset];
    889  1.1  mrg }
    890  1.1  mrg 
    891  1.1  mrg 
    892  1.1  mrg /* Stream read function for character(kind=1) internal units.  */
    893  1.1  mrg 
    894  1.1  mrg static ssize_t
    895  1.1  mrg mem_read (stream *s, void *buf, ssize_t nbytes)
    896  1.1  mrg {
    897  1.1  mrg   void *p;
    898  1.1  mrg   size_t nb = nbytes;
    899  1.1  mrg 
    900  1.1  mrg   p = mem_alloc_r (s, &nb);
    901  1.1  mrg   if (p)
    902  1.1  mrg     {
    903  1.1  mrg       memcpy (buf, p, nb);
    904  1.1  mrg       return (ssize_t) nb;
    905  1.1  mrg     }
    906  1.1  mrg   else
    907  1.1  mrg     return 0;
    908  1.1  mrg }
    909  1.1  mrg 
    910  1.1  mrg 
    911  1.1  mrg /* Stream read function for chracter(kind=4) internal units.  */
    912  1.1  mrg 
    913  1.1  mrg static ssize_t
    914  1.1  mrg mem_read4 (stream *s, void *buf, ssize_t nbytes)
    915  1.1  mrg {
    916  1.1  mrg   void *p;
    917  1.1  mrg   size_t nb = nbytes;
    918  1.1  mrg 
    919  1.1  mrg   p = mem_alloc_r4 (s, &nb);
    920  1.1  mrg   if (p)
    921  1.1  mrg     {
    922  1.1  mrg       memcpy (buf, p, nb * 4);
    923  1.1  mrg       return (ssize_t) nb;
    924  1.1  mrg     }
    925  1.1  mrg   else
    926  1.1  mrg     return 0;
    927  1.1  mrg }
    928  1.1  mrg 
    929  1.1  mrg 
    930  1.1  mrg /* Stream write function for character(kind=1) internal units.  */
    931  1.1  mrg 
    932  1.1  mrg static ssize_t
    933  1.1  mrg mem_write (stream *s, const void *buf, ssize_t nbytes)
    934  1.1  mrg {
    935  1.1  mrg   void *p;
    936  1.1  mrg   size_t nb = nbytes;
    937  1.1  mrg 
    938  1.1  mrg   p = mem_alloc_w (s, &nb);
    939  1.1  mrg   if (p)
    940  1.1  mrg     {
    941  1.1  mrg       memcpy (p, buf, nb);
    942  1.1  mrg       return (ssize_t) nb;
    943  1.1  mrg     }
    944  1.1  mrg   else
    945  1.1  mrg     return 0;
    946  1.1  mrg }
    947  1.1  mrg 
    948  1.1  mrg 
    949  1.1  mrg /* Stream write function for character(kind=4) internal units.  */
    950  1.1  mrg 
    951  1.1  mrg static ssize_t
    952  1.1  mrg mem_write4 (stream *s, const void *buf, ssize_t nwords)
    953  1.1  mrg {
    954  1.1  mrg   gfc_char4_t *p;
    955  1.1  mrg   size_t nw = nwords;
    956  1.1  mrg 
    957  1.1  mrg   p = mem_alloc_w4 (s, &nw);
    958  1.1  mrg   if (p)
    959  1.1  mrg     {
    960  1.1  mrg       while (nw--)
    961  1.1  mrg 	*p++ = (gfc_char4_t) *((char *) buf);
    962  1.1  mrg       return nwords;
    963  1.1  mrg     }
    964  1.1  mrg   else
    965  1.1  mrg     return 0;
    966  1.1  mrg }
    967  1.1  mrg 
    968  1.1  mrg 
    969  1.1  mrg static gfc_offset
    970  1.1  mrg mem_seek (stream *strm, gfc_offset offset, int whence)
    971  1.1  mrg {
    972  1.1  mrg   unix_stream *s = (unix_stream *)strm;
    973  1.1  mrg   switch (whence)
    974  1.1  mrg     {
    975  1.1  mrg     case SEEK_SET:
    976  1.1  mrg       break;
    977  1.1  mrg     case SEEK_CUR:
    978  1.1  mrg       offset += s->logical_offset;
    979  1.1  mrg       break;
    980  1.1  mrg     case SEEK_END:
    981  1.1  mrg       offset += s->file_length;
    982  1.1  mrg       break;
    983  1.1  mrg     default:
    984  1.1  mrg       return -1;
    985  1.1  mrg     }
    986  1.1  mrg 
    987  1.1  mrg   /* Note that for internal array I/O it's actually possible to have a
    988  1.1  mrg      negative offset, so don't check for that.  */
    989  1.1  mrg   if (offset > s->file_length)
    990  1.1  mrg     {
    991  1.1  mrg       errno = EINVAL;
    992  1.1  mrg       return -1;
    993  1.1  mrg     }
    994  1.1  mrg 
    995  1.1  mrg   s->logical_offset = offset;
    996  1.1  mrg 
    997  1.1  mrg   /* Returning < 0 is the error indicator for sseek(), so return 0 if
    998  1.1  mrg      offset is negative.  Thus if the return value is 0, the caller
    999  1.1  mrg      has to use stell() to get the real value of logical_offset.  */
   1000  1.1  mrg   if (offset >= 0)
   1001  1.1  mrg     return offset;
   1002  1.1  mrg   return 0;
   1003  1.1  mrg }
   1004  1.1  mrg 
   1005  1.1  mrg 
   1006  1.1  mrg static gfc_offset
   1007  1.1  mrg mem_tell (stream *s)
   1008  1.1  mrg {
   1009  1.1  mrg   return ((unix_stream *)s)->logical_offset;
   1010  1.1  mrg }
   1011  1.1  mrg 
   1012  1.1  mrg 
   1013  1.1  mrg static int
   1014  1.1  mrg mem_truncate (unix_stream *s __attribute__ ((unused)),
   1015  1.1  mrg 	      gfc_offset length __attribute__ ((unused)))
   1016  1.1  mrg {
   1017  1.1  mrg   return 0;
   1018  1.1  mrg }
   1019  1.1  mrg 
   1020  1.1  mrg 
   1021  1.1  mrg static int
   1022  1.1  mrg mem_flush (unix_stream *s __attribute__ ((unused)))
   1023  1.1  mrg {
   1024  1.1  mrg   return 0;
   1025  1.1  mrg }
   1026  1.1  mrg 
   1027  1.1  mrg 
   1028  1.1  mrg static int
   1029  1.1  mrg mem_close (unix_stream *s)
   1030  1.1  mrg {
   1031  1.1  mrg   if (s)
   1032  1.1  mrg     free (s);
   1033  1.1  mrg   return 0;
   1034  1.1  mrg }
   1035  1.1  mrg 
   1036  1.1  mrg static const struct stream_vtable mem_vtable = {
   1037  1.1  mrg   .read = (void *) mem_read,
   1038  1.1  mrg   .write = (void *) mem_write,
   1039  1.1  mrg   .seek = (void *) mem_seek,
   1040  1.1  mrg   .tell = (void *) mem_tell,
   1041  1.1  mrg   /* buf_size is not a typo, we just reuse an identical
   1042  1.1  mrg      implementation.  */
   1043  1.1  mrg   .size = (void *) buf_size,
   1044  1.1  mrg   .trunc = (void *) mem_truncate,
   1045  1.1  mrg   .close = (void *) mem_close,
   1046  1.1  mrg   .flush = (void *) mem_flush,
   1047  1.1  mrg   .markeor = (void *) raw_markeor
   1048  1.1  mrg };
   1049  1.1  mrg 
   1050  1.1  mrg static const struct stream_vtable mem4_vtable = {
   1051  1.1  mrg   .read = (void *) mem_read4,
   1052  1.1  mrg   .write = (void *) mem_write4,
   1053  1.1  mrg   .seek = (void *) mem_seek,
   1054  1.1  mrg   .tell = (void *) mem_tell,
   1055  1.1  mrg   /* buf_size is not a typo, we just reuse an identical
   1056  1.1  mrg      implementation.  */
   1057  1.1  mrg   .size = (void *) buf_size,
   1058  1.1  mrg   .trunc = (void *) mem_truncate,
   1059  1.1  mrg   .close = (void *) mem_close,
   1060  1.1  mrg   .flush = (void *) mem_flush,
   1061  1.1  mrg   .markeor = (void *) raw_markeor
   1062  1.1  mrg };
   1063  1.1  mrg 
   1064  1.1  mrg /*********************************************************************
   1065  1.1  mrg   Public functions -- A reimplementation of this module needs to
   1066  1.1  mrg   define functional equivalents of the following.
   1067  1.1  mrg *********************************************************************/
   1068  1.1  mrg 
   1069  1.1  mrg /* open_internal()-- Returns a stream structure from a character(kind=1)
   1070  1.1  mrg    internal file */
   1071  1.1  mrg 
   1072  1.1  mrg stream *
   1073  1.1  mrg open_internal (char *base, size_t length, gfc_offset offset)
   1074  1.1  mrg {
   1075  1.1  mrg   unix_stream *s;
   1076  1.1  mrg 
   1077  1.1  mrg   s = xcalloc (1, sizeof (unix_stream));
   1078  1.1  mrg 
   1079  1.1  mrg   s->buffer = base;
   1080  1.1  mrg   s->buffer_offset = offset;
   1081  1.1  mrg 
   1082  1.1  mrg   s->active = s->file_length = length;
   1083  1.1  mrg 
   1084  1.1  mrg   s->st.vptr = &mem_vtable;
   1085  1.1  mrg 
   1086  1.1  mrg   return (stream *) s;
   1087  1.1  mrg }
   1088  1.1  mrg 
   1089  1.1  mrg /* open_internal4()-- Returns a stream structure from a character(kind=4)
   1090  1.1  mrg    internal file */
   1091  1.1  mrg 
   1092  1.1  mrg stream *
   1093  1.1  mrg open_internal4 (char *base, size_t length, gfc_offset offset)
   1094  1.1  mrg {
   1095  1.1  mrg   unix_stream *s;
   1096  1.1  mrg 
   1097  1.1  mrg   s = xcalloc (1, sizeof (unix_stream));
   1098  1.1  mrg 
   1099  1.1  mrg   s->buffer = base;
   1100  1.1  mrg   s->buffer_offset = offset;
   1101  1.1  mrg 
   1102  1.1  mrg   s->active = s->file_length = length * sizeof (gfc_char4_t);
   1103  1.1  mrg 
   1104  1.1  mrg   s->st.vptr = &mem4_vtable;
   1105  1.1  mrg 
   1106  1.1  mrg   return (stream *)s;
   1107  1.1  mrg }
   1108  1.1  mrg 
   1109  1.1  mrg 
   1110  1.1  mrg /* fd_to_stream()-- Given an open file descriptor, build a stream
   1111  1.1  mrg    around it. */
   1112  1.1  mrg 
   1113  1.1  mrg static stream *
   1114  1.1  mrg fd_to_stream (int fd, bool unformatted)
   1115  1.1  mrg {
   1116  1.1  mrg   struct stat statbuf;
   1117  1.1  mrg   unix_stream *s;
   1118  1.1  mrg 
   1119  1.1  mrg   s = xcalloc (1, sizeof (unix_stream));
   1120  1.1  mrg 
   1121  1.1  mrg   s->fd = fd;
   1122  1.1  mrg 
   1123  1.1  mrg   /* Get the current length of the file. */
   1124  1.1  mrg 
   1125  1.1  mrg   if (TEMP_FAILURE_RETRY (fstat (fd, &statbuf)) == -1)
   1126  1.1  mrg     {
   1127  1.1  mrg       s->st_dev = s->st_ino = -1;
   1128  1.1  mrg       s->file_length = 0;
   1129  1.1  mrg       if (errno == EBADF)
   1130  1.1  mrg 	s->fd = -1;
   1131  1.1  mrg       raw_init (s);
   1132  1.1  mrg       return (stream *) s;
   1133  1.1  mrg     }
   1134  1.1  mrg 
   1135  1.1  mrg   s->st_dev = statbuf.st_dev;
   1136  1.1  mrg   s->st_ino = statbuf.st_ino;
   1137  1.1  mrg   s->file_length = statbuf.st_size;
   1138  1.1  mrg 
   1139  1.1  mrg   /* Only use buffered IO for regular files.  */
   1140  1.1  mrg   if (S_ISREG (statbuf.st_mode)
   1141  1.1  mrg       && !options.all_unbuffered
   1142  1.1  mrg       && !(options.unbuffered_preconnected &&
   1143  1.1  mrg 	   (s->fd == STDIN_FILENO
   1144  1.1  mrg 	    || s->fd == STDOUT_FILENO
   1145  1.1  mrg 	    || s->fd == STDERR_FILENO)))
   1146  1.1  mrg     buf_init (s, unformatted);
   1147  1.1  mrg   else
   1148  1.1  mrg     {
   1149  1.1  mrg       if (unformatted)
   1150  1.1  mrg 	{
   1151  1.1  mrg 	  s->unbuffered = true;
   1152  1.1  mrg 	  buf_init (s, unformatted);
   1153  1.1  mrg 	}
   1154  1.1  mrg       else
   1155  1.1  mrg 	raw_init (s);
   1156  1.1  mrg     }
   1157  1.1  mrg 
   1158  1.1  mrg   return (stream *) s;
   1159  1.1  mrg }
   1160  1.1  mrg 
   1161  1.1  mrg 
   1162  1.1  mrg /* Given the Fortran unit number, convert it to a C file descriptor.  */
   1163  1.1  mrg 
   1164  1.1  mrg int
   1165  1.1  mrg unit_to_fd (int unit)
   1166  1.1  mrg {
   1167  1.1  mrg   gfc_unit *us;
   1168  1.1  mrg   int fd;
   1169  1.1  mrg 
   1170  1.1  mrg   us = find_unit (unit);
   1171  1.1  mrg   if (us == NULL)
   1172  1.1  mrg     return -1;
   1173  1.1  mrg 
   1174  1.1  mrg   fd = ((unix_stream *) us->s)->fd;
   1175  1.1  mrg   unlock_unit (us);
   1176  1.1  mrg   return fd;
   1177  1.1  mrg }
   1178  1.1  mrg 
   1179  1.1  mrg 
   1180  1.1  mrg /* Set the close-on-exec flag for an existing fd, if the system
   1181  1.1  mrg    supports such.  */
   1182  1.1  mrg 
   1183  1.1  mrg static void __attribute__ ((unused))
   1184  1.1  mrg set_close_on_exec (int fd __attribute__ ((unused)))
   1185  1.1  mrg {
   1186  1.1  mrg   /* Mingw does not define F_SETFD.  */
   1187  1.1  mrg #if defined(HAVE_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC)
   1188  1.1  mrg   if (fd >= 0)
   1189  1.1  mrg     fcntl(fd, F_SETFD, FD_CLOEXEC);
   1190  1.1  mrg #endif
   1191  1.1  mrg }
   1192  1.1  mrg 
   1193  1.1  mrg 
   1194  1.1  mrg /* Helper function for tempfile(). Tries to open a temporary file in
   1195  1.1  mrg    the directory specified by tempdir. If successful, the file name is
   1196  1.1  mrg    stored in fname and the descriptor returned. Returns -1 on
   1197  1.1  mrg    failure.  */
   1198  1.1  mrg 
   1199  1.1  mrg static int
   1200  1.1  mrg tempfile_open (const char *tempdir, char **fname)
   1201  1.1  mrg {
   1202  1.1  mrg   int fd;
   1203  1.1  mrg   const char *slash = "/";
   1204  1.1  mrg #if defined(HAVE_UMASK) && defined(HAVE_MKSTEMP)
   1205  1.1  mrg   mode_t mode_mask;
   1206  1.1  mrg #endif
   1207  1.1  mrg 
   1208  1.1  mrg   if (!tempdir)
   1209  1.1  mrg     return -1;
   1210  1.1  mrg 
   1211  1.1  mrg   /* Check for the special case that tempdir ends with a slash or
   1212  1.1  mrg      backslash.  */
   1213  1.1  mrg   size_t tempdirlen = strlen (tempdir);
   1214  1.1  mrg   if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/'
   1215  1.1  mrg #ifdef __MINGW32__
   1216  1.1  mrg       || tempdir[tempdirlen - 1] == '\\'
   1217  1.1  mrg #endif
   1218  1.1  mrg      )
   1219  1.1  mrg     slash = "";
   1220  1.1  mrg 
   1221  1.1  mrg   /* Take care that the template is longer in the mktemp() branch.  */
   1222  1.1  mrg   char *template = xmalloc (tempdirlen + 23);
   1223  1.1  mrg 
   1224  1.1  mrg #ifdef HAVE_MKSTEMP
   1225  1.1  mrg   snprintf (template, tempdirlen + 23, "%s%sgfortrantmpXXXXXX",
   1226  1.1  mrg 	    tempdir, slash);
   1227  1.1  mrg 
   1228  1.1  mrg #ifdef HAVE_UMASK
   1229  1.1  mrg   /* Temporarily set the umask such that the file has 0600 permissions.  */
   1230  1.1  mrg   mode_mask = umask (S_IXUSR | S_IRWXG | S_IRWXO);
   1231  1.1  mrg #endif
   1232  1.1  mrg 
   1233  1.1  mrg #if defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
   1234  1.1  mrg   TEMP_FAILURE_RETRY (fd = mkostemp (template, O_CLOEXEC));
   1235  1.1  mrg #else
   1236  1.1  mrg   TEMP_FAILURE_RETRY (fd = mkstemp (template));
   1237  1.1  mrg   set_close_on_exec (fd);
   1238  1.1  mrg #endif
   1239  1.1  mrg 
   1240  1.1  mrg #ifdef HAVE_UMASK
   1241  1.1  mrg   (void) umask (mode_mask);
   1242  1.1  mrg #endif
   1243  1.1  mrg 
   1244  1.1  mrg #else /* HAVE_MKSTEMP */
   1245  1.1  mrg   fd = -1;
   1246  1.1  mrg   int count = 0;
   1247  1.1  mrg   size_t slashlen = strlen (slash);
   1248  1.1  mrg   int flags = O_RDWR | O_CREAT | O_EXCL;
   1249  1.1  mrg #if defined(HAVE_CRLF) && defined(O_BINARY)
   1250  1.1  mrg   flags |= O_BINARY;
   1251  1.1  mrg #endif
   1252  1.1  mrg #ifdef O_CLOEXEC
   1253  1.1  mrg   flags |= O_CLOEXEC;
   1254  1.1  mrg #endif
   1255  1.1  mrg   do
   1256  1.1  mrg     {
   1257  1.1  mrg       snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX",
   1258  1.1  mrg 		tempdir, slash);
   1259  1.1  mrg       if (count > 0)
   1260  1.1  mrg 	{
   1261  1.1  mrg 	  int c = count;
   1262  1.1  mrg 	  template[tempdirlen + slashlen + 13] = 'a' + (c% 26);
   1263  1.1  mrg 	  c /= 26;
   1264  1.1  mrg 	  template[tempdirlen + slashlen + 12] = 'a' + (c % 26);
   1265  1.1  mrg 	  c /= 26;
   1266  1.1  mrg 	  template[tempdirlen + slashlen + 11] = 'a' + (c % 26);
   1267  1.1  mrg 	  if (c >= 26)
   1268  1.1  mrg 	    break;
   1269  1.1  mrg 	}
   1270  1.1  mrg 
   1271  1.1  mrg       if (!mktemp (template))
   1272  1.1  mrg       {
   1273  1.1  mrg 	errno = EEXIST;
   1274  1.1  mrg 	count++;
   1275  1.1  mrg 	continue;
   1276  1.1  mrg       }
   1277  1.1  mrg 
   1278  1.1  mrg       TEMP_FAILURE_RETRY (fd = open (template, flags, S_IRUSR | S_IWUSR));
   1279  1.1  mrg     }
   1280  1.1  mrg   while (fd == -1 && errno == EEXIST);
   1281  1.1  mrg #ifndef O_CLOEXEC
   1282  1.1  mrg   set_close_on_exec (fd);
   1283  1.1  mrg #endif
   1284  1.1  mrg #endif /* HAVE_MKSTEMP */
   1285  1.1  mrg 
   1286  1.1  mrg   *fname = template;
   1287  1.1  mrg   return fd;
   1288  1.1  mrg }
   1289  1.1  mrg 
   1290  1.1  mrg 
   1291  1.1  mrg /* tempfile()-- Generate a temporary filename for a scratch file and
   1292  1.1  mrg    open it.  mkstemp() opens the file for reading and writing, but the
   1293  1.1  mrg    library mode prevents anything that is not allowed.  The descriptor
   1294  1.1  mrg    is returned, which is -1 on error.  The template is pointed to by
   1295  1.1  mrg    opp->file, which is copied into the unit structure
   1296  1.1  mrg    and freed later. */
   1297  1.1  mrg 
   1298  1.1  mrg static int
   1299  1.1  mrg tempfile (st_parameter_open *opp)
   1300  1.1  mrg {
   1301  1.1  mrg   const char *tempdir;
   1302  1.1  mrg   char *fname;
   1303  1.1  mrg   int fd = -1;
   1304  1.1  mrg 
   1305  1.1  mrg   tempdir = secure_getenv ("TMPDIR");
   1306  1.1  mrg   fd = tempfile_open (tempdir, &fname);
   1307  1.1  mrg #ifdef __MINGW32__
   1308  1.1  mrg   if (fd == -1)
   1309  1.1  mrg     {
   1310  1.1  mrg       char buffer[MAX_PATH + 1];
   1311  1.1  mrg       DWORD ret;
   1312  1.1  mrg       ret = GetTempPath (MAX_PATH, buffer);
   1313  1.1  mrg       /* If we are not able to get a temp-directory, we use
   1314  1.1  mrg 	 current directory.  */
   1315  1.1  mrg       if (ret > MAX_PATH || !ret)
   1316  1.1  mrg         buffer[0] = 0;
   1317  1.1  mrg       else
   1318  1.1  mrg         buffer[ret] = 0;
   1319  1.1  mrg       tempdir = strdup (buffer);
   1320  1.1  mrg       fd = tempfile_open (tempdir, &fname);
   1321  1.1  mrg     }
   1322  1.1  mrg #elif defined(__CYGWIN__)
   1323  1.1  mrg   if (fd == -1)
   1324  1.1  mrg     {
   1325  1.1  mrg       tempdir = secure_getenv ("TMP");
   1326  1.1  mrg       fd = tempfile_open (tempdir, &fname);
   1327  1.1  mrg     }
   1328  1.1  mrg   if (fd == -1)
   1329  1.1  mrg     {
   1330  1.1  mrg       tempdir = secure_getenv ("TEMP");
   1331  1.1  mrg       fd = tempfile_open (tempdir, &fname);
   1332  1.1  mrg     }
   1333  1.1  mrg #endif
   1334  1.1  mrg   if (fd == -1)
   1335  1.1  mrg     fd = tempfile_open (P_tmpdir, &fname);
   1336  1.1  mrg 
   1337  1.1  mrg   opp->file = fname;
   1338  1.1  mrg   opp->file_len = strlen (fname);	/* Don't include trailing nul */
   1339  1.1  mrg 
   1340  1.1  mrg   return fd;
   1341  1.1  mrg }
   1342  1.1  mrg 
   1343  1.1  mrg 
   1344  1.1  mrg /* regular_file2()-- Open a regular file.
   1345  1.1  mrg    Change flags->action if it is ACTION_UNSPECIFIED on entry,
   1346  1.1  mrg    unless an error occurs.
   1347  1.1  mrg    Returns the descriptor, which is less than zero on error. */
   1348  1.1  mrg 
   1349  1.1  mrg static int
   1350  1.1  mrg regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
   1351  1.1  mrg {
   1352  1.1  mrg   int mode;
   1353  1.1  mrg   int rwflag;
   1354  1.1  mrg   int crflag, crflag2;
   1355  1.1  mrg   int fd;
   1356  1.1  mrg 
   1357  1.1  mrg #ifdef __CYGWIN__
   1358  1.1  mrg   if (opp->file_len == 7)
   1359  1.1  mrg     {
   1360  1.1  mrg       if (strncmp (path, "CONOUT$", 7) == 0
   1361  1.1  mrg 	  || strncmp (path, "CONERR$", 7) == 0)
   1362  1.1  mrg 	{
   1363  1.1  mrg 	  fd = open ("/dev/conout", O_WRONLY);
   1364  1.1  mrg 	  flags->action = ACTION_WRITE;
   1365  1.1  mrg 	  return fd;
   1366  1.1  mrg 	}
   1367  1.1  mrg     }
   1368  1.1  mrg 
   1369  1.1  mrg   if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
   1370  1.1  mrg     {
   1371  1.1  mrg       fd = open ("/dev/conin", O_RDONLY);
   1372  1.1  mrg       flags->action = ACTION_READ;
   1373  1.1  mrg       return fd;
   1374  1.1  mrg     }
   1375  1.1  mrg #endif
   1376  1.1  mrg 
   1377  1.1  mrg 
   1378  1.1  mrg #ifdef __MINGW32__
   1379  1.1  mrg   if (opp->file_len == 7)
   1380  1.1  mrg     {
   1381  1.1  mrg       if (strncmp (path, "CONOUT$", 7) == 0
   1382  1.1  mrg 	  || strncmp (path, "CONERR$", 7) == 0)
   1383  1.1  mrg 	{
   1384  1.1  mrg 	  fd = open ("CONOUT$", O_WRONLY);
   1385  1.1  mrg 	  flags->action = ACTION_WRITE;
   1386  1.1  mrg 	  return fd;
   1387  1.1  mrg 	}
   1388  1.1  mrg     }
   1389  1.1  mrg 
   1390  1.1  mrg   if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
   1391  1.1  mrg     {
   1392  1.1  mrg       fd = open ("CONIN$", O_RDONLY);
   1393  1.1  mrg       flags->action = ACTION_READ;
   1394  1.1  mrg       return fd;
   1395  1.1  mrg     }
   1396  1.1  mrg #endif
   1397  1.1  mrg 
   1398  1.1  mrg   switch (flags->action)
   1399  1.1  mrg     {
   1400  1.1  mrg     case ACTION_READ:
   1401  1.1  mrg       rwflag = O_RDONLY;
   1402  1.1  mrg       break;
   1403  1.1  mrg 
   1404  1.1  mrg     case ACTION_WRITE:
   1405  1.1  mrg       rwflag = O_WRONLY;
   1406  1.1  mrg       break;
   1407  1.1  mrg 
   1408  1.1  mrg     case ACTION_READWRITE:
   1409  1.1  mrg     case ACTION_UNSPECIFIED:
   1410  1.1  mrg       rwflag = O_RDWR;
   1411  1.1  mrg       break;
   1412  1.1  mrg 
   1413  1.1  mrg     default:
   1414  1.1  mrg       internal_error (&opp->common, "regular_file(): Bad action");
   1415  1.1  mrg     }
   1416  1.1  mrg 
   1417  1.1  mrg   switch (flags->status)
   1418  1.1  mrg     {
   1419  1.1  mrg     case STATUS_NEW:
   1420  1.1  mrg       crflag = O_CREAT | O_EXCL;
   1421  1.1  mrg       break;
   1422  1.1  mrg 
   1423  1.1  mrg     case STATUS_OLD:		/* open will fail if the file does not exist*/
   1424  1.1  mrg       crflag = 0;
   1425  1.1  mrg       break;
   1426  1.1  mrg 
   1427  1.1  mrg     case STATUS_UNKNOWN:
   1428  1.1  mrg       if (rwflag == O_RDONLY)
   1429  1.1  mrg 	crflag = 0;
   1430  1.1  mrg       else
   1431  1.1  mrg 	crflag = O_CREAT;
   1432  1.1  mrg       break;
   1433  1.1  mrg 
   1434  1.1  mrg     case STATUS_REPLACE:
   1435  1.1  mrg       crflag = O_CREAT | O_TRUNC;
   1436  1.1  mrg       break;
   1437  1.1  mrg 
   1438  1.1  mrg     default:
   1439  1.1  mrg       /* Note: STATUS_SCRATCH is handled by tempfile () and should
   1440  1.1  mrg 	 never be seen here.  */
   1441  1.1  mrg       internal_error (&opp->common, "regular_file(): Bad status");
   1442  1.1  mrg     }
   1443  1.1  mrg 
   1444  1.1  mrg   /* rwflag |= O_LARGEFILE; */
   1445  1.1  mrg 
   1446  1.1  mrg #if defined(HAVE_CRLF) && defined(O_BINARY)
   1447  1.1  mrg   crflag |= O_BINARY;
   1448  1.1  mrg #endif
   1449  1.1  mrg 
   1450  1.1  mrg #ifdef O_CLOEXEC
   1451  1.1  mrg   crflag |= O_CLOEXEC;
   1452  1.1  mrg #endif
   1453  1.1  mrg 
   1454  1.1  mrg   mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
   1455  1.1  mrg   TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag, mode));
   1456  1.1  mrg   if (flags->action != ACTION_UNSPECIFIED)
   1457  1.1  mrg     return fd;
   1458  1.1  mrg 
   1459  1.1  mrg   if (fd >= 0)
   1460  1.1  mrg     {
   1461  1.1  mrg       flags->action = ACTION_READWRITE;
   1462  1.1  mrg       return fd;
   1463  1.1  mrg     }
   1464  1.1  mrg   if (errno != EACCES && errno != EPERM && errno != EROFS)
   1465  1.1  mrg      return fd;
   1466  1.1  mrg 
   1467  1.1  mrg   /* retry for read-only access */
   1468  1.1  mrg   rwflag = O_RDONLY;
   1469  1.1  mrg   if (flags->status == STATUS_UNKNOWN)
   1470  1.1  mrg     crflag2 = crflag & ~(O_CREAT);
   1471  1.1  mrg   else
   1472  1.1  mrg     crflag2 = crflag;
   1473  1.1  mrg   TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag2, mode));
   1474  1.1  mrg   if (fd >=0)
   1475  1.1  mrg     {
   1476  1.1  mrg       flags->action = ACTION_READ;
   1477  1.1  mrg       return fd;		/* success */
   1478  1.1  mrg     }
   1479  1.1  mrg 
   1480  1.1  mrg   if (errno != EACCES && errno != EPERM && errno != ENOENT)
   1481  1.1  mrg     return fd;			/* failure */
   1482  1.1  mrg 
   1483  1.1  mrg   /* retry for write-only access */
   1484  1.1  mrg   rwflag = O_WRONLY;
   1485  1.1  mrg   TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag, mode));
   1486  1.1  mrg   if (fd >=0)
   1487  1.1  mrg     {
   1488  1.1  mrg       flags->action = ACTION_WRITE;
   1489  1.1  mrg       return fd;		/* success */
   1490  1.1  mrg     }
   1491  1.1  mrg   return fd;			/* failure */
   1492  1.1  mrg }
   1493  1.1  mrg 
   1494  1.1  mrg 
   1495  1.1  mrg /* Lock the file, if necessary, based on SHARE flags.  */
   1496  1.1  mrg 
   1497  1.1  mrg #if defined(HAVE_FCNTL) && defined(F_SETLK) && defined(F_UNLCK)
   1498  1.1  mrg static int
   1499  1.1  mrg open_share (st_parameter_open *opp, int fd, unit_flags *flags)
   1500  1.1  mrg {
   1501  1.1  mrg   int r = 0;
   1502  1.1  mrg   struct flock f;
   1503  1.1  mrg   if (fd == STDOUT_FILENO || fd == STDERR_FILENO || fd == STDIN_FILENO)
   1504  1.1  mrg     return 0;
   1505  1.1  mrg 
   1506  1.1  mrg   f.l_start = 0;
   1507  1.1  mrg   f.l_len = 0;
   1508  1.1  mrg   f.l_whence = SEEK_SET;
   1509  1.1  mrg 
   1510  1.1  mrg   switch (flags->share)
   1511  1.1  mrg   {
   1512  1.1  mrg     case SHARE_DENYNONE:
   1513  1.1  mrg       f.l_type = F_RDLCK;
   1514  1.1  mrg       r = fcntl (fd, F_SETLK, &f);
   1515  1.1  mrg       break;
   1516  1.1  mrg     case SHARE_DENYRW:
   1517  1.1  mrg       /* Must be writable to hold write lock.  */
   1518  1.1  mrg       if (flags->action == ACTION_READ)
   1519  1.1  mrg 	{
   1520  1.1  mrg 	  generate_error (&opp->common, LIBERROR_BAD_ACTION,
   1521  1.1  mrg 	      "Cannot set write lock on file opened for READ");
   1522  1.1  mrg 	  return -1;
   1523  1.1  mrg 	}
   1524  1.1  mrg       f.l_type = F_WRLCK;
   1525  1.1  mrg       r = fcntl (fd, F_SETLK, &f);
   1526  1.1  mrg       break;
   1527  1.1  mrg     case SHARE_UNSPECIFIED:
   1528  1.1  mrg     default:
   1529  1.1  mrg       break;
   1530  1.1  mrg   }
   1531  1.1  mrg 
   1532  1.1  mrg   return r;
   1533  1.1  mrg }
   1534  1.1  mrg #else
   1535  1.1  mrg static int
   1536  1.1  mrg open_share (st_parameter_open *opp __attribute__ ((unused)),
   1537  1.1  mrg     int fd __attribute__ ((unused)),
   1538  1.1  mrg     unit_flags *flags __attribute__ ((unused)))
   1539  1.1  mrg {
   1540  1.1  mrg   return 0;
   1541  1.1  mrg }
   1542  1.1  mrg #endif /* defined(HAVE_FCNTL) ... */
   1543  1.1  mrg 
   1544  1.1  mrg 
   1545  1.1  mrg /* Wrapper around regular_file2, to make sure we free the path after
   1546  1.1  mrg    we're done.  */
   1547  1.1  mrg 
   1548  1.1  mrg static int
   1549  1.1  mrg regular_file (st_parameter_open *opp, unit_flags *flags)
   1550  1.1  mrg {
   1551  1.1  mrg   char *path = fc_strdup (opp->file, opp->file_len);
   1552  1.1  mrg   int fd = regular_file2 (path, opp, flags);
   1553  1.1  mrg   free (path);
   1554  1.1  mrg   return fd;
   1555  1.1  mrg }
   1556  1.1  mrg 
   1557  1.1  mrg /* open_external()-- Open an external file, unix specific version.
   1558  1.1  mrg    Change flags->action if it is ACTION_UNSPECIFIED on entry.
   1559  1.1  mrg    Returns NULL on operating system error. */
   1560  1.1  mrg 
   1561  1.1  mrg stream *
   1562  1.1  mrg open_external (st_parameter_open *opp, unit_flags *flags)
   1563  1.1  mrg {
   1564  1.1  mrg   int fd;
   1565  1.1  mrg 
   1566  1.1  mrg   if (flags->status == STATUS_SCRATCH)
   1567  1.1  mrg     {
   1568  1.1  mrg       fd = tempfile (opp);
   1569  1.1  mrg       if (flags->action == ACTION_UNSPECIFIED)
   1570  1.1  mrg 	flags->action = flags->readonly ? ACTION_READ : ACTION_READWRITE;
   1571  1.1  mrg 
   1572  1.1  mrg #if HAVE_UNLINK_OPEN_FILE
   1573  1.1  mrg       /* We can unlink scratch files now and it will go away when closed. */
   1574  1.1  mrg       if (fd >= 0)
   1575  1.1  mrg 	unlink (opp->file);
   1576  1.1  mrg #endif
   1577  1.1  mrg     }
   1578  1.1  mrg   else
   1579  1.1  mrg     {
   1580  1.1  mrg       /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
   1581  1.1  mrg          if it succeeds */
   1582  1.1  mrg       fd = regular_file (opp, flags);
   1583  1.1  mrg #ifndef O_CLOEXEC
   1584  1.1  mrg       set_close_on_exec (fd);
   1585  1.1  mrg #endif
   1586  1.1  mrg     }
   1587  1.1  mrg 
   1588  1.1  mrg   if (fd < 0)
   1589  1.1  mrg     return NULL;
   1590  1.1  mrg   fd = fix_fd (fd);
   1591  1.1  mrg 
   1592  1.1  mrg   if (open_share (opp, fd, flags) < 0)
   1593  1.1  mrg     return NULL;
   1594  1.1  mrg 
   1595  1.1  mrg   return fd_to_stream (fd, flags->form == FORM_UNFORMATTED);
   1596  1.1  mrg }
   1597  1.1  mrg 
   1598  1.1  mrg 
   1599  1.1  mrg /* input_stream()-- Return a stream pointer to the default input stream.
   1600  1.1  mrg    Called on initialization. */
   1601  1.1  mrg 
   1602  1.1  mrg stream *
   1603  1.1  mrg input_stream (void)
   1604  1.1  mrg {
   1605  1.1  mrg   return fd_to_stream (STDIN_FILENO, false);
   1606  1.1  mrg }
   1607  1.1  mrg 
   1608  1.1  mrg 
   1609  1.1  mrg /* output_stream()-- Return a stream pointer to the default output stream.
   1610  1.1  mrg    Called on initialization. */
   1611  1.1  mrg 
   1612  1.1  mrg stream *
   1613  1.1  mrg output_stream (void)
   1614  1.1  mrg {
   1615  1.1  mrg   stream *s;
   1616  1.1  mrg 
   1617  1.1  mrg #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
   1618  1.1  mrg   setmode (STDOUT_FILENO, O_BINARY);
   1619  1.1  mrg #endif
   1620  1.1  mrg 
   1621  1.1  mrg   s = fd_to_stream (STDOUT_FILENO, false);
   1622  1.1  mrg   return s;
   1623  1.1  mrg }
   1624  1.1  mrg 
   1625  1.1  mrg 
   1626  1.1  mrg /* error_stream()-- Return a stream pointer to the default error stream.
   1627  1.1  mrg    Called on initialization. */
   1628  1.1  mrg 
   1629  1.1  mrg stream *
   1630  1.1  mrg error_stream (void)
   1631  1.1  mrg {
   1632  1.1  mrg   stream *s;
   1633  1.1  mrg 
   1634  1.1  mrg #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
   1635  1.1  mrg   setmode (STDERR_FILENO, O_BINARY);
   1636  1.1  mrg #endif
   1637  1.1  mrg 
   1638  1.1  mrg   s = fd_to_stream (STDERR_FILENO, false);
   1639  1.1  mrg   return s;
   1640  1.1  mrg }
   1641  1.1  mrg 
   1642  1.1  mrg 
   1643  1.1  mrg /* compare_file_filename()-- Given an open stream and a fortran string
   1644  1.1  mrg    that is a filename, figure out if the file is the same as the
   1645  1.1  mrg    filename. */
   1646  1.1  mrg 
   1647  1.1  mrg int
   1648  1.1  mrg compare_file_filename (gfc_unit *u, const char *name, gfc_charlen_type len)
   1649  1.1  mrg {
   1650  1.1  mrg   struct stat st;
   1651  1.1  mrg   int ret;
   1652  1.1  mrg #ifdef HAVE_WORKING_STAT
   1653  1.1  mrg   unix_stream *s;
   1654  1.1  mrg #else
   1655  1.1  mrg # ifdef __MINGW32__
   1656  1.1  mrg   uint64_t id1, id2;
   1657  1.1  mrg # endif
   1658  1.1  mrg #endif
   1659  1.1  mrg 
   1660  1.1  mrg   char *path = fc_strdup (name, len);
   1661  1.1  mrg 
   1662  1.1  mrg   /* If the filename doesn't exist, then there is no match with the
   1663  1.1  mrg      existing file. */
   1664  1.1  mrg 
   1665  1.1  mrg   if (TEMP_FAILURE_RETRY (stat (path, &st)) < 0)
   1666  1.1  mrg     {
   1667  1.1  mrg       ret = 0;
   1668  1.1  mrg       goto done;
   1669  1.1  mrg     }
   1670  1.1  mrg 
   1671  1.1  mrg #ifdef HAVE_WORKING_STAT
   1672  1.1  mrg   s = (unix_stream *) (u->s);
   1673  1.1  mrg   ret = (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
   1674  1.1  mrg   goto done;
   1675  1.1  mrg #else
   1676  1.1  mrg 
   1677  1.1  mrg # ifdef __MINGW32__
   1678  1.1  mrg   /* We try to match files by a unique ID.  On some filesystems (network
   1679  1.1  mrg      fs and FAT), we can't generate this unique ID, and will simply compare
   1680  1.1  mrg      filenames.  */
   1681  1.1  mrg   id1 = id_from_path (path);
   1682  1.1  mrg   id2 = id_from_fd (((unix_stream *) (u->s))->fd);
   1683  1.1  mrg   if (id1 || id2)
   1684  1.1  mrg     {
   1685  1.1  mrg       ret = (id1 == id2);
   1686  1.1  mrg       goto done;
   1687  1.1  mrg     }
   1688  1.1  mrg # endif
   1689  1.1  mrg   if (u->filename)
   1690  1.1  mrg     ret = (strcmp(path, u->filename) == 0);
   1691  1.1  mrg   else
   1692  1.1  mrg     ret = 0;
   1693  1.1  mrg #endif
   1694  1.1  mrg  done:
   1695  1.1  mrg   free (path);
   1696  1.1  mrg   return ret;
   1697  1.1  mrg }
   1698  1.1  mrg 
   1699  1.1  mrg 
   1700  1.1  mrg #ifdef HAVE_WORKING_STAT
   1701  1.1  mrg # define FIND_FILE0_DECL struct stat *st
   1702  1.1  mrg # define FIND_FILE0_ARGS st
   1703  1.1  mrg #else
   1704  1.1  mrg # define FIND_FILE0_DECL uint64_t id, const char *path
   1705  1.1  mrg # define FIND_FILE0_ARGS id, path
   1706  1.1  mrg #endif
   1707  1.1  mrg 
   1708  1.1  mrg /* find_file0()-- Recursive work function for find_file() */
   1709  1.1  mrg 
   1710  1.1  mrg static gfc_unit *
   1711  1.1  mrg find_file0 (gfc_unit *u, FIND_FILE0_DECL)
   1712  1.1  mrg {
   1713  1.1  mrg   gfc_unit *v;
   1714  1.1  mrg #if defined(__MINGW32__) && !HAVE_WORKING_STAT
   1715  1.1  mrg   uint64_t id1;
   1716  1.1  mrg #endif
   1717  1.1  mrg 
   1718  1.1  mrg   if (u == NULL)
   1719  1.1  mrg     return NULL;
   1720  1.1  mrg 
   1721  1.1  mrg #ifdef HAVE_WORKING_STAT
   1722  1.1  mrg   if (u->s != NULL)
   1723  1.1  mrg     {
   1724  1.1  mrg       unix_stream *s = (unix_stream *) (u->s);
   1725  1.1  mrg       if (st[0].st_dev == s->st_dev && st[0].st_ino == s->st_ino)
   1726  1.1  mrg 	return u;
   1727  1.1  mrg     }
   1728  1.1  mrg #else
   1729  1.1  mrg # ifdef __MINGW32__
   1730  1.1  mrg   if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
   1731  1.1  mrg     {
   1732  1.1  mrg       if (id == id1)
   1733  1.1  mrg 	return u;
   1734  1.1  mrg     }
   1735  1.1  mrg   else
   1736  1.1  mrg # endif
   1737  1.1  mrg     if (u->filename && strcmp (u->filename, path) == 0)
   1738  1.1  mrg       return u;
   1739  1.1  mrg #endif
   1740  1.1  mrg 
   1741  1.1  mrg   v = find_file0 (u->left, FIND_FILE0_ARGS);
   1742  1.1  mrg   if (v != NULL)
   1743  1.1  mrg     return v;
   1744  1.1  mrg 
   1745  1.1  mrg   v = find_file0 (u->right, FIND_FILE0_ARGS);
   1746  1.1  mrg   if (v != NULL)
   1747  1.1  mrg     return v;
   1748  1.1  mrg 
   1749  1.1  mrg   return NULL;
   1750  1.1  mrg }
   1751  1.1  mrg 
   1752  1.1  mrg 
   1753  1.1  mrg /* find_file()-- Take the current filename and see if there is a unit
   1754  1.1  mrg    that has the file already open.  Returns a pointer to the unit if so. */
   1755  1.1  mrg 
   1756  1.1  mrg gfc_unit *
   1757  1.1  mrg find_file (const char *file, gfc_charlen_type file_len)
   1758  1.1  mrg {
   1759  1.1  mrg   struct stat st[1];
   1760  1.1  mrg   gfc_unit *u;
   1761  1.1  mrg #if defined(__MINGW32__) && !HAVE_WORKING_STAT
   1762  1.1  mrg   uint64_t id = 0ULL;
   1763  1.1  mrg #endif
   1764  1.1  mrg 
   1765  1.1  mrg   char *path = fc_strdup (file, file_len);
   1766  1.1  mrg 
   1767  1.1  mrg   if (TEMP_FAILURE_RETRY (stat (path, &st[0])) < 0)
   1768  1.1  mrg     {
   1769  1.1  mrg       u = NULL;
   1770  1.1  mrg       goto done;
   1771  1.1  mrg     }
   1772  1.1  mrg 
   1773  1.1  mrg #if defined(__MINGW32__) && !HAVE_WORKING_STAT
   1774  1.1  mrg   id = id_from_path (path);
   1775  1.1  mrg #endif
   1776  1.1  mrg 
   1777  1.1  mrg   LOCK (&unit_lock);
   1778  1.1  mrg retry:
   1779  1.1  mrg   u = find_file0 (unit_root, FIND_FILE0_ARGS);
   1780  1.1  mrg   if (u != NULL)
   1781  1.1  mrg     {
   1782  1.1  mrg       /* Fast path.  */
   1783  1.1  mrg       if (! __gthread_mutex_trylock (&u->lock))
   1784  1.1  mrg 	{
   1785  1.1  mrg 	  /* assert (u->closed == 0); */
   1786  1.1  mrg 	  UNLOCK (&unit_lock);
   1787  1.1  mrg 	  goto done;
   1788  1.1  mrg 	}
   1789  1.1  mrg 
   1790  1.1  mrg       inc_waiting_locked (u);
   1791  1.1  mrg     }
   1792  1.1  mrg   UNLOCK (&unit_lock);
   1793  1.1  mrg   if (u != NULL)
   1794  1.1  mrg     {
   1795  1.1  mrg       LOCK (&u->lock);
   1796  1.1  mrg       if (u->closed)
   1797  1.1  mrg 	{
   1798  1.1  mrg 	  LOCK (&unit_lock);
   1799  1.1  mrg 	  UNLOCK (&u->lock);
   1800  1.1  mrg 	  if (predec_waiting_locked (u) == 0)
   1801  1.1  mrg 	    free (u);
   1802  1.1  mrg 	  goto retry;
   1803  1.1  mrg 	}
   1804  1.1  mrg 
   1805  1.1  mrg       dec_waiting_unlocked (u);
   1806  1.1  mrg     }
   1807  1.1  mrg  done:
   1808  1.1  mrg   free (path);
   1809  1.1  mrg   return u;
   1810  1.1  mrg }
   1811  1.1  mrg 
   1812  1.1  mrg static gfc_unit *
   1813  1.1  mrg flush_all_units_1 (gfc_unit *u, int min_unit)
   1814  1.1  mrg {
   1815  1.1  mrg   while (u != NULL)
   1816  1.1  mrg     {
   1817  1.1  mrg       if (u->unit_number > min_unit)
   1818  1.1  mrg 	{
   1819  1.1  mrg 	  gfc_unit *r = flush_all_units_1 (u->left, min_unit);
   1820  1.1  mrg 	  if (r != NULL)
   1821  1.1  mrg 	    return r;
   1822  1.1  mrg 	}
   1823  1.1  mrg       if (u->unit_number >= min_unit)
   1824  1.1  mrg 	{
   1825  1.1  mrg 	  if (__gthread_mutex_trylock (&u->lock))
   1826  1.1  mrg 	    return u;
   1827  1.1  mrg 	  if (u->s)
   1828  1.1  mrg 	    sflush (u->s);
   1829  1.1  mrg 	  UNLOCK (&u->lock);
   1830  1.1  mrg 	}
   1831  1.1  mrg       u = u->right;
   1832  1.1  mrg     }
   1833  1.1  mrg   return NULL;
   1834  1.1  mrg }
   1835  1.1  mrg 
   1836  1.1  mrg void
   1837  1.1  mrg flush_all_units (void)
   1838  1.1  mrg {
   1839  1.1  mrg   gfc_unit *u;
   1840  1.1  mrg   int min_unit = 0;
   1841  1.1  mrg 
   1842  1.1  mrg   LOCK (&unit_lock);
   1843  1.1  mrg   do
   1844  1.1  mrg     {
   1845  1.1  mrg       u = flush_all_units_1 (unit_root, min_unit);
   1846  1.1  mrg       if (u != NULL)
   1847  1.1  mrg 	inc_waiting_locked (u);
   1848  1.1  mrg       UNLOCK (&unit_lock);
   1849  1.1  mrg       if (u == NULL)
   1850  1.1  mrg 	return;
   1851  1.1  mrg 
   1852  1.1  mrg       LOCK (&u->lock);
   1853  1.1  mrg 
   1854  1.1  mrg       min_unit = u->unit_number + 1;
   1855  1.1  mrg 
   1856  1.1  mrg       if (u->closed == 0)
   1857  1.1  mrg 	{
   1858  1.1  mrg 	  sflush (u->s);
   1859  1.1  mrg 	  LOCK (&unit_lock);
   1860  1.1  mrg 	  UNLOCK (&u->lock);
   1861  1.1  mrg 	  (void) predec_waiting_locked (u);
   1862  1.1  mrg 	}
   1863  1.1  mrg       else
   1864  1.1  mrg 	{
   1865  1.1  mrg 	  LOCK (&unit_lock);
   1866  1.1  mrg 	  UNLOCK (&u->lock);
   1867  1.1  mrg 	  if (predec_waiting_locked (u) == 0)
   1868  1.1  mrg 	    free (u);
   1869  1.1  mrg 	}
   1870  1.1  mrg     }
   1871  1.1  mrg   while (1);
   1872  1.1  mrg }
   1873  1.1  mrg 
   1874  1.1  mrg 
   1875  1.1  mrg /* Unlock the unit if necessary, based on SHARE flags.  */
   1876  1.1  mrg 
   1877  1.1  mrg int
   1878  1.1  mrg close_share (gfc_unit *u __attribute__ ((unused)))
   1879  1.1  mrg {
   1880  1.1  mrg   int r = 0;
   1881  1.1  mrg #if defined(HAVE_FCNTL) && defined(F_SETLK) && defined(F_UNLCK)
   1882  1.1  mrg   unix_stream *s = (unix_stream *) u->s;
   1883  1.1  mrg   int fd = s->fd;
   1884  1.1  mrg   struct flock f;
   1885  1.1  mrg 
   1886  1.1  mrg   switch (u->flags.share)
   1887  1.1  mrg   {
   1888  1.1  mrg     case SHARE_DENYRW:
   1889  1.1  mrg     case SHARE_DENYNONE:
   1890  1.1  mrg       if (fd != STDOUT_FILENO && fd != STDERR_FILENO && fd != STDIN_FILENO)
   1891  1.1  mrg 	{
   1892  1.1  mrg 	  f.l_start = 0;
   1893  1.1  mrg 	  f.l_len = 0;
   1894  1.1  mrg 	  f.l_whence = SEEK_SET;
   1895  1.1  mrg 	  f.l_type = F_UNLCK;
   1896  1.1  mrg 	  r = fcntl (fd, F_SETLK, &f);
   1897  1.1  mrg 	}
   1898  1.1  mrg       break;
   1899  1.1  mrg     case SHARE_UNSPECIFIED:
   1900  1.1  mrg     default:
   1901  1.1  mrg       break;
   1902  1.1  mrg   }
   1903  1.1  mrg 
   1904  1.1  mrg #endif
   1905  1.1  mrg   return r;
   1906  1.1  mrg }
   1907  1.1  mrg 
   1908  1.1  mrg 
   1909  1.1  mrg /* file_exists()-- Returns nonzero if the current filename exists on
   1910  1.1  mrg    the system */
   1911  1.1  mrg 
   1912  1.1  mrg int
   1913  1.1  mrg file_exists (const char *file, gfc_charlen_type file_len)
   1914  1.1  mrg {
   1915  1.1  mrg   char *path = fc_strdup (file, file_len);
   1916  1.1  mrg   int res = !(access (path, F_OK));
   1917  1.1  mrg   free (path);
   1918  1.1  mrg   return res;
   1919  1.1  mrg }
   1920  1.1  mrg 
   1921  1.1  mrg 
   1922  1.1  mrg /* file_size()-- Returns the size of the file.  */
   1923  1.1  mrg 
   1924  1.1  mrg GFC_IO_INT
   1925  1.1  mrg file_size (const char *file, gfc_charlen_type file_len)
   1926  1.1  mrg {
   1927  1.1  mrg   char *path = fc_strdup (file, file_len);
   1928  1.1  mrg   struct stat statbuf;
   1929  1.1  mrg   int err;
   1930  1.1  mrg   TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
   1931  1.1  mrg   free (path);
   1932  1.1  mrg   if (err == -1)
   1933  1.1  mrg     return -1;
   1934  1.1  mrg   return (GFC_IO_INT) statbuf.st_size;
   1935  1.1  mrg }
   1936  1.1  mrg 
   1937  1.1  mrg static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
   1938  1.1  mrg 
   1939  1.1  mrg /* inquire_sequential()-- Given a fortran string, determine if the
   1940  1.1  mrg    file is suitable for sequential access.  Returns a C-style
   1941  1.1  mrg    string. */
   1942  1.1  mrg 
   1943  1.1  mrg const char *
   1944  1.1  mrg inquire_sequential (const char *string, gfc_charlen_type len)
   1945  1.1  mrg {
   1946  1.1  mrg   struct stat statbuf;
   1947  1.1  mrg 
   1948  1.1  mrg   if (string == NULL)
   1949  1.1  mrg     return unknown;
   1950  1.1  mrg 
   1951  1.1  mrg   char *path = fc_strdup (string, len);
   1952  1.1  mrg   int err;
   1953  1.1  mrg   TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
   1954  1.1  mrg   free (path);
   1955  1.1  mrg   if (err == -1)
   1956  1.1  mrg     return unknown;
   1957  1.1  mrg 
   1958  1.1  mrg   if (S_ISREG (statbuf.st_mode) ||
   1959  1.1  mrg       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
   1960  1.1  mrg     return unknown;
   1961  1.1  mrg 
   1962  1.1  mrg   if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
   1963  1.1  mrg     return no;
   1964  1.1  mrg 
   1965  1.1  mrg   return unknown;
   1966  1.1  mrg }
   1967  1.1  mrg 
   1968  1.1  mrg 
   1969  1.1  mrg /* inquire_direct()-- Given a fortran string, determine if the file is
   1970  1.1  mrg    suitable for direct access.  Returns a C-style string. */
   1971  1.1  mrg 
   1972  1.1  mrg const char *
   1973  1.1  mrg inquire_direct (const char *string, gfc_charlen_type len)
   1974  1.1  mrg {
   1975  1.1  mrg   struct stat statbuf;
   1976  1.1  mrg 
   1977  1.1  mrg   if (string == NULL)
   1978  1.1  mrg     return unknown;
   1979  1.1  mrg 
   1980  1.1  mrg   char *path = fc_strdup (string, len);
   1981  1.1  mrg   int err;
   1982  1.1  mrg   TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
   1983  1.1  mrg   free (path);
   1984  1.1  mrg   if (err == -1)
   1985  1.1  mrg     return unknown;
   1986  1.1  mrg 
   1987  1.1  mrg   if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
   1988  1.1  mrg     return unknown;
   1989  1.1  mrg 
   1990  1.1  mrg   if (S_ISDIR (statbuf.st_mode) ||
   1991  1.1  mrg       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
   1992  1.1  mrg     return no;
   1993  1.1  mrg 
   1994  1.1  mrg   return unknown;
   1995  1.1  mrg }
   1996  1.1  mrg 
   1997  1.1  mrg 
   1998  1.1  mrg /* inquire_formatted()-- Given a fortran string, determine if the file
   1999  1.1  mrg    is suitable for formatted form.  Returns a C-style string. */
   2000  1.1  mrg 
   2001  1.1  mrg const char *
   2002  1.1  mrg inquire_formatted (const char *string, gfc_charlen_type len)
   2003  1.1  mrg {
   2004  1.1  mrg   struct stat statbuf;
   2005  1.1  mrg 
   2006  1.1  mrg   if (string == NULL)
   2007  1.1  mrg     return unknown;
   2008  1.1  mrg 
   2009  1.1  mrg   char *path = fc_strdup (string, len);
   2010  1.1  mrg   int err;
   2011  1.1  mrg   TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
   2012  1.1  mrg   free (path);
   2013  1.1  mrg   if (err == -1)
   2014  1.1  mrg     return unknown;
   2015  1.1  mrg 
   2016  1.1  mrg   if (S_ISREG (statbuf.st_mode) ||
   2017  1.1  mrg       S_ISBLK (statbuf.st_mode) ||
   2018  1.1  mrg       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
   2019  1.1  mrg     return unknown;
   2020  1.1  mrg 
   2021  1.1  mrg   if (S_ISDIR (statbuf.st_mode))
   2022  1.1  mrg     return no;
   2023  1.1  mrg 
   2024  1.1  mrg   return unknown;
   2025  1.1  mrg }
   2026  1.1  mrg 
   2027  1.1  mrg 
   2028  1.1  mrg /* inquire_unformatted()-- Given a fortran string, determine if the file
   2029  1.1  mrg    is suitable for unformatted form.  Returns a C-style string. */
   2030  1.1  mrg 
   2031  1.1  mrg const char *
   2032  1.1  mrg inquire_unformatted (const char *string, gfc_charlen_type len)
   2033  1.1  mrg {
   2034  1.1  mrg   return inquire_formatted (string, len);
   2035  1.1  mrg }
   2036  1.1  mrg 
   2037  1.1  mrg 
   2038  1.1  mrg /* inquire_access()-- Given a fortran string, determine if the file is
   2039  1.1  mrg    suitable for access. */
   2040  1.1  mrg 
   2041  1.1  mrg static const char *
   2042  1.1  mrg inquire_access (const char *string, gfc_charlen_type len, int mode)
   2043  1.1  mrg {
   2044  1.1  mrg   if (string == NULL)
   2045  1.1  mrg     return no;
   2046  1.1  mrg   char *path = fc_strdup (string, len);
   2047  1.1  mrg   int res = access (path, mode);
   2048  1.1  mrg   free (path);
   2049  1.1  mrg   if (res == -1)
   2050  1.1  mrg     return no;
   2051  1.1  mrg 
   2052  1.1  mrg   return yes;
   2053  1.1  mrg }
   2054  1.1  mrg 
   2055  1.1  mrg 
   2056  1.1  mrg /* inquire_read()-- Given a fortran string, determine if the file is
   2057  1.1  mrg    suitable for READ access. */
   2058  1.1  mrg 
   2059  1.1  mrg const char *
   2060  1.1  mrg inquire_read (const char *string, gfc_charlen_type len)
   2061  1.1  mrg {
   2062  1.1  mrg   return inquire_access (string, len, R_OK);
   2063  1.1  mrg }
   2064  1.1  mrg 
   2065  1.1  mrg 
   2066  1.1  mrg /* inquire_write()-- Given a fortran string, determine if the file is
   2067  1.1  mrg    suitable for READ access. */
   2068  1.1  mrg 
   2069  1.1  mrg const char *
   2070  1.1  mrg inquire_write (const char *string, gfc_charlen_type len)
   2071  1.1  mrg {
   2072  1.1  mrg   return inquire_access (string, len, W_OK);
   2073  1.1  mrg }
   2074  1.1  mrg 
   2075  1.1  mrg 
   2076  1.1  mrg /* inquire_readwrite()-- Given a fortran string, determine if the file is
   2077  1.1  mrg    suitable for read and write access. */
   2078  1.1  mrg 
   2079  1.1  mrg const char *
   2080  1.1  mrg inquire_readwrite (const char *string, gfc_charlen_type len)
   2081  1.1  mrg {
   2082  1.1  mrg   return inquire_access (string, len, R_OK | W_OK);
   2083  1.1  mrg }
   2084  1.1  mrg 
   2085  1.1  mrg 
   2086  1.1  mrg int
   2087  1.1  mrg stream_isatty (stream *s)
   2088  1.1  mrg {
   2089  1.1  mrg   return isatty (((unix_stream *) s)->fd);
   2090  1.1  mrg }
   2091  1.1  mrg 
   2092  1.1  mrg int
   2093  1.1  mrg stream_ttyname (stream *s  __attribute__ ((unused)),
   2094  1.1  mrg 		char *buf  __attribute__ ((unused)),
   2095  1.1  mrg 		size_t buflen  __attribute__ ((unused)))
   2096  1.1  mrg {
   2097  1.1  mrg #ifdef HAVE_TTYNAME_R
   2098  1.1  mrg   return ttyname_r (((unix_stream *)s)->fd, buf, buflen);
   2099  1.1  mrg #elif defined HAVE_TTYNAME
   2100  1.1  mrg   char *p;
   2101  1.1  mrg   size_t plen;
   2102  1.1  mrg   p = ttyname (((unix_stream *)s)->fd);
   2103  1.1  mrg   if (!p)
   2104  1.1  mrg     return errno;
   2105  1.1  mrg   plen = strlen (p);
   2106  1.1  mrg   if (buflen < plen)
   2107  1.1  mrg     plen = buflen;
   2108  1.1  mrg   memcpy (buf, p, plen);
   2109  1.1  mrg   return 0;
   2110  1.1  mrg #else
   2111  1.1  mrg   return ENOSYS;
   2112  1.1  mrg #endif
   2113  1.1  mrg }
   2114  1.1  mrg 
   2115  1.1  mrg 
   2116  1.1  mrg 
   2117  1.1  mrg 
   2118  1.1  mrg /* How files are stored:  This is an operating-system specific issue,
   2119  1.1  mrg    and therefore belongs here.  There are three cases to consider.
   2120  1.1  mrg 
   2121  1.1  mrg    Direct Access:
   2122  1.1  mrg       Records are written as block of bytes corresponding to the record
   2123  1.1  mrg       length of the file.  This goes for both formatted and unformatted
   2124  1.1  mrg       records.  Positioning is done explicitly for each data transfer,
   2125  1.1  mrg       so positioning is not much of an issue.
   2126  1.1  mrg 
   2127  1.1  mrg    Sequential Formatted:
   2128  1.1  mrg       Records are separated by newline characters.  The newline character
   2129  1.1  mrg       is prohibited from appearing in a string.  If it does, this will be
   2130  1.1  mrg       messed up on the next read.  End of file is also the end of a record.
   2131  1.1  mrg 
   2132  1.1  mrg    Sequential Unformatted:
   2133  1.1  mrg       In this case, we are merely copying bytes to and from main storage,
   2134  1.1  mrg       yet we need to keep track of varying record lengths.  We adopt
   2135  1.1  mrg       the solution used by f2c.  Each record contains a pair of length
   2136  1.1  mrg       markers:
   2137  1.1  mrg 
   2138  1.1  mrg 	Length of record n in bytes
   2139  1.1  mrg 	Data of record n
   2140  1.1  mrg 	Length of record n in bytes
   2141  1.1  mrg 
   2142  1.1  mrg 	Length of record n+1 in bytes
   2143  1.1  mrg 	Data of record n+1
   2144  1.1  mrg 	Length of record n+1 in bytes
   2145  1.1  mrg 
   2146  1.1  mrg      The length is stored at the end of a record to allow backspacing to the
   2147  1.1  mrg      previous record.  Between data transfer statements, the file pointer
   2148  1.1  mrg      is left pointing to the first length of the current record.
   2149  1.1  mrg 
   2150  1.1  mrg      ENDFILE records are never explicitly stored.
   2151  1.1  mrg 
   2152  1.1  mrg */
   2153