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