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