]> gcc.gnu.org Git - gcc.git/blame - libgfortran/io/unix.c
list_read.c (eat_separator): Set at_eo when a '/' is seen.
[gcc.git] / libgfortran / io / unix.c
CommitLineData
6de9cd9a
DN
1/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3
4This file is part of the GNU Fortran 95 runtime library (libgfortran).
5
6Libgfortran is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11Libgfortran is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with Libgfortran; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21/* Unix stream I/O module */
22
23#include "config.h"
24#include <stdlib.h>
25#include <limits.h>
26
27#include <unistd.h>
28#include <sys/stat.h>
29#include <fcntl.h>
30
31#include <sys/mman.h>
32#include <string.h>
33#include <errno.h>
34
35#include "libgfortran.h"
36#include "io.h"
37
38#ifndef PATH_MAX
39#define PATH_MAX 1024
40#endif
41
42#ifndef MAP_FAILED
43#define MAP_FAILED ((void *) -1)
44#endif
45
46/* This implementation of stream I/O is based on the paper:
47 *
48 * "Exploiting the advantages of mapped files for stream I/O",
49 * O. Krieger, M. Stumm and R. Umrau, "Proceedings of the 1992 Winter
50 * USENIX conference", p. 27-42.
51 *
52 * It differs in a number of ways from the version described in the
53 * paper. First of all, threads are not an issue during I/O and we
54 * also don't have to worry about having multiple regions, since
55 * fortran's I/O model only allows you to be one place at a time.
56 *
57 * On the other hand, we have to be able to writing at the end of a
58 * stream, read from the start of a stream or read and write blocks of
59 * bytes from an arbitrary position. After opening a file, a pointer
60 * to a stream structure is returned, which is used to handle file
61 * accesses until the file is closed.
62 *
63 * salloc_at_r(stream, len, where)-- Given a stream pointer, return a
64 * pointer to a block of memory that mirror the file at position
65 * 'where' that is 'len' bytes long. The len integer is updated to
66 * reflect how many bytes were actually read. The only reason for a
67 * short read is end of file. The file pointer is updated. The
68 * pointer is valid until the next call to salloc_*.
69 *
70 * salloc_at_w(stream, len, where)-- Given the stream pointer, returns
71 * a pointer to a block of memory that is updated to reflect the state
72 * of the file. The length of the buffer is always equal to that
73 * requested. The buffer must be completely set by the caller. When
74 * data has been written, the sfree() function must be called to
75 * indicate that the caller is done writing data to the buffer. This
76 * may or may not cause a physical write.
77 *
78 * Short forms of these are salloc_r() and salloc_w() which drop the
79 * 'where' parameter and use the current file pointer. */
80
81
82#define BUFFER_SIZE 8192
83
84typedef struct
85{
86 stream st;
87
88 int fd;
81f4be3c
TS
89 gfc_offset buffer_offset; /* File offset of the start of the buffer */
90 gfc_offset physical_offset; /* Current physical file offset */
91 gfc_offset logical_offset; /* Current logical file offset */
92 gfc_offset dirty_offset; /* Start of modified bytes in buffer */
bf1df0a0 93 gfc_offset file_length; /* Length of the file, -1 if not seekable. */
6de9cd9a
DN
94
95 char *buffer;
96 int len; /* Physical length of the current buffer */
97 int active; /* Length of valid bytes in the buffer */
98
99 int prot;
100 int ndirty; /* Dirty bytes starting at dirty_offset */
101
102 unsigned unbuffered:1, mmaped:1;
103
104 char small_buffer[BUFFER_SIZE];
105
106}
107unix_stream;
108
109/*move_pos_offset()-- Move the record pointer right or left
110 *relative to current position */
111
112int
113move_pos_offset (stream* st, int pos_off)
114{
115 unix_stream * str = (unix_stream*)st;
116 if (pos_off < 0)
117 {
118 str->active += pos_off;
119 if (str->active < 0)
120 str->active = 0;
121
122 str->logical_offset += pos_off;
123
124 if (str->dirty_offset+str->ndirty > str->logical_offset)
125 {
126 if (str->ndirty + pos_off > 0)
127 str->ndirty += pos_off ;
128 else
129 {
130 str->dirty_offset += pos_off + pos_off;
131 str->ndirty = 0 ;
132 }
133 }
134
135 return pos_off ;
136 }
137 return 0 ;
138}
139
140
141/* fix_fd()-- Given a file descriptor, make sure it is not one of the
142 * standard descriptors, returning a non-standard descriptor. If the
143 * user specifies that system errors should go to standard output,
144 * then closes standard output, we don't want the system errors to a
145 * file that has been given file descriptor 1 or 0. We want to send
146 * the error to the invalid descriptor. */
147
148static int
149fix_fd (int fd)
150{
151 int input, output, error;
152
153 input = output = error = 0;
154
155/* Unix allocates the lowest descriptors first, so a loop is not
156 * required, but this order is. */
157
158 if (fd == STDIN_FILENO)
159 {
160 fd = dup (fd);
161 input = 1;
162 }
163 if (fd == STDOUT_FILENO)
164 {
165 fd = dup (fd);
166 output = 1;
167 }
168 if (fd == STDERR_FILENO)
169 {
170 fd = dup (fd);
171 error = 1;
172 }
173
174 if (input)
175 close (STDIN_FILENO);
176 if (output)
177 close (STDOUT_FILENO);
178 if (error)
179 close (STDERR_FILENO);
180
181 return fd;
182}
183
184
185/* write()-- Write a buffer to a descriptor, allowing for short writes */
186
187static int
188writen (int fd, char *buffer, int len)
189{
190 int n, n0;
191
192 n0 = len;
193
194 while (len > 0)
195 {
196 n = write (fd, buffer, len);
197 if (n < 0)
198 return n;
199
200 buffer += n;
201 len -= n;
202 }
203
204 return n0;
205}
206
207
208#if 0
209/* readn()-- Read bytes into a buffer, allowing for short reads. If
210 * fewer than len bytes are returned, it is because we've hit the end
211 * of file. */
212
213static int
214readn (int fd, char *buffer, int len)
215{
216 int nread, n;
217
218 nread = 0;
219
220 while (len > 0)
221 {
222 n = read (fd, buffer, len);
223 if (n < 0)
224 return n;
225
226 if (n == 0)
227 return nread;
228
229 buffer += n;
230 nread += n;
231 len -= n;
232 }
233
234 return nread;
235}
236#endif
237
238
239/* get_oserror()-- Get the most recent operating system error. For
240 * unix, this is errno. */
241
242const char *
243get_oserror (void)
244{
245
246 return strerror (errno);
247}
248
249
250/* sys_exit()-- Terminate the program with an exit code */
251
252void
253sys_exit (int code)
254{
255
256 exit (code);
257}
258
259
260
261/*********************************************************************
262 File descriptor stream functions
263*********************************************************************/
264
265/* fd_flush()-- Write bytes that need to be written */
266
267static try
268fd_flush (unix_stream * s)
269{
270
271 if (s->ndirty == 0)
272 return SUCCESS;;
273
274 if (s->physical_offset != s->dirty_offset &&
275 lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
276 return FAILURE;
277
278 if (writen (s->fd, s->buffer + (s->dirty_offset - s->buffer_offset),
279 s->ndirty) < 0)
280 return FAILURE;
281
282 s->physical_offset = s->dirty_offset + s->ndirty;
bf1df0a0
BD
283
284 /* don't increment file_length if the file is non-seekable */
285 if (s->file_length != -1 && s->physical_offset > s->file_length)
6de9cd9a
DN
286 s->file_length = s->physical_offset;
287 s->ndirty = 0;
288
289 return SUCCESS;
290}
291
292
293/* fd_alloc()-- Arrange a buffer such that the salloc() request can be
294 * satisfied. This subroutine gets the buffer ready for whatever is
295 * to come next. */
296
297static void
81f4be3c 298fd_alloc (unix_stream * s, gfc_offset where, int *len)
6de9cd9a
DN
299{
300 char *new_buffer;
301 int n, read_len;
302
303 if (*len <= BUFFER_SIZE)
304 {
305 new_buffer = s->small_buffer;
306 read_len = BUFFER_SIZE;
307 }
308 else
309 {
310 new_buffer = get_mem (*len);
311 read_len = *len;
312 }
313
314 /* Salvage bytes currently within the buffer. This is important for
315 * devices that cannot seek. */
316
317 if (s->buffer != NULL && s->buffer_offset <= where &&
318 where <= s->buffer_offset + s->active)
319 {
320
321 n = s->active - (where - s->buffer_offset);
322 memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
323
324 s->active = n;
325 }
326 else
327 { /* new buffer starts off empty */
328 s->active = 0;
329 }
330
331 s->buffer_offset = where;
332
333 /* free the old buffer if necessary */
334
335 if (s->buffer != NULL && s->buffer != s->small_buffer)
336 free_mem (s->buffer);
337
338 s->buffer = new_buffer;
339 s->len = read_len;
340 s->mmaped = 0;
341}
342
343
344/* fd_alloc_r_at()-- Allocate a stream buffer for reading. Either
345 * we've already buffered the data or we need to load it. Returns
346 * NULL on I/O error. */
347
348static char *
81f4be3c 349fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
6de9cd9a 350{
81f4be3c 351 gfc_offset m;
6de9cd9a
DN
352 int n;
353
354 if (where == -1)
355 where = s->logical_offset;
356
357 if (s->buffer != NULL && s->buffer_offset <= where &&
358 where + *len <= s->buffer_offset + s->active)
359 {
360
361 /* Return a position within the current buffer */
362
363 s->logical_offset = where + *len;
364 return s->buffer + where - s->buffer_offset;
365 }
366
367 fd_alloc (s, where, len);
368
369 m = where + s->active;
370
371 if (s->physical_offset != m && lseek (s->fd, m, SEEK_SET) < 0)
372 return NULL;
373
374 n = read (s->fd, s->buffer + s->active, s->len - s->active);
375 if (n < 0)
376 return NULL;
377
378 s->physical_offset = where + n;
379
380 s->active += n;
381 if (s->active < *len)
382 *len = s->active; /* Bytes actually available */
383
384 s->logical_offset = where + *len;
385
386 return s->buffer;
387}
388
389
390/* fd_alloc_w_at()-- Allocate a stream buffer for writing. Either
391 * we've already buffered the data or we need to load it. */
392
393static char *
81f4be3c 394fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
6de9cd9a 395{
81f4be3c 396 gfc_offset n;
6de9cd9a
DN
397
398 if (where == -1)
399 where = s->logical_offset;
400
401 if (s->buffer == NULL || s->buffer_offset > where ||
402 where + *len > s->buffer_offset + s->len)
403 {
404
405 if (fd_flush (s) == FAILURE)
406 return NULL;
407 fd_alloc (s, where, len);
408 }
409
410 /* Return a position within the current buffer */
bf1df0a0
BD
411 if (s->ndirty == 0
412 || where > s->dirty_offset + s->ndirty
413 || s->dirty_offset > where + *len)
414 { /* Discontiguous blocks, start with a clean buffer. */
415 /* Flush the buffer. */
416 if (s->ndirty != 0)
417 fd_flush (s);
418 s->dirty_offset = where;
419 s->ndirty = *len;
6de9cd9a
DN
420 }
421 else
bf1df0a0
BD
422 {
423 gfc_offset start; /* Merge with the existing data. */
424 if (where < s->dirty_offset)
425 start = where;
426 else
427 start = s->dirty_offset;
428 if (where + *len > s->dirty_offset + s->ndirty)
429 s->ndirty = where + *len - start;
430 else
431 s->ndirty = s->dirty_offset + s->ndirty - start;
432 s->dirty_offset = start;
6de9cd9a
DN
433 }
434
435 s->logical_offset = where + *len;
436
437 n = s->logical_offset - s->buffer_offset;
438 if (n > s->active)
439 s->active = n;
440
441 return s->buffer + where - s->buffer_offset;
442}
443
444
445static try
446fd_sfree (unix_stream * s)
447{
448
449 if (s->ndirty != 0 &&
450 (s->buffer != s->small_buffer || options.all_unbuffered ||
451 s->unbuffered))
452 return fd_flush (s);
453
454 return SUCCESS;
455}
456
457
458static int
81f4be3c 459fd_seek (unix_stream * s, gfc_offset offset)
6de9cd9a
DN
460{
461
462 s->physical_offset = s->logical_offset = offset;
463
464 return (lseek (s->fd, offset, SEEK_SET) < 0) ? FAILURE : SUCCESS;
465}
466
467
468/* truncate_file()-- Given a unit, truncate the file at the current
469 * position. Sets the physical location to the new end of the file.
470 * Returns nonzero on error. */
471
472static try
473fd_truncate (unix_stream * s)
474{
475
bf1df0a0 476 if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
6de9cd9a
DN
477 return FAILURE;
478
bf1df0a0
BD
479 /* non-seekable files, like terminals and fifo's fail the lseek.
480 the fd is a regular file at this point */
6de9cd9a 481
bf1df0a0
BD
482 if (ftruncate (s->fd, s->logical_offset))
483 {
6de9cd9a 484 return FAILURE;
bf1df0a0
BD
485 }
486
487 s->physical_offset = s->file_length = s->logical_offset;
6de9cd9a
DN
488
489 return SUCCESS;
490}
491
492
493static try
494fd_close (unix_stream * s)
495{
496
497 if (fd_flush (s) == FAILURE)
498 return FAILURE;
499
500 if (s->buffer != NULL && s->buffer != s->small_buffer)
501 free_mem (s->buffer);
502
503 if (close (s->fd) < 0)
504 return FAILURE;
505
506 free_mem (s);
507
508 return SUCCESS;
509}
510
511
512static void
513fd_open (unix_stream * s)
514{
515
516 if (isatty (s->fd))
517 s->unbuffered = 1;
518
519 s->st.alloc_r_at = (void *) fd_alloc_r_at;
520 s->st.alloc_w_at = (void *) fd_alloc_w_at;
521 s->st.sfree = (void *) fd_sfree;
522 s->st.close = (void *) fd_close;
523 s->st.seek = (void *) fd_seek;
524 s->st.truncate = (void *) fd_truncate;
525
526 s->buffer = NULL;
527}
528
529
530/*********************************************************************
531 mmap stream functions
532
533 Because mmap() is not capable of extending a file, we have to keep
534 track of how long the file is. We also have to be able to detect end
535 of file conditions. If there are multiple writers to the file (which
536 can only happen outside the current program), things will get
537 confused. Then again, things will get confused anyway.
538
539*********************************************************************/
540
541#if HAVE_MMAP
542
543static int page_size, page_mask;
544
545/* mmap_flush()-- Deletes a memory mapping if something is mapped. */
546
547static try
548mmap_flush (unix_stream * s)
549{
550
551 if (!s->mmaped)
552 return fd_flush (s);
553
554 if (s->buffer == NULL)
555 return SUCCESS;
556
557 if (munmap (s->buffer, s->active))
558 return FAILURE;
559
560 s->buffer = NULL;
561 s->active = 0;
562
563 return SUCCESS;
564}
565
566
567/* mmap_alloc()-- mmap() a section of the file. The whole section is
568 * guaranteed to be mappable. */
569
570static try
81f4be3c 571mmap_alloc (unix_stream * s, gfc_offset where, int *len)
6de9cd9a 572{
81f4be3c 573 gfc_offset offset;
6de9cd9a
DN
574 int length;
575 char *p;
576
577 if (mmap_flush (s) == FAILURE)
578 return FAILURE;
579
580 offset = where & page_mask; /* Round down to the next page */
581
582 length = ((where - offset) & page_mask) + 2 * page_size;
583
584 p = mmap (NULL, length, s->prot, MAP_SHARED, s->fd, offset);
585 if (p == (char *) MAP_FAILED)
586 return FAILURE;
587
588 s->mmaped = 1;
589 s->buffer = p;
590 s->buffer_offset = offset;
591 s->active = length;
592
593 return SUCCESS;
594}
595
596
597static char *
81f4be3c 598mmap_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
6de9cd9a 599{
81f4be3c 600 gfc_offset m;
6de9cd9a
DN
601
602 if (where == -1)
603 where = s->logical_offset;
604
605 m = where + *len;
606
607 if ((s->buffer == NULL || s->buffer_offset > where ||
608 m > s->buffer_offset + s->active) &&
609 mmap_alloc (s, where, len) == FAILURE)
610 return NULL;
611
612 if (m > s->file_length)
613 {
614 *len = s->file_length - s->logical_offset;
615 s->logical_offset = s->file_length;
616 }
617 else
618 s->logical_offset = m;
619
620 return s->buffer + (where - s->buffer_offset);
621}
622
623
624static char *
81f4be3c 625mmap_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
6de9cd9a
DN
626{
627 if (where == -1)
628 where = s->logical_offset;
629
630 /* If we're extending the file, we have to use file descriptor
631 * methods. */
632
633 if (where + *len > s->file_length)
634 {
635 if (s->mmaped)
636 mmap_flush (s);
637 return fd_alloc_w_at (s, len, where);
638 }
639
640 if ((s->buffer == NULL || s->buffer_offset > where ||
641 where + *len > s->buffer_offset + s->active) &&
642 mmap_alloc (s, where, len) == FAILURE)
643 return NULL;
644
645 s->logical_offset = where + *len;
646
647 return s->buffer + where - s->buffer_offset;
648}
649
650
651static int
81f4be3c 652mmap_seek (unix_stream * s, gfc_offset offset)
6de9cd9a
DN
653{
654
655 s->logical_offset = offset;
656 return SUCCESS;
657}
658
659
660static try
661mmap_close (unix_stream * s)
662{
663 try t;
664
665 t = mmap_flush (s);
666
667 if (close (s->fd) < 0)
668 t = FAILURE;
669 free_mem (s);
670
671 return t;
672}
673
674
675static try
676mmap_sfree (unix_stream * s)
677{
678
679 return SUCCESS;
680}
681
682
683/* mmap_open()-- mmap_specific open. If the particular file cannot be
684 * mmap()-ed, we fall back to the file descriptor functions. */
685
686static try
687mmap_open (unix_stream * s)
688{
689 char *p;
690 int i;
691
692 page_size = getpagesize ();
693 page_mask = ~0;
694
695 p = mmap (0, page_size, s->prot, MAP_SHARED, s->fd, 0);
696 if (p == (char *) MAP_FAILED)
697 {
698 fd_open (s);
699 return SUCCESS;
700 }
701
702 munmap (p, page_size);
703
704 i = page_size >> 1;
705 while (i != 0)
706 {
707 page_mask <<= 1;
708 i >>= 1;
709 }
710
711 s->st.alloc_r_at = (void *) mmap_alloc_r_at;
712 s->st.alloc_w_at = (void *) mmap_alloc_w_at;
713 s->st.sfree = (void *) mmap_sfree;
714 s->st.close = (void *) mmap_close;
715 s->st.seek = (void *) mmap_seek;
716 s->st.truncate = (void *) fd_truncate;
717
718 if (lseek (s->fd, s->file_length, SEEK_SET) < 0)
719 return FAILURE;
720
721 return SUCCESS;
722}
723
724#endif
725
726
727/*********************************************************************
728 memory stream functions - These are used for internal files
729
730 The idea here is that a single stream structure is created and all
731 requests must be satisfied from it. The location and size of the
732 buffer is the character variable supplied to the READ or WRITE
733 statement.
734
735*********************************************************************/
736
737
738static char *
81f4be3c 739mem_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
6de9cd9a 740{
81f4be3c 741 gfc_offset n;
6de9cd9a
DN
742
743 if (where == -1)
744 where = s->logical_offset;
745
746 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
747 return NULL;
748
749 if (is_internal_unit() && where + *len > s->file_length)
750 return NULL;
751
752 s->logical_offset = where + *len;
753
754 n = (where - s->buffer_offset) - s->active;
755 if (*len > n)
756 *len = n;
757
758 return s->buffer + (where - s->buffer_offset);
759}
760
761
762static char *
81f4be3c 763mem_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
6de9cd9a 764{
81f4be3c 765 gfc_offset m;
6de9cd9a
DN
766
767 if (where == -1)
768 where = s->logical_offset;
769
770 m = where + *len;
771
772 if (where < s->buffer_offset || m > s->buffer_offset + s->active)
773 return NULL;
774
775 s->logical_offset = m;
776
777 return s->buffer + (where - s->buffer_offset);
778}
779
780
781static int
81f4be3c 782mem_seek (unix_stream * s, gfc_offset offset)
6de9cd9a
DN
783{
784
785 if (offset > s->file_length)
786 {
787 errno = ESPIPE;
788 return FAILURE;
789 }
790
791 s->logical_offset = offset;
792 return SUCCESS;
793}
794
795
796static int
797mem_truncate (unix_stream * s)
798{
799
800 return SUCCESS;
801}
802
803
804static try
805mem_close (unix_stream * s)
806{
807
808 return SUCCESS;
809}
810
811
812static try
813mem_sfree (unix_stream * s)
814{
815
816 return SUCCESS;
817}
818
819
820
821/*********************************************************************
822 Public functions -- A reimplementation of this module needs to
823 define functional equivalents of the following.
824*********************************************************************/
825
826/* empty_internal_buffer()-- Zero the buffer of Internal file */
827
828void
829empty_internal_buffer(stream *strm)
830{
831 unix_stream * s = (unix_stream *) strm;
832 memset(s->buffer, ' ', s->file_length);
833}
834
835/* open_internal()-- Returns a stream structure from an internal file */
836
837stream *
838open_internal (char *base, int length)
839{
840 unix_stream *s;
841
842 s = get_mem (sizeof (unix_stream));
843
844 s->buffer = base;
845 s->buffer_offset = 0;
846
847 s->logical_offset = 0;
848 s->active = s->file_length = length;
849
850 s->st.alloc_r_at = (void *) mem_alloc_r_at;
851 s->st.alloc_w_at = (void *) mem_alloc_w_at;
852 s->st.sfree = (void *) mem_sfree;
853 s->st.close = (void *) mem_close;
854 s->st.seek = (void *) mem_seek;
855 s->st.truncate = (void *) mem_truncate;
856
857 return (stream *) s;
858}
859
860
861/* fd_to_stream()-- Given an open file descriptor, build a stream
862 * around it. */
863
864static stream *
865fd_to_stream (int fd, int prot)
866{
867 struct stat statbuf;
868 unix_stream *s;
869
870 s = get_mem (sizeof (unix_stream));
871
872 s->fd = fd;
873 s->buffer_offset = 0;
874 s->physical_offset = 0;
875 s->logical_offset = 0;
876 s->prot = prot;
877
878 /* Get the current length of the file. */
879
880 fstat (fd, &statbuf);
881 s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
882
883#if HAVE_MMAP
884 mmap_open (s);
885#else
886 fd_open (s);
887#endif
888
889 return (stream *) s;
890}
891
892
893/* unpack_filename()-- Given a fortran string and a pointer to a
894 * buffer that is PATH_MAX characters, convert the fortran string to a
895 * C string in the buffer. Returns nonzero if this is not possible. */
896
897static int
898unpack_filename (char *cstring, const char *fstring, int len)
899{
900
901 len = fstrlen (fstring, len);
902 if (len >= PATH_MAX)
903 return 1;
904
905 memmove (cstring, fstring, len);
906 cstring[len] = '\0';
907
908 return 0;
909}
910
911
912/* tempfile()-- Generate a temporary filename for a scratch file and
913 * open it. mkstemp() opens the file for reading and writing, but the
914 * library mode prevents anything that is not allowed. The descriptor
915 * is returns, which is less than zero on error. The template is
916 * pointed to by ioparm.file, which is copied into the unit structure
917 * and freed later. */
918
919static int
920tempfile (void)
921{
922 const char *tempdir;
923 char *template;
924 int fd;
925
926 tempdir = getenv ("GFORTRAN_TMPDIR");
927 if (tempdir == NULL)
928 tempdir = getenv ("TMP");
929 if (tempdir == NULL)
930 tempdir = DEFAULT_TEMPDIR;
931
932 template = get_mem (strlen (tempdir) + 20);
933
934 st_sprintf (template, "%s/gfortantmpXXXXXX", tempdir);
935
936 fd = mkstemp (template);
937
938 if (fd < 0)
939 free_mem (template);
940 else
941 {
942 ioparm.file = template;
943 ioparm.file_len = strlen (template); /* Don't include trailing nul */
944 }
945
946 return fd;
947}
948
949
950/* regular_file()-- Open a regular file. Returns the descriptor, which is less than zero on error. */
951
952static int
953regular_file (unit_action action, unit_status status)
954{
955 char path[PATH_MAX + 1];
956 struct stat statbuf;
957 int mode;
958
959 if (unpack_filename (path, ioparm.file, ioparm.file_len))
960 {
961 errno = ENOENT; /* Fake an OS error */
962 return -1;
963 }
964
965 mode = 0;
966
967 switch (action)
968 {
969 case ACTION_READ:
970 mode = O_RDONLY;
971 break;
972
973 case ACTION_WRITE:
974 mode = O_WRONLY;
975 break;
976
977 case ACTION_READWRITE:
978 mode = O_RDWR;
979 break;
980
981 default:
982 internal_error ("regular_file(): Bad action");
983 }
984
985 switch (status)
986 {
987 case STATUS_NEW:
988 mode |= O_CREAT | O_EXCL;
989 break;
990
991 case STATUS_OLD: /* file must exist, so check for its existence */
992 if (stat (path, &statbuf) < 0)
993 return -1;
994 break;
995
996 case STATUS_UNKNOWN:
997 case STATUS_SCRATCH:
998 mode |= O_CREAT;
999 break;
1000
1001 case STATUS_REPLACE:
3e14aaa2 1002 mode |= O_CREAT | O_TRUNC;
6de9cd9a
DN
1003 break;
1004
1005 default:
1006 internal_error ("regular_file(): Bad status");
1007 }
1008
1009 // mode |= O_LARGEFILE;
1010
1011 return open (path, mode,
1012 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1013}
1014
1015
1016/* open_external()-- Open an external file, unix specific version.
1017 * Returns NULL on operating system error. */
1018
1019stream *
1020open_external (unit_action action, unit_status status)
1021{
1022 int fd, prot;
1023
1024 fd =
1025 (status == STATUS_SCRATCH) ? tempfile () : regular_file (action, status);
1026
1027 if (fd < 0)
1028 return NULL;
1029 fd = fix_fd (fd);
1030
1031 switch (action)
1032 {
1033 case ACTION_READ:
1034 prot = PROT_READ;
1035 break;
1036
1037 case ACTION_WRITE:
1038 prot = PROT_WRITE;
1039 break;
1040
1041 case ACTION_READWRITE:
1042 prot = PROT_READ | PROT_WRITE;
1043 break;
1044
1045 default:
1046 internal_error ("open_external(): Bad action");
1047 }
1048
1049 /* If this is a scratch file, we can unlink it now and the file will
1050 * go away when it is closed. */
1051
1052 if (status == STATUS_SCRATCH)
1053 unlink (ioparm.file);
1054
1055 return fd_to_stream (fd, prot);
1056}
1057
1058
1059/* input_stream()-- Return a stream pointer to the default input stream.
1060 * Called on initialization. */
1061
1062stream *
1063input_stream (void)
1064{
1065
1066 return fd_to_stream (STDIN_FILENO, PROT_READ);
1067}
1068
1069
1070/* output_stream()-- Return a stream pointer to the default input stream.
1071 * Called on initialization. */
1072
1073stream *
1074output_stream (void)
1075{
1076
1077 return fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1078}
1079
1080
1081/* init_error_stream()-- Return a pointer to the error stream. This
1082 * subroutine is called when the stream is needed, rather than at
1083 * initialization. We want to work even if memory has been seriously
1084 * corrupted. */
1085
1086stream *
1087init_error_stream (void)
1088{
1089 static unix_stream error;
1090
1091 memset (&error, '\0', sizeof (error));
1092
1093 error.fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1094
1095 error.st.alloc_w_at = (void *) fd_alloc_w_at;
1096 error.st.sfree = (void *) fd_sfree;
1097
1098 error.unbuffered = 1;
1099 error.buffer = error.small_buffer;
1100
1101 return (stream *) & error;
1102}
1103
1104
1105/* compare_file_filename()-- Given an open stream and a fortran string
1106 * that is a filename, figure out if the file is the same as the
1107 * filename. */
1108
1109int
1110compare_file_filename (stream * s, const char *name, int len)
1111{
1112 char path[PATH_MAX + 1];
1113 struct stat st1, st2;
1114
1115 if (unpack_filename (path, name, len))
1116 return 0; /* Can't be the same */
1117
1118 /* If the filename doesn't exist, then there is no match with the
1119 * existing file. */
1120
1121 if (stat (path, &st1) < 0)
1122 return 0;
1123
1124 fstat (((unix_stream *) s)->fd, &st2);
1125
1126 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
1127}
1128
1129
1130/* find_file0()-- Recursive work function for find_file() */
1131
909087e0
TS
1132static gfc_unit *
1133find_file0 (gfc_unit * u, struct stat *st1)
6de9cd9a
DN
1134{
1135 struct stat st2;
909087e0 1136 gfc_unit *v;
6de9cd9a
DN
1137
1138 if (u == NULL)
1139 return NULL;
1140
1141 if (fstat (((unix_stream *) u->s)->fd, &st2) >= 0 &&
1142 st1->st_dev == st2.st_dev && st1->st_ino == st2.st_ino)
1143 return u;
1144
1145 v = find_file0 (u->left, st1);
1146 if (v != NULL)
1147 return v;
1148
1149 v = find_file0 (u->right, st1);
1150 if (v != NULL)
1151 return v;
1152
1153 return NULL;
1154}
1155
1156
1157/* find_file()-- Take the current filename and see if there is a unit
1158 * that has the file already open. Returns a pointer to the unit if so. */
1159
909087e0 1160gfc_unit *
6de9cd9a
DN
1161find_file (void)
1162{
1163 char path[PATH_MAX + 1];
1164 struct stat statbuf;
1165
1166 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1167 return NULL;
1168
1169 if (stat (path, &statbuf) < 0)
1170 return NULL;
1171
1172 return find_file0 (g.unit_root, &statbuf);
1173}
1174
1175
1176/* stream_at_bof()-- Returns nonzero if the stream is at the beginning
1177 * of the file. */
1178
1179int
1180stream_at_bof (stream * s)
1181{
1182 unix_stream *us;
1183
1184 us = (unix_stream *) s;
1185
1186 if (!us->mmaped)
1187 return 0; /* File is not seekable */
1188
1189 return us->logical_offset == 0;
1190}
1191
1192
1193/* stream_at_eof()-- Returns nonzero if the stream is at the beginning
1194 * of the file. */
1195
1196int
1197stream_at_eof (stream * s)
1198{
1199 unix_stream *us;
1200
1201 us = (unix_stream *) s;
1202
1203 if (!us->mmaped)
1204 return 0; /* File is not seekable */
1205
1206 return us->logical_offset == us->dirty_offset;
1207}
1208
1209
1210/* delete_file()-- Given a unit structure, delete the file associated
1211 * with the unit. Returns nonzero if something went wrong. */
1212
1213int
909087e0 1214delete_file (gfc_unit * u)
6de9cd9a
DN
1215{
1216 char path[PATH_MAX + 1];
1217
1218 if (unpack_filename (path, u->file, u->file_len))
1219 { /* Shouldn't be possible */
1220 errno = ENOENT;
1221 return 1;
1222 }
1223
1224 return unlink (path);
1225}
1226
1227
1228/* file_exists()-- Returns nonzero if the current filename exists on
1229 * the system */
1230
1231int
1232file_exists (void)
1233{
1234 char path[PATH_MAX + 1];
1235 struct stat statbuf;
1236
1237 if (unpack_filename (path, ioparm.file, ioparm.file_len))
1238 return 0;
1239
1240 if (stat (path, &statbuf) < 0)
1241 return 0;
1242
1243 return 1;
1244}
1245
1246
1247
1248static const char *yes = "YES", *no = "NO", *unknown = "UNKNOWN";
1249
1250/* inquire_sequential()-- Given a fortran string, determine if the
1251 * file is suitable for sequential access. Returns a C-style
1252 * string. */
1253
1254const char *
1255inquire_sequential (const char *string, int len)
1256{
1257 char path[PATH_MAX + 1];
1258 struct stat statbuf;
1259
1260 if (string == NULL ||
1261 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1262 return unknown;
1263
1264 if (S_ISREG (statbuf.st_mode) ||
1265 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1266 return yes;
1267
1268 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1269 return no;
1270
1271 return unknown;
1272}
1273
1274
1275/* inquire_direct()-- Given a fortran string, determine if the file is
1276 * suitable for direct access. Returns a C-style string. */
1277
1278const char *
1279inquire_direct (const char *string, int len)
1280{
1281 char path[PATH_MAX + 1];
1282 struct stat statbuf;
1283
1284 if (string == NULL ||
1285 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1286 return unknown;
1287
1288 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1289 return yes;
1290
1291 if (S_ISDIR (statbuf.st_mode) ||
1292 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1293 return no;
1294
1295 return unknown;
1296}
1297
1298
1299/* inquire_formatted()-- Given a fortran string, determine if the file
1300 * is suitable for formatted form. Returns a C-style string. */
1301
1302const char *
1303inquire_formatted (const char *string, int len)
1304{
1305 char path[PATH_MAX + 1];
1306 struct stat statbuf;
1307
1308 if (string == NULL ||
1309 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1310 return unknown;
1311
1312 if (S_ISREG (statbuf.st_mode) ||
1313 S_ISBLK (statbuf.st_mode) ||
1314 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1315 return yes;
1316
1317 if (S_ISDIR (statbuf.st_mode))
1318 return no;
1319
1320 return unknown;
1321}
1322
1323
1324/* inquire_unformatted()-- Given a fortran string, determine if the file
1325 * is suitable for unformatted form. Returns a C-style string. */
1326
1327const char *
1328inquire_unformatted (const char *string, int len)
1329{
1330
1331 return inquire_formatted (string, len);
1332}
1333
1334
1335/* inquire_access()-- Given a fortran string, determine if the file is
1336 * suitable for access. */
1337
1338static const char *
1339inquire_access (const char *string, int len, int mode)
1340{
1341 char path[PATH_MAX + 1];
1342
1343 if (string == NULL || unpack_filename (path, string, len) ||
1344 access (path, mode) < 0)
1345 return no;
1346
1347 return yes;
1348}
1349
1350
1351/* inquire_read()-- Given a fortran string, determine if the file is
1352 * suitable for READ access. */
1353
1354const char *
1355inquire_read (const char *string, int len)
1356{
1357
1358 return inquire_access (string, len, R_OK);
1359}
1360
1361
1362/* inquire_write()-- Given a fortran string, determine if the file is
1363 * suitable for READ access. */
1364
1365const char *
1366inquire_write (const char *string, int len)
1367{
1368
1369 return inquire_access (string, len, W_OK);
1370}
1371
1372
1373/* inquire_readwrite()-- Given a fortran string, determine if the file is
1374 * suitable for read and write access. */
1375
1376const char *
1377inquire_readwrite (const char *string, int len)
1378{
1379
1380 return inquire_access (string, len, R_OK | W_OK);
1381}
1382
1383
1384/* file_length()-- Return the file length in bytes, -1 if unknown */
1385
81f4be3c 1386gfc_offset
6de9cd9a
DN
1387file_length (stream * s)
1388{
1389
1390 return ((unix_stream *) s)->file_length;
1391}
1392
1393
1394/* file_position()-- Return the current position of the file */
1395
81f4be3c 1396gfc_offset
6de9cd9a
DN
1397file_position (stream * s)
1398{
1399
1400 return ((unix_stream *) s)->logical_offset;
1401}
1402
1403
1404/* is_seekable()-- Return nonzero if the stream is seekable, zero if
1405 * it is not */
1406
1407int
1408is_seekable (stream * s)
1409{
bf1df0a0
BD
1410 /* by convention, if file_length == -1, the file is not seekable
1411 note that a mmapped file is always seekable, an fd_ file may
1412 or may not be. */
1413 return ((unix_stream *) s)->file_length!=-1;
6de9cd9a
DN
1414}
1415
000aa32a
JB
1416try
1417flush (stream *s)
1418{
1419 return fd_flush( (unix_stream *) s);
1420}
1421
6de9cd9a
DN
1422
1423/* How files are stored: This is an operating-system specific issue,
1424 and therefore belongs here. There are three cases to consider.
1425
1426 Direct Access:
1427 Records are written as block of bytes corresponding to the record
1428 length of the file. This goes for both formatted and unformatted
1429 records. Positioning is done explicitly for each data transfer,
1430 so positioning is not much of an issue.
1431
1432 Sequential Formatted:
1433 Records are separated by newline characters. The newline character
1434 is prohibited from appearing in a string. If it does, this will be
1435 messed up on the next read. End of file is also the end of a record.
1436
1437 Sequential Unformatted:
1438 In this case, we are merely copying bytes to and from main storage,
1439 yet we need to keep track of varying record lengths. We adopt
1440 the solution used by f2c. Each record contains a pair of length
1441 markers:
1442
1443 Length of record n in bytes
1444 Data of record n
1445 Length of record n in bytes
1446
1447 Length of record n+1 in bytes
1448 Data of record n+1
1449 Length of record n+1 in bytes
1450
1451 The length is stored at the end of a record to allow backspacing to the
1452 previous record. Between data transfer statements, the file pointer
1453 is left pointing to the first length of the current record.
1454
1455 ENDFILE records are never explicitly stored.
1456
1457*/
This page took 0.215619 seconds and 5 git commands to generate.