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