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