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