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