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