]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/io/unix.c
re PR preprocessor/34602 (Internal error with invalid #line directive)
[thirdparty/gcc.git] / libgfortran / io / unix.c
CommitLineData
0dce3ca1 1/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
8f2a1406 2 Free Software Foundation, Inc.
6de9cd9a
DN
3 Contributed by Andy Vaught
4
5This file is part of the GNU Fortran 95 runtime library (libgfortran).
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
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
57dea9f6
TM
12In addition to the permissions in the GNU General Public License, the
13Free Software Foundation gives you unlimited permission to link the
14compiled version of this file into combinations with other programs,
15and to distribute those combinations without any restriction coming
16from the use of this file. (The General Public License restrictions
17do apply in other respects; for example, they cover modification of
18the file, and distribution when not linked into a combine
19executable.)
20
6de9cd9a
DN
21Libgfortran is distributed in the hope that it will be useful,
22but WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24GNU General Public License for more details.
25
26You should have received a copy of the GNU General Public License
27along with Libgfortran; see the file COPYING. If not, write to
fe2ae685
KC
28the Free Software Foundation, 51 Franklin Street, Fifth Floor,
29Boston, MA 02110-1301, USA. */
6de9cd9a
DN
30
31/* Unix stream I/O module */
32
36ae8a61 33#include "io.h"
6de9cd9a
DN
34#include <stdlib.h>
35#include <limits.h>
36
37#include <unistd.h>
38#include <sys/stat.h>
39#include <fcntl.h>
59154ed2 40#include <assert.h>
6de9cd9a 41
6de9cd9a
DN
42#include <string.h>
43#include <errno.h>
44
fe046210
FXC
45
46/* For mingw, we don't identify files by their inode number, but by a
47 64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
48#if defined(__MINGW32__) && !HAVE_WORKING_STAT
49
50#define WIN32_LEAN_AND_MEAN
51#include <windows.h>
52
53static uint64_t
54id_from_handle (HANDLE hFile)
55{
56 BY_HANDLE_FILE_INFORMATION FileInformation;
57
58 if (hFile == INVALID_HANDLE_VALUE)
59 return 0;
60
61 memset (&FileInformation, 0, sizeof(FileInformation));
62 if (!GetFileInformationByHandle (hFile, &FileInformation))
63 return 0;
64
65 return ((uint64_t) FileInformation.nFileIndexLow)
66 | (((uint64_t) FileInformation.nFileIndexHigh) << 32);
67}
68
69
70static uint64_t
71id_from_path (const char *path)
72{
73 HANDLE hFile;
74 uint64_t res;
75
76 if (!path || !*path || access (path, F_OK))
77 return (uint64_t) -1;
78
79 hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
80 FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
81 NULL);
82 res = id_from_handle (hFile);
83 CloseHandle (hFile);
84 return res;
85}
86
87
88static uint64_t
89id_from_fd (const int fd)
90{
91 return id_from_handle ((HANDLE) _get_osfhandle (fd));
92}
93
94#endif
95
96
97
c7ba5f8d
FXC
98#ifndef SSIZE_MAX
99#define SSIZE_MAX SHRT_MAX
100#endif
101
6de9cd9a
DN
102#ifndef PATH_MAX
103#define PATH_MAX 1024
104#endif
105
f596fc98
AL
106#ifndef PROT_READ
107#define PROT_READ 1
108#endif
109
110#ifndef PROT_WRITE
111#define PROT_WRITE 2
112#endif
113
41724e6a
AL
114/* These flags aren't defined on all targets (mingw32), so provide them
115 here. */
116#ifndef S_IRGRP
117#define S_IRGRP 0
118#endif
119
120#ifndef S_IWGRP
121#define S_IWGRP 0
122#endif
123
124#ifndef S_IROTH
125#define S_IROTH 0
126#endif
127
128#ifndef S_IWOTH
129#define S_IWOTH 0
130#endif
131
0dce3ca1
FXC
132
133/* Unix stream I/O module */
134
135#define BUFFER_SIZE 8192
136
137typedef struct
138{
139 stream st;
140
141 int fd;
142 gfc_offset buffer_offset; /* File offset of the start of the buffer */
143 gfc_offset physical_offset; /* Current physical file offset */
144 gfc_offset logical_offset; /* Current logical file offset */
145 gfc_offset dirty_offset; /* Start of modified bytes in buffer */
146 gfc_offset file_length; /* Length of the file, -1 if not seekable. */
147
0dce3ca1
FXC
148 int len; /* Physical length of the current buffer */
149 int active; /* Length of valid bytes in the buffer */
150
151 int prot;
152 int ndirty; /* Dirty bytes starting at dirty_offset */
153
154 int special_file; /* =1 if the fd refers to a special file */
155
c132497f 156 int unbuffered; /* =1 if the stream is not buffered */
0dce3ca1 157
d40150cc 158 char *buffer;
899583cb 159 char small_buffer[BUFFER_SIZE];
0dce3ca1
FXC
160}
161unix_stream;
162
c132497f
JB
163
164/* Stream structure for internal files. Fields must be kept in sync
165 with unix_stream above, except for the buffer. For internal files
166 we point the buffer pointer directly at the destination memory. */
167
168typedef struct
169{
170 stream st;
171
172 int fd;
173 gfc_offset buffer_offset; /* File offset of the start of the buffer */
174 gfc_offset physical_offset; /* Current physical file offset */
175 gfc_offset logical_offset; /* Current logical file offset */
176 gfc_offset dirty_offset; /* Start of modified bytes in buffer */
177 gfc_offset file_length; /* Length of the file, -1 if not seekable. */
178
179 int len; /* Physical length of the current buffer */
180 int active; /* Length of valid bytes in the buffer */
181
182 int prot;
183 int ndirty; /* Dirty bytes starting at dirty_offset */
184
185 int special_file; /* =1 if the fd refers to a special file */
186
187 int unbuffered; /* =1 if the stream is not buffered */
188
189 char *buffer;
190}
191int_stream;
192
6de9cd9a
DN
193/* This implementation of stream I/O is based on the paper:
194 *
195 * "Exploiting the advantages of mapped files for stream I/O",
196 * O. Krieger, M. Stumm and R. Umrau, "Proceedings of the 1992 Winter
197 * USENIX conference", p. 27-42.
198 *
199 * It differs in a number of ways from the version described in the
200 * paper. First of all, threads are not an issue during I/O and we
201 * also don't have to worry about having multiple regions, since
202 * fortran's I/O model only allows you to be one place at a time.
203 *
204 * On the other hand, we have to be able to writing at the end of a
205 * stream, read from the start of a stream or read and write blocks of
206 * bytes from an arbitrary position. After opening a file, a pointer
207 * to a stream structure is returned, which is used to handle file
208 * accesses until the file is closed.
209 *
210 * salloc_at_r(stream, len, where)-- Given a stream pointer, return a
211 * pointer to a block of memory that mirror the file at position
212 * 'where' that is 'len' bytes long. The len integer is updated to
213 * reflect how many bytes were actually read. The only reason for a
214 * short read is end of file. The file pointer is updated. The
215 * pointer is valid until the next call to salloc_*.
216 *
217 * salloc_at_w(stream, len, where)-- Given the stream pointer, returns
218 * a pointer to a block of memory that is updated to reflect the state
219 * of the file. The length of the buffer is always equal to that
220 * requested. The buffer must be completely set by the caller. When
221 * data has been written, the sfree() function must be called to
222 * indicate that the caller is done writing data to the buffer. This
223 * may or may not cause a physical write.
224 *
225 * Short forms of these are salloc_r() and salloc_w() which drop the
226 * 'where' parameter and use the current file pointer. */
227
228
6de9cd9a
DN
229/*move_pos_offset()-- Move the record pointer right or left
230 *relative to current position */
231
232int
233move_pos_offset (stream* st, int pos_off)
234{
235 unix_stream * str = (unix_stream*)st;
236 if (pos_off < 0)
237 {
2f06ccc6 238 str->logical_offset += pos_off;
6de9cd9a 239
2f06ccc6 240 if (str->dirty_offset + str->ndirty > str->logical_offset)
6de9cd9a 241 {
2f06ccc6
FXC
242 if (str->ndirty + pos_off > 0)
243 str->ndirty += pos_off;
6de9cd9a
DN
244 else
245 {
246 str->dirty_offset += pos_off + pos_off;
2f06ccc6 247 str->ndirty = 0;
6de9cd9a
DN
248 }
249 }
250
2f06ccc6 251 return pos_off;
6de9cd9a 252 }
2f06ccc6 253 return 0;
6de9cd9a
DN
254}
255
256
257/* fix_fd()-- Given a file descriptor, make sure it is not one of the
258 * standard descriptors, returning a non-standard descriptor. If the
259 * user specifies that system errors should go to standard output,
260 * then closes standard output, we don't want the system errors to a
261 * file that has been given file descriptor 1 or 0. We want to send
262 * the error to the invalid descriptor. */
263
264static int
265fix_fd (int fd)
266{
2515e5a7 267#ifdef HAVE_DUP
6de9cd9a
DN
268 int input, output, error;
269
270 input = output = error = 0;
271
f21edfd6
RH
272 /* Unix allocates the lowest descriptors first, so a loop is not
273 required, but this order is. */
6de9cd9a
DN
274 if (fd == STDIN_FILENO)
275 {
276 fd = dup (fd);
277 input = 1;
278 }
279 if (fd == STDOUT_FILENO)
280 {
281 fd = dup (fd);
282 output = 1;
283 }
284 if (fd == STDERR_FILENO)
285 {
286 fd = dup (fd);
287 error = 1;
288 }
289
290 if (input)
291 close (STDIN_FILENO);
292 if (output)
293 close (STDOUT_FILENO);
294 if (error)
295 close (STDERR_FILENO);
2515e5a7 296#endif
6de9cd9a
DN
297
298 return fd;
299}
300
b65b81f9
FXC
301int
302is_preconnected (stream * s)
303{
304 int fd;
305
306 fd = ((unix_stream *) s)->fd;
307 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
308 return 1;
309 else
310 return 0;
311}
6de9cd9a 312
159840cb
FXC
313/* If the stream corresponds to a preconnected unit, we flush the
314 corresponding C stream. This is bugware for mixed C-Fortran codes
315 where the C code doesn't flush I/O before returning. */
316void
317flush_if_preconnected (stream * s)
318{
319 int fd;
320
321 fd = ((unix_stream *) s)->fd;
322 if (fd == STDIN_FILENO)
323 fflush (stdin);
324 else if (fd == STDOUT_FILENO)
325 fflush (stdout);
326 else if (fd == STDERR_FILENO)
327 fflush (stderr);
328}
329
6de9cd9a 330
0dc43461
JB
331/* Reset a stream after reading/writing. Assumes that the buffers have
332 been flushed. */
333
334inline static void
335reset_stream (unix_stream * s, size_t bytes_rw)
6de9cd9a 336{
0dc43461
JB
337 s->physical_offset += bytes_rw;
338 s->logical_offset = s->physical_offset;
339 if (s->file_length != -1 && s->physical_offset > s->file_length)
340 s->file_length = s->physical_offset;
341}
6de9cd9a 342
6de9cd9a 343
0dc43461
JB
344/* Read bytes into a buffer, allowing for short reads. If the nbytes
345 * argument is less on return than on entry, it is because we've hit
346 * the end of file. */
6de9cd9a 347
0dc43461
JB
348static int
349do_read (unix_stream * s, void * buf, size_t * nbytes)
350{
351 ssize_t trans;
352 size_t bytes_left;
353 char *buf_st;
354 int status;
355
356 status = 0;
357 bytes_left = *nbytes;
358 buf_st = (char *) buf;
359
360 /* We must read in a loop since some systems don't restart system
361 calls in case of a signal. */
362 while (bytes_left > 0)
363 {
364 /* Requests between SSIZE_MAX and SIZE_MAX are undefined by SUSv3,
365 so we must read in chunks smaller than SSIZE_MAX. */
366 trans = (bytes_left < SSIZE_MAX) ? bytes_left : SSIZE_MAX;
367 trans = read (s->fd, buf_st, trans);
368 if (trans < 0)
369 {
370 if (errno == EINTR)
371 continue;
372 else
373 {
374 status = errno;
375 break;
376 }
377 }
378 else if (trans == 0) /* We hit EOF. */
379 break;
380 buf_st += trans;
381 bytes_left -= trans;
6de9cd9a
DN
382 }
383
0dc43461
JB
384 *nbytes -= bytes_left;
385 return status;
6de9cd9a
DN
386}
387
388
0dc43461 389/* Write a buffer to a stream, allowing for short writes. */
6de9cd9a
DN
390
391static int
0dc43461 392do_write (unix_stream * s, const void * buf, size_t * nbytes)
6de9cd9a 393{
0dc43461
JB
394 ssize_t trans;
395 size_t bytes_left;
396 char *buf_st;
397 int status;
398
399 status = 0;
400 bytes_left = *nbytes;
401 buf_st = (char *) buf;
402
403 /* We must write in a loop since some systems don't restart system
404 calls in case of a signal. */
405 while (bytes_left > 0)
6de9cd9a 406 {
0dc43461
JB
407 /* Requests between SSIZE_MAX and SIZE_MAX are undefined by SUSv3,
408 so we must write in chunks smaller than SSIZE_MAX. */
409 trans = (bytes_left < SSIZE_MAX) ? bytes_left : SSIZE_MAX;
410 trans = write (s->fd, buf_st, trans);
411 if (trans < 0)
412 {
413 if (errno == EINTR)
414 continue;
415 else
416 {
417 status = errno;
418 break;
419 }
420 }
421 buf_st += trans;
422 bytes_left -= trans;
6de9cd9a
DN
423 }
424
0dc43461
JB
425 *nbytes -= bytes_left;
426 return status;
6de9cd9a 427}
6de9cd9a
DN
428
429
430/* get_oserror()-- Get the most recent operating system error. For
431 * unix, this is errno. */
432
433const char *
434get_oserror (void)
435{
6de9cd9a
DN
436 return strerror (errno);
437}
438
439
6de9cd9a
DN
440/*********************************************************************
441 File descriptor stream functions
442*********************************************************************/
443
0dc43461 444
6de9cd9a
DN
445/* fd_flush()-- Write bytes that need to be written */
446
447static try
448fd_flush (unix_stream * s)
449{
0dc43461
JB
450 size_t writelen;
451
6de9cd9a 452 if (s->ndirty == 0)
779f3975
JD
453 return SUCCESS;
454
455 if (s->file_length != -1 && s->physical_offset != s->dirty_offset &&
6de9cd9a
DN
456 lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
457 return FAILURE;
458
0dc43461
JB
459 writelen = s->ndirty;
460 if (do_write (s, s->buffer + (s->dirty_offset - s->buffer_offset),
461 &writelen) != 0)
6de9cd9a
DN
462 return FAILURE;
463
0dc43461 464 s->physical_offset = s->dirty_offset + writelen;
bf1df0a0
BD
465
466 /* don't increment file_length if the file is non-seekable */
467 if (s->file_length != -1 && s->physical_offset > s->file_length)
0dc43461
JB
468 s->file_length = s->physical_offset;
469
470 s->ndirty -= writelen;
471 if (s->ndirty != 0)
472 return FAILURE;
6de9cd9a
DN
473
474 return SUCCESS;
475}
476
477
478/* fd_alloc()-- Arrange a buffer such that the salloc() request can be
479 * satisfied. This subroutine gets the buffer ready for whatever is
480 * to come next. */
481
482static void
8f2a1406
AJ
483fd_alloc (unix_stream * s, gfc_offset where,
484 int *len __attribute__ ((unused)))
6de9cd9a 485{
899583cb
JD
486 char *new_buffer;
487 int n, read_len;
488
489 if (*len <= BUFFER_SIZE)
490 {
491 new_buffer = s->small_buffer;
492 read_len = BUFFER_SIZE;
493 }
494 else
495 {
496 new_buffer = get_mem (*len);
497 read_len = *len;
498 }
6de9cd9a
DN
499
500 /* Salvage bytes currently within the buffer. This is important for
501 * devices that cannot seek. */
502
899583cb 503 if (s->buffer != NULL && s->buffer_offset <= where &&
6de9cd9a
DN
504 where <= s->buffer_offset + s->active)
505 {
506
507 n = s->active - (where - s->buffer_offset);
899583cb 508 memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
6de9cd9a
DN
509
510 s->active = n;
511 }
512 else
513 { /* new buffer starts off empty */
514 s->active = 0;
515 }
516
517 s->buffer_offset = where;
518
899583cb
JD
519 /* free the old buffer if necessary */
520
521 if (s->buffer != NULL && s->buffer != s->small_buffer)
522 free_mem (s->buffer);
523
524 s->buffer = new_buffer;
525 s->len = read_len;
6de9cd9a
DN
526}
527
528
529/* fd_alloc_r_at()-- Allocate a stream buffer for reading. Either
530 * we've already buffered the data or we need to load it. Returns
531 * NULL on I/O error. */
532
533static char *
81f4be3c 534fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
6de9cd9a 535{
81f4be3c 536 gfc_offset m;
6de9cd9a
DN
537
538 if (where == -1)
539 where = s->logical_offset;
540
541 if (s->buffer != NULL && s->buffer_offset <= where &&
542 where + *len <= s->buffer_offset + s->active)
543 {
544
545 /* Return a position within the current buffer */
546
547 s->logical_offset = where + *len;
548 return s->buffer + where - s->buffer_offset;
549 }
550
551 fd_alloc (s, where, len);
552
553 m = where + s->active;
554
555 if (s->physical_offset != m && lseek (s->fd, m, SEEK_SET) < 0)
556 return NULL;
557
c1d70e1a
TK
558 /* do_read() hangs on read from terminals for *BSD-systems. Only
559 use read() in that case. */
560
561 if (s->special_file)
562 {
563 ssize_t n;
564
565 n = read (s->fd, s->buffer + s->active, s->len - s->active);
566 if (n < 0)
567 return NULL;
568
d5f9d080 569 s->physical_offset = m + n;
c1d70e1a
TK
570 s->active += n;
571 }
572 else
573 {
574 size_t n;
6de9cd9a 575
c1d70e1a
TK
576 n = s->len - s->active;
577 if (do_read (s, s->buffer + s->active, &n) != 0)
578 return NULL;
579
d5f9d080 580 s->physical_offset = m + n;
c1d70e1a
TK
581 s->active += n;
582 }
6de9cd9a 583
6de9cd9a
DN
584 if (s->active < *len)
585 *len = s->active; /* Bytes actually available */
586
587 s->logical_offset = where + *len;
588
589 return s->buffer;
590}
591
592
593/* fd_alloc_w_at()-- Allocate a stream buffer for writing. Either
594 * we've already buffered the data or we need to load it. */
595
596static char *
81f4be3c 597fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
6de9cd9a 598{
81f4be3c 599 gfc_offset n;
6de9cd9a
DN
600
601 if (where == -1)
602 where = s->logical_offset;
603
604 if (s->buffer == NULL || s->buffer_offset > where ||
605 where + *len > s->buffer_offset + s->len)
606 {
607
608 if (fd_flush (s) == FAILURE)
609 return NULL;
610 fd_alloc (s, where, len);
611 }
612
613 /* Return a position within the current buffer */
bf1df0a0
BD
614 if (s->ndirty == 0
615 || where > s->dirty_offset + s->ndirty
616 || s->dirty_offset > where + *len)
617 { /* Discontiguous blocks, start with a clean buffer. */
618 /* Flush the buffer. */
619 if (s->ndirty != 0)
620 fd_flush (s);
621 s->dirty_offset = where;
622 s->ndirty = *len;
6de9cd9a
DN
623 }
624 else
bf1df0a0
BD
625 {
626 gfc_offset start; /* Merge with the existing data. */
627 if (where < s->dirty_offset)
628 start = where;
629 else
630 start = s->dirty_offset;
631 if (where + *len > s->dirty_offset + s->ndirty)
632 s->ndirty = where + *len - start;
633 else
634 s->ndirty = s->dirty_offset + s->ndirty - start;
d40150cc 635 s->dirty_offset = start;
6de9cd9a
DN
636 }
637
638 s->logical_offset = where + *len;
639
779f3975
JD
640 /* Don't increment file_length if the file is non-seekable. */
641
642 if (s->file_length != -1 && s->logical_offset > s->file_length)
643 s->file_length = s->logical_offset;
78579b60 644
6de9cd9a
DN
645 n = s->logical_offset - s->buffer_offset;
646 if (n > s->active)
647 s->active = n;
648
649 return s->buffer + where - s->buffer_offset;
650}
651
652
653static try
654fd_sfree (unix_stream * s)
655{
6de9cd9a 656 if (s->ndirty != 0 &&
899583cb
JD
657 (s->buffer != s->small_buffer || options.all_unbuffered ||
658 s->unbuffered))
6de9cd9a
DN
659 return fd_flush (s);
660
661 return SUCCESS;
662}
663
664
0dc43461 665static try
81f4be3c 666fd_seek (unix_stream * s, gfc_offset offset)
6de9cd9a 667{
779f3975
JD
668
669 if (s->file_length == -1)
670 return SUCCESS;
671
c5418dcb
JD
672 if (s->physical_offset == offset) /* Are we lucky and avoid syscall? */
673 {
674 s->logical_offset = offset;
675 return SUCCESS;
676 }
6de9cd9a 677
dcdc26df
DF
678 if (lseek (s->fd, offset, SEEK_SET) >= 0)
679 {
680 s->physical_offset = s->logical_offset = offset;
681 s->active = 0;
682 return SUCCESS;
683 }
c5418dcb 684
dcdc26df 685 return FAILURE;
6de9cd9a
DN
686}
687
688
689/* truncate_file()-- Given a unit, truncate the file at the current
690 * position. Sets the physical location to the new end of the file.
691 * Returns nonzero on error. */
692
693static try
694fd_truncate (unix_stream * s)
695{
779f3975
JD
696 /* Non-seekable files, like terminals and fifo's fail the lseek so just
697 return success, there is nothing to truncate. If its not a pipe there
698 is a real problem. */
bf1df0a0 699 if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
779f3975
JD
700 {
701 if (errno == ESPIPE)
702 return SUCCESS;
703 else
704 return FAILURE;
705 }
6de9cd9a 706
779f3975
JD
707 /* Using ftruncate on a seekable special file (like /dev/null)
708 is undefined, so we treat it as if the ftruncate succeeded. */
1fb2002d 709#ifdef HAVE_FTRUNCATE
5133e4b9 710 if (s->special_file || ftruncate (s->fd, s->logical_offset))
1fb2002d
FXC
711#else
712#ifdef HAVE_CHSIZE
5133e4b9 713 if (s->special_file || chsize (s->fd, s->logical_offset))
1fb2002d
FXC
714#endif
715#endif
802fc826
BD
716 {
717 s->physical_offset = s->file_length = 0;
99c6db71 718 return SUCCESS;
802fc826 719 }
bf1df0a0
BD
720
721 s->physical_offset = s->file_length = s->logical_offset;
844234fb 722 s->active = 0;
6de9cd9a
DN
723 return SUCCESS;
724}
725
726
82b8244c
JB
727/* Similar to memset(), but operating on a stream instead of a string.
728 Takes care of not using too much memory. */
729
730static try
731fd_sset (unix_stream * s, int c, size_t n)
732{
733 size_t bytes_left;
734 int trans;
735 void *p;
736
737 bytes_left = n;
738
739 while (bytes_left > 0)
740 {
741 /* memset() in chunks of BUFFER_SIZE. */
742 trans = (bytes_left < BUFFER_SIZE) ? bytes_left : BUFFER_SIZE;
743
744 p = fd_alloc_w_at (s, &trans, -1);
745 if (p)
746 memset (p, c, trans);
747 else
748 return FAILURE;
749
750 bytes_left -= trans;
751 }
752
753 return SUCCESS;
754}
0dc43461
JB
755
756
757/* Stream read function. Avoids using a buffer for big reads. The
758 interface is like POSIX read(), but the nbytes argument is a
759 pointer; on return it contains the number of bytes written. The
760 function return value is the status indicator (0 for success). */
761
762static int
763fd_read (unix_stream * s, void * buf, size_t * nbytes)
764{
765 void *p;
766 int tmp, status;
767
768 if (*nbytes < BUFFER_SIZE && !s->unbuffered)
769 {
770 tmp = *nbytes;
771 p = fd_alloc_r_at (s, &tmp, -1);
772 if (p)
773 {
774 *nbytes = tmp;
775 memcpy (buf, p, *nbytes);
776 return 0;
777 }
778 else
779 {
780 *nbytes = 0;
781 return errno;
782 }
783 }
784
785 /* If the request is bigger than BUFFER_SIZE we flush the buffers
786 and read directly. */
787 if (fd_flush (s) == FAILURE)
788 {
789 *nbytes = 0;
790 return errno;
791 }
792
c5418dcb 793 if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
0dc43461
JB
794 {
795 *nbytes = 0;
796 return errno;
797 }
798
799 status = do_read (s, buf, nbytes);
800 reset_stream (s, *nbytes);
801 return status;
802}
803
804
805/* Stream write function. Avoids using a buffer for big writes. The
806 interface is like POSIX write(), but the nbytes argument is a
807 pointer; on return it contains the number of bytes written. The
808 function return value is the status indicator (0 for success). */
809
810static int
811fd_write (unix_stream * s, const void * buf, size_t * nbytes)
812{
813 void *p;
814 int tmp, status;
815
816 if (*nbytes < BUFFER_SIZE && !s->unbuffered)
817 {
818 tmp = *nbytes;
819 p = fd_alloc_w_at (s, &tmp, -1);
820 if (p)
821 {
822 *nbytes = tmp;
823 memcpy (p, buf, *nbytes);
824 return 0;
825 }
826 else
827 {
828 *nbytes = 0;
829 return errno;
830 }
831 }
832
833 /* If the request is bigger than BUFFER_SIZE we flush the buffers
834 and write directly. */
835 if (fd_flush (s) == FAILURE)
836 {
837 *nbytes = 0;
838 return errno;
839 }
840
c5418dcb 841 if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
0dc43461
JB
842 {
843 *nbytes = 0;
844 return errno;
845 }
846
847 status = do_write (s, buf, nbytes);
848 reset_stream (s, *nbytes);
849 return status;
850}
851
852
6de9cd9a
DN
853static try
854fd_close (unix_stream * s)
855{
6de9cd9a
DN
856 if (fd_flush (s) == FAILURE)
857 return FAILURE;
858
899583cb
JD
859 if (s->buffer != NULL && s->buffer != s->small_buffer)
860 free_mem (s->buffer);
861
12e59662
FXC
862 if (s->fd != STDOUT_FILENO && s->fd != STDERR_FILENO)
863 {
864 if (close (s->fd) < 0)
865 return FAILURE;
866 }
6de9cd9a
DN
867
868 free_mem (s);
869
870 return SUCCESS;
871}
872
873
874static void
875fd_open (unix_stream * s)
876{
6de9cd9a
DN
877 if (isatty (s->fd))
878 s->unbuffered = 1;
879
880 s->st.alloc_r_at = (void *) fd_alloc_r_at;
881 s->st.alloc_w_at = (void *) fd_alloc_w_at;
882 s->st.sfree = (void *) fd_sfree;
883 s->st.close = (void *) fd_close;
884 s->st.seek = (void *) fd_seek;
200809cb 885 s->st.trunc = (void *) fd_truncate;
0dc43461
JB
886 s->st.read = (void *) fd_read;
887 s->st.write = (void *) fd_write;
82b8244c 888 s->st.set = (void *) fd_sset;
6de9cd9a 889
899583cb 890 s->buffer = NULL;
6de9cd9a
DN
891}
892
893
6de9cd9a 894
0dc43461 895
6de9cd9a
DN
896/*********************************************************************
897 memory stream functions - These are used for internal files
898
899 The idea here is that a single stream structure is created and all
900 requests must be satisfied from it. The location and size of the
901 buffer is the character variable supplied to the READ or WRITE
902 statement.
903
904*********************************************************************/
905
906
907static char *
c132497f 908mem_alloc_r_at (int_stream * s, int *len, gfc_offset where)
6de9cd9a 909{
81f4be3c 910 gfc_offset n;
6de9cd9a
DN
911
912 if (where == -1)
913 where = s->logical_offset;
914
915 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
916 return NULL;
917
6de9cd9a
DN
918 s->logical_offset = where + *len;
919
bd72d66c 920 n = s->buffer_offset + s->active - where;
6de9cd9a
DN
921 if (*len > n)
922 *len = n;
923
924 return s->buffer + (where - s->buffer_offset);
925}
926
927
928static char *
c132497f 929mem_alloc_w_at (int_stream * s, int *len, gfc_offset where)
6de9cd9a 930{
81f4be3c 931 gfc_offset m;
6de9cd9a 932
59154ed2
JD
933 assert (*len >= 0); /* Negative values not allowed. */
934
6de9cd9a
DN
935 if (where == -1)
936 where = s->logical_offset;
937
938 m = where + *len;
939
59154ed2 940 if (where < s->buffer_offset)
6de9cd9a
DN
941 return NULL;
942
59154ed2 943 if (m > s->file_length)
aed6ee24 944 return NULL;
59154ed2 945
6de9cd9a
DN
946 s->logical_offset = m;
947
948 return s->buffer + (where - s->buffer_offset);
949}
950
951
0dc43461
JB
952/* Stream read function for internal units. This is not actually used
953 at the moment, as all internal IO is formatted and the formatted IO
954 routines use mem_alloc_r_at. */
955
956static int
c132497f 957mem_read (int_stream * s, void * buf, size_t * nbytes)
0dc43461
JB
958{
959 void *p;
960 int tmp;
961
962 tmp = *nbytes;
963 p = mem_alloc_r_at (s, &tmp, -1);
964 if (p)
965 {
966 *nbytes = tmp;
967 memcpy (buf, p, *nbytes);
968 return 0;
969 }
970 else
971 {
972 *nbytes = 0;
973 return errno;
974 }
975}
976
977
978/* Stream write function for internal units. This is not actually used
979 at the moment, as all internal IO is formatted and the formatted IO
980 routines use mem_alloc_w_at. */
981
982static int
c132497f 983mem_write (int_stream * s, const void * buf, size_t * nbytes)
0dc43461
JB
984{
985 void *p;
986 int tmp;
987
988 errno = 0;
989
990 tmp = *nbytes;
991 p = mem_alloc_w_at (s, &tmp, -1);
992 if (p)
993 {
994 *nbytes = tmp;
995 memcpy (p, buf, *nbytes);
996 return 0;
997 }
998 else
999 {
1000 *nbytes = 0;
1001 return errno;
1002 }
1003}
1004
1005
6de9cd9a 1006static int
c132497f 1007mem_seek (int_stream * s, gfc_offset offset)
6de9cd9a 1008{
6de9cd9a
DN
1009 if (offset > s->file_length)
1010 {
1011 errno = ESPIPE;
1012 return FAILURE;
1013 }
1014
1015 s->logical_offset = offset;
1016 return SUCCESS;
1017}
1018
1019
82b8244c 1020static try
c132497f 1021mem_set (int_stream * s, int c, size_t n)
82b8244c
JB
1022{
1023 void *p;
1024 int len;
1025
1026 len = n;
1027
1028 p = mem_alloc_w_at (s, &len, -1);
1029 if (p)
1030 {
1031 memset (p, c, len);
1032 return SUCCESS;
1033 }
1034 else
1035 return FAILURE;
1036}
1037
1038
6de9cd9a 1039static int
c132497f 1040mem_truncate (int_stream * s __attribute__ ((unused)))
6de9cd9a 1041{
6de9cd9a
DN
1042 return SUCCESS;
1043}
1044
1045
1046static try
c132497f 1047mem_close (int_stream * s)
6de9cd9a 1048{
54ffdb12
JD
1049 if (s != NULL)
1050 free_mem (s);
6de9cd9a
DN
1051
1052 return SUCCESS;
1053}
1054
1055
1056static try
c132497f 1057mem_sfree (int_stream * s __attribute__ ((unused)))
6de9cd9a 1058{
6de9cd9a
DN
1059 return SUCCESS;
1060}
1061
1062
1063
1064/*********************************************************************
1065 Public functions -- A reimplementation of this module needs to
1066 define functional equivalents of the following.
1067*********************************************************************/
1068
1069/* empty_internal_buffer()-- Zero the buffer of Internal file */
1070
1071void
1072empty_internal_buffer(stream *strm)
1073{
c132497f 1074 int_stream * s = (int_stream *) strm;
f21edfd6 1075 memset(s->buffer, ' ', s->file_length);
6de9cd9a
DN
1076}
1077
1078/* open_internal()-- Returns a stream structure from an internal file */
1079
1080stream *
1081open_internal (char *base, int length)
1082{
c132497f 1083 int_stream *s;
6de9cd9a 1084
c132497f
JB
1085 s = get_mem (sizeof (int_stream));
1086 memset (s, '\0', sizeof (int_stream));
6de9cd9a
DN
1087
1088 s->buffer = base;
1089 s->buffer_offset = 0;
1090
1091 s->logical_offset = 0;
1092 s->active = s->file_length = length;
1093
1094 s->st.alloc_r_at = (void *) mem_alloc_r_at;
1095 s->st.alloc_w_at = (void *) mem_alloc_w_at;
1096 s->st.sfree = (void *) mem_sfree;
1097 s->st.close = (void *) mem_close;
1098 s->st.seek = (void *) mem_seek;
200809cb 1099 s->st.trunc = (void *) mem_truncate;
0dc43461
JB
1100 s->st.read = (void *) mem_read;
1101 s->st.write = (void *) mem_write;
82b8244c 1102 s->st.set = (void *) mem_set;
6de9cd9a
DN
1103
1104 return (stream *) s;
1105}
1106
1107
1108/* fd_to_stream()-- Given an open file descriptor, build a stream
1109 * around it. */
1110
1111static stream *
ca0d06ac 1112fd_to_stream (int fd, int prot)
6de9cd9a
DN
1113{
1114 struct stat statbuf;
1115 unix_stream *s;
1116
1117 s = get_mem (sizeof (unix_stream));
c42a19d5 1118 memset (s, '\0', sizeof (unix_stream));
6de9cd9a
DN
1119
1120 s->fd = fd;
1121 s->buffer_offset = 0;
1122 s->physical_offset = 0;
1123 s->logical_offset = 0;
1124 s->prot = prot;
1125
1126 /* Get the current length of the file. */
1127
1128 fstat (fd, &statbuf);
779f3975
JD
1129
1130 if (lseek (fd, 0, SEEK_CUR) == (off_t) -1)
1131 s->file_length = -1;
1132 else
1133 s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
1134
5133e4b9 1135 s->special_file = !S_ISREG (statbuf.st_mode);
6de9cd9a 1136
6de9cd9a 1137 fd_open (s);
6de9cd9a
DN
1138
1139 return (stream *) s;
1140}
1141
1142
df65f093
SK
1143/* Given the Fortran unit number, convert it to a C file descriptor. */
1144
1145int
5e805e44 1146unit_to_fd (int unit)
df65f093 1147{
df65f093 1148 gfc_unit *us;
5e805e44 1149 int fd;
df65f093 1150
5e805e44 1151 us = find_unit (unit);
df65f093
SK
1152 if (us == NULL)
1153 return -1;
1154
5e805e44
JJ
1155 fd = ((unix_stream *) us->s)->fd;
1156 unlock_unit (us);
1157 return fd;
df65f093
SK
1158}
1159
1160
6de9cd9a
DN
1161/* unpack_filename()-- Given a fortran string and a pointer to a
1162 * buffer that is PATH_MAX characters, convert the fortran string to a
1163 * C string in the buffer. Returns nonzero if this is not possible. */
1164
10c682a0 1165int
6de9cd9a
DN
1166unpack_filename (char *cstring, const char *fstring, int len)
1167{
6de9cd9a
DN
1168 len = fstrlen (fstring, len);
1169 if (len >= PATH_MAX)
1170 return 1;
1171
1172 memmove (cstring, fstring, len);
1173 cstring[len] = '\0';
1174
1175 return 0;
1176}
1177
1178
1179/* tempfile()-- Generate a temporary filename for a scratch file and
1180 * open it. mkstemp() opens the file for reading and writing, but the
1181 * library mode prevents anything that is not allowed. The descriptor
41724e6a 1182 * is returned, which is -1 on error. The template is pointed to by
5e805e44 1183 * opp->file, which is copied into the unit structure
6de9cd9a
DN
1184 * and freed later. */
1185
1186static int
5e805e44 1187tempfile (st_parameter_open *opp)
6de9cd9a
DN
1188{
1189 const char *tempdir;
1190 char *template;
1191 int fd;
1192
1193 tempdir = getenv ("GFORTRAN_TMPDIR");
1194 if (tempdir == NULL)
1195 tempdir = getenv ("TMP");
e087fdd8
FXC
1196 if (tempdir == NULL)
1197 tempdir = getenv ("TEMP");
6de9cd9a
DN
1198 if (tempdir == NULL)
1199 tempdir = DEFAULT_TEMPDIR;
1200
1201 template = get_mem (strlen (tempdir) + 20);
1202
d8163f5c 1203 sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
41724e6a
AL
1204
1205#ifdef HAVE_MKSTEMP
6de9cd9a
DN
1206
1207 fd = mkstemp (template);
1208
41724e6a
AL
1209#else /* HAVE_MKSTEMP */
1210
1211 if (mktemp (template))
1212 do
8824fd4c 1213#if defined(HAVE_CRLF) && defined(O_BINARY)
3c127520
FXC
1214 fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
1215 S_IREAD | S_IWRITE);
1216#else
e087fdd8 1217 fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
3c127520 1218#endif
41724e6a
AL
1219 while (!(fd == -1 && errno == EEXIST) && mktemp (template));
1220 else
1221 fd = -1;
1222
1223#endif /* HAVE_MKSTEMP */
1224
6de9cd9a
DN
1225 if (fd < 0)
1226 free_mem (template);
1227 else
1228 {
5e805e44
JJ
1229 opp->file = template;
1230 opp->file_len = strlen (template); /* Don't include trailing nul */
6de9cd9a
DN
1231 }
1232
1233 return fd;
1234}
1235
1236
6ecf6dcb 1237/* regular_file()-- Open a regular file.
d02b2c64
TK
1238 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
1239 * unless an error occurs.
6ecf6dcb 1240 * Returns the descriptor, which is less than zero on error. */
6de9cd9a
DN
1241
1242static int
5e805e44 1243regular_file (st_parameter_open *opp, unit_flags *flags)
6de9cd9a
DN
1244{
1245 char path[PATH_MAX + 1];
6de9cd9a 1246 int mode;
6ecf6dcb 1247 int rwflag;
d02b2c64 1248 int crflag;
6ecf6dcb 1249 int fd;
6de9cd9a 1250
5e805e44 1251 if (unpack_filename (path, opp->file, opp->file_len))
6de9cd9a
DN
1252 {
1253 errno = ENOENT; /* Fake an OS error */
1254 return -1;
1255 }
1256
6ecf6dcb 1257 rwflag = 0;
6de9cd9a 1258
6ecf6dcb 1259 switch (flags->action)
6de9cd9a
DN
1260 {
1261 case ACTION_READ:
6ecf6dcb 1262 rwflag = O_RDONLY;
6de9cd9a
DN
1263 break;
1264
1265 case ACTION_WRITE:
6ecf6dcb 1266 rwflag = O_WRONLY;
6de9cd9a
DN
1267 break;
1268
1269 case ACTION_READWRITE:
6ecf6dcb
SE
1270 case ACTION_UNSPECIFIED:
1271 rwflag = O_RDWR;
6de9cd9a
DN
1272 break;
1273
1274 default:
5e805e44 1275 internal_error (&opp->common, "regular_file(): Bad action");
6de9cd9a
DN
1276 }
1277
6ecf6dcb 1278 switch (flags->status)
6de9cd9a
DN
1279 {
1280 case STATUS_NEW:
d02b2c64 1281 crflag = O_CREAT | O_EXCL;
6de9cd9a
DN
1282 break;
1283
d02b2c64
TK
1284 case STATUS_OLD: /* open will fail if the file does not exist*/
1285 crflag = 0;
6de9cd9a
DN
1286 break;
1287
1288 case STATUS_UNKNOWN:
1289 case STATUS_SCRATCH:
d02b2c64 1290 crflag = O_CREAT;
6de9cd9a
DN
1291 break;
1292
1293 case STATUS_REPLACE:
d70d13ac 1294 crflag = O_CREAT | O_TRUNC;
6de9cd9a
DN
1295 break;
1296
1297 default:
5e805e44 1298 internal_error (&opp->common, "regular_file(): Bad status");
6de9cd9a
DN
1299 }
1300
6ecf6dcb 1301 /* rwflag |= O_LARGEFILE; */
6de9cd9a 1302
8824fd4c 1303#if defined(HAVE_CRLF) && defined(O_BINARY)
3c127520
FXC
1304 crflag |= O_BINARY;
1305#endif
1306
6ecf6dcb 1307 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
d02b2c64
TK
1308 fd = open (path, rwflag | crflag, mode);
1309 if (flags->action != ACTION_UNSPECIFIED)
d70d13ac 1310 return fd;
d02b2c64
TK
1311
1312 if (fd >= 0)
6ecf6dcb 1313 {
d02b2c64
TK
1314 flags->action = ACTION_READWRITE;
1315 return fd;
6ecf6dcb 1316 }
d70d13ac 1317 if (errno != EACCES && errno != EROFS)
d02b2c64
TK
1318 return fd;
1319
1320 /* retry for read-only access */
1321 rwflag = O_RDONLY;
1322 fd = open (path, rwflag | crflag, mode);
1323 if (fd >=0)
1324 {
1325 flags->action = ACTION_READ;
1326 return fd; /* success */
1327 }
1328
1329 if (errno != EACCES)
1330 return fd; /* failure */
1331
1332 /* retry for write-only access */
1333 rwflag = O_WRONLY;
1334 fd = open (path, rwflag | crflag, mode);
1335 if (fd >=0)
1336 {
1337 flags->action = ACTION_WRITE;
1338 return fd; /* success */
1339 }
1340 return fd; /* failure */
6de9cd9a
DN
1341}
1342
1343
1344/* open_external()-- Open an external file, unix specific version.
6ecf6dcb 1345 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
6de9cd9a
DN
1346 * Returns NULL on operating system error. */
1347
1348stream *
5e805e44 1349open_external (st_parameter_open *opp, unit_flags *flags)
6de9cd9a
DN
1350{
1351 int fd, prot;
1352
6ecf6dcb
SE
1353 if (flags->status == STATUS_SCRATCH)
1354 {
5e805e44 1355 fd = tempfile (opp);
6ecf6dcb
SE
1356 if (flags->action == ACTION_UNSPECIFIED)
1357 flags->action = ACTION_READWRITE;
10c682a0
FXC
1358
1359#if HAVE_UNLINK_OPEN_FILE
6ecf6dcb 1360 /* We can unlink scratch files now and it will go away when closed. */
5e805e44
JJ
1361 if (fd >= 0)
1362 unlink (opp->file);
10c682a0 1363#endif
6ecf6dcb
SE
1364 }
1365 else
1366 {
d02b2c64
TK
1367 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1368 * if it succeeds */
5e805e44 1369 fd = regular_file (opp, flags);
6ecf6dcb 1370 }
6de9cd9a
DN
1371
1372 if (fd < 0)
1373 return NULL;
1374 fd = fix_fd (fd);
1375
6ecf6dcb 1376 switch (flags->action)
6de9cd9a
DN
1377 {
1378 case ACTION_READ:
1379 prot = PROT_READ;
1380 break;
1381
1382 case ACTION_WRITE:
1383 prot = PROT_WRITE;
1384 break;
1385
1386 case ACTION_READWRITE:
1387 prot = PROT_READ | PROT_WRITE;
1388 break;
1389
1390 default:
5e805e44 1391 internal_error (&opp->common, "open_external(): Bad action");
6de9cd9a
DN
1392 }
1393
ca0d06ac 1394 return fd_to_stream (fd, prot);
6de9cd9a
DN
1395}
1396
1397
1398/* input_stream()-- Return a stream pointer to the default input stream.
1399 * Called on initialization. */
1400
1401stream *
1402input_stream (void)
1403{
ca0d06ac 1404 return fd_to_stream (STDIN_FILENO, PROT_READ);
6de9cd9a
DN
1405}
1406
1407
fbac3363 1408/* output_stream()-- Return a stream pointer to the default output stream.
6de9cd9a
DN
1409 * Called on initialization. */
1410
1411stream *
1412output_stream (void)
1413{
1f94e1d8
FXC
1414 stream * s;
1415
6a7c793f
DS
1416#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1417 setmode (STDOUT_FILENO, O_BINARY);
1418#endif
1f94e1d8
FXC
1419
1420 s = fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1421 if (options.unbuffered_preconnected)
1422 ((unix_stream *) s)->unbuffered = 1;
1423 return s;
6de9cd9a
DN
1424}
1425
1426
fbac3363
DE
1427/* error_stream()-- Return a stream pointer to the default error stream.
1428 * Called on initialization. */
1429
1430stream *
1431error_stream (void)
1432{
1f94e1d8
FXC
1433 stream * s;
1434
6a7c793f
DS
1435#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1436 setmode (STDERR_FILENO, O_BINARY);
1437#endif
1f94e1d8
FXC
1438
1439 s = fd_to_stream (STDERR_FILENO, PROT_WRITE);
1440 if (options.unbuffered_preconnected)
1441 ((unix_stream *) s)->unbuffered = 1;
1442 return s;
fbac3363
DE
1443}
1444
6de9cd9a 1445
d8163f5c
TK
1446/* st_vprintf()-- vprintf function for error output. To avoid buffer
1447 overruns, we limit the length of the buffer to ST_VPRINTF_SIZE. 2k
1448 is big enough to completely fill a 80x25 terminal, so it shuld be
1449 OK. We use a direct write() because it is simpler and least likely
f353733a
TK
1450 to be clobbered by memory corruption. Writing an error message
1451 longer than that is an error. */
6de9cd9a 1452
d8163f5c 1453#define ST_VPRINTF_SIZE 2048
6de9cd9a 1454
d8163f5c
TK
1455int
1456st_vprintf (const char *format, va_list ap)
1457{
1458 static char buffer[ST_VPRINTF_SIZE];
1459 int written;
1460 int fd;
6de9cd9a 1461
d8163f5c
TK
1462 fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1463#ifdef HAVE_VSNPRINTF
1464 written = vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
1465#else
f353733a
TK
1466 written = vsprintf(buffer, format, ap);
1467
1468 if (written >= ST_VPRINTF_SIZE-1)
1469 {
1470 /* The error message was longer than our buffer. Ouch. Because
1471 we may have messed up things badly, report the error and
1472 quit. */
1473#define ERROR_MESSAGE "Internal error: buffer overrun in st_vprintf()\n"
1474 write (fd, buffer, ST_VPRINTF_SIZE-1);
1475 write (fd, ERROR_MESSAGE, strlen(ERROR_MESSAGE));
1476 sys_exit(2);
1477#undef ERROR_MESSAGE
1478
1479 }
d8163f5c 1480#endif
f353733a 1481
d8163f5c
TK
1482 written = write (fd, buffer, written);
1483 return written;
6de9cd9a
DN
1484}
1485
d8163f5c
TK
1486/* st_printf()-- printf() function for error output. This just calls
1487 st_vprintf() to do the actual work. */
0dce3ca1
FXC
1488
1489int
1490st_printf (const char *format, ...)
1491{
d8163f5c
TK
1492 int written;
1493 va_list ap;
1494 va_start (ap, format);
1495 written = st_vprintf(format, ap);
1496 va_end (ap);
1497 return written;
0dce3ca1
FXC
1498}
1499
6de9cd9a
DN
1500
1501/* compare_file_filename()-- Given an open stream and a fortran string
1502 * that is a filename, figure out if the file is the same as the
1503 * filename. */
1504
1505int
ad238e4f 1506compare_file_filename (gfc_unit *u, const char *name, int len)
6de9cd9a
DN
1507{
1508 char path[PATH_MAX + 1];
ad238e4f
FXC
1509 struct stat st1;
1510#ifdef HAVE_WORKING_STAT
1511 struct stat st2;
fe046210
FXC
1512#else
1513# ifdef __MINGW32__
1514 uint64_t id1, id2;
1515# endif
ad238e4f 1516#endif
6de9cd9a
DN
1517
1518 if (unpack_filename (path, name, len))
1519 return 0; /* Can't be the same */
1520
1521 /* If the filename doesn't exist, then there is no match with the
1522 * existing file. */
1523
1524 if (stat (path, &st1) < 0)
1525 return 0;
1526
ad238e4f
FXC
1527#ifdef HAVE_WORKING_STAT
1528 fstat (((unix_stream *) (u->s))->fd, &st2);
6de9cd9a 1529 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
ad238e4f 1530#else
fe046210
FXC
1531
1532# ifdef __MINGW32__
1533 /* We try to match files by a unique ID. On some filesystems (network
1534 fs and FAT), we can't generate this unique ID, and will simply compare
1535 filenames. */
1536 id1 = id_from_path (path);
1537 id2 = id_from_fd (((unix_stream *) (u->s))->fd);
1538 if (id1 || id2)
1539 return (id1 == id2);
1540# endif
1541
ad238e4f
FXC
1542 if (len != u->file_len)
1543 return 0;
1544 return (memcmp(path, u->file, len) == 0);
1545#endif
6de9cd9a
DN
1546}
1547
1548
5e805e44
JJ
1549#ifdef HAVE_WORKING_STAT
1550# define FIND_FILE0_DECL struct stat *st
1551# define FIND_FILE0_ARGS st
1552#else
fe046210
FXC
1553# define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
1554# define FIND_FILE0_ARGS id, file, file_len
5e805e44
JJ
1555#endif
1556
6de9cd9a
DN
1557/* find_file0()-- Recursive work function for find_file() */
1558
909087e0 1559static gfc_unit *
5e805e44 1560find_file0 (gfc_unit *u, FIND_FILE0_DECL)
6de9cd9a 1561{
909087e0 1562 gfc_unit *v;
fe046210
FXC
1563#if defined(__MINGW32__) && !HAVE_WORKING_STAT
1564 uint64_t id1;
1565#endif
6de9cd9a
DN
1566
1567 if (u == NULL)
1568 return NULL;
1569
ad238e4f 1570#ifdef HAVE_WORKING_STAT
5e805e44
JJ
1571 if (u->s != NULL
1572 && fstat (((unix_stream *) u->s)->fd, &st[1]) >= 0 &&
1573 st[0].st_dev == st[1].st_dev && st[0].st_ino == st[1].st_ino)
6de9cd9a 1574 return u;
ad238e4f 1575#else
fe046210
FXC
1576# ifdef __MINGW32__
1577 if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
1578 {
1579 if (id == id1)
1580 return u;
1581 }
1582 else
1583# endif
1584 if (compare_string (u->file_len, u->file, file_len, file) == 0)
1585 return u;
ad238e4f 1586#endif
6de9cd9a 1587
5e805e44 1588 v = find_file0 (u->left, FIND_FILE0_ARGS);
6de9cd9a
DN
1589 if (v != NULL)
1590 return v;
1591
5e805e44 1592 v = find_file0 (u->right, FIND_FILE0_ARGS);
6de9cd9a
DN
1593 if (v != NULL)
1594 return v;
1595
1596 return NULL;
1597}
1598
1599
1600/* find_file()-- Take the current filename and see if there is a unit
1601 * that has the file already open. Returns a pointer to the unit if so. */
1602
909087e0 1603gfc_unit *
5e805e44 1604find_file (const char *file, gfc_charlen_type file_len)
6de9cd9a
DN
1605{
1606 char path[PATH_MAX + 1];
5e805e44
JJ
1607 struct stat st[2];
1608 gfc_unit *u;
fe046210 1609 uint64_t id;
6de9cd9a 1610
5e805e44 1611 if (unpack_filename (path, file, file_len))
6de9cd9a
DN
1612 return NULL;
1613
5e805e44 1614 if (stat (path, &st[0]) < 0)
6de9cd9a
DN
1615 return NULL;
1616
fe046210
FXC
1617#if defined(__MINGW32__) && !HAVE_WORKING_STAT
1618 id = id_from_path (path);
1619#else
1620 id = 0;
1621#endif
1622
5e805e44
JJ
1623 __gthread_mutex_lock (&unit_lock);
1624retry:
1625 u = find_file0 (unit_root, FIND_FILE0_ARGS);
1626 if (u != NULL)
1627 {
1628 /* Fast path. */
1629 if (! __gthread_mutex_trylock (&u->lock))
1630 {
1631 /* assert (u->closed == 0); */
1632 __gthread_mutex_unlock (&unit_lock);
1633 return u;
1634 }
1635
1636 inc_waiting_locked (u);
1637 }
1638 __gthread_mutex_unlock (&unit_lock);
1639 if (u != NULL)
1640 {
1641 __gthread_mutex_lock (&u->lock);
1642 if (u->closed)
1643 {
1644 __gthread_mutex_lock (&unit_lock);
1645 __gthread_mutex_unlock (&u->lock);
1646 if (predec_waiting_locked (u) == 0)
1647 free_mem (u);
1648 goto retry;
1649 }
1650
1651 dec_waiting_unlocked (u);
1652 }
1653 return u;
1654}
1655
1656static gfc_unit *
1657flush_all_units_1 (gfc_unit *u, int min_unit)
1658{
1659 while (u != NULL)
1660 {
1661 if (u->unit_number > min_unit)
1662 {
1663 gfc_unit *r = flush_all_units_1 (u->left, min_unit);
1664 if (r != NULL)
1665 return r;
1666 }
1667 if (u->unit_number >= min_unit)
1668 {
1669 if (__gthread_mutex_trylock (&u->lock))
1670 return u;
1671 if (u->s)
1672 flush (u->s);
1673 __gthread_mutex_unlock (&u->lock);
1674 }
1675 u = u->right;
1676 }
1677 return NULL;
1678}
1679
1680void
1681flush_all_units (void)
1682{
1683 gfc_unit *u;
1684 int min_unit = 0;
1685
1686 __gthread_mutex_lock (&unit_lock);
1687 do
1688 {
1689 u = flush_all_units_1 (unit_root, min_unit);
1690 if (u != NULL)
1691 inc_waiting_locked (u);
1692 __gthread_mutex_unlock (&unit_lock);
1693 if (u == NULL)
1694 return;
1695
1696 __gthread_mutex_lock (&u->lock);
1697
1698 min_unit = u->unit_number + 1;
1699
1700 if (u->closed == 0)
1701 {
1702 flush (u->s);
1703 __gthread_mutex_lock (&unit_lock);
1704 __gthread_mutex_unlock (&u->lock);
1705 (void) predec_waiting_locked (u);
1706 }
1707 else
1708 {
1709 __gthread_mutex_lock (&unit_lock);
1710 __gthread_mutex_unlock (&u->lock);
1711 if (predec_waiting_locked (u) == 0)
1712 free_mem (u);
1713 }
1714 }
1715 while (1);
6de9cd9a
DN
1716}
1717
1718
1719/* stream_at_bof()-- Returns nonzero if the stream is at the beginning
1720 * of the file. */
1721
1722int
1723stream_at_bof (stream * s)
1724{
1725 unix_stream *us;
1726
b68d2bed
JB
1727 if (!is_seekable (s))
1728 return 0;
6de9cd9a 1729
b68d2bed 1730 us = (unix_stream *) s;
6de9cd9a
DN
1731
1732 return us->logical_offset == 0;
1733}
1734
1735
8824fd4c 1736/* stream_at_eof()-- Returns nonzero if the stream is at the end
6de9cd9a
DN
1737 * of the file. */
1738
1739int
1740stream_at_eof (stream * s)
1741{
1742 unix_stream *us;
1743
b68d2bed
JB
1744 if (!is_seekable (s))
1745 return 0;
6de9cd9a 1746
b68d2bed 1747 us = (unix_stream *) s;
6de9cd9a
DN
1748
1749 return us->logical_offset == us->dirty_offset;
1750}
1751
1752
1753/* delete_file()-- Given a unit structure, delete the file associated
1754 * with the unit. Returns nonzero if something went wrong. */
1755
1756int
909087e0 1757delete_file (gfc_unit * u)
6de9cd9a
DN
1758{
1759 char path[PATH_MAX + 1];
1760
1761 if (unpack_filename (path, u->file, u->file_len))
1762 { /* Shouldn't be possible */
1763 errno = ENOENT;
1764 return 1;
1765 }
1766
1767 return unlink (path);
1768}
1769
1770
1771/* file_exists()-- Returns nonzero if the current filename exists on
1772 * the system */
1773
1774int
5e805e44 1775file_exists (const char *file, gfc_charlen_type file_len)
6de9cd9a
DN
1776{
1777 char path[PATH_MAX + 1];
1778 struct stat statbuf;
1779
5e805e44 1780 if (unpack_filename (path, file, file_len))
6de9cd9a
DN
1781 return 0;
1782
1783 if (stat (path, &statbuf) < 0)
1784 return 0;
1785
1786 return 1;
1787}
1788
1789
1790
09003779 1791static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
6de9cd9a
DN
1792
1793/* inquire_sequential()-- Given a fortran string, determine if the
1794 * file is suitable for sequential access. Returns a C-style
1795 * string. */
1796
1797const char *
1798inquire_sequential (const char *string, int len)
1799{
1800 char path[PATH_MAX + 1];
1801 struct stat statbuf;
1802
1803 if (string == NULL ||
1804 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1805 return unknown;
1806
1807 if (S_ISREG (statbuf.st_mode) ||
1808 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1809 return yes;
1810
1811 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1812 return no;
1813
1814 return unknown;
1815}
1816
1817
1818/* inquire_direct()-- Given a fortran string, determine if the file is
1819 * suitable for direct access. Returns a C-style string. */
1820
1821const char *
1822inquire_direct (const char *string, int len)
1823{
1824 char path[PATH_MAX + 1];
1825 struct stat statbuf;
1826
1827 if (string == NULL ||
1828 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1829 return unknown;
1830
1831 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1832 return yes;
1833
1834 if (S_ISDIR (statbuf.st_mode) ||
1835 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1836 return no;
1837
1838 return unknown;
1839}
1840
1841
1842/* inquire_formatted()-- Given a fortran string, determine if the file
1843 * is suitable for formatted form. Returns a C-style string. */
1844
1845const char *
1846inquire_formatted (const char *string, int len)
1847{
1848 char path[PATH_MAX + 1];
1849 struct stat statbuf;
1850
1851 if (string == NULL ||
1852 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1853 return unknown;
1854
1855 if (S_ISREG (statbuf.st_mode) ||
1856 S_ISBLK (statbuf.st_mode) ||
1857 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1858 return yes;
1859
1860 if (S_ISDIR (statbuf.st_mode))
1861 return no;
1862
1863 return unknown;
1864}
1865
1866
1867/* inquire_unformatted()-- Given a fortran string, determine if the file
1868 * is suitable for unformatted form. Returns a C-style string. */
1869
1870const char *
1871inquire_unformatted (const char *string, int len)
1872{
6de9cd9a
DN
1873 return inquire_formatted (string, len);
1874}
1875
1876
2515e5a7
FXC
1877#ifndef HAVE_ACCESS
1878
1879#ifndef W_OK
1880#define W_OK 2
1881#endif
1882
1883#ifndef R_OK
1884#define R_OK 4
1885#endif
1886
1887/* Fallback implementation of access() on systems that don't have it.
1888 Only modes R_OK and W_OK are used in this file. */
1889
1890static int
1891fallback_access (const char *path, int mode)
1892{
1893 if ((mode & R_OK) && open (path, O_RDONLY) < 0)
1894 return -1;
1895
1896 if ((mode & W_OK) && open (path, O_WRONLY) < 0)
1897 return -1;
1898
1899 return 0;
1900}
1901
1902#undef access
1903#define access fallback_access
1904#endif
1905
1906
6de9cd9a
DN
1907/* inquire_access()-- Given a fortran string, determine if the file is
1908 * suitable for access. */
1909
1910static const char *
1911inquire_access (const char *string, int len, int mode)
1912{
1913 char path[PATH_MAX + 1];
1914
1915 if (string == NULL || unpack_filename (path, string, len) ||
1916 access (path, mode) < 0)
1917 return no;
1918
1919 return yes;
1920}
1921
1922
1923/* inquire_read()-- Given a fortran string, determine if the file is
1924 * suitable for READ access. */
1925
1926const char *
1927inquire_read (const char *string, int len)
1928{
6de9cd9a
DN
1929 return inquire_access (string, len, R_OK);
1930}
1931
1932
1933/* inquire_write()-- Given a fortran string, determine if the file is
1934 * suitable for READ access. */
1935
1936const char *
1937inquire_write (const char *string, int len)
1938{
6de9cd9a
DN
1939 return inquire_access (string, len, W_OK);
1940}
1941
1942
1943/* inquire_readwrite()-- Given a fortran string, determine if the file is
1944 * suitable for read and write access. */
1945
1946const char *
1947inquire_readwrite (const char *string, int len)
1948{
6de9cd9a
DN
1949 return inquire_access (string, len, R_OK | W_OK);
1950}
1951
1952
1953/* file_length()-- Return the file length in bytes, -1 if unknown */
1954
81f4be3c 1955gfc_offset
6de9cd9a
DN
1956file_length (stream * s)
1957{
6de9cd9a
DN
1958 return ((unix_stream *) s)->file_length;
1959}
1960
1961
1962/* file_position()-- Return the current position of the file */
1963
81f4be3c 1964gfc_offset
7ab8aa36 1965file_position (stream *s)
6de9cd9a 1966{
6de9cd9a
DN
1967 return ((unix_stream *) s)->logical_offset;
1968}
1969
1970
1971/* is_seekable()-- Return nonzero if the stream is seekable, zero if
1972 * it is not */
1973
1974int
7ab8aa36 1975is_seekable (stream *s)
6de9cd9a 1976{
0dc43461
JB
1977 /* By convention, if file_length == -1, the file is not
1978 seekable. */
bf1df0a0 1979 return ((unix_stream *) s)->file_length!=-1;
6de9cd9a
DN
1980}
1981
7ab8aa36
JD
1982
1983/* is_special()-- Return nonzero if the stream is not a regular file. */
1984
9a7b6ea7 1985int
7ab8aa36
JD
1986is_special (stream *s)
1987{
1988 return ((unix_stream *) s)->special_file;
1989}
1990
1991
000aa32a
JB
1992try
1993flush (stream *s)
1994{
1995 return fd_flush( (unix_stream *) s);
1996}
1997
ae8b8789
FXC
1998int
1999stream_isatty (stream *s)
2000{
2001 return isatty (((unix_stream *) s)->fd);
2002}
2003
2004char *
008afe51 2005stream_ttyname (stream *s __attribute__ ((unused)))
ae8b8789 2006{
8845001b 2007#ifdef HAVE_TTYNAME
ae8b8789 2008 return ttyname (((unix_stream *) s)->fd);
8845001b
FXC
2009#else
2010 return NULL;
2011#endif
ae8b8789
FXC
2012}
2013
5d723e54
FXC
2014gfc_offset
2015stream_offset (stream *s)
2016{
2017 return (((unix_stream *) s)->logical_offset);
2018}
2019
6de9cd9a
DN
2020
2021/* How files are stored: This is an operating-system specific issue,
2022 and therefore belongs here. There are three cases to consider.
2023
2024 Direct Access:
2025 Records are written as block of bytes corresponding to the record
2026 length of the file. This goes for both formatted and unformatted
2027 records. Positioning is done explicitly for each data transfer,
2028 so positioning is not much of an issue.
2029
2030 Sequential Formatted:
2031 Records are separated by newline characters. The newline character
2032 is prohibited from appearing in a string. If it does, this will be
2033 messed up on the next read. End of file is also the end of a record.
2034
2035 Sequential Unformatted:
2036 In this case, we are merely copying bytes to and from main storage,
2037 yet we need to keep track of varying record lengths. We adopt
2038 the solution used by f2c. Each record contains a pair of length
2039 markers:
2040
2041 Length of record n in bytes
2042 Data of record n
2043 Length of record n in bytes
2044
2045 Length of record n+1 in bytes
2046 Data of record n+1
2047 Length of record n+1 in bytes
2048
2049 The length is stored at the end of a record to allow backspacing to the
2050 previous record. Between data transfer statements, the file pointer
2051 is left pointing to the first length of the current record.
2052
2053 ENDFILE records are never explicitly stored.
2054
2055*/