Home | History | Annotate | Line # | Download | only in io
unix.c revision 1.1.1.4
      1  1.1.1.4  mrg /* Copyright (C) 2002-2024 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.1.4  mrg   free (s);
   1032      1.1  mrg   return 0;
   1033      1.1  mrg }
   1034      1.1  mrg 
   1035      1.1  mrg static const struct stream_vtable mem_vtable = {
   1036      1.1  mrg   .read = (void *) mem_read,
   1037      1.1  mrg   .write = (void *) mem_write,
   1038      1.1  mrg   .seek = (void *) mem_seek,
   1039      1.1  mrg   .tell = (void *) mem_tell,
   1040      1.1  mrg   /* buf_size is not a typo, we just reuse an identical
   1041      1.1  mrg      implementation.  */
   1042      1.1  mrg   .size = (void *) buf_size,
   1043      1.1  mrg   .trunc = (void *) mem_truncate,
   1044      1.1  mrg   .close = (void *) mem_close,
   1045      1.1  mrg   .flush = (void *) mem_flush,
   1046      1.1  mrg   .markeor = (void *) raw_markeor
   1047      1.1  mrg };
   1048      1.1  mrg 
   1049      1.1  mrg static const struct stream_vtable mem4_vtable = {
   1050      1.1  mrg   .read = (void *) mem_read4,
   1051      1.1  mrg   .write = (void *) mem_write4,
   1052      1.1  mrg   .seek = (void *) mem_seek,
   1053      1.1  mrg   .tell = (void *) mem_tell,
   1054      1.1  mrg   /* buf_size is not a typo, we just reuse an identical
   1055      1.1  mrg      implementation.  */
   1056      1.1  mrg   .size = (void *) buf_size,
   1057      1.1  mrg   .trunc = (void *) mem_truncate,
   1058      1.1  mrg   .close = (void *) mem_close,
   1059      1.1  mrg   .flush = (void *) mem_flush,
   1060      1.1  mrg   .markeor = (void *) raw_markeor
   1061      1.1  mrg };
   1062      1.1  mrg 
   1063      1.1  mrg /*********************************************************************
   1064      1.1  mrg   Public functions -- A reimplementation of this module needs to
   1065      1.1  mrg   define functional equivalents of the following.
   1066      1.1  mrg *********************************************************************/
   1067      1.1  mrg 
   1068      1.1  mrg /* open_internal()-- Returns a stream structure from a character(kind=1)
   1069      1.1  mrg    internal file */
   1070      1.1  mrg 
   1071      1.1  mrg stream *
   1072      1.1  mrg open_internal (char *base, size_t length, gfc_offset offset)
   1073      1.1  mrg {
   1074      1.1  mrg   unix_stream *s;
   1075      1.1  mrg 
   1076      1.1  mrg   s = xcalloc (1, sizeof (unix_stream));
   1077      1.1  mrg 
   1078      1.1  mrg   s->buffer = base;
   1079      1.1  mrg   s->buffer_offset = offset;
   1080      1.1  mrg 
   1081      1.1  mrg   s->active = s->file_length = length;
   1082      1.1  mrg 
   1083      1.1  mrg   s->st.vptr = &mem_vtable;
   1084      1.1  mrg 
   1085      1.1  mrg   return (stream *) s;
   1086      1.1  mrg }
   1087      1.1  mrg 
   1088      1.1  mrg /* open_internal4()-- Returns a stream structure from a character(kind=4)
   1089      1.1  mrg    internal file */
   1090      1.1  mrg 
   1091      1.1  mrg stream *
   1092      1.1  mrg open_internal4 (char *base, size_t length, gfc_offset offset)
   1093      1.1  mrg {
   1094      1.1  mrg   unix_stream *s;
   1095      1.1  mrg 
   1096      1.1  mrg   s = xcalloc (1, sizeof (unix_stream));
   1097      1.1  mrg 
   1098      1.1  mrg   s->buffer = base;
   1099      1.1  mrg   s->buffer_offset = offset;
   1100      1.1  mrg 
   1101      1.1  mrg   s->active = s->file_length = length * sizeof (gfc_char4_t);
   1102      1.1  mrg 
   1103      1.1  mrg   s->st.vptr = &mem4_vtable;
   1104      1.1  mrg 
   1105      1.1  mrg   return (stream *)s;
   1106      1.1  mrg }
   1107      1.1  mrg 
   1108      1.1  mrg 
   1109      1.1  mrg /* fd_to_stream()-- Given an open file descriptor, build a stream
   1110      1.1  mrg    around it. */
   1111      1.1  mrg 
   1112      1.1  mrg static stream *
   1113      1.1  mrg fd_to_stream (int fd, bool unformatted)
   1114      1.1  mrg {
   1115      1.1  mrg   struct stat statbuf;
   1116      1.1  mrg   unix_stream *s;
   1117      1.1  mrg 
   1118      1.1  mrg   s = xcalloc (1, sizeof (unix_stream));
   1119      1.1  mrg 
   1120      1.1  mrg   s->fd = fd;
   1121      1.1  mrg 
   1122      1.1  mrg   /* Get the current length of the file. */
   1123      1.1  mrg 
   1124      1.1  mrg   if (TEMP_FAILURE_RETRY (fstat (fd, &statbuf)) == -1)
   1125      1.1  mrg     {
   1126      1.1  mrg       s->st_dev = s->st_ino = -1;
   1127      1.1  mrg       s->file_length = 0;
   1128      1.1  mrg       if (errno == EBADF)
   1129      1.1  mrg 	s->fd = -1;
   1130      1.1  mrg       raw_init (s);
   1131      1.1  mrg       return (stream *) s;
   1132      1.1  mrg     }
   1133      1.1  mrg 
   1134      1.1  mrg   s->st_dev = statbuf.st_dev;
   1135      1.1  mrg   s->st_ino = statbuf.st_ino;
   1136      1.1  mrg   s->file_length = statbuf.st_size;
   1137      1.1  mrg 
   1138      1.1  mrg   /* Only use buffered IO for regular files.  */
   1139      1.1  mrg   if (S_ISREG (statbuf.st_mode)
   1140      1.1  mrg       && !options.all_unbuffered
   1141      1.1  mrg       && !(options.unbuffered_preconnected &&
   1142      1.1  mrg 	   (s->fd == STDIN_FILENO
   1143      1.1  mrg 	    || s->fd == STDOUT_FILENO
   1144      1.1  mrg 	    || s->fd == STDERR_FILENO)))
   1145      1.1  mrg     buf_init (s, unformatted);
   1146      1.1  mrg   else
   1147      1.1  mrg     {
   1148      1.1  mrg       if (unformatted)
   1149      1.1  mrg 	{
   1150      1.1  mrg 	  s->unbuffered = true;
   1151      1.1  mrg 	  buf_init (s, unformatted);
   1152      1.1  mrg 	}
   1153      1.1  mrg       else
   1154      1.1  mrg 	raw_init (s);
   1155      1.1  mrg     }
   1156      1.1  mrg 
   1157      1.1  mrg   return (stream *) s;
   1158      1.1  mrg }
   1159      1.1  mrg 
   1160      1.1  mrg 
   1161      1.1  mrg /* Given the Fortran unit number, convert it to a C file descriptor.  */
   1162      1.1  mrg 
   1163      1.1  mrg int
   1164      1.1  mrg unit_to_fd (int unit)
   1165      1.1  mrg {
   1166      1.1  mrg   gfc_unit *us;
   1167      1.1  mrg   int fd;
   1168      1.1  mrg 
   1169      1.1  mrg   us = find_unit (unit);
   1170      1.1  mrg   if (us == NULL)
   1171      1.1  mrg     return -1;
   1172      1.1  mrg 
   1173      1.1  mrg   fd = ((unix_stream *) us->s)->fd;
   1174      1.1  mrg   unlock_unit (us);
   1175      1.1  mrg   return fd;
   1176      1.1  mrg }
   1177      1.1  mrg 
   1178      1.1  mrg 
   1179      1.1  mrg /* Set the close-on-exec flag for an existing fd, if the system
   1180      1.1  mrg    supports such.  */
   1181      1.1  mrg 
   1182      1.1  mrg static void __attribute__ ((unused))
   1183      1.1  mrg set_close_on_exec (int fd __attribute__ ((unused)))
   1184      1.1  mrg {
   1185      1.1  mrg   /* Mingw does not define F_SETFD.  */
   1186      1.1  mrg #if defined(HAVE_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC)
   1187      1.1  mrg   if (fd >= 0)
   1188      1.1  mrg     fcntl(fd, F_SETFD, FD_CLOEXEC);
   1189      1.1  mrg #endif
   1190      1.1  mrg }
   1191      1.1  mrg 
   1192      1.1  mrg 
   1193      1.1  mrg /* Helper function for tempfile(). Tries to open a temporary file in
   1194      1.1  mrg    the directory specified by tempdir. If successful, the file name is
   1195      1.1  mrg    stored in fname and the descriptor returned. Returns -1 on
   1196      1.1  mrg    failure.  */
   1197      1.1  mrg 
   1198      1.1  mrg static int
   1199      1.1  mrg tempfile_open (const char *tempdir, char **fname)
   1200      1.1  mrg {
   1201      1.1  mrg   int fd;
   1202      1.1  mrg   const char *slash = "/";
   1203      1.1  mrg #if defined(HAVE_UMASK) && defined(HAVE_MKSTEMP)
   1204      1.1  mrg   mode_t mode_mask;
   1205      1.1  mrg #endif
   1206      1.1  mrg 
   1207      1.1  mrg   if (!tempdir)
   1208      1.1  mrg     return -1;
   1209      1.1  mrg 
   1210      1.1  mrg   /* Check for the special case that tempdir ends with a slash or
   1211      1.1  mrg      backslash.  */
   1212      1.1  mrg   size_t tempdirlen = strlen (tempdir);
   1213      1.1  mrg   if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/'
   1214      1.1  mrg #ifdef __MINGW32__
   1215      1.1  mrg       || tempdir[tempdirlen - 1] == '\\'
   1216      1.1  mrg #endif
   1217      1.1  mrg      )
   1218      1.1  mrg     slash = "";
   1219      1.1  mrg 
   1220      1.1  mrg   /* Take care that the template is longer in the mktemp() branch.  */
   1221      1.1  mrg   char *template = xmalloc (tempdirlen + 23);
   1222      1.1  mrg 
   1223      1.1  mrg #ifdef HAVE_MKSTEMP
   1224      1.1  mrg   snprintf (template, tempdirlen + 23, "%s%sgfortrantmpXXXXXX",
   1225      1.1  mrg 	    tempdir, slash);
   1226      1.1  mrg 
   1227      1.1  mrg #ifdef HAVE_UMASK
   1228      1.1  mrg   /* Temporarily set the umask such that the file has 0600 permissions.  */
   1229      1.1  mrg   mode_mask = umask (S_IXUSR | S_IRWXG | S_IRWXO);
   1230      1.1  mrg #endif
   1231      1.1  mrg 
   1232      1.1  mrg #if defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
   1233      1.1  mrg   TEMP_FAILURE_RETRY (fd = mkostemp (template, O_CLOEXEC));
   1234      1.1  mrg #else
   1235      1.1  mrg   TEMP_FAILURE_RETRY (fd = mkstemp (template));
   1236      1.1  mrg   set_close_on_exec (fd);
   1237      1.1  mrg #endif
   1238      1.1  mrg 
   1239      1.1  mrg #ifdef HAVE_UMASK
   1240      1.1  mrg   (void) umask (mode_mask);
   1241      1.1  mrg #endif
   1242      1.1  mrg 
   1243      1.1  mrg #else /* HAVE_MKSTEMP */
   1244      1.1  mrg   fd = -1;
   1245      1.1  mrg   int count = 0;
   1246      1.1  mrg   size_t slashlen = strlen (slash);
   1247      1.1  mrg   int flags = O_RDWR | O_CREAT | O_EXCL;
   1248      1.1  mrg #if defined(HAVE_CRLF) && defined(O_BINARY)
   1249      1.1  mrg   flags |= O_BINARY;
   1250      1.1  mrg #endif
   1251      1.1  mrg #ifdef O_CLOEXEC
   1252      1.1  mrg   flags |= O_CLOEXEC;
   1253      1.1  mrg #endif
   1254      1.1  mrg   do
   1255      1.1  mrg     {
   1256      1.1  mrg       snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX",
   1257      1.1  mrg 		tempdir, slash);
   1258      1.1  mrg       if (count > 0)
   1259      1.1  mrg 	{
   1260      1.1  mrg 	  int c = count;
   1261      1.1  mrg 	  template[tempdirlen + slashlen + 13] = 'a' + (c% 26);
   1262      1.1  mrg 	  c /= 26;
   1263      1.1  mrg 	  template[tempdirlen + slashlen + 12] = 'a' + (c % 26);
   1264      1.1  mrg 	  c /= 26;
   1265      1.1  mrg 	  template[tempdirlen + slashlen + 11] = 'a' + (c % 26);
   1266      1.1  mrg 	  if (c >= 26)
   1267      1.1  mrg 	    break;
   1268      1.1  mrg 	}
   1269      1.1  mrg 
   1270      1.1  mrg       if (!mktemp (template))
   1271      1.1  mrg       {
   1272      1.1  mrg 	errno = EEXIST;
   1273      1.1  mrg 	count++;
   1274      1.1  mrg 	continue;
   1275      1.1  mrg       }
   1276      1.1  mrg 
   1277      1.1  mrg       TEMP_FAILURE_RETRY (fd = open (template, flags, S_IRUSR | S_IWUSR));
   1278      1.1  mrg     }
   1279      1.1  mrg   while (fd == -1 && errno == EEXIST);
   1280      1.1  mrg #ifndef O_CLOEXEC
   1281      1.1  mrg   set_close_on_exec (fd);
   1282      1.1  mrg #endif
   1283      1.1  mrg #endif /* HAVE_MKSTEMP */
   1284      1.1  mrg 
   1285      1.1  mrg   *fname = template;
   1286      1.1  mrg   return fd;
   1287      1.1  mrg }
   1288      1.1  mrg 
   1289      1.1  mrg 
   1290      1.1  mrg /* tempfile()-- Generate a temporary filename for a scratch file and
   1291      1.1  mrg    open it.  mkstemp() opens the file for reading and writing, but the
   1292      1.1  mrg    library mode prevents anything that is not allowed.  The descriptor
   1293      1.1  mrg    is returned, which is -1 on error.  The template is pointed to by
   1294      1.1  mrg    opp->file, which is copied into the unit structure
   1295      1.1  mrg    and freed later. */
   1296      1.1  mrg 
   1297      1.1  mrg static int
   1298      1.1  mrg tempfile (st_parameter_open *opp)
   1299      1.1  mrg {
   1300      1.1  mrg   const char *tempdir;
   1301      1.1  mrg   char *fname;
   1302      1.1  mrg   int fd = -1;
   1303      1.1  mrg 
   1304      1.1  mrg   tempdir = secure_getenv ("TMPDIR");
   1305      1.1  mrg   fd = tempfile_open (tempdir, &fname);
   1306      1.1  mrg #ifdef __MINGW32__
   1307      1.1  mrg   if (fd == -1)
   1308      1.1  mrg     {
   1309      1.1  mrg       char buffer[MAX_PATH + 1];
   1310      1.1  mrg       DWORD ret;
   1311      1.1  mrg       ret = GetTempPath (MAX_PATH, buffer);
   1312      1.1  mrg       /* If we are not able to get a temp-directory, we use
   1313      1.1  mrg 	 current directory.  */
   1314      1.1  mrg       if (ret > MAX_PATH || !ret)
   1315      1.1  mrg         buffer[0] = 0;
   1316      1.1  mrg       else
   1317      1.1  mrg         buffer[ret] = 0;
   1318      1.1  mrg       tempdir = strdup (buffer);
   1319      1.1  mrg       fd = tempfile_open (tempdir, &fname);
   1320      1.1  mrg     }
   1321      1.1  mrg #elif defined(__CYGWIN__)
   1322      1.1  mrg   if (fd == -1)
   1323      1.1  mrg     {
   1324      1.1  mrg       tempdir = secure_getenv ("TMP");
   1325      1.1  mrg       fd = tempfile_open (tempdir, &fname);
   1326      1.1  mrg     }
   1327      1.1  mrg   if (fd == -1)
   1328      1.1  mrg     {
   1329      1.1  mrg       tempdir = secure_getenv ("TEMP");
   1330      1.1  mrg       fd = tempfile_open (tempdir, &fname);
   1331      1.1  mrg     }
   1332      1.1  mrg #endif
   1333      1.1  mrg   if (fd == -1)
   1334      1.1  mrg     fd = tempfile_open (P_tmpdir, &fname);
   1335      1.1  mrg 
   1336      1.1  mrg   opp->file = fname;
   1337      1.1  mrg   opp->file_len = strlen (fname);	/* Don't include trailing nul */
   1338      1.1  mrg 
   1339      1.1  mrg   return fd;
   1340      1.1  mrg }
   1341      1.1  mrg 
   1342      1.1  mrg 
   1343      1.1  mrg /* regular_file2()-- Open a regular file.
   1344      1.1  mrg    Change flags->action if it is ACTION_UNSPECIFIED on entry,
   1345      1.1  mrg    unless an error occurs.
   1346      1.1  mrg    Returns the descriptor, which is less than zero on error. */
   1347      1.1  mrg 
   1348      1.1  mrg static int
   1349      1.1  mrg regular_file2 (const char *path, st_parameter_open *opp, unit_flags *flags)
   1350      1.1  mrg {
   1351      1.1  mrg   int mode;
   1352      1.1  mrg   int rwflag;
   1353      1.1  mrg   int crflag, crflag2;
   1354      1.1  mrg   int fd;
   1355      1.1  mrg 
   1356      1.1  mrg #ifdef __CYGWIN__
   1357      1.1  mrg   if (opp->file_len == 7)
   1358      1.1  mrg     {
   1359      1.1  mrg       if (strncmp (path, "CONOUT$", 7) == 0
   1360      1.1  mrg 	  || strncmp (path, "CONERR$", 7) == 0)
   1361      1.1  mrg 	{
   1362      1.1  mrg 	  fd = open ("/dev/conout", O_WRONLY);
   1363      1.1  mrg 	  flags->action = ACTION_WRITE;
   1364      1.1  mrg 	  return fd;
   1365      1.1  mrg 	}
   1366      1.1  mrg     }
   1367      1.1  mrg 
   1368      1.1  mrg   if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
   1369      1.1  mrg     {
   1370      1.1  mrg       fd = open ("/dev/conin", O_RDONLY);
   1371      1.1  mrg       flags->action = ACTION_READ;
   1372      1.1  mrg       return fd;
   1373      1.1  mrg     }
   1374      1.1  mrg #endif
   1375      1.1  mrg 
   1376      1.1  mrg 
   1377      1.1  mrg #ifdef __MINGW32__
   1378      1.1  mrg   if (opp->file_len == 7)
   1379      1.1  mrg     {
   1380      1.1  mrg       if (strncmp (path, "CONOUT$", 7) == 0
   1381      1.1  mrg 	  || strncmp (path, "CONERR$", 7) == 0)
   1382      1.1  mrg 	{
   1383      1.1  mrg 	  fd = open ("CONOUT$", O_WRONLY);
   1384      1.1  mrg 	  flags->action = ACTION_WRITE;
   1385      1.1  mrg 	  return fd;
   1386      1.1  mrg 	}
   1387      1.1  mrg     }
   1388      1.1  mrg 
   1389      1.1  mrg   if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
   1390      1.1  mrg     {
   1391      1.1  mrg       fd = open ("CONIN$", O_RDONLY);
   1392      1.1  mrg       flags->action = ACTION_READ;
   1393      1.1  mrg       return fd;
   1394      1.1  mrg     }
   1395      1.1  mrg #endif
   1396      1.1  mrg 
   1397      1.1  mrg   switch (flags->action)
   1398      1.1  mrg     {
   1399      1.1  mrg     case ACTION_READ:
   1400      1.1  mrg       rwflag = O_RDONLY;
   1401      1.1  mrg       break;
   1402      1.1  mrg 
   1403      1.1  mrg     case ACTION_WRITE:
   1404      1.1  mrg       rwflag = O_WRONLY;
   1405      1.1  mrg       break;
   1406      1.1  mrg 
   1407      1.1  mrg     case ACTION_READWRITE:
   1408      1.1  mrg     case ACTION_UNSPECIFIED:
   1409      1.1  mrg       rwflag = O_RDWR;
   1410      1.1  mrg       break;
   1411      1.1  mrg 
   1412      1.1  mrg     default:
   1413      1.1  mrg       internal_error (&opp->common, "regular_file(): Bad action");
   1414      1.1  mrg     }
   1415      1.1  mrg 
   1416      1.1  mrg   switch (flags->status)
   1417      1.1  mrg     {
   1418      1.1  mrg     case STATUS_NEW:
   1419      1.1  mrg       crflag = O_CREAT | O_EXCL;
   1420      1.1  mrg       break;
   1421      1.1  mrg 
   1422      1.1  mrg     case STATUS_OLD:		/* open will fail if the file does not exist*/
   1423      1.1  mrg       crflag = 0;
   1424      1.1  mrg       break;
   1425      1.1  mrg 
   1426      1.1  mrg     case STATUS_UNKNOWN:
   1427      1.1  mrg       if (rwflag == O_RDONLY)
   1428      1.1  mrg 	crflag = 0;
   1429      1.1  mrg       else
   1430      1.1  mrg 	crflag = O_CREAT;
   1431      1.1  mrg       break;
   1432      1.1  mrg 
   1433      1.1  mrg     case STATUS_REPLACE:
   1434      1.1  mrg       crflag = O_CREAT | O_TRUNC;
   1435      1.1  mrg       break;
   1436      1.1  mrg 
   1437      1.1  mrg     default:
   1438      1.1  mrg       /* Note: STATUS_SCRATCH is handled by tempfile () and should
   1439      1.1  mrg 	 never be seen here.  */
   1440      1.1  mrg       internal_error (&opp->common, "regular_file(): Bad status");
   1441      1.1  mrg     }
   1442      1.1  mrg 
   1443      1.1  mrg   /* rwflag |= O_LARGEFILE; */
   1444      1.1  mrg 
   1445      1.1  mrg #if defined(HAVE_CRLF) && defined(O_BINARY)
   1446      1.1  mrg   crflag |= O_BINARY;
   1447      1.1  mrg #endif
   1448      1.1  mrg 
   1449      1.1  mrg #ifdef O_CLOEXEC
   1450      1.1  mrg   crflag |= O_CLOEXEC;
   1451      1.1  mrg #endif
   1452      1.1  mrg 
   1453      1.1  mrg   mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
   1454      1.1  mrg   TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag, mode));
   1455      1.1  mrg   if (flags->action != ACTION_UNSPECIFIED)
   1456      1.1  mrg     return fd;
   1457      1.1  mrg 
   1458      1.1  mrg   if (fd >= 0)
   1459      1.1  mrg     {
   1460      1.1  mrg       flags->action = ACTION_READWRITE;
   1461      1.1  mrg       return fd;
   1462      1.1  mrg     }
   1463      1.1  mrg   if (errno != EACCES && errno != EPERM && errno != EROFS)
   1464      1.1  mrg      return fd;
   1465      1.1  mrg 
   1466      1.1  mrg   /* retry for read-only access */
   1467      1.1  mrg   rwflag = O_RDONLY;
   1468      1.1  mrg   if (flags->status == STATUS_UNKNOWN)
   1469      1.1  mrg     crflag2 = crflag & ~(O_CREAT);
   1470      1.1  mrg   else
   1471      1.1  mrg     crflag2 = crflag;
   1472      1.1  mrg   TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag2, mode));
   1473      1.1  mrg   if (fd >=0)
   1474      1.1  mrg     {
   1475      1.1  mrg       flags->action = ACTION_READ;
   1476      1.1  mrg       return fd;		/* success */
   1477      1.1  mrg     }
   1478      1.1  mrg 
   1479      1.1  mrg   if (errno != EACCES && errno != EPERM && errno != ENOENT)
   1480      1.1  mrg     return fd;			/* failure */
   1481      1.1  mrg 
   1482      1.1  mrg   /* retry for write-only access */
   1483      1.1  mrg   rwflag = O_WRONLY;
   1484      1.1  mrg   TEMP_FAILURE_RETRY (fd = open (path, rwflag | crflag, mode));
   1485      1.1  mrg   if (fd >=0)
   1486      1.1  mrg     {
   1487      1.1  mrg       flags->action = ACTION_WRITE;
   1488      1.1  mrg       return fd;		/* success */
   1489      1.1  mrg     }
   1490      1.1  mrg   return fd;			/* failure */
   1491      1.1  mrg }
   1492      1.1  mrg 
   1493      1.1  mrg 
   1494      1.1  mrg /* Lock the file, if necessary, based on SHARE flags.  */
   1495      1.1  mrg 
   1496      1.1  mrg #if defined(HAVE_FCNTL) && defined(F_SETLK) && defined(F_UNLCK)
   1497      1.1  mrg static int
   1498      1.1  mrg open_share (st_parameter_open *opp, int fd, unit_flags *flags)
   1499      1.1  mrg {
   1500      1.1  mrg   int r = 0;
   1501      1.1  mrg   struct flock f;
   1502      1.1  mrg   if (fd == STDOUT_FILENO || fd == STDERR_FILENO || fd == STDIN_FILENO)
   1503      1.1  mrg     return 0;
   1504      1.1  mrg 
   1505      1.1  mrg   f.l_start = 0;
   1506      1.1  mrg   f.l_len = 0;
   1507      1.1  mrg   f.l_whence = SEEK_SET;
   1508      1.1  mrg 
   1509      1.1  mrg   switch (flags->share)
   1510      1.1  mrg   {
   1511      1.1  mrg     case SHARE_DENYNONE:
   1512      1.1  mrg       f.l_type = F_RDLCK;
   1513      1.1  mrg       r = fcntl (fd, F_SETLK, &f);
   1514      1.1  mrg       break;
   1515      1.1  mrg     case SHARE_DENYRW:
   1516      1.1  mrg       /* Must be writable to hold write lock.  */
   1517      1.1  mrg       if (flags->action == ACTION_READ)
   1518      1.1  mrg 	{
   1519      1.1  mrg 	  generate_error (&opp->common, LIBERROR_BAD_ACTION,
   1520      1.1  mrg 	      "Cannot set write lock on file opened for READ");
   1521      1.1  mrg 	  return -1;
   1522      1.1  mrg 	}
   1523      1.1  mrg       f.l_type = F_WRLCK;
   1524      1.1  mrg       r = fcntl (fd, F_SETLK, &f);
   1525      1.1  mrg       break;
   1526      1.1  mrg     case SHARE_UNSPECIFIED:
   1527      1.1  mrg     default:
   1528      1.1  mrg       break;
   1529      1.1  mrg   }
   1530      1.1  mrg 
   1531      1.1  mrg   return r;
   1532      1.1  mrg }
   1533      1.1  mrg #else
   1534      1.1  mrg static int
   1535      1.1  mrg open_share (st_parameter_open *opp __attribute__ ((unused)),
   1536      1.1  mrg     int fd __attribute__ ((unused)),
   1537      1.1  mrg     unit_flags *flags __attribute__ ((unused)))
   1538      1.1  mrg {
   1539      1.1  mrg   return 0;
   1540      1.1  mrg }
   1541      1.1  mrg #endif /* defined(HAVE_FCNTL) ... */
   1542      1.1  mrg 
   1543      1.1  mrg 
   1544      1.1  mrg /* Wrapper around regular_file2, to make sure we free the path after
   1545      1.1  mrg    we're done.  */
   1546      1.1  mrg 
   1547      1.1  mrg static int
   1548      1.1  mrg regular_file (st_parameter_open *opp, unit_flags *flags)
   1549      1.1  mrg {
   1550      1.1  mrg   char *path = fc_strdup (opp->file, opp->file_len);
   1551      1.1  mrg   int fd = regular_file2 (path, opp, flags);
   1552      1.1  mrg   free (path);
   1553      1.1  mrg   return fd;
   1554      1.1  mrg }
   1555      1.1  mrg 
   1556      1.1  mrg /* open_external()-- Open an external file, unix specific version.
   1557      1.1  mrg    Change flags->action if it is ACTION_UNSPECIFIED on entry.
   1558      1.1  mrg    Returns NULL on operating system error. */
   1559      1.1  mrg 
   1560      1.1  mrg stream *
   1561      1.1  mrg open_external (st_parameter_open *opp, unit_flags *flags)
   1562      1.1  mrg {
   1563      1.1  mrg   int fd;
   1564      1.1  mrg 
   1565      1.1  mrg   if (flags->status == STATUS_SCRATCH)
   1566      1.1  mrg     {
   1567      1.1  mrg       fd = tempfile (opp);
   1568      1.1  mrg       if (flags->action == ACTION_UNSPECIFIED)
   1569      1.1  mrg 	flags->action = flags->readonly ? ACTION_READ : ACTION_READWRITE;
   1570      1.1  mrg 
   1571      1.1  mrg #if HAVE_UNLINK_OPEN_FILE
   1572      1.1  mrg       /* We can unlink scratch files now and it will go away when closed. */
   1573      1.1  mrg       if (fd >= 0)
   1574      1.1  mrg 	unlink (opp->file);
   1575      1.1  mrg #endif
   1576      1.1  mrg     }
   1577      1.1  mrg   else
   1578      1.1  mrg     {
   1579      1.1  mrg       /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
   1580      1.1  mrg          if it succeeds */
   1581      1.1  mrg       fd = regular_file (opp, flags);
   1582      1.1  mrg #ifndef O_CLOEXEC
   1583      1.1  mrg       set_close_on_exec (fd);
   1584      1.1  mrg #endif
   1585      1.1  mrg     }
   1586      1.1  mrg 
   1587      1.1  mrg   if (fd < 0)
   1588      1.1  mrg     return NULL;
   1589      1.1  mrg   fd = fix_fd (fd);
   1590      1.1  mrg 
   1591      1.1  mrg   if (open_share (opp, fd, flags) < 0)
   1592      1.1  mrg     return NULL;
   1593      1.1  mrg 
   1594      1.1  mrg   return fd_to_stream (fd, flags->form == FORM_UNFORMATTED);
   1595      1.1  mrg }
   1596      1.1  mrg 
   1597      1.1  mrg 
   1598      1.1  mrg /* input_stream()-- Return a stream pointer to the default input stream.
   1599      1.1  mrg    Called on initialization. */
   1600      1.1  mrg 
   1601      1.1  mrg stream *
   1602      1.1  mrg input_stream (void)
   1603      1.1  mrg {
   1604      1.1  mrg   return fd_to_stream (STDIN_FILENO, false);
   1605      1.1  mrg }
   1606      1.1  mrg 
   1607      1.1  mrg 
   1608      1.1  mrg /* output_stream()-- Return a stream pointer to the default output stream.
   1609      1.1  mrg    Called on initialization. */
   1610      1.1  mrg 
   1611      1.1  mrg stream *
   1612      1.1  mrg output_stream (void)
   1613      1.1  mrg {
   1614      1.1  mrg   stream *s;
   1615      1.1  mrg 
   1616      1.1  mrg #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
   1617      1.1  mrg   setmode (STDOUT_FILENO, O_BINARY);
   1618      1.1  mrg #endif
   1619      1.1  mrg 
   1620      1.1  mrg   s = fd_to_stream (STDOUT_FILENO, false);
   1621      1.1  mrg   return s;
   1622      1.1  mrg }
   1623      1.1  mrg 
   1624      1.1  mrg 
   1625      1.1  mrg /* error_stream()-- Return a stream pointer to the default error stream.
   1626      1.1  mrg    Called on initialization. */
   1627      1.1  mrg 
   1628      1.1  mrg stream *
   1629      1.1  mrg error_stream (void)
   1630      1.1  mrg {
   1631      1.1  mrg   stream *s;
   1632      1.1  mrg 
   1633      1.1  mrg #if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
   1634      1.1  mrg   setmode (STDERR_FILENO, O_BINARY);
   1635      1.1  mrg #endif
   1636      1.1  mrg 
   1637      1.1  mrg   s = fd_to_stream (STDERR_FILENO, false);
   1638      1.1  mrg   return s;
   1639      1.1  mrg }
   1640      1.1  mrg 
   1641      1.1  mrg 
   1642      1.1  mrg /* compare_file_filename()-- Given an open stream and a fortran string
   1643      1.1  mrg    that is a filename, figure out if the file is the same as the
   1644      1.1  mrg    filename. */
   1645      1.1  mrg 
   1646      1.1  mrg int
   1647      1.1  mrg compare_file_filename (gfc_unit *u, const char *name, gfc_charlen_type len)
   1648      1.1  mrg {
   1649      1.1  mrg   struct stat st;
   1650      1.1  mrg   int ret;
   1651      1.1  mrg #ifdef HAVE_WORKING_STAT
   1652      1.1  mrg   unix_stream *s;
   1653      1.1  mrg #else
   1654      1.1  mrg # ifdef __MINGW32__
   1655      1.1  mrg   uint64_t id1, id2;
   1656      1.1  mrg # endif
   1657      1.1  mrg #endif
   1658      1.1  mrg 
   1659      1.1  mrg   char *path = fc_strdup (name, len);
   1660      1.1  mrg 
   1661      1.1  mrg   /* If the filename doesn't exist, then there is no match with the
   1662      1.1  mrg      existing file. */
   1663      1.1  mrg 
   1664      1.1  mrg   if (TEMP_FAILURE_RETRY (stat (path, &st)) < 0)
   1665      1.1  mrg     {
   1666      1.1  mrg       ret = 0;
   1667      1.1  mrg       goto done;
   1668      1.1  mrg     }
   1669      1.1  mrg 
   1670      1.1  mrg #ifdef HAVE_WORKING_STAT
   1671      1.1  mrg   s = (unix_stream *) (u->s);
   1672      1.1  mrg   ret = (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
   1673      1.1  mrg   goto done;
   1674      1.1  mrg #else
   1675      1.1  mrg 
   1676      1.1  mrg # ifdef __MINGW32__
   1677      1.1  mrg   /* We try to match files by a unique ID.  On some filesystems (network
   1678      1.1  mrg      fs and FAT), we can't generate this unique ID, and will simply compare
   1679      1.1  mrg      filenames.  */
   1680      1.1  mrg   id1 = id_from_path (path);
   1681      1.1  mrg   id2 = id_from_fd (((unix_stream *) (u->s))->fd);
   1682      1.1  mrg   if (id1 || id2)
   1683      1.1  mrg     {
   1684      1.1  mrg       ret = (id1 == id2);
   1685      1.1  mrg       goto done;
   1686      1.1  mrg     }
   1687      1.1  mrg # endif
   1688      1.1  mrg   if (u->filename)
   1689      1.1  mrg     ret = (strcmp(path, u->filename) == 0);
   1690      1.1  mrg   else
   1691      1.1  mrg     ret = 0;
   1692      1.1  mrg #endif
   1693      1.1  mrg  done:
   1694      1.1  mrg   free (path);
   1695      1.1  mrg   return ret;
   1696      1.1  mrg }
   1697      1.1  mrg 
   1698      1.1  mrg 
   1699      1.1  mrg #ifdef HAVE_WORKING_STAT
   1700      1.1  mrg # define FIND_FILE0_DECL struct stat *st
   1701      1.1  mrg # define FIND_FILE0_ARGS st
   1702      1.1  mrg #else
   1703      1.1  mrg # define FIND_FILE0_DECL uint64_t id, const char *path
   1704      1.1  mrg # define FIND_FILE0_ARGS id, path
   1705      1.1  mrg #endif
   1706      1.1  mrg 
   1707      1.1  mrg /* find_file0()-- Recursive work function for find_file() */
   1708      1.1  mrg 
   1709      1.1  mrg static gfc_unit *
   1710      1.1  mrg find_file0 (gfc_unit *u, FIND_FILE0_DECL)
   1711      1.1  mrg {
   1712      1.1  mrg   gfc_unit *v;
   1713      1.1  mrg #if defined(__MINGW32__) && !HAVE_WORKING_STAT
   1714      1.1  mrg   uint64_t id1;
   1715      1.1  mrg #endif
   1716      1.1  mrg 
   1717      1.1  mrg   if (u == NULL)
   1718      1.1  mrg     return NULL;
   1719      1.1  mrg 
   1720      1.1  mrg #ifdef HAVE_WORKING_STAT
   1721      1.1  mrg   if (u->s != NULL)
   1722      1.1  mrg     {
   1723      1.1  mrg       unix_stream *s = (unix_stream *) (u->s);
   1724      1.1  mrg       if (st[0].st_dev == s->st_dev && st[0].st_ino == s->st_ino)
   1725      1.1  mrg 	return u;
   1726      1.1  mrg     }
   1727      1.1  mrg #else
   1728      1.1  mrg # ifdef __MINGW32__
   1729      1.1  mrg   if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
   1730      1.1  mrg     {
   1731      1.1  mrg       if (id == id1)
   1732      1.1  mrg 	return u;
   1733      1.1  mrg     }
   1734      1.1  mrg   else
   1735      1.1  mrg # endif
   1736      1.1  mrg     if (u->filename && strcmp (u->filename, path) == 0)
   1737      1.1  mrg       return u;
   1738      1.1  mrg #endif
   1739      1.1  mrg 
   1740      1.1  mrg   v = find_file0 (u->left, FIND_FILE0_ARGS);
   1741      1.1  mrg   if (v != NULL)
   1742      1.1  mrg     return v;
   1743      1.1  mrg 
   1744      1.1  mrg   v = find_file0 (u->right, FIND_FILE0_ARGS);
   1745      1.1  mrg   if (v != NULL)
   1746      1.1  mrg     return v;
   1747      1.1  mrg 
   1748      1.1  mrg   return NULL;
   1749      1.1  mrg }
   1750      1.1  mrg 
   1751      1.1  mrg 
   1752      1.1  mrg /* find_file()-- Take the current filename and see if there is a unit
   1753      1.1  mrg    that has the file already open.  Returns a pointer to the unit if so. */
   1754      1.1  mrg 
   1755      1.1  mrg gfc_unit *
   1756      1.1  mrg find_file (const char *file, gfc_charlen_type file_len)
   1757      1.1  mrg {
   1758      1.1  mrg   struct stat st[1];
   1759      1.1  mrg   gfc_unit *u;
   1760      1.1  mrg #if defined(__MINGW32__) && !HAVE_WORKING_STAT
   1761      1.1  mrg   uint64_t id = 0ULL;
   1762      1.1  mrg #endif
   1763      1.1  mrg 
   1764      1.1  mrg   char *path = fc_strdup (file, file_len);
   1765      1.1  mrg 
   1766      1.1  mrg   if (TEMP_FAILURE_RETRY (stat (path, &st[0])) < 0)
   1767      1.1  mrg     {
   1768      1.1  mrg       u = NULL;
   1769      1.1  mrg       goto done;
   1770      1.1  mrg     }
   1771      1.1  mrg 
   1772      1.1  mrg #if defined(__MINGW32__) && !HAVE_WORKING_STAT
   1773      1.1  mrg   id = id_from_path (path);
   1774      1.1  mrg #endif
   1775      1.1  mrg 
   1776  1.1.1.4  mrg   RDLOCK (&unit_rwlock);
   1777      1.1  mrg retry:
   1778      1.1  mrg   u = find_file0 (unit_root, FIND_FILE0_ARGS);
   1779      1.1  mrg   if (u != NULL)
   1780      1.1  mrg     {
   1781      1.1  mrg       /* Fast path.  */
   1782      1.1  mrg       if (! __gthread_mutex_trylock (&u->lock))
   1783      1.1  mrg 	{
   1784      1.1  mrg 	  /* assert (u->closed == 0); */
   1785  1.1.1.4  mrg 	  RWUNLOCK (&unit_rwlock);
   1786      1.1  mrg 	  goto done;
   1787      1.1  mrg 	}
   1788      1.1  mrg 
   1789      1.1  mrg       inc_waiting_locked (u);
   1790      1.1  mrg     }
   1791  1.1.1.4  mrg   RWUNLOCK (&unit_rwlock);
   1792      1.1  mrg   if (u != NULL)
   1793      1.1  mrg     {
   1794      1.1  mrg       LOCK (&u->lock);
   1795      1.1  mrg       if (u->closed)
   1796      1.1  mrg 	{
   1797  1.1.1.4  mrg 	  RDLOCK (&unit_rwlock);
   1798      1.1  mrg 	  UNLOCK (&u->lock);
   1799      1.1  mrg 	  if (predec_waiting_locked (u) == 0)
   1800      1.1  mrg 	    free (u);
   1801      1.1  mrg 	  goto retry;
   1802      1.1  mrg 	}
   1803      1.1  mrg 
   1804      1.1  mrg       dec_waiting_unlocked (u);
   1805      1.1  mrg     }
   1806      1.1  mrg  done:
   1807      1.1  mrg   free (path);
   1808      1.1  mrg   return u;
   1809      1.1  mrg }
   1810      1.1  mrg 
   1811      1.1  mrg static gfc_unit *
   1812      1.1  mrg flush_all_units_1 (gfc_unit *u, int min_unit)
   1813      1.1  mrg {
   1814      1.1  mrg   while (u != NULL)
   1815      1.1  mrg     {
   1816      1.1  mrg       if (u->unit_number > min_unit)
   1817      1.1  mrg 	{
   1818      1.1  mrg 	  gfc_unit *r = flush_all_units_1 (u->left, min_unit);
   1819      1.1  mrg 	  if (r != NULL)
   1820      1.1  mrg 	    return r;
   1821      1.1  mrg 	}
   1822      1.1  mrg       if (u->unit_number >= min_unit)
   1823      1.1  mrg 	{
   1824      1.1  mrg 	  if (__gthread_mutex_trylock (&u->lock))
   1825      1.1  mrg 	    return u;
   1826      1.1  mrg 	  if (u->s)
   1827      1.1  mrg 	    sflush (u->s);
   1828      1.1  mrg 	  UNLOCK (&u->lock);
   1829      1.1  mrg 	}
   1830      1.1  mrg       u = u->right;
   1831      1.1  mrg     }
   1832      1.1  mrg   return NULL;
   1833      1.1  mrg }
   1834      1.1  mrg 
   1835      1.1  mrg void
   1836      1.1  mrg flush_all_units (void)
   1837      1.1  mrg {
   1838      1.1  mrg   gfc_unit *u;
   1839      1.1  mrg   int min_unit = 0;
   1840      1.1  mrg 
   1841  1.1.1.4  mrg   WRLOCK (&unit_rwlock);
   1842      1.1  mrg   do
   1843      1.1  mrg     {
   1844      1.1  mrg       u = flush_all_units_1 (unit_root, min_unit);
   1845      1.1  mrg       if (u != NULL)
   1846      1.1  mrg 	inc_waiting_locked (u);
   1847  1.1.1.4  mrg       RWUNLOCK (&unit_rwlock);
   1848      1.1  mrg       if (u == NULL)
   1849      1.1  mrg 	return;
   1850      1.1  mrg 
   1851      1.1  mrg       LOCK (&u->lock);
   1852      1.1  mrg 
   1853      1.1  mrg       min_unit = u->unit_number + 1;
   1854      1.1  mrg 
   1855      1.1  mrg       if (u->closed == 0)
   1856      1.1  mrg 	{
   1857      1.1  mrg 	  sflush (u->s);
   1858  1.1.1.4  mrg 	  WRLOCK (&unit_rwlock);
   1859      1.1  mrg 	  UNLOCK (&u->lock);
   1860      1.1  mrg 	  (void) predec_waiting_locked (u);
   1861      1.1  mrg 	}
   1862      1.1  mrg       else
   1863      1.1  mrg 	{
   1864  1.1.1.4  mrg 	  WRLOCK (&unit_rwlock);
   1865      1.1  mrg 	  UNLOCK (&u->lock);
   1866      1.1  mrg 	  if (predec_waiting_locked (u) == 0)
   1867      1.1  mrg 	    free (u);
   1868      1.1  mrg 	}
   1869      1.1  mrg     }
   1870      1.1  mrg   while (1);
   1871      1.1  mrg }
   1872      1.1  mrg 
   1873      1.1  mrg 
   1874      1.1  mrg /* Unlock the unit if necessary, based on SHARE flags.  */
   1875      1.1  mrg 
   1876      1.1  mrg int
   1877      1.1  mrg close_share (gfc_unit *u __attribute__ ((unused)))
   1878      1.1  mrg {
   1879      1.1  mrg   int r = 0;
   1880      1.1  mrg #if defined(HAVE_FCNTL) && defined(F_SETLK) && defined(F_UNLCK)
   1881      1.1  mrg   unix_stream *s = (unix_stream *) u->s;
   1882      1.1  mrg   int fd = s->fd;
   1883      1.1  mrg   struct flock f;
   1884      1.1  mrg 
   1885      1.1  mrg   switch (u->flags.share)
   1886      1.1  mrg   {
   1887      1.1  mrg     case SHARE_DENYRW:
   1888      1.1  mrg     case SHARE_DENYNONE:
   1889      1.1  mrg       if (fd != STDOUT_FILENO && fd != STDERR_FILENO && fd != STDIN_FILENO)
   1890      1.1  mrg 	{
   1891      1.1  mrg 	  f.l_start = 0;
   1892      1.1  mrg 	  f.l_len = 0;
   1893      1.1  mrg 	  f.l_whence = SEEK_SET;
   1894      1.1  mrg 	  f.l_type = F_UNLCK;
   1895      1.1  mrg 	  r = fcntl (fd, F_SETLK, &f);
   1896      1.1  mrg 	}
   1897      1.1  mrg       break;
   1898      1.1  mrg     case SHARE_UNSPECIFIED:
   1899      1.1  mrg     default:
   1900      1.1  mrg       break;
   1901      1.1  mrg   }
   1902      1.1  mrg 
   1903      1.1  mrg #endif
   1904      1.1  mrg   return r;
   1905      1.1  mrg }
   1906      1.1  mrg 
   1907      1.1  mrg 
   1908      1.1  mrg /* file_exists()-- Returns nonzero if the current filename exists on
   1909      1.1  mrg    the system */
   1910      1.1  mrg 
   1911      1.1  mrg int
   1912      1.1  mrg file_exists (const char *file, gfc_charlen_type file_len)
   1913      1.1  mrg {
   1914      1.1  mrg   char *path = fc_strdup (file, file_len);
   1915      1.1  mrg   int res = !(access (path, F_OK));
   1916      1.1  mrg   free (path);
   1917      1.1  mrg   return res;
   1918      1.1  mrg }
   1919      1.1  mrg 
   1920      1.1  mrg 
   1921      1.1  mrg /* file_size()-- Returns the size of the file.  */
   1922      1.1  mrg 
   1923      1.1  mrg GFC_IO_INT
   1924      1.1  mrg file_size (const char *file, gfc_charlen_type file_len)
   1925      1.1  mrg {
   1926      1.1  mrg   char *path = fc_strdup (file, file_len);
   1927      1.1  mrg   struct stat statbuf;
   1928      1.1  mrg   int err;
   1929      1.1  mrg   TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
   1930      1.1  mrg   free (path);
   1931      1.1  mrg   if (err == -1)
   1932      1.1  mrg     return -1;
   1933      1.1  mrg   return (GFC_IO_INT) statbuf.st_size;
   1934      1.1  mrg }
   1935      1.1  mrg 
   1936      1.1  mrg static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
   1937      1.1  mrg 
   1938      1.1  mrg /* inquire_sequential()-- Given a fortran string, determine if the
   1939      1.1  mrg    file is suitable for sequential access.  Returns a C-style
   1940      1.1  mrg    string. */
   1941      1.1  mrg 
   1942      1.1  mrg const char *
   1943      1.1  mrg inquire_sequential (const char *string, gfc_charlen_type len)
   1944      1.1  mrg {
   1945      1.1  mrg   struct stat statbuf;
   1946      1.1  mrg 
   1947      1.1  mrg   if (string == NULL)
   1948      1.1  mrg     return unknown;
   1949      1.1  mrg 
   1950      1.1  mrg   char *path = fc_strdup (string, len);
   1951      1.1  mrg   int err;
   1952      1.1  mrg   TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
   1953      1.1  mrg   free (path);
   1954      1.1  mrg   if (err == -1)
   1955      1.1  mrg     return unknown;
   1956      1.1  mrg 
   1957      1.1  mrg   if (S_ISREG (statbuf.st_mode) ||
   1958      1.1  mrg       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
   1959      1.1  mrg     return unknown;
   1960      1.1  mrg 
   1961      1.1  mrg   if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
   1962      1.1  mrg     return no;
   1963      1.1  mrg 
   1964      1.1  mrg   return unknown;
   1965      1.1  mrg }
   1966      1.1  mrg 
   1967      1.1  mrg 
   1968      1.1  mrg /* inquire_direct()-- Given a fortran string, determine if the file is
   1969      1.1  mrg    suitable for direct access.  Returns a C-style string. */
   1970      1.1  mrg 
   1971      1.1  mrg const char *
   1972      1.1  mrg inquire_direct (const char *string, gfc_charlen_type len)
   1973      1.1  mrg {
   1974      1.1  mrg   struct stat statbuf;
   1975      1.1  mrg 
   1976      1.1  mrg   if (string == NULL)
   1977      1.1  mrg     return unknown;
   1978      1.1  mrg 
   1979      1.1  mrg   char *path = fc_strdup (string, len);
   1980      1.1  mrg   int err;
   1981      1.1  mrg   TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
   1982      1.1  mrg   free (path);
   1983      1.1  mrg   if (err == -1)
   1984      1.1  mrg     return unknown;
   1985      1.1  mrg 
   1986      1.1  mrg   if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
   1987      1.1  mrg     return unknown;
   1988      1.1  mrg 
   1989      1.1  mrg   if (S_ISDIR (statbuf.st_mode) ||
   1990      1.1  mrg       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
   1991      1.1  mrg     return no;
   1992      1.1  mrg 
   1993      1.1  mrg   return unknown;
   1994      1.1  mrg }
   1995      1.1  mrg 
   1996      1.1  mrg 
   1997      1.1  mrg /* inquire_formatted()-- Given a fortran string, determine if the file
   1998      1.1  mrg    is suitable for formatted form.  Returns a C-style string. */
   1999      1.1  mrg 
   2000      1.1  mrg const char *
   2001      1.1  mrg inquire_formatted (const char *string, gfc_charlen_type len)
   2002      1.1  mrg {
   2003      1.1  mrg   struct stat statbuf;
   2004      1.1  mrg 
   2005      1.1  mrg   if (string == NULL)
   2006      1.1  mrg     return unknown;
   2007      1.1  mrg 
   2008      1.1  mrg   char *path = fc_strdup (string, len);
   2009      1.1  mrg   int err;
   2010      1.1  mrg   TEMP_FAILURE_RETRY (err = stat (path, &statbuf));
   2011      1.1  mrg   free (path);
   2012      1.1  mrg   if (err == -1)
   2013      1.1  mrg     return unknown;
   2014      1.1  mrg 
   2015      1.1  mrg   if (S_ISREG (statbuf.st_mode) ||
   2016      1.1  mrg       S_ISBLK (statbuf.st_mode) ||
   2017      1.1  mrg       S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
   2018      1.1  mrg     return unknown;
   2019      1.1  mrg 
   2020      1.1  mrg   if (S_ISDIR (statbuf.st_mode))
   2021      1.1  mrg     return no;
   2022      1.1  mrg 
   2023      1.1  mrg   return unknown;
   2024      1.1  mrg }
   2025      1.1  mrg 
   2026      1.1  mrg 
   2027      1.1  mrg /* inquire_unformatted()-- Given a fortran string, determine if the file
   2028      1.1  mrg    is suitable for unformatted form.  Returns a C-style string. */
   2029      1.1  mrg 
   2030      1.1  mrg const char *
   2031      1.1  mrg inquire_unformatted (const char *string, gfc_charlen_type len)
   2032      1.1  mrg {
   2033      1.1  mrg   return inquire_formatted (string, len);
   2034      1.1  mrg }
   2035      1.1  mrg 
   2036      1.1  mrg 
   2037      1.1  mrg /* inquire_access()-- Given a fortran string, determine if the file is
   2038      1.1  mrg    suitable for access. */
   2039      1.1  mrg 
   2040      1.1  mrg static const char *
   2041      1.1  mrg inquire_access (const char *string, gfc_charlen_type len, int mode)
   2042      1.1  mrg {
   2043      1.1  mrg   if (string == NULL)
   2044      1.1  mrg     return no;
   2045      1.1  mrg   char *path = fc_strdup (string, len);
   2046      1.1  mrg   int res = access (path, mode);
   2047      1.1  mrg   free (path);
   2048      1.1  mrg   if (res == -1)
   2049      1.1  mrg     return no;
   2050      1.1  mrg 
   2051      1.1  mrg   return yes;
   2052      1.1  mrg }
   2053      1.1  mrg 
   2054      1.1  mrg 
   2055      1.1  mrg /* inquire_read()-- Given a fortran string, determine if the file is
   2056      1.1  mrg    suitable for READ access. */
   2057      1.1  mrg 
   2058      1.1  mrg const char *
   2059      1.1  mrg inquire_read (const char *string, gfc_charlen_type len)
   2060      1.1  mrg {
   2061      1.1  mrg   return inquire_access (string, len, R_OK);
   2062      1.1  mrg }
   2063      1.1  mrg 
   2064      1.1  mrg 
   2065      1.1  mrg /* inquire_write()-- Given a fortran string, determine if the file is
   2066      1.1  mrg    suitable for READ access. */
   2067      1.1  mrg 
   2068      1.1  mrg const char *
   2069      1.1  mrg inquire_write (const char *string, gfc_charlen_type len)
   2070      1.1  mrg {
   2071      1.1  mrg   return inquire_access (string, len, W_OK);
   2072      1.1  mrg }
   2073      1.1  mrg 
   2074      1.1  mrg 
   2075      1.1  mrg /* inquire_readwrite()-- Given a fortran string, determine if the file is
   2076      1.1  mrg    suitable for read and write access. */
   2077      1.1  mrg 
   2078      1.1  mrg const char *
   2079      1.1  mrg inquire_readwrite (const char *string, gfc_charlen_type len)
   2080      1.1  mrg {
   2081      1.1  mrg   return inquire_access (string, len, R_OK | W_OK);
   2082      1.1  mrg }
   2083      1.1  mrg 
   2084      1.1  mrg 
   2085      1.1  mrg int
   2086      1.1  mrg stream_isatty (stream *s)
   2087      1.1  mrg {
   2088      1.1  mrg   return isatty (((unix_stream *) s)->fd);
   2089      1.1  mrg }
   2090      1.1  mrg 
   2091      1.1  mrg int
   2092      1.1  mrg stream_ttyname (stream *s  __attribute__ ((unused)),
   2093      1.1  mrg 		char *buf  __attribute__ ((unused)),
   2094      1.1  mrg 		size_t buflen  __attribute__ ((unused)))
   2095      1.1  mrg {
   2096      1.1  mrg #ifdef HAVE_TTYNAME_R
   2097      1.1  mrg   return ttyname_r (((unix_stream *)s)->fd, buf, buflen);
   2098      1.1  mrg #elif defined HAVE_TTYNAME
   2099      1.1  mrg   char *p;
   2100      1.1  mrg   size_t plen;
   2101      1.1  mrg   p = ttyname (((unix_stream *)s)->fd);
   2102      1.1  mrg   if (!p)
   2103      1.1  mrg     return errno;
   2104      1.1  mrg   plen = strlen (p);
   2105      1.1  mrg   if (buflen < plen)
   2106      1.1  mrg     plen = buflen;
   2107      1.1  mrg   memcpy (buf, p, plen);
   2108      1.1  mrg   return 0;
   2109      1.1  mrg #else
   2110      1.1  mrg   return ENOSYS;
   2111      1.1  mrg #endif
   2112      1.1  mrg }
   2113      1.1  mrg 
   2114      1.1  mrg 
   2115      1.1  mrg 
   2116      1.1  mrg 
   2117      1.1  mrg /* How files are stored:  This is an operating-system specific issue,
   2118      1.1  mrg    and therefore belongs here.  There are three cases to consider.
   2119      1.1  mrg 
   2120      1.1  mrg    Direct Access:
   2121      1.1  mrg       Records are written as block of bytes corresponding to the record
   2122      1.1  mrg       length of the file.  This goes for both formatted and unformatted
   2123      1.1  mrg       records.  Positioning is done explicitly for each data transfer,
   2124      1.1  mrg       so positioning is not much of an issue.
   2125      1.1  mrg 
   2126      1.1  mrg    Sequential Formatted:
   2127      1.1  mrg       Records are separated by newline characters.  The newline character
   2128      1.1  mrg       is prohibited from appearing in a string.  If it does, this will be
   2129      1.1  mrg       messed up on the next read.  End of file is also the end of a record.
   2130      1.1  mrg 
   2131      1.1  mrg    Sequential Unformatted:
   2132      1.1  mrg       In this case, we are merely copying bytes to and from main storage,
   2133      1.1  mrg       yet we need to keep track of varying record lengths.  We adopt
   2134      1.1  mrg       the solution used by f2c.  Each record contains a pair of length
   2135      1.1  mrg       markers:
   2136      1.1  mrg 
   2137      1.1  mrg 	Length of record n in bytes
   2138      1.1  mrg 	Data of record n
   2139      1.1  mrg 	Length of record n in bytes
   2140      1.1  mrg 
   2141      1.1  mrg 	Length of record n+1 in bytes
   2142      1.1  mrg 	Data of record n+1
   2143      1.1  mrg 	Length of record n+1 in bytes
   2144      1.1  mrg 
   2145      1.1  mrg      The length is stored at the end of a record to allow backspacing to the
   2146      1.1  mrg      previous record.  Between data transfer statements, the file pointer
   2147      1.1  mrg      is left pointing to the first length of the current record.
   2148      1.1  mrg 
   2149      1.1  mrg      ENDFILE records are never explicitly stored.
   2150      1.1  mrg 
   2151      1.1  mrg */
   2152