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