]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/io/unix.c
re PR fortran/43832 (OPEN statement not diagnosing missing unit number)
[thirdparty/gcc.git] / libgfortran / io / unix.c
CommitLineData
a1ff2ab8 1/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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
10fa280a
TB
499 {
500 if (s->file_length != -1 && s->physical_offset != s->logical_offset)
501 {
502 if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
503 return -1;
504 s->physical_offset = s->logical_offset;
505 }
506
507 nbyte = raw_write (s, buf, nbyte);
508 s->physical_offset += nbyte;
509 }
6de9cd9a 510 }
7812c78c 511 s->logical_offset += nbyte;
779f3975 512 /* Don't increment file_length if the file is non-seekable. */
779f3975 513 if (s->file_length != -1 && s->logical_offset > s->file_length)
7812c78c
JD
514 s->file_length = s->logical_offset;
515 return nbyte;
6de9cd9a
DN
516}
517
a4384bad
JB
518static gfc_offset
519buf_seek (unix_stream * s, gfc_offset offset, int whence)
6de9cd9a 520{
7812c78c 521 switch (whence)
779f3975 522 {
7812c78c
JD
523 case SEEK_SET:
524 break;
525 case SEEK_CUR:
526 offset += s->logical_offset;
527 break;
528 case SEEK_END:
529 offset += s->file_length;
530 break;
531 default:
532 return -1;
779f3975 533 }
7812c78c 534 if (offset < 0)
802fc826 535 {
7812c78c
JD
536 errno = EINVAL;
537 return -1;
802fc826 538 }
7812c78c
JD
539 s->logical_offset = offset;
540 return offset;
6de9cd9a
DN
541}
542
a4384bad 543static gfc_offset
7812c78c 544buf_tell (unix_stream * s)
82b8244c 545{
7812c78c 546 return s->logical_offset;
82b8244c 547}
0dc43461 548
0dc43461 549static int
a4384bad 550buf_truncate (unix_stream * s, gfc_offset length)
0dc43461 551{
7812c78c 552 int r;
0dc43461 553
7812c78c
JD
554 if (buf_flush (s) != 0)
555 return -1;
556 r = raw_truncate (s, length);
557 if (r == 0)
558 s->file_length = length;
559 return r;
0dc43461
JB
560}
561
0dc43461 562static int
7812c78c 563buf_close (unix_stream * s)
6de9cd9a 564{
7812c78c
JD
565 if (buf_flush (s) != 0)
566 return -1;
567 free_mem (s->buffer);
568 return raw_close (s);
6de9cd9a
DN
569}
570
7812c78c
JD
571static int
572buf_init (unix_stream * s)
6de9cd9a 573{
7812c78c
JD
574 s->st.read = (void *) buf_read;
575 s->st.write = (void *) buf_write;
576 s->st.seek = (void *) buf_seek;
577 s->st.tell = (void *) buf_tell;
d26014d2 578 s->st.trunc = (void *) buf_truncate;
7812c78c
JD
579 s->st.close = (void *) buf_close;
580 s->st.flush = (void *) buf_flush;
6de9cd9a 581
7812c78c
JD
582 s->buffer = get_mem (BUFFER_SIZE);
583 return 0;
6de9cd9a
DN
584}
585
586
6de9cd9a
DN
587/*********************************************************************
588 memory stream functions - These are used for internal files
589
590 The idea here is that a single stream structure is created and all
591 requests must be satisfied from it. The location and size of the
592 buffer is the character variable supplied to the READ or WRITE
593 statement.
594
595*********************************************************************/
596
597
7812c78c
JD
598char *
599mem_alloc_r (stream * strm, int * len)
6de9cd9a 600{
7812c78c 601 unix_stream * s = (unix_stream *) strm;
81f4be3c 602 gfc_offset n;
15877a88 603 gfc_offset where = s->logical_offset;
6de9cd9a
DN
604
605 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
606 return NULL;
607
bd72d66c 608 n = s->buffer_offset + s->active - where;
6de9cd9a
DN
609 if (*len > n)
610 *len = n;
611
7812c78c
JD
612 s->logical_offset = where + *len;
613
6de9cd9a
DN
614 return s->buffer + (where - s->buffer_offset);
615}
616
617
7812c78c
JD
618char *
619mem_alloc_w (stream * strm, int * len)
6de9cd9a 620{
7812c78c 621 unix_stream * s = (unix_stream *) strm;
81f4be3c 622 gfc_offset m;
15877a88 623 gfc_offset where = s->logical_offset;
6de9cd9a 624
6de9cd9a
DN
625 m = where + *len;
626
59154ed2 627 if (where < s->buffer_offset)
6de9cd9a
DN
628 return NULL;
629
59154ed2 630 if (m > s->file_length)
aed6ee24 631 return NULL;
59154ed2 632
6de9cd9a
DN
633 s->logical_offset = m;
634
635 return s->buffer + (where - s->buffer_offset);
636}
637
638
15877a88 639/* Stream read function for internal units. */
0dc43461 640
7812c78c
JD
641static ssize_t
642mem_read (stream * s, void * buf, ssize_t nbytes)
0dc43461
JB
643{
644 void *p;
7812c78c 645 int nb = nbytes;
0dc43461 646
7812c78c 647 p = mem_alloc_r (s, &nb);
0dc43461
JB
648 if (p)
649 {
7812c78c
JD
650 memcpy (buf, p, nb);
651 return (ssize_t) nb;
0dc43461
JB
652 }
653 else
7812c78c 654 return 0;
0dc43461
JB
655}
656
657
658/* Stream write function for internal units. This is not actually used
659 at the moment, as all internal IO is formatted and the formatted IO
660 routines use mem_alloc_w_at. */
661
7812c78c
JD
662static ssize_t
663mem_write (stream * s, const void * buf, ssize_t nbytes)
0dc43461
JB
664{
665 void *p;
7812c78c 666 int nb = nbytes;
0dc43461 667
7812c78c 668 p = mem_alloc_w (s, &nb);
0dc43461
JB
669 if (p)
670 {
7812c78c
JD
671 memcpy (p, buf, nb);
672 return (ssize_t) nb;
0dc43461
JB
673 }
674 else
7812c78c 675 return 0;
0dc43461
JB
676}
677
678
a4384bad
JB
679static gfc_offset
680mem_seek (stream * strm, gfc_offset offset, int whence)
6de9cd9a 681{
7812c78c
JD
682 unix_stream * s = (unix_stream *) strm;
683 switch (whence)
684 {
685 case SEEK_SET:
686 break;
687 case SEEK_CUR:
688 offset += s->logical_offset;
689 break;
690 case SEEK_END:
691 offset += s->file_length;
692 break;
693 default:
694 return -1;
695 }
696
697 /* Note that for internal array I/O it's actually possible to have a
698 negative offset, so don't check for that. */
6de9cd9a
DN
699 if (offset > s->file_length)
700 {
7812c78c
JD
701 errno = EINVAL;
702 return -1;
6de9cd9a
DN
703 }
704
705 s->logical_offset = offset;
7812c78c
JD
706
707 /* Returning < 0 is the error indicator for sseek(), so return 0 if
708 offset is negative. Thus if the return value is 0, the caller
709 has to use stell() to get the real value of logical_offset. */
710 if (offset >= 0)
711 return offset;
712 return 0;
6de9cd9a
DN
713}
714
715
a4384bad 716static gfc_offset
7812c78c 717mem_tell (stream * s)
82b8244c 718{
7812c78c 719 return ((unix_stream *)s)->logical_offset;
82b8244c
JB
720}
721
722
6de9cd9a 723static int
7812c78c 724mem_truncate (unix_stream * s __attribute__ ((unused)),
a4384bad 725 gfc_offset length __attribute__ ((unused)))
6de9cd9a 726{
7812c78c 727 return 0;
6de9cd9a
DN
728}
729
730
7812c78c
JD
731static int
732mem_flush (unix_stream * s __attribute__ ((unused)))
6de9cd9a 733{
7812c78c 734 return 0;
6de9cd9a
DN
735}
736
737
7812c78c
JD
738static int
739mem_close (unix_stream * s)
6de9cd9a 740{
7812c78c
JD
741 if (s != NULL)
742 free_mem (s);
6de9cd9a 743
7812c78c
JD
744 return 0;
745}
6de9cd9a
DN
746
747
748/*********************************************************************
749 Public functions -- A reimplementation of this module needs to
750 define functional equivalents of the following.
751*********************************************************************/
752
753/* empty_internal_buffer()-- Zero the buffer of Internal file */
754
755void
756empty_internal_buffer(stream *strm)
757{
7812c78c 758 unix_stream * s = (unix_stream *) strm;
f21edfd6 759 memset(s->buffer, ' ', s->file_length);
6de9cd9a
DN
760}
761
762/* open_internal()-- Returns a stream structure from an internal file */
763
764stream *
9370b3c0 765open_internal (char *base, int length, gfc_offset offset)
6de9cd9a 766{
7812c78c 767 unix_stream *s;
6de9cd9a 768
7812c78c
JD
769 s = get_mem (sizeof (unix_stream));
770 memset (s, '\0', sizeof (unix_stream));
6de9cd9a
DN
771
772 s->buffer = base;
9370b3c0 773 s->buffer_offset = offset;
6de9cd9a
DN
774
775 s->logical_offset = 0;
776 s->active = s->file_length = length;
777
6de9cd9a
DN
778 s->st.close = (void *) mem_close;
779 s->st.seek = (void *) mem_seek;
7812c78c 780 s->st.tell = (void *) mem_tell;
d26014d2 781 s->st.trunc = (void *) mem_truncate;
0dc43461
JB
782 s->st.read = (void *) mem_read;
783 s->st.write = (void *) mem_write;
7812c78c 784 s->st.flush = (void *) mem_flush;
6de9cd9a
DN
785
786 return (stream *) s;
787}
788
789
790/* fd_to_stream()-- Given an open file descriptor, build a stream
791 * around it. */
792
793static stream *
ca0d06ac 794fd_to_stream (int fd, int prot)
6de9cd9a 795{
c9828e78 796 gfstat_t statbuf;
6de9cd9a
DN
797 unix_stream *s;
798
799 s = get_mem (sizeof (unix_stream));
c42a19d5 800 memset (s, '\0', sizeof (unix_stream));
6de9cd9a
DN
801
802 s->fd = fd;
803 s->buffer_offset = 0;
804 s->physical_offset = 0;
805 s->logical_offset = 0;
806 s->prot = prot;
807
808 /* Get the current length of the file. */
809
810 fstat (fd, &statbuf);
779f3975 811
a4384bad 812 if (lseek (fd, 0, SEEK_CUR) == (gfc_offset) -1)
779f3975
JD
813 s->file_length = -1;
814 else
815 s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
816
5133e4b9 817 s->special_file = !S_ISREG (statbuf.st_mode);
6de9cd9a 818
7812c78c
JD
819 if (isatty (s->fd) || options.all_unbuffered
820 ||(options.unbuffered_preconnected &&
821 (s->fd == STDIN_FILENO
822 || s->fd == STDOUT_FILENO
823 || s->fd == STDERR_FILENO)))
824 raw_init (s);
825 else
826 buf_init (s);
6de9cd9a
DN
827
828 return (stream *) s;
829}
830
831
df65f093
SK
832/* Given the Fortran unit number, convert it to a C file descriptor. */
833
834int
5e805e44 835unit_to_fd (int unit)
df65f093 836{
df65f093 837 gfc_unit *us;
5e805e44 838 int fd;
df65f093 839
5e805e44 840 us = find_unit (unit);
df65f093
SK
841 if (us == NULL)
842 return -1;
843
5e805e44
JJ
844 fd = ((unix_stream *) us->s)->fd;
845 unlock_unit (us);
846 return fd;
df65f093
SK
847}
848
849
6de9cd9a
DN
850/* unpack_filename()-- Given a fortran string and a pointer to a
851 * buffer that is PATH_MAX characters, convert the fortran string to a
852 * C string in the buffer. Returns nonzero if this is not possible. */
853
10c682a0 854int
6de9cd9a
DN
855unpack_filename (char *cstring, const char *fstring, int len)
856{
6de9cd9a
DN
857 len = fstrlen (fstring, len);
858 if (len >= PATH_MAX)
859 return 1;
860
861 memmove (cstring, fstring, len);
862 cstring[len] = '\0';
863
864 return 0;
865}
866
867
868/* tempfile()-- Generate a temporary filename for a scratch file and
869 * open it. mkstemp() opens the file for reading and writing, but the
870 * library mode prevents anything that is not allowed. The descriptor
41724e6a 871 * is returned, which is -1 on error. The template is pointed to by
5e805e44 872 * opp->file, which is copied into the unit structure
6de9cd9a
DN
873 * and freed later. */
874
875static int
5e805e44 876tempfile (st_parameter_open *opp)
6de9cd9a
DN
877{
878 const char *tempdir;
879 char *template;
880 int fd;
881
882 tempdir = getenv ("GFORTRAN_TMPDIR");
883 if (tempdir == NULL)
884 tempdir = getenv ("TMP");
e087fdd8
FXC
885 if (tempdir == NULL)
886 tempdir = getenv ("TEMP");
6de9cd9a
DN
887 if (tempdir == NULL)
888 tempdir = DEFAULT_TEMPDIR;
889
890 template = get_mem (strlen (tempdir) + 20);
891
d8163f5c 892 sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
41724e6a
AL
893
894#ifdef HAVE_MKSTEMP
6de9cd9a
DN
895
896 fd = mkstemp (template);
897
41724e6a
AL
898#else /* HAVE_MKSTEMP */
899
900 if (mktemp (template))
901 do
8824fd4c 902#if defined(HAVE_CRLF) && defined(O_BINARY)
3c127520 903 fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
10256cbe 904 S_IREAD | S_IWRITE);
3c127520 905#else
e087fdd8 906 fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
3c127520 907#endif
41724e6a
AL
908 while (!(fd == -1 && errno == EEXIST) && mktemp (template));
909 else
910 fd = -1;
911
912#endif /* HAVE_MKSTEMP */
913
6de9cd9a
DN
914 if (fd < 0)
915 free_mem (template);
916 else
917 {
5e805e44
JJ
918 opp->file = template;
919 opp->file_len = strlen (template); /* Don't include trailing nul */
6de9cd9a
DN
920 }
921
922 return fd;
923}
924
925
6ecf6dcb 926/* regular_file()-- Open a regular file.
d02b2c64
TK
927 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
928 * unless an error occurs.
6ecf6dcb 929 * Returns the descriptor, which is less than zero on error. */
6de9cd9a
DN
930
931static int
5e805e44 932regular_file (st_parameter_open *opp, unit_flags *flags)
6de9cd9a
DN
933{
934 char path[PATH_MAX + 1];
6de9cd9a 935 int mode;
6ecf6dcb 936 int rwflag;
d02b2c64 937 int crflag;
6ecf6dcb 938 int fd;
6de9cd9a 939
5e805e44 940 if (unpack_filename (path, opp->file, opp->file_len))
6de9cd9a
DN
941 {
942 errno = ENOENT; /* Fake an OS error */
943 return -1;
944 }
945
d8771b59
JD
946#ifdef __CYGWIN__
947 if (opp->file_len == 7)
948 {
949 if (strncmp (path, "CONOUT$", 7) == 0
950 || strncmp (path, "CONERR$", 7) == 0)
951 {
952 fd = open ("/dev/conout", O_WRONLY);
953 flags->action = ACTION_WRITE;
954 return fd;
955 }
956 }
957
958 if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
959 {
960 fd = open ("/dev/conin", O_RDONLY);
961 flags->action = ACTION_READ;
962 return fd;
963 }
964#endif
965
37d1bbbc
JD
966
967#ifdef __MINGW32__
968 if (opp->file_len == 7)
969 {
970 if (strncmp (path, "CONOUT$", 7) == 0
971 || strncmp (path, "CONERR$", 7) == 0)
972 {
973 fd = open ("CONOUT$", O_WRONLY);
974 flags->action = ACTION_WRITE;
975 return fd;
976 }
977 }
978
979 if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
980 {
981 fd = open ("CONIN$", O_RDONLY);
982 flags->action = ACTION_READ;
983 return fd;
984 }
985#endif
986
6ecf6dcb 987 rwflag = 0;
6de9cd9a 988
6ecf6dcb 989 switch (flags->action)
6de9cd9a
DN
990 {
991 case ACTION_READ:
6ecf6dcb 992 rwflag = O_RDONLY;
6de9cd9a
DN
993 break;
994
995 case ACTION_WRITE:
6ecf6dcb 996 rwflag = O_WRONLY;
6de9cd9a
DN
997 break;
998
999 case ACTION_READWRITE:
6ecf6dcb
SE
1000 case ACTION_UNSPECIFIED:
1001 rwflag = O_RDWR;
6de9cd9a
DN
1002 break;
1003
1004 default:
5e805e44 1005 internal_error (&opp->common, "regular_file(): Bad action");
6de9cd9a
DN
1006 }
1007
6ecf6dcb 1008 switch (flags->status)
6de9cd9a
DN
1009 {
1010 case STATUS_NEW:
d02b2c64 1011 crflag = O_CREAT | O_EXCL;
6de9cd9a
DN
1012 break;
1013
d02b2c64
TK
1014 case STATUS_OLD: /* open will fail if the file does not exist*/
1015 crflag = 0;
6de9cd9a
DN
1016 break;
1017
1018 case STATUS_UNKNOWN:
1019 case STATUS_SCRATCH:
d02b2c64 1020 crflag = O_CREAT;
6de9cd9a
DN
1021 break;
1022
1023 case STATUS_REPLACE:
d70d13ac 1024 crflag = O_CREAT | O_TRUNC;
6de9cd9a
DN
1025 break;
1026
1027 default:
5e805e44 1028 internal_error (&opp->common, "regular_file(): Bad status");
6de9cd9a
DN
1029 }
1030
6ecf6dcb 1031 /* rwflag |= O_LARGEFILE; */
6de9cd9a 1032
8824fd4c 1033#if defined(HAVE_CRLF) && defined(O_BINARY)
3c127520
FXC
1034 crflag |= O_BINARY;
1035#endif
1036
6ecf6dcb 1037 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
d02b2c64
TK
1038 fd = open (path, rwflag | crflag, mode);
1039 if (flags->action != ACTION_UNSPECIFIED)
d70d13ac 1040 return fd;
d02b2c64
TK
1041
1042 if (fd >= 0)
6ecf6dcb 1043 {
d02b2c64
TK
1044 flags->action = ACTION_READWRITE;
1045 return fd;
6ecf6dcb 1046 }
d70d13ac 1047 if (errno != EACCES && errno != EROFS)
d02b2c64
TK
1048 return fd;
1049
1050 /* retry for read-only access */
1051 rwflag = O_RDONLY;
1052 fd = open (path, rwflag | crflag, mode);
1053 if (fd >=0)
1054 {
1055 flags->action = ACTION_READ;
10256cbe 1056 return fd; /* success */
d02b2c64
TK
1057 }
1058
1059 if (errno != EACCES)
10256cbe 1060 return fd; /* failure */
d02b2c64
TK
1061
1062 /* retry for write-only access */
1063 rwflag = O_WRONLY;
1064 fd = open (path, rwflag | crflag, mode);
1065 if (fd >=0)
1066 {
1067 flags->action = ACTION_WRITE;
10256cbe 1068 return fd; /* success */
d02b2c64 1069 }
10256cbe 1070 return fd; /* failure */
6de9cd9a
DN
1071}
1072
1073
1074/* open_external()-- Open an external file, unix specific version.
6ecf6dcb 1075 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
6de9cd9a
DN
1076 * Returns NULL on operating system error. */
1077
1078stream *
5e805e44 1079open_external (st_parameter_open *opp, unit_flags *flags)
6de9cd9a
DN
1080{
1081 int fd, prot;
1082
6ecf6dcb
SE
1083 if (flags->status == STATUS_SCRATCH)
1084 {
5e805e44 1085 fd = tempfile (opp);
6ecf6dcb 1086 if (flags->action == ACTION_UNSPECIFIED)
10256cbe 1087 flags->action = ACTION_READWRITE;
10c682a0
FXC
1088
1089#if HAVE_UNLINK_OPEN_FILE
6ecf6dcb 1090 /* We can unlink scratch files now and it will go away when closed. */
5e805e44
JJ
1091 if (fd >= 0)
1092 unlink (opp->file);
10c682a0 1093#endif
6ecf6dcb
SE
1094 }
1095 else
1096 {
d02b2c64
TK
1097 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1098 * if it succeeds */
5e805e44 1099 fd = regular_file (opp, flags);
6ecf6dcb 1100 }
6de9cd9a
DN
1101
1102 if (fd < 0)
1103 return NULL;
1104 fd = fix_fd (fd);
1105
6ecf6dcb 1106 switch (flags->action)
6de9cd9a
DN
1107 {
1108 case ACTION_READ:
1109 prot = PROT_READ;
1110 break;
1111
1112 case ACTION_WRITE:
1113 prot = PROT_WRITE;
1114 break;
1115
1116 case ACTION_READWRITE:
1117 prot = PROT_READ | PROT_WRITE;
1118 break;
1119
1120 default:
5e805e44 1121 internal_error (&opp->common, "open_external(): Bad action");
6de9cd9a
DN
1122 }
1123
ca0d06ac 1124 return fd_to_stream (fd, prot);
6de9cd9a
DN
1125}
1126
1127
1128/* input_stream()-- Return a stream pointer to the default input stream.
1129 * Called on initialization. */
1130
1131stream *
1132input_stream (void)
1133{
ca0d06ac 1134 return fd_to_stream (STDIN_FILENO, PROT_READ);
6de9cd9a
DN
1135}
1136
1137
fbac3363 1138/* output_stream()-- Return a stream pointer to the default output stream.
6de9cd9a
DN
1139 * Called on initialization. */
1140
1141stream *
1142output_stream (void)
1143{
1f94e1d8
FXC
1144 stream * s;
1145
6a7c793f
DS
1146#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1147 setmode (STDOUT_FILENO, O_BINARY);
1148#endif
1f94e1d8
FXC
1149
1150 s = fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1f94e1d8 1151 return s;
6de9cd9a
DN
1152}
1153
1154
fbac3363
DE
1155/* error_stream()-- Return a stream pointer to the default error stream.
1156 * Called on initialization. */
1157
1158stream *
1159error_stream (void)
1160{
1f94e1d8
FXC
1161 stream * s;
1162
6a7c793f
DS
1163#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1164 setmode (STDERR_FILENO, O_BINARY);
1165#endif
1f94e1d8
FXC
1166
1167 s = fd_to_stream (STDERR_FILENO, PROT_WRITE);
1f94e1d8 1168 return s;
fbac3363
DE
1169}
1170
6de9cd9a 1171
d8163f5c
TK
1172/* st_vprintf()-- vprintf function for error output. To avoid buffer
1173 overruns, we limit the length of the buffer to ST_VPRINTF_SIZE. 2k
1174 is big enough to completely fill a 80x25 terminal, so it shuld be
1175 OK. We use a direct write() because it is simpler and least likely
f353733a
TK
1176 to be clobbered by memory corruption. Writing an error message
1177 longer than that is an error. */
6de9cd9a 1178
d8163f5c 1179#define ST_VPRINTF_SIZE 2048
6de9cd9a 1180
d8163f5c
TK
1181int
1182st_vprintf (const char *format, va_list ap)
1183{
1184 static char buffer[ST_VPRINTF_SIZE];
1185 int written;
1186 int fd;
6de9cd9a 1187
d8163f5c
TK
1188 fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1189#ifdef HAVE_VSNPRINTF
1190 written = vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
1191#else
f353733a
TK
1192 written = vsprintf(buffer, format, ap);
1193
1194 if (written >= ST_VPRINTF_SIZE-1)
1195 {
1196 /* The error message was longer than our buffer. Ouch. Because
1197 we may have messed up things badly, report the error and
1198 quit. */
1199#define ERROR_MESSAGE "Internal error: buffer overrun in st_vprintf()\n"
1200 write (fd, buffer, ST_VPRINTF_SIZE-1);
1201 write (fd, ERROR_MESSAGE, strlen(ERROR_MESSAGE));
1202 sys_exit(2);
1203#undef ERROR_MESSAGE
1204
1205 }
d8163f5c 1206#endif
f353733a 1207
d8163f5c
TK
1208 written = write (fd, buffer, written);
1209 return written;
6de9cd9a
DN
1210}
1211
d8163f5c
TK
1212/* st_printf()-- printf() function for error output. This just calls
1213 st_vprintf() to do the actual work. */
0dce3ca1
FXC
1214
1215int
1216st_printf (const char *format, ...)
1217{
d8163f5c
TK
1218 int written;
1219 va_list ap;
1220 va_start (ap, format);
1221 written = st_vprintf(format, ap);
1222 va_end (ap);
1223 return written;
0dce3ca1
FXC
1224}
1225
6de9cd9a
DN
1226
1227/* compare_file_filename()-- Given an open stream and a fortran string
1228 * that is a filename, figure out if the file is the same as the
1229 * filename. */
1230
1231int
ad238e4f 1232compare_file_filename (gfc_unit *u, const char *name, int len)
6de9cd9a
DN
1233{
1234 char path[PATH_MAX + 1];
c9828e78 1235 gfstat_t st1;
ad238e4f 1236#ifdef HAVE_WORKING_STAT
c9828e78 1237 gfstat_t st2;
fe046210
FXC
1238#else
1239# ifdef __MINGW32__
1240 uint64_t id1, id2;
1241# endif
ad238e4f 1242#endif
6de9cd9a
DN
1243
1244 if (unpack_filename (path, name, len))
1245 return 0; /* Can't be the same */
1246
1247 /* If the filename doesn't exist, then there is no match with the
1248 * existing file. */
1249
1250 if (stat (path, &st1) < 0)
1251 return 0;
1252
ad238e4f
FXC
1253#ifdef HAVE_WORKING_STAT
1254 fstat (((unix_stream *) (u->s))->fd, &st2);
6de9cd9a 1255 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
ad238e4f 1256#else
fe046210
FXC
1257
1258# ifdef __MINGW32__
1259 /* We try to match files by a unique ID. On some filesystems (network
1260 fs and FAT), we can't generate this unique ID, and will simply compare
1261 filenames. */
1262 id1 = id_from_path (path);
1263 id2 = id_from_fd (((unix_stream *) (u->s))->fd);
1264 if (id1 || id2)
1265 return (id1 == id2);
1266# endif
1267
ad238e4f
FXC
1268 if (len != u->file_len)
1269 return 0;
1270 return (memcmp(path, u->file, len) == 0);
1271#endif
6de9cd9a
DN
1272}
1273
1274
5e805e44 1275#ifdef HAVE_WORKING_STAT
c9828e78 1276# define FIND_FILE0_DECL gfstat_t *st
5e805e44
JJ
1277# define FIND_FILE0_ARGS st
1278#else
fe046210
FXC
1279# define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
1280# define FIND_FILE0_ARGS id, file, file_len
5e805e44
JJ
1281#endif
1282
6de9cd9a
DN
1283/* find_file0()-- Recursive work function for find_file() */
1284
909087e0 1285static gfc_unit *
5e805e44 1286find_file0 (gfc_unit *u, FIND_FILE0_DECL)
6de9cd9a 1287{
909087e0 1288 gfc_unit *v;
fe046210
FXC
1289#if defined(__MINGW32__) && !HAVE_WORKING_STAT
1290 uint64_t id1;
1291#endif
6de9cd9a
DN
1292
1293 if (u == NULL)
1294 return NULL;
1295
ad238e4f 1296#ifdef HAVE_WORKING_STAT
5e805e44
JJ
1297 if (u->s != NULL
1298 && fstat (((unix_stream *) u->s)->fd, &st[1]) >= 0 &&
1299 st[0].st_dev == st[1].st_dev && st[0].st_ino == st[1].st_ino)
6de9cd9a 1300 return u;
ad238e4f 1301#else
fe046210
FXC
1302# ifdef __MINGW32__
1303 if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
1304 {
1305 if (id == id1)
1306 return u;
1307 }
1308 else
1309# endif
1310 if (compare_string (u->file_len, u->file, file_len, file) == 0)
1311 return u;
ad238e4f 1312#endif
6de9cd9a 1313
5e805e44 1314 v = find_file0 (u->left, FIND_FILE0_ARGS);
6de9cd9a
DN
1315 if (v != NULL)
1316 return v;
1317
5e805e44 1318 v = find_file0 (u->right, FIND_FILE0_ARGS);
6de9cd9a
DN
1319 if (v != NULL)
1320 return v;
1321
1322 return NULL;
1323}
1324
1325
1326/* find_file()-- Take the current filename and see if there is a unit
1327 * that has the file already open. Returns a pointer to the unit if so. */
1328
909087e0 1329gfc_unit *
5e805e44 1330find_file (const char *file, gfc_charlen_type file_len)
6de9cd9a
DN
1331{
1332 char path[PATH_MAX + 1];
c9828e78 1333 gfstat_t st[2];
5e805e44 1334 gfc_unit *u;
509f7fdc
KT
1335#if defined(__MINGW32__) && !HAVE_WORKING_STAT
1336 uint64_t id = 0ULL;
1337#endif
6de9cd9a 1338
5e805e44 1339 if (unpack_filename (path, file, file_len))
6de9cd9a
DN
1340 return NULL;
1341
5e805e44 1342 if (stat (path, &st[0]) < 0)
6de9cd9a
DN
1343 return NULL;
1344
fe046210 1345#if defined(__MINGW32__) && !HAVE_WORKING_STAT
509f7fdc 1346 id = id_from_path (path);
fe046210
FXC
1347#endif
1348
5e805e44
JJ
1349 __gthread_mutex_lock (&unit_lock);
1350retry:
1351 u = find_file0 (unit_root, FIND_FILE0_ARGS);
1352 if (u != NULL)
1353 {
1354 /* Fast path. */
1355 if (! __gthread_mutex_trylock (&u->lock))
1356 {
1357 /* assert (u->closed == 0); */
1358 __gthread_mutex_unlock (&unit_lock);
1359 return u;
1360 }
1361
1362 inc_waiting_locked (u);
1363 }
1364 __gthread_mutex_unlock (&unit_lock);
1365 if (u != NULL)
1366 {
1367 __gthread_mutex_lock (&u->lock);
1368 if (u->closed)
1369 {
1370 __gthread_mutex_lock (&unit_lock);
1371 __gthread_mutex_unlock (&u->lock);
1372 if (predec_waiting_locked (u) == 0)
1373 free_mem (u);
1374 goto retry;
1375 }
1376
1377 dec_waiting_unlocked (u);
1378 }
1379 return u;
1380}
1381
1382static gfc_unit *
1383flush_all_units_1 (gfc_unit *u, int min_unit)
1384{
1385 while (u != NULL)
1386 {
1387 if (u->unit_number > min_unit)
1388 {
1389 gfc_unit *r = flush_all_units_1 (u->left, min_unit);
1390 if (r != NULL)
1391 return r;
1392 }
1393 if (u->unit_number >= min_unit)
1394 {
1395 if (__gthread_mutex_trylock (&u->lock))
1396 return u;
1397 if (u->s)
7812c78c 1398 sflush (u->s);
5e805e44
JJ
1399 __gthread_mutex_unlock (&u->lock);
1400 }
1401 u = u->right;
1402 }
1403 return NULL;
1404}
1405
1406void
1407flush_all_units (void)
1408{
1409 gfc_unit *u;
1410 int min_unit = 0;
1411
1412 __gthread_mutex_lock (&unit_lock);
1413 do
1414 {
1415 u = flush_all_units_1 (unit_root, min_unit);
1416 if (u != NULL)
1417 inc_waiting_locked (u);
1418 __gthread_mutex_unlock (&unit_lock);
1419 if (u == NULL)
1420 return;
1421
1422 __gthread_mutex_lock (&u->lock);
1423
1424 min_unit = u->unit_number + 1;
1425
1426 if (u->closed == 0)
1427 {
7812c78c 1428 sflush (u->s);
5e805e44
JJ
1429 __gthread_mutex_lock (&unit_lock);
1430 __gthread_mutex_unlock (&u->lock);
1431 (void) predec_waiting_locked (u);
1432 }
1433 else
1434 {
1435 __gthread_mutex_lock (&unit_lock);
1436 __gthread_mutex_unlock (&u->lock);
1437 if (predec_waiting_locked (u) == 0)
1438 free_mem (u);
1439 }
1440 }
1441 while (1);
6de9cd9a
DN
1442}
1443
1444
6de9cd9a
DN
1445/* delete_file()-- Given a unit structure, delete the file associated
1446 * with the unit. Returns nonzero if something went wrong. */
1447
1448int
909087e0 1449delete_file (gfc_unit * u)
6de9cd9a
DN
1450{
1451 char path[PATH_MAX + 1];
1452
1453 if (unpack_filename (path, u->file, u->file_len))
1454 { /* Shouldn't be possible */
1455 errno = ENOENT;
1456 return 1;
1457 }
1458
1459 return unlink (path);
1460}
1461
1462
1463/* file_exists()-- Returns nonzero if the current filename exists on
1464 * the system */
1465
1466int
5e805e44 1467file_exists (const char *file, gfc_charlen_type file_len)
6de9cd9a
DN
1468{
1469 char path[PATH_MAX + 1];
c9828e78 1470 gfstat_t statbuf;
6de9cd9a 1471
5e805e44 1472 if (unpack_filename (path, file, file_len))
6de9cd9a
DN
1473 return 0;
1474
1475 if (stat (path, &statbuf) < 0)
1476 return 0;
1477
1478 return 1;
1479}
1480
1481
41c3cddc
JD
1482/* file_size()-- Returns the size of the file. */
1483
1484GFC_IO_INT
1485file_size (const char *file, gfc_charlen_type file_len)
1486{
1487 char path[PATH_MAX + 1];
1488 gfstat_t statbuf;
1489
1490 if (unpack_filename (path, file, file_len))
1491 return -1;
1492
1493 if (stat (path, &statbuf) < 0)
1494 return -1;
1495
1496 return (GFC_IO_INT) statbuf.st_size;
1497}
6de9cd9a 1498
09003779 1499static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
6de9cd9a
DN
1500
1501/* inquire_sequential()-- Given a fortran string, determine if the
1502 * file is suitable for sequential access. Returns a C-style
1503 * string. */
1504
1505const char *
1506inquire_sequential (const char *string, int len)
1507{
1508 char path[PATH_MAX + 1];
c9828e78 1509 gfstat_t statbuf;
6de9cd9a
DN
1510
1511 if (string == NULL ||
1512 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1513 return unknown;
1514
1515 if (S_ISREG (statbuf.st_mode) ||
1516 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
17c2c96c 1517 return unknown;
6de9cd9a
DN
1518
1519 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1520 return no;
1521
1522 return unknown;
1523}
1524
1525
1526/* inquire_direct()-- Given a fortran string, determine if the file is
1527 * suitable for direct access. Returns a C-style string. */
1528
1529const char *
1530inquire_direct (const char *string, int len)
1531{
1532 char path[PATH_MAX + 1];
c9828e78 1533 gfstat_t statbuf;
6de9cd9a
DN
1534
1535 if (string == NULL ||
1536 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1537 return unknown;
1538
1539 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
17c2c96c 1540 return unknown;
6de9cd9a
DN
1541
1542 if (S_ISDIR (statbuf.st_mode) ||
1543 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1544 return no;
1545
1546 return unknown;
1547}
1548
1549
1550/* inquire_formatted()-- Given a fortran string, determine if the file
1551 * is suitable for formatted form. Returns a C-style string. */
1552
1553const char *
1554inquire_formatted (const char *string, int len)
1555{
1556 char path[PATH_MAX + 1];
c9828e78 1557 gfstat_t statbuf;
6de9cd9a
DN
1558
1559 if (string == NULL ||
1560 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1561 return unknown;
1562
1563 if (S_ISREG (statbuf.st_mode) ||
1564 S_ISBLK (statbuf.st_mode) ||
1565 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
17c2c96c 1566 return unknown;
6de9cd9a
DN
1567
1568 if (S_ISDIR (statbuf.st_mode))
1569 return no;
1570
1571 return unknown;
1572}
1573
1574
1575/* inquire_unformatted()-- Given a fortran string, determine if the file
1576 * is suitable for unformatted form. Returns a C-style string. */
1577
1578const char *
1579inquire_unformatted (const char *string, int len)
1580{
6de9cd9a
DN
1581 return inquire_formatted (string, len);
1582}
1583
1584
2515e5a7
FXC
1585#ifndef HAVE_ACCESS
1586
1587#ifndef W_OK
1588#define W_OK 2
1589#endif
1590
1591#ifndef R_OK
1592#define R_OK 4
1593#endif
1594
1595/* Fallback implementation of access() on systems that don't have it.
1596 Only modes R_OK and W_OK are used in this file. */
1597
1598static int
1599fallback_access (const char *path, int mode)
1600{
1601 if ((mode & R_OK) && open (path, O_RDONLY) < 0)
1602 return -1;
1603
1604 if ((mode & W_OK) && open (path, O_WRONLY) < 0)
1605 return -1;
1606
1607 return 0;
1608}
1609
1610#undef access
1611#define access fallback_access
1612#endif
1613
1614
6de9cd9a
DN
1615/* inquire_access()-- Given a fortran string, determine if the file is
1616 * suitable for access. */
1617
1618static const char *
1619inquire_access (const char *string, int len, int mode)
1620{
1621 char path[PATH_MAX + 1];
1622
1623 if (string == NULL || unpack_filename (path, string, len) ||
1624 access (path, mode) < 0)
1625 return no;
1626
1627 return yes;
1628}
1629
1630
1631/* inquire_read()-- Given a fortran string, determine if the file is
1632 * suitable for READ access. */
1633
1634const char *
1635inquire_read (const char *string, int len)
1636{
6de9cd9a
DN
1637 return inquire_access (string, len, R_OK);
1638}
1639
1640
1641/* inquire_write()-- Given a fortran string, determine if the file is
1642 * suitable for READ access. */
1643
1644const char *
1645inquire_write (const char *string, int len)
1646{
6de9cd9a
DN
1647 return inquire_access (string, len, W_OK);
1648}
1649
1650
1651/* inquire_readwrite()-- Given a fortran string, determine if the file is
1652 * suitable for read and write access. */
1653
1654const char *
1655inquire_readwrite (const char *string, int len)
1656{
6de9cd9a
DN
1657 return inquire_access (string, len, R_OK | W_OK);
1658}
1659
1660
1661/* file_length()-- Return the file length in bytes, -1 if unknown */
1662
81f4be3c 1663gfc_offset
6de9cd9a
DN
1664file_length (stream * s)
1665{
a4384bad 1666 gfc_offset curr, end;
7812c78c
JD
1667 if (!is_seekable (s))
1668 return -1;
1669 curr = stell (s);
1670 if (curr == -1)
1671 return curr;
1672 end = sseek (s, 0, SEEK_END);
1673 sseek (s, curr, SEEK_SET);
1674 return end;
6de9cd9a
DN
1675}
1676
1677
1678/* is_seekable()-- Return nonzero if the stream is seekable, zero if
1679 * it is not */
1680
1681int
7ab8aa36 1682is_seekable (stream *s)
6de9cd9a 1683{
0dc43461
JB
1684 /* By convention, if file_length == -1, the file is not
1685 seekable. */
bf1df0a0 1686 return ((unix_stream *) s)->file_length!=-1;
6de9cd9a
DN
1687}
1688
7ab8aa36
JD
1689
1690/* is_special()-- Return nonzero if the stream is not a regular file. */
1691
9a7b6ea7 1692int
7ab8aa36
JD
1693is_special (stream *s)
1694{
1695 return ((unix_stream *) s)->special_file;
1696}
1697
1698
ae8b8789
FXC
1699int
1700stream_isatty (stream *s)
1701{
1702 return isatty (((unix_stream *) s)->fd);
1703}
1704
1705char *
008afe51 1706stream_ttyname (stream *s __attribute__ ((unused)))
ae8b8789 1707{
8845001b 1708#ifdef HAVE_TTYNAME
ae8b8789 1709 return ttyname (((unix_stream *) s)->fd);
8845001b
FXC
1710#else
1711 return NULL;
1712#endif
ae8b8789
FXC
1713}
1714
6de9cd9a
DN
1715
1716/* How files are stored: This is an operating-system specific issue,
1717 and therefore belongs here. There are three cases to consider.
1718
1719 Direct Access:
1720 Records are written as block of bytes corresponding to the record
1721 length of the file. This goes for both formatted and unformatted
1722 records. Positioning is done explicitly for each data transfer,
1723 so positioning is not much of an issue.
1724
1725 Sequential Formatted:
1726 Records are separated by newline characters. The newline character
1727 is prohibited from appearing in a string. If it does, this will be
1728 messed up on the next read. End of file is also the end of a record.
1729
1730 Sequential Unformatted:
1731 In this case, we are merely copying bytes to and from main storage,
1732 yet we need to keep track of varying record lengths. We adopt
1733 the solution used by f2c. Each record contains a pair of length
1734 markers:
1735
10256cbe
JD
1736 Length of record n in bytes
1737 Data of record n
1738 Length of record n in bytes
6de9cd9a 1739
10256cbe
JD
1740 Length of record n+1 in bytes
1741 Data of record n+1
1742 Length of record n+1 in bytes
6de9cd9a
DN
1743
1744 The length is stored at the end of a record to allow backspacing to the
1745 previous record. Between data transfer statements, the file pointer
1746 is left pointing to the first length of the current record.
1747
1748 ENDFILE records are never explicitly stored.
1749
1750*/