]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/io/unix.c
2008-04-05 Richard Guenther <rguenther@suse.de>
[thirdparty/gcc.git] / libgfortran / io / unix.c
CommitLineData
76c0a846 1/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
a0007dfa 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
41f2d5e8 33#include "io.h"
4ee9c684 34#include <stdlib.h>
35#include <limits.h>
36
37#include <unistd.h>
38#include <sys/stat.h>
39#include <fcntl.h>
2639e4cd 40#include <assert.h>
4ee9c684 41
4ee9c684 42#include <string.h>
43#include <errno.h>
44
c0ecd33c 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
8df8ec57 98#ifndef SSIZE_MAX
99#define SSIZE_MAX SHRT_MAX
100#endif
101
4ee9c684 102#ifndef PATH_MAX
103#define PATH_MAX 1024
104#endif
105
d2455565 106#ifndef PROT_READ
107#define PROT_READ 1
108#endif
109
110#ifndef PROT_WRITE
111#define PROT_WRITE 2
112#endif
113
7dfba97b 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
76c0a846 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
76c0a846 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
71668ec3 156 int unbuffered; /* =1 if the stream is not buffered */
76c0a846 157
4f240726 158 char *buffer;
5d5f00d5 159 char small_buffer[BUFFER_SIZE];
76c0a846 160}
161unix_stream;
162
71668ec3 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
4ee9c684 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
4ee9c684 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 {
363dcb81 238 str->logical_offset += pos_off;
4ee9c684 239
363dcb81 240 if (str->dirty_offset + str->ndirty > str->logical_offset)
4ee9c684 241 {
363dcb81 242 if (str->ndirty + pos_off > 0)
243 str->ndirty += pos_off;
4ee9c684 244 else
245 {
246 str->dirty_offset += pos_off + pos_off;
363dcb81 247 str->ndirty = 0;
4ee9c684 248 }
249 }
250
363dcb81 251 return pos_off;
4ee9c684 252 }
363dcb81 253 return 0;
4ee9c684 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{
e0582811 267#ifdef HAVE_DUP
4ee9c684 268 int input, output, error;
269
270 input = output = error = 0;
271
7145fd06 272 /* Unix allocates the lowest descriptors first, so a loop is not
273 required, but this order is. */
4ee9c684 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);
e0582811 296#endif
4ee9c684 297
298 return fd;
299}
300
353c8a95 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}
4ee9c684 312
2488b3b6 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
4ee9c684 330
b2a112ca 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)
4ee9c684 336{
b2a112ca 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}
4ee9c684 342
4ee9c684 343
b2a112ca 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. */
4ee9c684 347
b2a112ca 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;
4ee9c684 382 }
383
b2a112ca 384 *nbytes -= bytes_left;
385 return status;
4ee9c684 386}
387
388
b2a112ca 389/* Write a buffer to a stream, allowing for short writes. */
4ee9c684 390
391static int
b2a112ca 392do_write (unix_stream * s, const void * buf, size_t * nbytes)
4ee9c684 393{
b2a112ca 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)
4ee9c684 406 {
b2a112ca 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;
4ee9c684 423 }
424
b2a112ca 425 *nbytes -= bytes_left;
426 return status;
4ee9c684 427}
4ee9c684 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{
4ee9c684 436 return strerror (errno);
437}
438
439
4ee9c684 440/*********************************************************************
441 File descriptor stream functions
442*********************************************************************/
443
b2a112ca 444
4ee9c684 445/* fd_flush()-- Write bytes that need to be written */
446
447static try
448fd_flush (unix_stream * s)
449{
b2a112ca 450 size_t writelen;
451
4ee9c684 452 if (s->ndirty == 0)
352597f9 453 return SUCCESS;
454
455 if (s->file_length != -1 && s->physical_offset != s->dirty_offset &&
4ee9c684 456 lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
457 return FAILURE;
458
b2a112ca 459 writelen = s->ndirty;
460 if (do_write (s, s->buffer + (s->dirty_offset - s->buffer_offset),
461 &writelen) != 0)
4ee9c684 462 return FAILURE;
463
b2a112ca 464 s->physical_offset = s->dirty_offset + writelen;
5a78b88f 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)
b2a112ca 468 s->file_length = s->physical_offset;
469
470 s->ndirty -= writelen;
471 if (s->ndirty != 0)
472 return FAILURE;
4ee9c684 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
a0007dfa 483fd_alloc (unix_stream * s, gfc_offset where,
484 int *len __attribute__ ((unused)))
4ee9c684 485{
5d5f00d5 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 }
4ee9c684 499
500 /* Salvage bytes currently within the buffer. This is important for
501 * devices that cannot seek. */
502
5d5f00d5 503 if (s->buffer != NULL && s->buffer_offset <= where &&
4ee9c684 504 where <= s->buffer_offset + s->active)
505 {
506
507 n = s->active - (where - s->buffer_offset);
5d5f00d5 508 memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
4ee9c684 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
5d5f00d5 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;
4ee9c684 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 *
b093181d 534fd_alloc_r_at (unix_stream * s, int *len, gfc_offset where)
4ee9c684 535{
b093181d 536 gfc_offset m;
4ee9c684 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
fef3501c 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
cfe0acf0 569 s->physical_offset = m + n;
fef3501c 570 s->active += n;
571 }
572 else
573 {
574 size_t n;
4ee9c684 575
fef3501c 576 n = s->len - s->active;
577 if (do_read (s, s->buffer + s->active, &n) != 0)
578 return NULL;
579
cfe0acf0 580 s->physical_offset = m + n;
fef3501c 581 s->active += n;
582 }
4ee9c684 583
4ee9c684 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 *
b093181d 597fd_alloc_w_at (unix_stream * s, int *len, gfc_offset where)
4ee9c684 598{
b093181d 599 gfc_offset n;
4ee9c684 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 */
5a78b88f 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;
4ee9c684 623 }
624 else
5a78b88f 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;
4f240726 635 s->dirty_offset = start;
4ee9c684 636 }
637
638 s->logical_offset = where + *len;
639
352597f9 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;
f82543e7 644
4ee9c684 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{
4ee9c684 656 if (s->ndirty != 0 &&
5d5f00d5 657 (s->buffer != s->small_buffer || options.all_unbuffered ||
658 s->unbuffered))
4ee9c684 659 return fd_flush (s);
660
661 return SUCCESS;
662}
663
664
b2a112ca 665static try
b093181d 666fd_seek (unix_stream * s, gfc_offset offset)
4ee9c684 667{
352597f9 668
669 if (s->file_length == -1)
670 return SUCCESS;
671
b3ac1032 672 if (s->physical_offset == offset) /* Are we lucky and avoid syscall? */
673 {
674 s->logical_offset = offset;
675 return SUCCESS;
676 }
4ee9c684 677
7d866870 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 }
b3ac1032 684
7d866870 685 return FAILURE;
4ee9c684 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{
352597f9 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. */
5a78b88f 699 if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
352597f9 700 {
701 if (errno == ESPIPE)
702 return SUCCESS;
703 else
704 return FAILURE;
705 }
4ee9c684 706
352597f9 707 /* Using ftruncate on a seekable special file (like /dev/null)
708 is undefined, so we treat it as if the ftruncate succeeded. */
a93b7f1c 709 if (!s->special_file
710 && (
a54b1ce7 711#ifdef HAVE_FTRUNCATE
a93b7f1c 712 ftruncate (s->fd, s->logical_offset) != 0
713#elif defined HAVE_CHSIZE
714 chsize (s->fd, s->logical_offset) != 0
a54b1ce7 715#else
a93b7f1c 716 /* If we have neither, always fail and exit, noisily. */
717 runtime_error ("required ftruncate or chsize support not present"), 1
a54b1ce7 718#endif
a93b7f1c 719 ))
72909c79 720 {
a93b7f1c 721 /* The truncation failed and we need to handle this gracefully.
722 The file length remains the same, but the file-descriptor
723 offset needs adjustment per the successful lseek above.
724 (Similarly, the contents of the buffer isn't valid anymore.)
725 A ftruncate call does not affect the physical (file-descriptor)
726 offset, according to the ftruncate manual, so neither should a
727 failed call. */
728 s->physical_offset = s->logical_offset;
729 s->active = 0;
730 return FAILURE;
72909c79 731 }
5a78b88f 732
733 s->physical_offset = s->file_length = s->logical_offset;
8c39329b 734 s->active = 0;
4ee9c684 735 return SUCCESS;
736}
737
738
56f281a2 739/* Similar to memset(), but operating on a stream instead of a string.
740 Takes care of not using too much memory. */
741
742static try
743fd_sset (unix_stream * s, int c, size_t n)
744{
745 size_t bytes_left;
746 int trans;
747 void *p;
748
749 bytes_left = n;
750
751 while (bytes_left > 0)
752 {
753 /* memset() in chunks of BUFFER_SIZE. */
754 trans = (bytes_left < BUFFER_SIZE) ? bytes_left : BUFFER_SIZE;
755
756 p = fd_alloc_w_at (s, &trans, -1);
757 if (p)
758 memset (p, c, trans);
759 else
760 return FAILURE;
761
762 bytes_left -= trans;
763 }
764
765 return SUCCESS;
766}
b2a112ca 767
768
769/* Stream read function. Avoids using a buffer for big reads. The
770 interface is like POSIX read(), but the nbytes argument is a
771 pointer; on return it contains the number of bytes written. The
772 function return value is the status indicator (0 for success). */
773
774static int
775fd_read (unix_stream * s, void * buf, size_t * nbytes)
776{
777 void *p;
778 int tmp, status;
779
780 if (*nbytes < BUFFER_SIZE && !s->unbuffered)
781 {
782 tmp = *nbytes;
783 p = fd_alloc_r_at (s, &tmp, -1);
784 if (p)
785 {
786 *nbytes = tmp;
787 memcpy (buf, p, *nbytes);
788 return 0;
789 }
790 else
791 {
792 *nbytes = 0;
793 return errno;
794 }
795 }
796
797 /* If the request is bigger than BUFFER_SIZE we flush the buffers
798 and read directly. */
799 if (fd_flush (s) == FAILURE)
800 {
801 *nbytes = 0;
802 return errno;
803 }
804
b3ac1032 805 if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
b2a112ca 806 {
807 *nbytes = 0;
808 return errno;
809 }
810
811 status = do_read (s, buf, nbytes);
812 reset_stream (s, *nbytes);
813 return status;
814}
815
816
817/* Stream write function. Avoids using a buffer for big writes. The
818 interface is like POSIX write(), but the nbytes argument is a
819 pointer; on return it contains the number of bytes written. The
820 function return value is the status indicator (0 for success). */
821
822static int
823fd_write (unix_stream * s, const void * buf, size_t * nbytes)
824{
825 void *p;
826 int tmp, status;
827
828 if (*nbytes < BUFFER_SIZE && !s->unbuffered)
829 {
830 tmp = *nbytes;
831 p = fd_alloc_w_at (s, &tmp, -1);
832 if (p)
833 {
834 *nbytes = tmp;
835 memcpy (p, buf, *nbytes);
836 return 0;
837 }
838 else
839 {
840 *nbytes = 0;
841 return errno;
842 }
843 }
844
845 /* If the request is bigger than BUFFER_SIZE we flush the buffers
846 and write directly. */
847 if (fd_flush (s) == FAILURE)
848 {
849 *nbytes = 0;
850 return errno;
851 }
852
b3ac1032 853 if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
b2a112ca 854 {
855 *nbytes = 0;
856 return errno;
857 }
858
859 status = do_write (s, buf, nbytes);
860 reset_stream (s, *nbytes);
861 return status;
862}
863
864
4ee9c684 865static try
866fd_close (unix_stream * s)
867{
4ee9c684 868 if (fd_flush (s) == FAILURE)
869 return FAILURE;
870
5d5f00d5 871 if (s->buffer != NULL && s->buffer != s->small_buffer)
872 free_mem (s->buffer);
873
582dd191 874 if (s->fd != STDOUT_FILENO && s->fd != STDERR_FILENO && s->fd != STDIN_FILENO)
f8f6940b 875 {
876 if (close (s->fd) < 0)
877 return FAILURE;
878 }
4ee9c684 879
880 free_mem (s);
881
882 return SUCCESS;
883}
884
885
886static void
887fd_open (unix_stream * s)
888{
4ee9c684 889 if (isatty (s->fd))
890 s->unbuffered = 1;
891
892 s->st.alloc_r_at = (void *) fd_alloc_r_at;
893 s->st.alloc_w_at = (void *) fd_alloc_w_at;
894 s->st.sfree = (void *) fd_sfree;
895 s->st.close = (void *) fd_close;
896 s->st.seek = (void *) fd_seek;
52a2cc79 897 s->st.trunc = (void *) fd_truncate;
b2a112ca 898 s->st.read = (void *) fd_read;
899 s->st.write = (void *) fd_write;
56f281a2 900 s->st.set = (void *) fd_sset;
4ee9c684 901
5d5f00d5 902 s->buffer = NULL;
4ee9c684 903}
904
905
4ee9c684 906
b2a112ca 907
4ee9c684 908/*********************************************************************
909 memory stream functions - These are used for internal files
910
911 The idea here is that a single stream structure is created and all
912 requests must be satisfied from it. The location and size of the
913 buffer is the character variable supplied to the READ or WRITE
914 statement.
915
916*********************************************************************/
917
918
919static char *
71668ec3 920mem_alloc_r_at (int_stream * s, int *len, gfc_offset where)
4ee9c684 921{
b093181d 922 gfc_offset n;
4ee9c684 923
924 if (where == -1)
925 where = s->logical_offset;
926
927 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
928 return NULL;
929
4ee9c684 930 s->logical_offset = where + *len;
931
11de4bf9 932 n = s->buffer_offset + s->active - where;
4ee9c684 933 if (*len > n)
934 *len = n;
935
936 return s->buffer + (where - s->buffer_offset);
937}
938
939
940static char *
71668ec3 941mem_alloc_w_at (int_stream * s, int *len, gfc_offset where)
4ee9c684 942{
b093181d 943 gfc_offset m;
4ee9c684 944
2639e4cd 945 assert (*len >= 0); /* Negative values not allowed. */
946
4ee9c684 947 if (where == -1)
948 where = s->logical_offset;
949
950 m = where + *len;
951
2639e4cd 952 if (where < s->buffer_offset)
4ee9c684 953 return NULL;
954
2639e4cd 955 if (m > s->file_length)
72231bd6 956 return NULL;
2639e4cd 957
4ee9c684 958 s->logical_offset = m;
959
960 return s->buffer + (where - s->buffer_offset);
961}
962
963
b2a112ca 964/* Stream read function for internal units. This is not actually used
965 at the moment, as all internal IO is formatted and the formatted IO
966 routines use mem_alloc_r_at. */
967
968static int
71668ec3 969mem_read (int_stream * s, void * buf, size_t * nbytes)
b2a112ca 970{
971 void *p;
972 int tmp;
973
974 tmp = *nbytes;
975 p = mem_alloc_r_at (s, &tmp, -1);
976 if (p)
977 {
978 *nbytes = tmp;
979 memcpy (buf, p, *nbytes);
980 return 0;
981 }
982 else
983 {
984 *nbytes = 0;
985 return errno;
986 }
987}
988
989
990/* Stream write function for internal units. This is not actually used
991 at the moment, as all internal IO is formatted and the formatted IO
992 routines use mem_alloc_w_at. */
993
994static int
71668ec3 995mem_write (int_stream * s, const void * buf, size_t * nbytes)
b2a112ca 996{
997 void *p;
998 int tmp;
999
1000 errno = 0;
1001
1002 tmp = *nbytes;
1003 p = mem_alloc_w_at (s, &tmp, -1);
1004 if (p)
1005 {
1006 *nbytes = tmp;
1007 memcpy (p, buf, *nbytes);
1008 return 0;
1009 }
1010 else
1011 {
1012 *nbytes = 0;
1013 return errno;
1014 }
1015}
1016
1017
4ee9c684 1018static int
71668ec3 1019mem_seek (int_stream * s, gfc_offset offset)
4ee9c684 1020{
4ee9c684 1021 if (offset > s->file_length)
1022 {
1023 errno = ESPIPE;
1024 return FAILURE;
1025 }
1026
1027 s->logical_offset = offset;
1028 return SUCCESS;
1029}
1030
1031
56f281a2 1032static try
71668ec3 1033mem_set (int_stream * s, int c, size_t n)
56f281a2 1034{
1035 void *p;
1036 int len;
1037
1038 len = n;
1039
1040 p = mem_alloc_w_at (s, &len, -1);
1041 if (p)
1042 {
1043 memset (p, c, len);
1044 return SUCCESS;
1045 }
1046 else
1047 return FAILURE;
1048}
1049
1050
4ee9c684 1051static int
71668ec3 1052mem_truncate (int_stream * s __attribute__ ((unused)))
4ee9c684 1053{
4ee9c684 1054 return SUCCESS;
1055}
1056
1057
1058static try
71668ec3 1059mem_close (int_stream * s)
4ee9c684 1060{
46ca759c 1061 if (s != NULL)
1062 free_mem (s);
4ee9c684 1063
1064 return SUCCESS;
1065}
1066
1067
1068static try
71668ec3 1069mem_sfree (int_stream * s __attribute__ ((unused)))
4ee9c684 1070{
4ee9c684 1071 return SUCCESS;
1072}
1073
1074
1075
1076/*********************************************************************
1077 Public functions -- A reimplementation of this module needs to
1078 define functional equivalents of the following.
1079*********************************************************************/
1080
1081/* empty_internal_buffer()-- Zero the buffer of Internal file */
1082
1083void
1084empty_internal_buffer(stream *strm)
1085{
71668ec3 1086 int_stream * s = (int_stream *) strm;
7145fd06 1087 memset(s->buffer, ' ', s->file_length);
4ee9c684 1088}
1089
1090/* open_internal()-- Returns a stream structure from an internal file */
1091
1092stream *
cf4abc57 1093open_internal (char *base, int length, gfc_offset offset)
4ee9c684 1094{
71668ec3 1095 int_stream *s;
4ee9c684 1096
71668ec3 1097 s = get_mem (sizeof (int_stream));
1098 memset (s, '\0', sizeof (int_stream));
4ee9c684 1099
1100 s->buffer = base;
cf4abc57 1101 s->buffer_offset = offset;
4ee9c684 1102
1103 s->logical_offset = 0;
1104 s->active = s->file_length = length;
1105
1106 s->st.alloc_r_at = (void *) mem_alloc_r_at;
1107 s->st.alloc_w_at = (void *) mem_alloc_w_at;
1108 s->st.sfree = (void *) mem_sfree;
1109 s->st.close = (void *) mem_close;
1110 s->st.seek = (void *) mem_seek;
52a2cc79 1111 s->st.trunc = (void *) mem_truncate;
b2a112ca 1112 s->st.read = (void *) mem_read;
1113 s->st.write = (void *) mem_write;
56f281a2 1114 s->st.set = (void *) mem_set;
4ee9c684 1115
1116 return (stream *) s;
1117}
1118
1119
1120/* fd_to_stream()-- Given an open file descriptor, build a stream
1121 * around it. */
1122
1123static stream *
f0b5d33f 1124fd_to_stream (int fd, int prot)
4ee9c684 1125{
1126 struct stat statbuf;
1127 unix_stream *s;
1128
1129 s = get_mem (sizeof (unix_stream));
8f8ad899 1130 memset (s, '\0', sizeof (unix_stream));
4ee9c684 1131
1132 s->fd = fd;
1133 s->buffer_offset = 0;
1134 s->physical_offset = 0;
1135 s->logical_offset = 0;
1136 s->prot = prot;
1137
1138 /* Get the current length of the file. */
1139
1140 fstat (fd, &statbuf);
352597f9 1141
1142 if (lseek (fd, 0, SEEK_CUR) == (off_t) -1)
1143 s->file_length = -1;
1144 else
1145 s->file_length = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
1146
227e9423 1147 s->special_file = !S_ISREG (statbuf.st_mode);
4ee9c684 1148
4ee9c684 1149 fd_open (s);
4ee9c684 1150
1151 return (stream *) s;
1152}
1153
1154
771c1b50 1155/* Given the Fortran unit number, convert it to a C file descriptor. */
1156
1157int
60c514ba 1158unit_to_fd (int unit)
771c1b50 1159{
771c1b50 1160 gfc_unit *us;
60c514ba 1161 int fd;
771c1b50 1162
60c514ba 1163 us = find_unit (unit);
771c1b50 1164 if (us == NULL)
1165 return -1;
1166
60c514ba 1167 fd = ((unix_stream *) us->s)->fd;
1168 unlock_unit (us);
1169 return fd;
771c1b50 1170}
1171
1172
4ee9c684 1173/* unpack_filename()-- Given a fortran string and a pointer to a
1174 * buffer that is PATH_MAX characters, convert the fortran string to a
1175 * C string in the buffer. Returns nonzero if this is not possible. */
1176
1dc95e51 1177int
4ee9c684 1178unpack_filename (char *cstring, const char *fstring, int len)
1179{
4ee9c684 1180 len = fstrlen (fstring, len);
1181 if (len >= PATH_MAX)
1182 return 1;
1183
1184 memmove (cstring, fstring, len);
1185 cstring[len] = '\0';
1186
1187 return 0;
1188}
1189
1190
1191/* tempfile()-- Generate a temporary filename for a scratch file and
1192 * open it. mkstemp() opens the file for reading and writing, but the
1193 * library mode prevents anything that is not allowed. The descriptor
7dfba97b 1194 * is returned, which is -1 on error. The template is pointed to by
60c514ba 1195 * opp->file, which is copied into the unit structure
4ee9c684 1196 * and freed later. */
1197
1198static int
60c514ba 1199tempfile (st_parameter_open *opp)
4ee9c684 1200{
1201 const char *tempdir;
1202 char *template;
1203 int fd;
1204
1205 tempdir = getenv ("GFORTRAN_TMPDIR");
1206 if (tempdir == NULL)
1207 tempdir = getenv ("TMP");
ac09d5cc 1208 if (tempdir == NULL)
1209 tempdir = getenv ("TEMP");
4ee9c684 1210 if (tempdir == NULL)
1211 tempdir = DEFAULT_TEMPDIR;
1212
1213 template = get_mem (strlen (tempdir) + 20);
1214
5a037dbd 1215 sprintf (template, "%s/gfortrantmpXXXXXX", tempdir);
7dfba97b 1216
1217#ifdef HAVE_MKSTEMP
4ee9c684 1218
1219 fd = mkstemp (template);
1220
7dfba97b 1221#else /* HAVE_MKSTEMP */
1222
1223 if (mktemp (template))
1224 do
cf6a3896 1225#if defined(HAVE_CRLF) && defined(O_BINARY)
cf55c3cf 1226 fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
1227 S_IREAD | S_IWRITE);
1228#else
ac09d5cc 1229 fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
cf55c3cf 1230#endif
7dfba97b 1231 while (!(fd == -1 && errno == EEXIST) && mktemp (template));
1232 else
1233 fd = -1;
1234
1235#endif /* HAVE_MKSTEMP */
1236
4ee9c684 1237 if (fd < 0)
1238 free_mem (template);
1239 else
1240 {
60c514ba 1241 opp->file = template;
1242 opp->file_len = strlen (template); /* Don't include trailing nul */
4ee9c684 1243 }
1244
1245 return fd;
1246}
1247
1248
6d12c489 1249/* regular_file()-- Open a regular file.
2d6ba0f9 1250 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
1251 * unless an error occurs.
6d12c489 1252 * Returns the descriptor, which is less than zero on error. */
4ee9c684 1253
1254static int
60c514ba 1255regular_file (st_parameter_open *opp, unit_flags *flags)
4ee9c684 1256{
1257 char path[PATH_MAX + 1];
4ee9c684 1258 int mode;
6d12c489 1259 int rwflag;
2d6ba0f9 1260 int crflag;
6d12c489 1261 int fd;
4ee9c684 1262
60c514ba 1263 if (unpack_filename (path, opp->file, opp->file_len))
4ee9c684 1264 {
1265 errno = ENOENT; /* Fake an OS error */
1266 return -1;
1267 }
1268
6d12c489 1269 rwflag = 0;
4ee9c684 1270
6d12c489 1271 switch (flags->action)
4ee9c684 1272 {
1273 case ACTION_READ:
6d12c489 1274 rwflag = O_RDONLY;
4ee9c684 1275 break;
1276
1277 case ACTION_WRITE:
6d12c489 1278 rwflag = O_WRONLY;
4ee9c684 1279 break;
1280
1281 case ACTION_READWRITE:
6d12c489 1282 case ACTION_UNSPECIFIED:
1283 rwflag = O_RDWR;
4ee9c684 1284 break;
1285
1286 default:
60c514ba 1287 internal_error (&opp->common, "regular_file(): Bad action");
4ee9c684 1288 }
1289
6d12c489 1290 switch (flags->status)
4ee9c684 1291 {
1292 case STATUS_NEW:
2d6ba0f9 1293 crflag = O_CREAT | O_EXCL;
4ee9c684 1294 break;
1295
2d6ba0f9 1296 case STATUS_OLD: /* open will fail if the file does not exist*/
1297 crflag = 0;
4ee9c684 1298 break;
1299
1300 case STATUS_UNKNOWN:
1301 case STATUS_SCRATCH:
2d6ba0f9 1302 crflag = O_CREAT;
4ee9c684 1303 break;
1304
1305 case STATUS_REPLACE:
a638be8f 1306 crflag = O_CREAT | O_TRUNC;
4ee9c684 1307 break;
1308
1309 default:
60c514ba 1310 internal_error (&opp->common, "regular_file(): Bad status");
4ee9c684 1311 }
1312
6d12c489 1313 /* rwflag |= O_LARGEFILE; */
4ee9c684 1314
cf6a3896 1315#if defined(HAVE_CRLF) && defined(O_BINARY)
cf55c3cf 1316 crflag |= O_BINARY;
1317#endif
1318
6d12c489 1319 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
2d6ba0f9 1320 fd = open (path, rwflag | crflag, mode);
1321 if (flags->action != ACTION_UNSPECIFIED)
a638be8f 1322 return fd;
2d6ba0f9 1323
1324 if (fd >= 0)
6d12c489 1325 {
2d6ba0f9 1326 flags->action = ACTION_READWRITE;
1327 return fd;
6d12c489 1328 }
a638be8f 1329 if (errno != EACCES && errno != EROFS)
2d6ba0f9 1330 return fd;
1331
1332 /* retry for read-only access */
1333 rwflag = O_RDONLY;
1334 fd = open (path, rwflag | crflag, mode);
1335 if (fd >=0)
1336 {
1337 flags->action = ACTION_READ;
1338 return fd; /* success */
1339 }
1340
1341 if (errno != EACCES)
1342 return fd; /* failure */
1343
1344 /* retry for write-only access */
1345 rwflag = O_WRONLY;
1346 fd = open (path, rwflag | crflag, mode);
1347 if (fd >=0)
1348 {
1349 flags->action = ACTION_WRITE;
1350 return fd; /* success */
1351 }
1352 return fd; /* failure */
4ee9c684 1353}
1354
1355
1356/* open_external()-- Open an external file, unix specific version.
6d12c489 1357 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
4ee9c684 1358 * Returns NULL on operating system error. */
1359
1360stream *
60c514ba 1361open_external (st_parameter_open *opp, unit_flags *flags)
4ee9c684 1362{
1363 int fd, prot;
1364
6d12c489 1365 if (flags->status == STATUS_SCRATCH)
1366 {
60c514ba 1367 fd = tempfile (opp);
6d12c489 1368 if (flags->action == ACTION_UNSPECIFIED)
1369 flags->action = ACTION_READWRITE;
1dc95e51 1370
1371#if HAVE_UNLINK_OPEN_FILE
6d12c489 1372 /* We can unlink scratch files now and it will go away when closed. */
60c514ba 1373 if (fd >= 0)
1374 unlink (opp->file);
1dc95e51 1375#endif
6d12c489 1376 }
1377 else
1378 {
2d6ba0f9 1379 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1380 * if it succeeds */
60c514ba 1381 fd = regular_file (opp, flags);
6d12c489 1382 }
4ee9c684 1383
1384 if (fd < 0)
1385 return NULL;
1386 fd = fix_fd (fd);
1387
6d12c489 1388 switch (flags->action)
4ee9c684 1389 {
1390 case ACTION_READ:
1391 prot = PROT_READ;
1392 break;
1393
1394 case ACTION_WRITE:
1395 prot = PROT_WRITE;
1396 break;
1397
1398 case ACTION_READWRITE:
1399 prot = PROT_READ | PROT_WRITE;
1400 break;
1401
1402 default:
60c514ba 1403 internal_error (&opp->common, "open_external(): Bad action");
4ee9c684 1404 }
1405
f0b5d33f 1406 return fd_to_stream (fd, prot);
4ee9c684 1407}
1408
1409
1410/* input_stream()-- Return a stream pointer to the default input stream.
1411 * Called on initialization. */
1412
1413stream *
1414input_stream (void)
1415{
f0b5d33f 1416 return fd_to_stream (STDIN_FILENO, PROT_READ);
4ee9c684 1417}
1418
1419
ff81ee3b 1420/* output_stream()-- Return a stream pointer to the default output stream.
4ee9c684 1421 * Called on initialization. */
1422
1423stream *
1424output_stream (void)
1425{
3e45a719 1426 stream * s;
1427
e693d7f1 1428#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1429 setmode (STDOUT_FILENO, O_BINARY);
1430#endif
3e45a719 1431
1432 s = fd_to_stream (STDOUT_FILENO, PROT_WRITE);
1433 if (options.unbuffered_preconnected)
1434 ((unix_stream *) s)->unbuffered = 1;
1435 return s;
4ee9c684 1436}
1437
1438
ff81ee3b 1439/* error_stream()-- Return a stream pointer to the default error stream.
1440 * Called on initialization. */
1441
1442stream *
1443error_stream (void)
1444{
3e45a719 1445 stream * s;
1446
e693d7f1 1447#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1448 setmode (STDERR_FILENO, O_BINARY);
1449#endif
3e45a719 1450
1451 s = fd_to_stream (STDERR_FILENO, PROT_WRITE);
1452 if (options.unbuffered_preconnected)
1453 ((unix_stream *) s)->unbuffered = 1;
1454 return s;
ff81ee3b 1455}
1456
4ee9c684 1457
5a037dbd 1458/* st_vprintf()-- vprintf function for error output. To avoid buffer
1459 overruns, we limit the length of the buffer to ST_VPRINTF_SIZE. 2k
1460 is big enough to completely fill a 80x25 terminal, so it shuld be
1461 OK. We use a direct write() because it is simpler and least likely
0e80ec22 1462 to be clobbered by memory corruption. Writing an error message
1463 longer than that is an error. */
4ee9c684 1464
5a037dbd 1465#define ST_VPRINTF_SIZE 2048
4ee9c684 1466
5a037dbd 1467int
1468st_vprintf (const char *format, va_list ap)
1469{
1470 static char buffer[ST_VPRINTF_SIZE];
1471 int written;
1472 int fd;
4ee9c684 1473
5a037dbd 1474 fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1475#ifdef HAVE_VSNPRINTF
1476 written = vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
1477#else
0e80ec22 1478 written = vsprintf(buffer, format, ap);
1479
1480 if (written >= ST_VPRINTF_SIZE-1)
1481 {
1482 /* The error message was longer than our buffer. Ouch. Because
1483 we may have messed up things badly, report the error and
1484 quit. */
1485#define ERROR_MESSAGE "Internal error: buffer overrun in st_vprintf()\n"
1486 write (fd, buffer, ST_VPRINTF_SIZE-1);
1487 write (fd, ERROR_MESSAGE, strlen(ERROR_MESSAGE));
1488 sys_exit(2);
1489#undef ERROR_MESSAGE
1490
1491 }
5a037dbd 1492#endif
0e80ec22 1493
5a037dbd 1494 written = write (fd, buffer, written);
1495 return written;
4ee9c684 1496}
1497
5a037dbd 1498/* st_printf()-- printf() function for error output. This just calls
1499 st_vprintf() to do the actual work. */
76c0a846 1500
1501int
1502st_printf (const char *format, ...)
1503{
5a037dbd 1504 int written;
1505 va_list ap;
1506 va_start (ap, format);
1507 written = st_vprintf(format, ap);
1508 va_end (ap);
1509 return written;
76c0a846 1510}
1511
4ee9c684 1512
1513/* compare_file_filename()-- Given an open stream and a fortran string
1514 * that is a filename, figure out if the file is the same as the
1515 * filename. */
1516
1517int
daad4fd5 1518compare_file_filename (gfc_unit *u, const char *name, int len)
4ee9c684 1519{
1520 char path[PATH_MAX + 1];
daad4fd5 1521 struct stat st1;
1522#ifdef HAVE_WORKING_STAT
1523 struct stat st2;
c0ecd33c 1524#else
1525# ifdef __MINGW32__
1526 uint64_t id1, id2;
1527# endif
daad4fd5 1528#endif
4ee9c684 1529
1530 if (unpack_filename (path, name, len))
1531 return 0; /* Can't be the same */
1532
1533 /* If the filename doesn't exist, then there is no match with the
1534 * existing file. */
1535
1536 if (stat (path, &st1) < 0)
1537 return 0;
1538
daad4fd5 1539#ifdef HAVE_WORKING_STAT
1540 fstat (((unix_stream *) (u->s))->fd, &st2);
4ee9c684 1541 return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino);
daad4fd5 1542#else
c0ecd33c 1543
1544# ifdef __MINGW32__
1545 /* We try to match files by a unique ID. On some filesystems (network
1546 fs and FAT), we can't generate this unique ID, and will simply compare
1547 filenames. */
1548 id1 = id_from_path (path);
1549 id2 = id_from_fd (((unix_stream *) (u->s))->fd);
1550 if (id1 || id2)
1551 return (id1 == id2);
1552# endif
1553
daad4fd5 1554 if (len != u->file_len)
1555 return 0;
1556 return (memcmp(path, u->file, len) == 0);
1557#endif
4ee9c684 1558}
1559
1560
60c514ba 1561#ifdef HAVE_WORKING_STAT
1562# define FIND_FILE0_DECL struct stat *st
1563# define FIND_FILE0_ARGS st
1564#else
c0ecd33c 1565# define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
1566# define FIND_FILE0_ARGS id, file, file_len
60c514ba 1567#endif
1568
4ee9c684 1569/* find_file0()-- Recursive work function for find_file() */
1570
f02dd226 1571static gfc_unit *
60c514ba 1572find_file0 (gfc_unit *u, FIND_FILE0_DECL)
4ee9c684 1573{
f02dd226 1574 gfc_unit *v;
c0ecd33c 1575#if defined(__MINGW32__) && !HAVE_WORKING_STAT
1576 uint64_t id1;
1577#endif
4ee9c684 1578
1579 if (u == NULL)
1580 return NULL;
1581
daad4fd5 1582#ifdef HAVE_WORKING_STAT
60c514ba 1583 if (u->s != NULL
1584 && fstat (((unix_stream *) u->s)->fd, &st[1]) >= 0 &&
1585 st[0].st_dev == st[1].st_dev && st[0].st_ino == st[1].st_ino)
4ee9c684 1586 return u;
daad4fd5 1587#else
c0ecd33c 1588# ifdef __MINGW32__
1589 if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
1590 {
1591 if (id == id1)
1592 return u;
1593 }
1594 else
1595# endif
1596 if (compare_string (u->file_len, u->file, file_len, file) == 0)
1597 return u;
daad4fd5 1598#endif
4ee9c684 1599
60c514ba 1600 v = find_file0 (u->left, FIND_FILE0_ARGS);
4ee9c684 1601 if (v != NULL)
1602 return v;
1603
60c514ba 1604 v = find_file0 (u->right, FIND_FILE0_ARGS);
4ee9c684 1605 if (v != NULL)
1606 return v;
1607
1608 return NULL;
1609}
1610
1611
1612/* find_file()-- Take the current filename and see if there is a unit
1613 * that has the file already open. Returns a pointer to the unit if so. */
1614
f02dd226 1615gfc_unit *
60c514ba 1616find_file (const char *file, gfc_charlen_type file_len)
4ee9c684 1617{
1618 char path[PATH_MAX + 1];
60c514ba 1619 struct stat st[2];
1620 gfc_unit *u;
c0ecd33c 1621 uint64_t id;
4ee9c684 1622
60c514ba 1623 if (unpack_filename (path, file, file_len))
4ee9c684 1624 return NULL;
1625
60c514ba 1626 if (stat (path, &st[0]) < 0)
4ee9c684 1627 return NULL;
1628
c0ecd33c 1629#if defined(__MINGW32__) && !HAVE_WORKING_STAT
1630 id = id_from_path (path);
1631#else
1632 id = 0;
1633#endif
1634
60c514ba 1635 __gthread_mutex_lock (&unit_lock);
1636retry:
1637 u = find_file0 (unit_root, FIND_FILE0_ARGS);
1638 if (u != NULL)
1639 {
1640 /* Fast path. */
1641 if (! __gthread_mutex_trylock (&u->lock))
1642 {
1643 /* assert (u->closed == 0); */
1644 __gthread_mutex_unlock (&unit_lock);
1645 return u;
1646 }
1647
1648 inc_waiting_locked (u);
1649 }
1650 __gthread_mutex_unlock (&unit_lock);
1651 if (u != NULL)
1652 {
1653 __gthread_mutex_lock (&u->lock);
1654 if (u->closed)
1655 {
1656 __gthread_mutex_lock (&unit_lock);
1657 __gthread_mutex_unlock (&u->lock);
1658 if (predec_waiting_locked (u) == 0)
1659 free_mem (u);
1660 goto retry;
1661 }
1662
1663 dec_waiting_unlocked (u);
1664 }
1665 return u;
1666}
1667
1668static gfc_unit *
1669flush_all_units_1 (gfc_unit *u, int min_unit)
1670{
1671 while (u != NULL)
1672 {
1673 if (u->unit_number > min_unit)
1674 {
1675 gfc_unit *r = flush_all_units_1 (u->left, min_unit);
1676 if (r != NULL)
1677 return r;
1678 }
1679 if (u->unit_number >= min_unit)
1680 {
1681 if (__gthread_mutex_trylock (&u->lock))
1682 return u;
1683 if (u->s)
1684 flush (u->s);
1685 __gthread_mutex_unlock (&u->lock);
1686 }
1687 u = u->right;
1688 }
1689 return NULL;
1690}
1691
1692void
1693flush_all_units (void)
1694{
1695 gfc_unit *u;
1696 int min_unit = 0;
1697
1698 __gthread_mutex_lock (&unit_lock);
1699 do
1700 {
1701 u = flush_all_units_1 (unit_root, min_unit);
1702 if (u != NULL)
1703 inc_waiting_locked (u);
1704 __gthread_mutex_unlock (&unit_lock);
1705 if (u == NULL)
1706 return;
1707
1708 __gthread_mutex_lock (&u->lock);
1709
1710 min_unit = u->unit_number + 1;
1711
1712 if (u->closed == 0)
1713 {
1714 flush (u->s);
1715 __gthread_mutex_lock (&unit_lock);
1716 __gthread_mutex_unlock (&u->lock);
1717 (void) predec_waiting_locked (u);
1718 }
1719 else
1720 {
1721 __gthread_mutex_lock (&unit_lock);
1722 __gthread_mutex_unlock (&u->lock);
1723 if (predec_waiting_locked (u) == 0)
1724 free_mem (u);
1725 }
1726 }
1727 while (1);
4ee9c684 1728}
1729
1730
1731/* stream_at_bof()-- Returns nonzero if the stream is at the beginning
1732 * of the file. */
1733
1734int
1735stream_at_bof (stream * s)
1736{
1737 unix_stream *us;
1738
5df4b62f 1739 if (!is_seekable (s))
1740 return 0;
4ee9c684 1741
5df4b62f 1742 us = (unix_stream *) s;
4ee9c684 1743
1744 return us->logical_offset == 0;
1745}
1746
1747
cf6a3896 1748/* stream_at_eof()-- Returns nonzero if the stream is at the end
4ee9c684 1749 * of the file. */
1750
1751int
1752stream_at_eof (stream * s)
1753{
1754 unix_stream *us;
1755
5df4b62f 1756 if (!is_seekable (s))
1757 return 0;
4ee9c684 1758
5df4b62f 1759 us = (unix_stream *) s;
4ee9c684 1760
1761 return us->logical_offset == us->dirty_offset;
1762}
1763
1764
1765/* delete_file()-- Given a unit structure, delete the file associated
1766 * with the unit. Returns nonzero if something went wrong. */
1767
1768int
f02dd226 1769delete_file (gfc_unit * u)
4ee9c684 1770{
1771 char path[PATH_MAX + 1];
1772
1773 if (unpack_filename (path, u->file, u->file_len))
1774 { /* Shouldn't be possible */
1775 errno = ENOENT;
1776 return 1;
1777 }
1778
1779 return unlink (path);
1780}
1781
1782
1783/* file_exists()-- Returns nonzero if the current filename exists on
1784 * the system */
1785
1786int
60c514ba 1787file_exists (const char *file, gfc_charlen_type file_len)
4ee9c684 1788{
1789 char path[PATH_MAX + 1];
1790 struct stat statbuf;
1791
60c514ba 1792 if (unpack_filename (path, file, file_len))
4ee9c684 1793 return 0;
1794
1795 if (stat (path, &statbuf) < 0)
1796 return 0;
1797
1798 return 1;
1799}
1800
1801
1802
fb35179a 1803static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
4ee9c684 1804
1805/* inquire_sequential()-- Given a fortran string, determine if the
1806 * file is suitable for sequential access. Returns a C-style
1807 * string. */
1808
1809const char *
1810inquire_sequential (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) ||
1820 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
2e1fa727 1821 return unknown;
4ee9c684 1822
1823 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1824 return no;
1825
1826 return unknown;
1827}
1828
1829
1830/* inquire_direct()-- Given a fortran string, determine if the file is
1831 * suitable for direct access. Returns a C-style string. */
1832
1833const char *
1834inquire_direct (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) || S_ISBLK (statbuf.st_mode))
2e1fa727 1844 return unknown;
4ee9c684 1845
1846 if (S_ISDIR (statbuf.st_mode) ||
1847 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1848 return no;
1849
1850 return unknown;
1851}
1852
1853
1854/* inquire_formatted()-- Given a fortran string, determine if the file
1855 * is suitable for formatted form. Returns a C-style string. */
1856
1857const char *
1858inquire_formatted (const char *string, int len)
1859{
1860 char path[PATH_MAX + 1];
1861 struct stat statbuf;
1862
1863 if (string == NULL ||
1864 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1865 return unknown;
1866
1867 if (S_ISREG (statbuf.st_mode) ||
1868 S_ISBLK (statbuf.st_mode) ||
1869 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
2e1fa727 1870 return unknown;
4ee9c684 1871
1872 if (S_ISDIR (statbuf.st_mode))
1873 return no;
1874
1875 return unknown;
1876}
1877
1878
1879/* inquire_unformatted()-- Given a fortran string, determine if the file
1880 * is suitable for unformatted form. Returns a C-style string. */
1881
1882const char *
1883inquire_unformatted (const char *string, int len)
1884{
4ee9c684 1885 return inquire_formatted (string, len);
1886}
1887
1888
e0582811 1889#ifndef HAVE_ACCESS
1890
1891#ifndef W_OK
1892#define W_OK 2
1893#endif
1894
1895#ifndef R_OK
1896#define R_OK 4
1897#endif
1898
1899/* Fallback implementation of access() on systems that don't have it.
1900 Only modes R_OK and W_OK are used in this file. */
1901
1902static int
1903fallback_access (const char *path, int mode)
1904{
1905 if ((mode & R_OK) && open (path, O_RDONLY) < 0)
1906 return -1;
1907
1908 if ((mode & W_OK) && open (path, O_WRONLY) < 0)
1909 return -1;
1910
1911 return 0;
1912}
1913
1914#undef access
1915#define access fallback_access
1916#endif
1917
1918
4ee9c684 1919/* inquire_access()-- Given a fortran string, determine if the file is
1920 * suitable for access. */
1921
1922static const char *
1923inquire_access (const char *string, int len, int mode)
1924{
1925 char path[PATH_MAX + 1];
1926
1927 if (string == NULL || unpack_filename (path, string, len) ||
1928 access (path, mode) < 0)
1929 return no;
1930
1931 return yes;
1932}
1933
1934
1935/* inquire_read()-- Given a fortran string, determine if the file is
1936 * suitable for READ access. */
1937
1938const char *
1939inquire_read (const char *string, int len)
1940{
4ee9c684 1941 return inquire_access (string, len, R_OK);
1942}
1943
1944
1945/* inquire_write()-- Given a fortran string, determine if the file is
1946 * suitable for READ access. */
1947
1948const char *
1949inquire_write (const char *string, int len)
1950{
4ee9c684 1951 return inquire_access (string, len, W_OK);
1952}
1953
1954
1955/* inquire_readwrite()-- Given a fortran string, determine if the file is
1956 * suitable for read and write access. */
1957
1958const char *
1959inquire_readwrite (const char *string, int len)
1960{
4ee9c684 1961 return inquire_access (string, len, R_OK | W_OK);
1962}
1963
1964
1965/* file_length()-- Return the file length in bytes, -1 if unknown */
1966
b093181d 1967gfc_offset
4ee9c684 1968file_length (stream * s)
1969{
4ee9c684 1970 return ((unix_stream *) s)->file_length;
1971}
1972
1973
1974/* file_position()-- Return the current position of the file */
1975
b093181d 1976gfc_offset
6e34b5c4 1977file_position (stream *s)
4ee9c684 1978{
4ee9c684 1979 return ((unix_stream *) s)->logical_offset;
1980}
1981
1982
1983/* is_seekable()-- Return nonzero if the stream is seekable, zero if
1984 * it is not */
1985
1986int
6e34b5c4 1987is_seekable (stream *s)
4ee9c684 1988{
b2a112ca 1989 /* By convention, if file_length == -1, the file is not
1990 seekable. */
5a78b88f 1991 return ((unix_stream *) s)->file_length!=-1;
4ee9c684 1992}
1993
6e34b5c4 1994
1995/* is_special()-- Return nonzero if the stream is not a regular file. */
1996
09478184 1997int
6e34b5c4 1998is_special (stream *s)
1999{
2000 return ((unix_stream *) s)->special_file;
2001}
2002
2003
b0342e98 2004try
2005flush (stream *s)
2006{
2007 return fd_flush( (unix_stream *) s);
2008}
2009
60d77e0d 2010int
2011stream_isatty (stream *s)
2012{
2013 return isatty (((unix_stream *) s)->fd);
2014}
2015
2016char *
7b3e325b 2017stream_ttyname (stream *s __attribute__ ((unused)))
60d77e0d 2018{
f2c0a16d 2019#ifdef HAVE_TTYNAME
60d77e0d 2020 return ttyname (((unix_stream *) s)->fd);
f2c0a16d 2021#else
2022 return NULL;
2023#endif
60d77e0d 2024}
2025
16de8065 2026gfc_offset
2027stream_offset (stream *s)
2028{
2029 return (((unix_stream *) s)->logical_offset);
2030}
2031
4ee9c684 2032
2033/* How files are stored: This is an operating-system specific issue,
2034 and therefore belongs here. There are three cases to consider.
2035
2036 Direct Access:
2037 Records are written as block of bytes corresponding to the record
2038 length of the file. This goes for both formatted and unformatted
2039 records. Positioning is done explicitly for each data transfer,
2040 so positioning is not much of an issue.
2041
2042 Sequential Formatted:
2043 Records are separated by newline characters. The newline character
2044 is prohibited from appearing in a string. If it does, this will be
2045 messed up on the next read. End of file is also the end of a record.
2046
2047 Sequential Unformatted:
2048 In this case, we are merely copying bytes to and from main storage,
2049 yet we need to keep track of varying record lengths. We adopt
2050 the solution used by f2c. Each record contains a pair of length
2051 markers:
2052
2053 Length of record n in bytes
2054 Data of record n
2055 Length of record n in bytes
2056
2057 Length of record n+1 in bytes
2058 Data of record n+1
2059 Length of record n+1 in bytes
2060
2061 The length is stored at the end of a record to allow backspacing to the
2062 previous record. Between data transfer statements, the file pointer
2063 is left pointing to the first length of the current record.
2064
2065 ENDFILE records are never explicitly stored.
2066
2067*/