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