]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/io/unix.c
Remove DOS line endings.
[thirdparty/gcc.git] / libgfortran / io / unix.c
CommitLineData
a0007dfa 1/* Copyright (C) 2002, 2003, 2004, 2005
2 Free Software Foundation, Inc.
4ee9c684 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
b417ea8c 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
4ee9c684 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
5ac2525b 28the Free Software Foundation, 51 Franklin Street, Fifth Floor,
29Boston, MA 02110-1301, USA. */
4ee9c684 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>
91e6f54a 38#include <stdio.h>
4ee9c684 39#include <sys/stat.h>
40#include <fcntl.h>
2639e4cd 41#include <assert.h>
4ee9c684 42
4ee9c684 43#include <string.h>
44#include <errno.h>
45
46#include "libgfortran.h"
47#include "io.h"
60c514ba 48#include "unix.h"
4ee9c684 49
8df8ec57 50#ifndef SSIZE_MAX
51#define SSIZE_MAX SHRT_MAX
52#endif
53
4ee9c684 54#ifndef PATH_MAX
55#define PATH_MAX 1024
56#endif
57
d2455565 58#ifndef PROT_READ
59#define PROT_READ 1
60#endif
61
62#ifndef PROT_WRITE
63#define PROT_WRITE 2
64#endif
65
7dfba97b 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
4ee9c684 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
4ee9c684 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 {
363dcb81 129 str->logical_offset += pos_off;
4ee9c684 130
363dcb81 131 if (str->dirty_offset + str->ndirty > str->logical_offset)
4ee9c684 132 {
363dcb81 133 if (str->ndirty + pos_off > 0)
134 str->ndirty += pos_off;
4ee9c684 135 else
136 {
137 str->dirty_offset += pos_off + pos_off;
363dcb81 138 str->ndirty = 0;
4ee9c684 139 }
140 }
141
363dcb81 142 return pos_off;
4ee9c684 143 }
363dcb81 144 return 0;
4ee9c684 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
7145fd06 162 /* Unix allocates the lowest descriptors first, so a loop is not
163 required, but this order is. */
4ee9c684 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
353c8a95 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}
4ee9c684 202
2488b3b6 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
4ee9c684 220
b2a112ca 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)
4ee9c684 226{
b2a112ca 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}
4ee9c684 232
4ee9c684 233
b2a112ca 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. */
4ee9c684 237
b2a112ca 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;
4ee9c684 272 }
273
b2a112ca 274 *nbytes -= bytes_left;
275 return status;
4ee9c684 276}
277
278
b2a112ca 279/* Write a buffer to a stream, allowing for short writes. */
4ee9c684 280
281static int
b2a112ca 282do_write (unix_stream * s, const void * buf, size_t * nbytes)
4ee9c684 283{
b2a112ca 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)
4ee9c684 296 {
b2a112ca 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;
4ee9c684 313 }
314
b2a112ca 315 *nbytes -= bytes_left;
316 return status;
4ee9c684 317}
4ee9c684 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{
4ee9c684 326 return strerror (errno);
327}
328
329
330/* sys_exit()-- Terminate the program with an exit code */
331
332void
333sys_exit (int code)
334{
4ee9c684 335 exit (code);
336}
337
338
4ee9c684 339/*********************************************************************
340 File descriptor stream functions
341*********************************************************************/
342
b2a112ca 343
4ee9c684 344/* fd_flush()-- Write bytes that need to be written */
345
346static try
347fd_flush (unix_stream * s)
348{
b2a112ca 349 size_t writelen;
350
4ee9c684 351 if (s->ndirty == 0)
352597f9 352 return SUCCESS;
353
354 if (s->file_length != -1 && s->physical_offset != s->dirty_offset &&
4ee9c684 355 lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
356 return FAILURE;
357
b2a112ca 358 writelen = s->ndirty;
359 if (do_write (s, s->buffer + (s->dirty_offset - s->buffer_offset),
360 &writelen) != 0)
4ee9c684 361 return FAILURE;
362
b2a112ca 363 s->physical_offset = s->dirty_offset + writelen;
5a78b88f 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)
b2a112ca 367 s->file_length = s->physical_offset;
368
369 s->ndirty -= writelen;
370 if (s->ndirty != 0)
371 return FAILURE;
4ee9c684 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
a0007dfa 382fd_alloc (unix_stream * s, gfc_offset where,
383 int *len __attribute__ ((unused)))
4ee9c684 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;
4ee9c684 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 *
b093181d 433fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
4ee9c684 434{
b093181d 435 gfc_offset m;
4ee9c684 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
fef3501c 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;
4ee9c684 474
fef3501c 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 }
4ee9c684 482
4ee9c684 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 *
b093181d 496fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
4ee9c684 497{
b093181d 498 gfc_offset n;
4ee9c684 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 */
5a78b88f 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;
4ee9c684 522 }
523 else
5a78b88f 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;
4ee9c684 535 }
536
537 s->logical_offset = where + *len;
538
352597f9 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;
f82543e7 543
4ee9c684 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{
4ee9c684 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
b2a112ca 564static try
b093181d 565fd_seek (unix_stream * s, gfc_offset offset)
4ee9c684 566{
352597f9 567
568 if (s->file_length == -1)
569 return SUCCESS;
570
b3ac1032 571 if (s->physical_offset == offset) /* Are we lucky and avoid syscall? */
572 {
573 s->logical_offset = offset;
574 return SUCCESS;
575 }
4ee9c684 576
b3ac1032 577 s->physical_offset = s->logical_offset = offset;
25545daf 578 s->active = 0;
b3ac1032 579
580 return (lseek (s->fd, offset, SEEK_SET) < 0) ? FAILURE : SUCCESS;
4ee9c684 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{
352597f9 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. */
5a78b88f 594 if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
352597f9 595 {
596 if (errno == ESPIPE)
597 return SUCCESS;
598 else
599 return FAILURE;
600 }
4ee9c684 601
352597f9 602 /* Using ftruncate on a seekable special file (like /dev/null)
603 is undefined, so we treat it as if the ftruncate succeeded. */
a54b1ce7 604#ifdef HAVE_FTRUNCATE
227e9423 605 if (s->special_file || ftruncate (s->fd, s->logical_offset))
a54b1ce7 606#else
607#ifdef HAVE_CHSIZE
227e9423 608 if (s->special_file || chsize (s->fd, s->logical_offset))
a54b1ce7 609#endif
610#endif
72909c79 611 {
612 s->physical_offset = s->file_length = 0;
1c201879 613 return SUCCESS;
72909c79 614 }
5a78b88f 615
616 s->physical_offset = s->file_length = s->logical_offset;
8c39329b 617 s->active = 0;
4ee9c684 618 return SUCCESS;
619}
620
621
56f281a2 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}
b2a112ca 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
b3ac1032 688 if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
b2a112ca 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
b3ac1032 736 if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
b2a112ca 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
4ee9c684 748static try
749fd_close (unix_stream * s)
750{
4ee9c684 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
f8f6940b 757 if (s->fd != STDOUT_FILENO && s->fd != STDERR_FILENO)
758 {
759 if (close (s->fd) < 0)
760 return FAILURE;
761 }
4ee9c684 762
763 free_mem (s);
764
765 return SUCCESS;
766}
767
768
769static void
770fd_open (unix_stream * s)
771{
4ee9c684 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;
b2a112ca 781 s->st.read = (void *) fd_read;
782 s->st.write = (void *) fd_write;
56f281a2 783 s->st.set = (void *) fd_sset;
4ee9c684 784
785 s->buffer = NULL;
786}
787
788
4ee9c684 789
b2a112ca 790
4ee9c684 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 *
b093181d 803mem_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
4ee9c684 804{
b093181d 805 gfc_offset n;
4ee9c684 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
4ee9c684 813 s->logical_offset = where + *len;
814
11de4bf9 815 n = s->buffer_offset + s->active - where;
4ee9c684 816 if (*len > n)
817 *len = n;
818
819 return s->buffer + (where - s->buffer_offset);
820}
821
822
823static char *
b093181d 824mem_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
4ee9c684 825{
b093181d 826 gfc_offset m;
4ee9c684 827
2639e4cd 828 assert (*len >= 0); /* Negative values not allowed. */
829
4ee9c684 830 if (where == -1)
831 where = s->logical_offset;
832
833 m = where + *len;
834
2639e4cd 835 if (where < s->buffer_offset)
4ee9c684 836 return NULL;
837
2639e4cd 838 if (m > s->file_length)
72231bd6 839 return NULL;
2639e4cd 840
4ee9c684 841 s->logical_offset = m;
842
843 return s->buffer + (where - s->buffer_offset);
844}
845
846
b2a112ca 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
4ee9c684 901static int
b093181d 902mem_seek (unix_stream * s, gfc_offset offset)
4ee9c684 903{
4ee9c684 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
56f281a2 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
4ee9c684 934static int
a0007dfa 935mem_truncate (unix_stream * s __attribute__ ((unused)))
4ee9c684 936{
4ee9c684 937 return SUCCESS;
938}
939
940
941static try
942mem_close (unix_stream * s)
943{
46ca759c 944 if (s != NULL)
945 free_mem (s);
4ee9c684 946
947 return SUCCESS;
948}
949
950
951static try
a0007dfa 952mem_sfree (unix_stream * s __attribute__ ((unused)))
4ee9c684 953{
4ee9c684 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{
7145fd06 969 unix_stream * s = (unix_stream *) strm;
970 memset(s->buffer, ' ', s->file_length);
4ee9c684 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));
8f8ad899 981 memset (s, '\0', sizeof (unix_stream));
4ee9c684 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;
b2a112ca 995 s->st.read = (void *) mem_read;
996 s->st.write = (void *) mem_write;
56f281a2 997 s->st.set = (void *) mem_set;
4ee9c684 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 *
f0b5d33f 1007fd_to_stream (int fd, int prot)
4ee9c684 1008{
1009 struct stat statbuf;
1010 unix_stream *s;
1011
1012 s = get_mem (sizeof (unix_stream));
8f8ad899 1013 memset (s, '\0', sizeof (unix_stream));
4ee9c684 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);
352597f9 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
227e9423 1030 s->special_file = !S_ISREG (statbuf.st_mode);
4ee9c684 1031
4ee9c684 1032 fd_open (s);
4ee9c684 1033
1034 return (stream *) s;
1035}
1036
1037
771c1b50 1038/* Given the Fortran unit number, convert it to a C file descriptor. */
1039
1040int
60c514ba 1041unit_to_fd (int unit)
771c1b50 1042{
771c1b50 1043 gfc_unit *us;
60c514ba 1044 int fd;
771c1b50 1045
60c514ba 1046 us = find_unit (unit);
771c1b50 1047 if (us == NULL)
1048 return -1;
1049
60c514ba 1050 fd = ((unix_stream *) us->s)->fd;
1051 unlock_unit (us);
1052 return fd;
771c1b50 1053}
1054
1055
4ee9c684 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
1dc95e51 1060int
4ee9c684 1061unpack_filename (char *cstring, const char *fstring, int len)
1062{
4ee9c684 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
7dfba97b 1077 * is returned, which is -1 on error. The template is pointed to by
60c514ba 1078 * opp->file, which is copied into the unit structure
4ee9c684 1079 * and freed later. */
1080
1081static int
60c514ba 1082tempfile (st_parameter_open *opp)
4ee9c684 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");
ac09d5cc 1091 if (tempdir == NULL)
1092 tempdir = getenv ("TEMP");
4ee9c684 1093 if (tempdir == NULL)
1094 tempdir = DEFAULT_TEMPDIR;
1095
1096 template = get_mem (strlen (tempdir) + 20);
1097
7dfba97b 1098 st_sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
1099
1100#ifdef HAVE_MKSTEMP
4ee9c684 1101
1102 fd = mkstemp (template);
1103
7dfba97b 1104#else /* HAVE_MKSTEMP */
1105
1106 if (mktemp (template))
1107 do
cf6a3896 1108#if defined(HAVE_CRLF) && defined(O_BINARY)
cf55c3cf 1109 fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
1110 S_IREAD | S_IWRITE);
1111#else
ac09d5cc 1112 fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
cf55c3cf 1113#endif
7dfba97b 1114 while (!(fd == -1 && errno == EEXIST) && mktemp (template));
1115 else
1116 fd = -1;
1117
1118#endif /* HAVE_MKSTEMP */
1119
4ee9c684 1120 if (fd < 0)
1121 free_mem (template);
1122 else
1123 {
60c514ba 1124 opp->file = template;
1125 opp->file_len = strlen (template); /* Don't include trailing nul */
4ee9c684 1126 }
1127
1128 return fd;
1129}
1130
1131
6d12c489 1132/* regular_file()-- Open a regular file.
2d6ba0f9 1133 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
1134 * unless an error occurs.
6d12c489 1135 * Returns the descriptor, which is less than zero on error. */
4ee9c684 1136
1137static int
60c514ba 1138regular_file (st_parameter_open *opp, unit_flags *flags)
4ee9c684 1139{
1140 char path[PATH_MAX + 1];
4ee9c684 1141 int mode;
6d12c489 1142 int rwflag;
2d6ba0f9 1143 int crflag;
6d12c489 1144 int fd;
4ee9c684 1145
60c514ba 1146 if (unpack_filename (path, opp->file, opp->file_len))
4ee9c684 1147 {
1148 errno = ENOENT; /* Fake an OS error */
1149 return -1;
1150 }
1151
6d12c489 1152 rwflag = 0;
4ee9c684 1153
6d12c489 1154 switch (flags->action)
4ee9c684 1155 {
1156 case ACTION_READ:
6d12c489 1157 rwflag = O_RDONLY;
4ee9c684 1158 break;
1159
1160 case ACTION_WRITE:
6d12c489 1161 rwflag = O_WRONLY;
4ee9c684 1162 break;
1163
1164 case ACTION_READWRITE:
6d12c489 1165 case ACTION_UNSPECIFIED:
1166 rwflag = O_RDWR;
4ee9c684 1167 break;
1168
1169 default:
60c514ba 1170 internal_error (&opp->common, "regular_file(): Bad action");
4ee9c684 1171 }
1172
6d12c489 1173 switch (flags->status)
4ee9c684 1174 {
1175 case STATUS_NEW:
2d6ba0f9 1176 crflag = O_CREAT | O_EXCL;
4ee9c684 1177 break;
1178
2d6ba0f9 1179 case STATUS_OLD: /* open will fail if the file does not exist*/
1180 crflag = 0;
4ee9c684 1181 break;
1182
1183 case STATUS_UNKNOWN:
1184 case STATUS_SCRATCH:
2d6ba0f9 1185 crflag = O_CREAT;
4ee9c684 1186 break;
1187
1188 case STATUS_REPLACE:
2d6ba0f9 1189 crflag = O_CREAT | O_TRUNC;
4ee9c684 1190 break;
1191
1192 default:
60c514ba 1193 internal_error (&opp->common, "regular_file(): Bad status");
4ee9c684 1194 }
1195
6d12c489 1196 /* rwflag |= O_LARGEFILE; */
4ee9c684 1197
cf6a3896 1198#if defined(HAVE_CRLF) && defined(O_BINARY)
cf55c3cf 1199 crflag |= O_BINARY;
1200#endif
1201
6d12c489 1202 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
2d6ba0f9 1203 fd = open (path, rwflag | crflag, mode);
1204 if (flags->action != ACTION_UNSPECIFIED)
1205 return fd;
1206
1207 if (fd >= 0)
6d12c489 1208 {
2d6ba0f9 1209 flags->action = ACTION_READWRITE;
1210 return fd;
6d12c489 1211 }
2d6ba0f9 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 */
4ee9c684 1236}
1237
1238
1239/* open_external()-- Open an external file, unix specific version.
6d12c489 1240 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
4ee9c684 1241 * Returns NULL on operating system error. */
1242
1243stream *
60c514ba 1244open_external (st_parameter_open *opp, unit_flags *flags)
4ee9c684 1245{
1246 int fd, prot;
1247
6d12c489 1248 if (flags->status == STATUS_SCRATCH)
1249 {
60c514ba 1250 fd = tempfile (opp);
6d12c489 1251 if (flags->action == ACTION_UNSPECIFIED)
1252 flags->action = ACTION_READWRITE;
1dc95e51 1253
1254#if HAVE_UNLINK_OPEN_FILE
6d12c489 1255 /* We can unlink scratch files now and it will go away when closed. */
60c514ba 1256 if (fd >= 0)
1257 unlink (opp->file);
1dc95e51 1258#endif
6d12c489 1259 }
1260 else
1261 {
2d6ba0f9 1262 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1263 * if it succeeds */
60c514ba 1264 fd = regular_file (opp, flags);
6d12c489 1265 }
4ee9c684 1266
1267 if (fd < 0)
1268 return NULL;
1269 fd = fix_fd (fd);
1270
6d12c489 1271 switch (flags->action)
4ee9c684 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:
60c514ba 1286 internal_error (&opp->common, "open_external(): Bad action");
4ee9c684 1287 }
1288
f0b5d33f 1289 return fd_to_stream (fd, prot);
4ee9c684 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{
f0b5d33f 1299 return fd_to_stream (STDIN_FILENO, PROT_READ);
4ee9c684 1300}
1301
1302
ff81ee3b 1303/* output_stream()-- Return a stream pointer to the default output stream.
4ee9c684 1304 * Called on initialization. */
1305
1306stream *
1307output_stream (void)
1308{
e693d7f1 1309#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1310 setmode (STDOUT_FILENO, O_BINARY);
1311#endif
f0b5d33f 1312 return fd_to_stream (STDOUT_FILENO, PROT_WRITE);
4ee9c684 1313}
1314
1315
ff81ee3b 1316/* error_stream()-- Return a stream pointer to the default error stream.
1317 * Called on initialization. */
1318
1319stream *
1320error_stream (void)
1321{
e693d7f1 1322#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1323 setmode (STDERR_FILENO, O_BINARY);
1324#endif
f0b5d33f 1325 return fd_to_stream (STDERR_FILENO, PROT_WRITE);
ff81ee3b 1326}
1327
4ee9c684 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 *
60c514ba 1334init_error_stream (unix_stream *error)
4ee9c684 1335{
60c514ba 1336 memset (error, '\0', sizeof (*error));
4ee9c684 1337
60c514ba 1338 error->fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
4ee9c684 1339
60c514ba 1340 error->st.alloc_w_at = (void *) fd_alloc_w_at;
1341 error->st.sfree = (void *) fd_sfree;
4ee9c684 1342
60c514ba 1343 error->unbuffered = 1;
1344 error->buffer = error->small_buffer;
4ee9c684 1345
60c514ba 1346 return (stream *) error;
4ee9c684 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
daad4fd5 1355compare_file_filename (gfc_unit *u, const char *name, int len)
4ee9c684 1356{
1357 char path[PATH_MAX + 1];
daad4fd5 1358 struct stat st1;
1359#ifdef HAVE_WORKING_STAT
1360 struct stat st2;
1361#endif
4ee9c684 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
daad4fd5 1372#ifdef HAVE_WORKING_STAT
1373 fstat (((unix_stream *) (u->s))->fd, &st2);
4ee9c684 1374 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
daad4fd5 1375#else
1376 if (len != u->file_len)
1377 return 0;
1378 return (memcmp(path, u->file, len) == 0);
1379#endif
4ee9c684 1380}
1381
1382
60c514ba 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
4ee9c684 1391/* find_file0()-- Recursive work function for find_file() */
1392
f02dd226 1393static gfc_unit *
60c514ba 1394find_file0 (gfc_unit *u, FIND_FILE0_DECL)
4ee9c684 1395{
f02dd226 1396 gfc_unit *v;
4ee9c684 1397
1398 if (u == NULL)
1399 return NULL;
1400
daad4fd5 1401#ifdef HAVE_WORKING_STAT
60c514ba 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)
4ee9c684 1405 return u;
daad4fd5 1406#else
60c514ba 1407 if (compare_string (u->file_len, u->file, file_len, file) == 0)
daad4fd5 1408 return u;
1409#endif
4ee9c684 1410
60c514ba 1411 v = find_file0 (u->left, FIND_FILE0_ARGS);
4ee9c684 1412 if (v != NULL)
1413 return v;
1414
60c514ba 1415 v = find_file0 (u->right, FIND_FILE0_ARGS);
4ee9c684 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
f02dd226 1426gfc_unit *
60c514ba 1427find_file (const char *file, gfc_charlen_type file_len)
4ee9c684 1428{
1429 char path[PATH_MAX + 1];
60c514ba 1430 struct stat st[2];
1431 gfc_unit *u;
4ee9c684 1432
60c514ba 1433 if (unpack_filename (path, file, file_len))
4ee9c684 1434 return NULL;
1435
60c514ba 1436 if (stat (path, &st[0]) < 0)
4ee9c684 1437 return NULL;
1438
60c514ba 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);
4ee9c684 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
5df4b62f 1543 if (!is_seekable (s))
1544 return 0;
4ee9c684 1545
5df4b62f 1546 us = (unix_stream *) s;
4ee9c684 1547
1548 return us->logical_offset == 0;
1549}
1550
1551
cf6a3896 1552/* stream_at_eof()-- Returns nonzero if the stream is at the end
4ee9c684 1553 * of the file. */
1554
1555int
1556stream_at_eof (stream * s)
1557{
1558 unix_stream *us;
1559
5df4b62f 1560 if (!is_seekable (s))
1561 return 0;
4ee9c684 1562
5df4b62f 1563 us = (unix_stream *) s;
4ee9c684 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
f02dd226 1573delete_file (gfc_unit * u)
4ee9c684 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
60c514ba 1591file_exists (const char *file, gfc_charlen_type file_len)
4ee9c684 1592{
1593 char path[PATH_MAX + 1];
1594 struct stat statbuf;
1595
60c514ba 1596 if (unpack_filename (path, file, file_len))
4ee9c684 1597 return 0;
1598
1599 if (stat (path, &statbuf) < 0)
1600 return 0;
1601
1602 return 1;
1603}
1604
1605
1606
fb35179a 1607static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
4ee9c684 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{
4ee9c684 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{
4ee9c684 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{
4ee9c684 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{
4ee9c684 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
b093181d 1741gfc_offset
4ee9c684 1742file_length (stream * s)
1743{
4ee9c684 1744 return ((unix_stream *) s)->file_length;
1745}
1746
1747
1748/* file_position()-- Return the current position of the file */
1749
b093181d 1750gfc_offset
4ee9c684 1751file_position (stream * s)
1752{
4ee9c684 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{
b2a112ca 1763 /* By convention, if file_length == -1, the file is not
1764 seekable. */
5a78b88f 1765 return ((unix_stream *) s)->file_length!=-1;
4ee9c684 1766}
1767
b0342e98 1768try
1769flush (stream *s)
1770{
1771 return fd_flush( (unix_stream *) s);
1772}
1773
60d77e0d 1774int
1775stream_isatty (stream *s)
1776{
1777 return isatty (((unix_stream *) s)->fd);
1778}
1779
1780char *
1781stream_ttyname (stream *s)
1782{
f2c0a16d 1783#ifdef HAVE_TTYNAME
60d77e0d 1784 return ttyname (((unix_stream *) s)->fd);
f2c0a16d 1785#else
1786 return NULL;
1787#endif
60d77e0d 1788}
1789
16de8065 1790gfc_offset
1791stream_offset (stream *s)
1792{
1793 return (((unix_stream *) s)->logical_offset);
1794}
1795
4ee9c684 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*/