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