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