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