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