]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/io/unix.c
* be.po, ca.po, da.po, de.po, el.po, es.po, fi.po, fr.po, id.po,
[thirdparty/gcc.git] / libgfortran / io / unix.c
CommitLineData
e213d8e0 1/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2 2011
a0007dfa 3 Free Software Foundation, Inc.
4ee9c684 4 Contributed by Andy Vaught
84d33b91 5 F2003 I/O support contributed by Jerry DeLisle
4ee9c684 6
5e62a3cc 7This file is part of the GNU Fortran runtime library (libgfortran).
4ee9c684 8
9Libgfortran is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
6bc9506f 11the Free Software Foundation; either version 3, or (at your option)
4ee9c684 12any later version.
13
14Libgfortran is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
6bc9506f 19Under Section 7 of GPL version 3, you are granted additional
20permissions described in the GCC Runtime Library Exception, version
213.1, as published by the Free Software Foundation.
22
23You should have received a copy of the GNU General Public License and
24a copy of the GCC Runtime Library Exception along with this program;
25see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26<http://www.gnu.org/licenses/>. */
4ee9c684 27
28/* Unix stream I/O module */
29
41f2d5e8 30#include "io.h"
f65f6629 31#include "unix.h"
4ee9c684 32#include <stdlib.h>
33#include <limits.h>
34
35#include <unistd.h>
36#include <sys/stat.h>
37#include <fcntl.h>
2639e4cd 38#include <assert.h>
4ee9c684 39
4ee9c684 40#include <string.h>
41#include <errno.h>
42
c0ecd33c 43
44/* For mingw, we don't identify files by their inode number, but by a
45 64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
7a4491a4 46#ifdef __MINGW32__
c0ecd33c 47
48#define WIN32_LEAN_AND_MEAN
49#include <windows.h>
50
4dbc0658 51#define lseek _lseeki64
7a4491a4 52#define fstat _fstati64
53#define stat _stati64
54typedef struct _stati64 gfstat_t;
4dbc0658 55
7a4491a4 56#ifndef HAVE_WORKING_STAT
c0ecd33c 57static uint64_t
58id_from_handle (HANDLE hFile)
59{
60 BY_HANDLE_FILE_INFORMATION FileInformation;
61
62 if (hFile == INVALID_HANDLE_VALUE)
63 return 0;
64
65 memset (&FileInformation, 0, sizeof(FileInformation));
66 if (!GetFileInformationByHandle (hFile, &FileInformation))
67 return 0;
68
69 return ((uint64_t) FileInformation.nFileIndexLow)
70 | (((uint64_t) FileInformation.nFileIndexHigh) << 32);
71}
72
73
74static uint64_t
75id_from_path (const char *path)
76{
77 HANDLE hFile;
78 uint64_t res;
79
80 if (!path || !*path || access (path, F_OK))
81 return (uint64_t) -1;
82
83 hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
84 FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
85 NULL);
86 res = id_from_handle (hFile);
87 CloseHandle (hFile);
88 return res;
89}
90
91
92static uint64_t
93id_from_fd (const int fd)
94{
95 return id_from_handle ((HANDLE) _get_osfhandle (fd));
96}
97
98#endif
99
7a4491a4 100#else
101typedef struct stat gfstat_t;
102#endif
103
4ee9c684 104#ifndef PATH_MAX
105#define PATH_MAX 1024
106#endif
107
7dfba97b 108/* These flags aren't defined on all targets (mingw32), so provide them
109 here. */
110#ifndef S_IRGRP
111#define S_IRGRP 0
112#endif
113
114#ifndef S_IWGRP
115#define S_IWGRP 0
116#endif
117
118#ifndef S_IROTH
119#define S_IROTH 0
120#endif
121
122#ifndef S_IWOTH
123#define S_IWOTH 0
124#endif
125
76c0a846 126
fb053cd1 127#ifndef HAVE_ACCESS
128
129#ifndef W_OK
130#define W_OK 2
131#endif
132
133#ifndef R_OK
134#define R_OK 4
135#endif
136
137#ifndef F_OK
138#define F_OK 0
139#endif
140
141/* Fallback implementation of access() on systems that don't have it.
142 Only modes R_OK, W_OK and F_OK are used in this file. */
143
144static int
145fallback_access (const char *path, int mode)
146{
398e846b 147 int fd;
148
149 if ((mode & R_OK) && (fd = open (path, O_RDONLY)) < 0)
fb053cd1 150 return -1;
398e846b 151 close (fd);
fb053cd1 152
398e846b 153 if ((mode & W_OK) && (fd = open (path, O_WRONLY)) < 0)
fb053cd1 154 return -1;
398e846b 155 close (fd);
fb053cd1 156
157 if (mode == F_OK)
158 {
159 gfstat_t st;
160 return stat (path, &st);
161 }
162
163 return 0;
164}
165
166#undef access
167#define access fallback_access
168#endif
169
170
65f15010 171/* Unix and internal stream I/O module */
76c0a846 172
65f15010 173static const int BUFFER_SIZE = 8192;
76c0a846 174
3479b863 175typedef struct
176{
177 stream st;
178
179 gfc_offset buffer_offset; /* File offset of the start of the buffer */
180 gfc_offset physical_offset; /* Current physical file offset */
181 gfc_offset logical_offset; /* Current logical file offset */
182 gfc_offset file_length; /* Length of the file, -1 if not seekable. */
183
184 char *buffer; /* Pointer to the buffer. */
185 int fd; /* The POSIX file descriptor. */
186
187 int active; /* Length of valid bytes in the buffer */
188
189 int ndirty; /* Dirty bytes starting at buffer_offset */
190
01cd2c93 191 int special_file; /* =1 if the fd refers to a special file */
192
193 /* Cached stat(2) values. */
194 dev_t st_dev;
195 ino_t st_ino;
3479b863 196}
197unix_stream;
198
199
4ee9c684 200/* fix_fd()-- Given a file descriptor, make sure it is not one of the
201 * standard descriptors, returning a non-standard descriptor. If the
202 * user specifies that system errors should go to standard output,
203 * then closes standard output, we don't want the system errors to a
204 * file that has been given file descriptor 1 or 0. We want to send
205 * the error to the invalid descriptor. */
206
207static int
208fix_fd (int fd)
209{
e0582811 210#ifdef HAVE_DUP
4ee9c684 211 int input, output, error;
212
213 input = output = error = 0;
214
7145fd06 215 /* Unix allocates the lowest descriptors first, so a loop is not
216 required, but this order is. */
4ee9c684 217 if (fd == STDIN_FILENO)
218 {
219 fd = dup (fd);
220 input = 1;
221 }
222 if (fd == STDOUT_FILENO)
223 {
224 fd = dup (fd);
225 output = 1;
226 }
227 if (fd == STDERR_FILENO)
228 {
229 fd = dup (fd);
230 error = 1;
231 }
232
233 if (input)
234 close (STDIN_FILENO);
235 if (output)
236 close (STDOUT_FILENO);
237 if (error)
238 close (STDERR_FILENO);
e0582811 239#endif
4ee9c684 240
241 return fd;
242}
243
244
2488b3b6 245/* If the stream corresponds to a preconnected unit, we flush the
246 corresponding C stream. This is bugware for mixed C-Fortran codes
247 where the C code doesn't flush I/O before returning. */
248void
249flush_if_preconnected (stream * s)
250{
251 int fd;
252
253 fd = ((unix_stream *) s)->fd;
254 if (fd == STDIN_FILENO)
255 fflush (stdin);
256 else if (fd == STDOUT_FILENO)
257 fflush (stdout);
258 else if (fd == STDERR_FILENO)
259 fflush (stderr);
260}
261
4ee9c684 262
65f15010 263/********************************************************************
264Raw I/O functions (read, write, seek, tell, truncate, close).
265
266These functions wrap the basic POSIX I/O syscalls. Any deviation in
267semantics is a bug, except the following: write restarts in case
268of being interrupted by a signal, and as the first argument the
269functions take the unix_stream struct rather than an integer file
270descriptor. Also, for POSIX read() and write() a nbyte argument larger
271than SSIZE_MAX is undefined; here the type of nbyte is ssize_t rather
272than size_t as for POSIX read/write.
273*********************************************************************/
4ee9c684 274
b2a112ca 275static int
65f15010 276raw_flush (unix_stream * s __attribute__ ((unused)))
b2a112ca 277{
65f15010 278 return 0;
4ee9c684 279}
280
65f15010 281static ssize_t
282raw_read (unix_stream * s, void * buf, ssize_t nbyte)
283{
284 /* For read we can't do I/O in a loop like raw_write does, because
285 that will break applications that wait for interactive I/O. */
286 return read (s->fd, buf, nbyte);
287}
4ee9c684 288
65f15010 289static ssize_t
290raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
4ee9c684 291{
65f15010 292 ssize_t trans, bytes_left;
b2a112ca 293 char *buf_st;
b2a112ca 294
65f15010 295 bytes_left = nbyte;
b2a112ca 296 buf_st = (char *) buf;
297
298 /* We must write in a loop since some systems don't restart system
299 calls in case of a signal. */
300 while (bytes_left > 0)
4ee9c684 301 {
65f15010 302 trans = write (s->fd, buf_st, bytes_left);
b2a112ca 303 if (trans < 0)
304 {
305 if (errno == EINTR)
306 continue;
307 else
65f15010 308 return trans;
b2a112ca 309 }
310 buf_st += trans;
311 bytes_left -= trans;
4ee9c684 312 }
313
65f15010 314 return nbyte - bytes_left;
4ee9c684 315}
4ee9c684 316
4dbc0658 317static gfc_offset
318raw_seek (unix_stream * s, gfc_offset offset, int whence)
65f15010 319{
320 return lseek (s->fd, offset, whence);
321}
4ee9c684 322
4dbc0658 323static gfc_offset
65f15010 324raw_tell (unix_stream * s)
325{
326 return lseek (s->fd, 0, SEEK_CUR);
327}
4ee9c684 328
65f15010 329static int
4dbc0658 330raw_truncate (unix_stream * s, gfc_offset length)
4ee9c684 331{
4dbc0658 332#ifdef __MINGW32__
333 HANDLE h;
334 gfc_offset cur;
335
336 if (isatty (s->fd))
337 {
338 errno = EBADF;
339 return -1;
340 }
db23ac43 341 h = (HANDLE) _get_osfhandle (s->fd);
4dbc0658 342 if (h == INVALID_HANDLE_VALUE)
343 {
344 errno = EBADF;
345 return -1;
346 }
347 cur = lseek (s->fd, 0, SEEK_CUR);
348 if (cur == -1)
349 return -1;
350 if (lseek (s->fd, length, SEEK_SET) == -1)
351 goto error;
352 if (!SetEndOfFile (h))
353 {
354 errno = EBADF;
355 goto error;
356 }
357 if (lseek (s->fd, cur, SEEK_SET) == -1)
358 return -1;
359 return 0;
360 error:
361 lseek (s->fd, cur, SEEK_SET);
362 return -1;
363#elif defined HAVE_FTRUNCATE
65f15010 364 return ftruncate (s->fd, length);
365#elif defined HAVE_CHSIZE
366 return chsize (s->fd, length);
367#else
368 runtime_error ("required ftruncate or chsize support not present");
369 return -1;
370#endif
4ee9c684 371}
372
65f15010 373static int
374raw_close (unix_stream * s)
375{
376 int retval;
377
8b89aa85 378 if (s->fd != STDOUT_FILENO
379 && s->fd != STDERR_FILENO
380 && s->fd != STDIN_FILENO)
381 retval = close (s->fd);
382 else
6ffeb312 383 retval = 0;
5e62a3cc 384 free (s);
65f15010 385 return retval;
386}
4ee9c684 387
65f15010 388static int
389raw_init (unix_stream * s)
390{
391 s->st.read = (void *) raw_read;
392 s->st.write = (void *) raw_write;
393 s->st.seek = (void *) raw_seek;
394 s->st.tell = (void *) raw_tell;
afd927a4 395 s->st.trunc = (void *) raw_truncate;
65f15010 396 s->st.close = (void *) raw_close;
397 s->st.flush = (void *) raw_flush;
4ee9c684 398
65f15010 399 s->buffer = NULL;
400 return 0;
401}
b2a112ca 402
4ee9c684 403
65f15010 404/*********************************************************************
405Buffered I/O functions. These functions have the same semantics as the
406raw I/O functions above, except that they are buffered in order to
407improve performance. The buffer must be flushed when switching from
408reading to writing and vice versa.
409*********************************************************************/
410
411static int
412buf_flush (unix_stream * s)
4ee9c684 413{
65f15010 414 int writelen;
415
416 /* Flushing in read mode means discarding read bytes. */
417 s->active = 0;
b2a112ca 418
4ee9c684 419 if (s->ndirty == 0)
65f15010 420 return 0;
352597f9 421
65f15010 422 if (s->file_length != -1 && s->physical_offset != s->buffer_offset
423 && lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
424 return -1;
4ee9c684 425
65f15010 426 writelen = raw_write (s, s->buffer, s->ndirty);
4ee9c684 427
65f15010 428 s->physical_offset = s->buffer_offset + writelen;
5a78b88f 429
65f15010 430 /* Don't increment file_length if the file is non-seekable. */
5a78b88f 431 if (s->file_length != -1 && s->physical_offset > s->file_length)
65f15010 432 s->file_length = s->physical_offset;
b2a112ca 433
434 s->ndirty -= writelen;
435 if (s->ndirty != 0)
65f15010 436 return -1;
4ee9c684 437
9a43d9ca 438#ifdef _WIN32
439 _commit (s->fd);
440#endif
441
65f15010 442 return 0;
4ee9c684 443}
444
65f15010 445static ssize_t
446buf_read (unix_stream * s, void * buf, ssize_t nbyte)
4ee9c684 447{
65f15010 448 if (s->active == 0)
449 s->buffer_offset = s->logical_offset;
5d5f00d5 450
65f15010 451 /* Is the data we want in the buffer? */
452 if (s->logical_offset + nbyte <= s->buffer_offset + s->active
453 && s->buffer_offset <= s->logical_offset)
454 memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset), nbyte);
5d5f00d5 455 else
456 {
65f15010 457 /* First copy the active bytes if applicable, then read the rest
458 either directly or filling the buffer. */
459 char *p;
460 int nread = 0;
461 ssize_t to_read, did_read;
462 gfc_offset new_logical;
463
464 p = (char *) buf;
465 if (s->logical_offset >= s->buffer_offset
466 && s->buffer_offset + s->active >= s->logical_offset)
467 {
468 nread = s->active - (s->logical_offset - s->buffer_offset);
469 memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset),
470 nread);
471 p += nread;
472 }
473 /* At this point we consider all bytes in the buffer discarded. */
474 to_read = nbyte - nread;
475 new_logical = s->logical_offset + nread;
476 if (s->file_length != -1 && s->physical_offset != new_logical
477 && lseek (s->fd, new_logical, SEEK_SET) < 0)
478 return -1;
479 s->buffer_offset = s->physical_offset = new_logical;
480 if (to_read <= BUFFER_SIZE/2)
481 {
482 did_read = raw_read (s, s->buffer, BUFFER_SIZE);
483 s->physical_offset += did_read;
484 s->active = did_read;
485 did_read = (did_read > to_read) ? to_read : did_read;
486 memcpy (p, s->buffer, did_read);
487 }
488 else
489 {
490 did_read = raw_read (s, p, to_read);
491 s->physical_offset += did_read;
492 s->active = 0;
493 }
494 nbyte = did_read + nread;
4ee9c684 495 }
65f15010 496 s->logical_offset += nbyte;
497 return nbyte;
4ee9c684 498}
499
65f15010 500static ssize_t
501buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
4ee9c684 502{
65f15010 503 if (s->ndirty == 0)
504 s->buffer_offset = s->logical_offset;
505
506 /* Does the data fit into the buffer? As a special case, if the
507 buffer is empty and the request is bigger than BUFFER_SIZE/2,
508 write directly. This avoids the case where the buffer would have
509 to be flushed at every write. */
510 if (!(s->ndirty == 0 && nbyte > BUFFER_SIZE/2)
511 && s->logical_offset + nbyte <= s->buffer_offset + BUFFER_SIZE
512 && s->buffer_offset <= s->logical_offset
513 && s->buffer_offset + s->ndirty >= s->logical_offset)
fef3501c 514 {
65f15010 515 memcpy (s->buffer + (s->logical_offset - s->buffer_offset), buf, nbyte);
516 int nd = (s->logical_offset - s->buffer_offset) + nbyte;
517 if (nd > s->ndirty)
518 s->ndirty = nd;
fef3501c 519 }
520 else
521 {
65f15010 522 /* Flush, and either fill the buffer with the new data, or if
523 the request is bigger than the buffer size, write directly
524 bypassing the buffer. */
525 buf_flush (s);
526 if (nbyte <= BUFFER_SIZE/2)
527 {
528 memcpy (s->buffer, buf, nbyte);
529 s->buffer_offset = s->logical_offset;
530 s->ndirty += nbyte;
531 }
532 else
35a97371 533 {
534 if (s->file_length != -1 && s->physical_offset != s->logical_offset)
535 {
536 if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
537 return -1;
538 s->physical_offset = s->logical_offset;
539 }
540
541 nbyte = raw_write (s, buf, nbyte);
542 s->physical_offset += nbyte;
543 }
4ee9c684 544 }
65f15010 545 s->logical_offset += nbyte;
352597f9 546 /* Don't increment file_length if the file is non-seekable. */
352597f9 547 if (s->file_length != -1 && s->logical_offset > s->file_length)
65f15010 548 s->file_length = s->logical_offset;
549 return nbyte;
4ee9c684 550}
551
4dbc0658 552static gfc_offset
553buf_seek (unix_stream * s, gfc_offset offset, int whence)
4ee9c684 554{
65f15010 555 switch (whence)
352597f9 556 {
65f15010 557 case SEEK_SET:
558 break;
559 case SEEK_CUR:
560 offset += s->logical_offset;
561 break;
562 case SEEK_END:
563 offset += s->file_length;
564 break;
565 default:
566 return -1;
352597f9 567 }
65f15010 568 if (offset < 0)
72909c79 569 {
65f15010 570 errno = EINVAL;
571 return -1;
72909c79 572 }
65f15010 573 s->logical_offset = offset;
574 return offset;
4ee9c684 575}
576
4dbc0658 577static gfc_offset
65f15010 578buf_tell (unix_stream * s)
56f281a2 579{
65f15010 580 return s->logical_offset;
56f281a2 581}
b2a112ca 582
b2a112ca 583static int
4dbc0658 584buf_truncate (unix_stream * s, gfc_offset length)
b2a112ca 585{
65f15010 586 int r;
b2a112ca 587
65f15010 588 if (buf_flush (s) != 0)
589 return -1;
590 r = raw_truncate (s, length);
591 if (r == 0)
592 s->file_length = length;
593 return r;
b2a112ca 594}
595
b2a112ca 596static int
65f15010 597buf_close (unix_stream * s)
4ee9c684 598{
65f15010 599 if (buf_flush (s) != 0)
600 return -1;
5e62a3cc 601 free (s->buffer);
65f15010 602 return raw_close (s);
4ee9c684 603}
604
65f15010 605static int
606buf_init (unix_stream * s)
4ee9c684 607{
65f15010 608 s->st.read = (void *) buf_read;
609 s->st.write = (void *) buf_write;
610 s->st.seek = (void *) buf_seek;
611 s->st.tell = (void *) buf_tell;
afd927a4 612 s->st.trunc = (void *) buf_truncate;
65f15010 613 s->st.close = (void *) buf_close;
614 s->st.flush = (void *) buf_flush;
4ee9c684 615
65f15010 616 s->buffer = get_mem (BUFFER_SIZE);
617 return 0;
4ee9c684 618}
619
620
4ee9c684 621/*********************************************************************
622 memory stream functions - These are used for internal files
623
624 The idea here is that a single stream structure is created and all
625 requests must be satisfied from it. The location and size of the
626 buffer is the character variable supplied to the READ or WRITE
627 statement.
628
629*********************************************************************/
630
65f15010 631char *
632mem_alloc_r (stream * strm, int * len)
4ee9c684 633{
65f15010 634 unix_stream * s = (unix_stream *) strm;
b093181d 635 gfc_offset n;
d875179d 636 gfc_offset where = s->logical_offset;
4ee9c684 637
638 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
639 return NULL;
640
11de4bf9 641 n = s->buffer_offset + s->active - where;
4ee9c684 642 if (*len > n)
643 *len = n;
644
65f15010 645 s->logical_offset = where + *len;
646
4ee9c684 647 return s->buffer + (where - s->buffer_offset);
648}
649
650
e0aaacb7 651char *
652mem_alloc_r4 (stream * strm, int * len)
653{
654 unix_stream * s = (unix_stream *) strm;
655 gfc_offset n;
656 gfc_offset where = s->logical_offset;
657
658 if (where < s->buffer_offset || where > s->buffer_offset + s->active)
659 return NULL;
660
661 n = s->buffer_offset + s->active - where;
662 if (*len > n)
663 *len = n;
664
665 s->logical_offset = where + *len;
666
667 return s->buffer + (where - s->buffer_offset) * 4;
668}
669
670
65f15010 671char *
672mem_alloc_w (stream * strm, int * len)
4ee9c684 673{
65f15010 674 unix_stream * s = (unix_stream *) strm;
b093181d 675 gfc_offset m;
d875179d 676 gfc_offset where = s->logical_offset;
4ee9c684 677
4ee9c684 678 m = where + *len;
679
2639e4cd 680 if (where < s->buffer_offset)
4ee9c684 681 return NULL;
682
2639e4cd 683 if (m > s->file_length)
72231bd6 684 return NULL;
2639e4cd 685
4ee9c684 686 s->logical_offset = m;
687
688 return s->buffer + (where - s->buffer_offset);
689}
690
691
1bb7bffb 692gfc_char4_t *
e0aaacb7 693mem_alloc_w4 (stream * strm, int * len)
694{
695 unix_stream * s = (unix_stream *) strm;
696 gfc_offset m;
697 gfc_offset where = s->logical_offset;
1bb7bffb 698 gfc_char4_t *result = (gfc_char4_t *) s->buffer;
e0aaacb7 699
700 m = where + *len;
701
702 if (where < s->buffer_offset)
703 return NULL;
704
705 if (m > s->file_length)
706 return NULL;
707
708 s->logical_offset = m;
1bb7bffb 709 return &result[where - s->buffer_offset];
e0aaacb7 710}
711
712
713/* Stream read function for character(kine=1) internal units. */
b2a112ca 714
65f15010 715static ssize_t
716mem_read (stream * s, void * buf, ssize_t nbytes)
b2a112ca 717{
718 void *p;
65f15010 719 int nb = nbytes;
b2a112ca 720
65f15010 721 p = mem_alloc_r (s, &nb);
b2a112ca 722 if (p)
723 {
65f15010 724 memcpy (buf, p, nb);
725 return (ssize_t) nb;
b2a112ca 726 }
727 else
65f15010 728 return 0;
b2a112ca 729}
730
731
e0aaacb7 732/* Stream read function for chracter(kind=4) internal units. */
733
734static ssize_t
735mem_read4 (stream * s, void * buf, ssize_t nbytes)
736{
737 void *p;
738 int nb = nbytes;
739
740 p = mem_alloc_r (s, &nb);
741 if (p)
742 {
743 memcpy (buf, p, nb);
744 return (ssize_t) nb;
745 }
746 else
747 return 0;
748}
749
750
751/* Stream write function for character(kind=1) internal units. */
b2a112ca 752
65f15010 753static ssize_t
754mem_write (stream * s, const void * buf, ssize_t nbytes)
b2a112ca 755{
756 void *p;
65f15010 757 int nb = nbytes;
b2a112ca 758
65f15010 759 p = mem_alloc_w (s, &nb);
b2a112ca 760 if (p)
761 {
65f15010 762 memcpy (p, buf, nb);
763 return (ssize_t) nb;
b2a112ca 764 }
765 else
65f15010 766 return 0;
b2a112ca 767}
768
769
e0aaacb7 770/* Stream write function for character(kind=4) internal units. */
771
772static ssize_t
773mem_write4 (stream * s, const void * buf, ssize_t nwords)
774{
775 gfc_char4_t *p;
776 int nw = nwords;
777
1bb7bffb 778 p = mem_alloc_w4 (s, &nw);
e0aaacb7 779 if (p)
780 {
781 while (nw--)
782 *p++ = (gfc_char4_t) *((char *) buf);
783 return nwords;
784 }
785 else
786 return 0;
787}
788
789
4dbc0658 790static gfc_offset
791mem_seek (stream * strm, gfc_offset offset, int whence)
4ee9c684 792{
65f15010 793 unix_stream * s = (unix_stream *) strm;
794 switch (whence)
795 {
796 case SEEK_SET:
797 break;
798 case SEEK_CUR:
799 offset += s->logical_offset;
800 break;
801 case SEEK_END:
802 offset += s->file_length;
803 break;
804 default:
805 return -1;
806 }
807
808 /* Note that for internal array I/O it's actually possible to have a
809 negative offset, so don't check for that. */
4ee9c684 810 if (offset > s->file_length)
811 {
65f15010 812 errno = EINVAL;
813 return -1;
4ee9c684 814 }
815
816 s->logical_offset = offset;
65f15010 817
818 /* Returning < 0 is the error indicator for sseek(), so return 0 if
819 offset is negative. Thus if the return value is 0, the caller
820 has to use stell() to get the real value of logical_offset. */
821 if (offset >= 0)
822 return offset;
823 return 0;
4ee9c684 824}
825
826
4dbc0658 827static gfc_offset
65f15010 828mem_tell (stream * s)
56f281a2 829{
65f15010 830 return ((unix_stream *)s)->logical_offset;
56f281a2 831}
832
833
4ee9c684 834static int
65f15010 835mem_truncate (unix_stream * s __attribute__ ((unused)),
4dbc0658 836 gfc_offset length __attribute__ ((unused)))
4ee9c684 837{
65f15010 838 return 0;
4ee9c684 839}
840
841
65f15010 842static int
843mem_flush (unix_stream * s __attribute__ ((unused)))
4ee9c684 844{
65f15010 845 return 0;
4ee9c684 846}
847
848
65f15010 849static int
850mem_close (unix_stream * s)
4ee9c684 851{
65f15010 852 if (s != NULL)
5e62a3cc 853 free (s);
4ee9c684 854
65f15010 855 return 0;
856}
4ee9c684 857
858
859/*********************************************************************
860 Public functions -- A reimplementation of this module needs to
861 define functional equivalents of the following.
862*********************************************************************/
863
e0aaacb7 864/* open_internal()-- Returns a stream structure from a character(kind=1)
865 internal file */
4ee9c684 866
867stream *
cf4abc57 868open_internal (char *base, int length, gfc_offset offset)
4ee9c684 869{
65f15010 870 unix_stream *s;
4ee9c684 871
65f15010 872 s = get_mem (sizeof (unix_stream));
873 memset (s, '\0', sizeof (unix_stream));
4ee9c684 874
875 s->buffer = base;
cf4abc57 876 s->buffer_offset = offset;
4ee9c684 877
878 s->logical_offset = 0;
879 s->active = s->file_length = length;
880
4ee9c684 881 s->st.close = (void *) mem_close;
882 s->st.seek = (void *) mem_seek;
65f15010 883 s->st.tell = (void *) mem_tell;
afd927a4 884 s->st.trunc = (void *) mem_truncate;
b2a112ca 885 s->st.read = (void *) mem_read;
886 s->st.write = (void *) mem_write;
65f15010 887 s->st.flush = (void *) mem_flush;
4ee9c684 888
e0aaacb7 889 return (stream *) s;
890}
891
892/* open_internal4()-- Returns a stream structure from a character(kind=4)
893 internal file */
894
895stream *
896open_internal4 (char *base, int length, gfc_offset offset)
897{
898 unix_stream *s;
899
900 s = get_mem (sizeof (unix_stream));
901 memset (s, '\0', sizeof (unix_stream));
902
903 s->buffer = base;
904 s->buffer_offset = offset;
905
906 s->logical_offset = 0;
907 s->active = s->file_length = length;
908
909 s->st.close = (void *) mem_close;
910 s->st.seek = (void *) mem_seek;
911 s->st.tell = (void *) mem_tell;
912 s->st.trunc = (void *) mem_truncate;
913 s->st.read = (void *) mem_read4;
914 s->st.write = (void *) mem_write4;
915 s->st.flush = (void *) mem_flush;
916
4ee9c684 917 return (stream *) s;
918}
919
920
921/* fd_to_stream()-- Given an open file descriptor, build a stream
922 * around it. */
923
924static stream *
aadbd4ae 925fd_to_stream (int fd)
4ee9c684 926{
7a4491a4 927 gfstat_t statbuf;
4ee9c684 928 unix_stream *s;
929
930 s = get_mem (sizeof (unix_stream));
8f8ad899 931 memset (s, '\0', sizeof (unix_stream));
4ee9c684 932
933 s->fd = fd;
934 s->buffer_offset = 0;
935 s->physical_offset = 0;
936 s->logical_offset = 0;
4ee9c684 937
938 /* Get the current length of the file. */
939
940 fstat (fd, &statbuf);
352597f9 941
01cd2c93 942 s->st_dev = statbuf.st_dev;
943 s->st_ino = statbuf.st_ino;
227e9423 944 s->special_file = !S_ISREG (statbuf.st_mode);
4ee9c684 945
01cd2c93 946 if (S_ISREG (statbuf.st_mode))
947 s->file_length = statbuf.st_size;
948 else if (S_ISBLK (statbuf.st_mode))
949 {
950 /* Hopefully more portable than ioctl(fd, BLKGETSIZE64, &size)? */
951 gfc_offset cur = lseek (fd, 0, SEEK_CUR);
952 s->file_length = lseek (fd, 0, SEEK_END);
953 lseek (fd, cur, SEEK_SET);
954 }
955 else
956 s->file_length = -1;
957
958 if (!(S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
959 || options.all_unbuffered
65f15010 960 ||(options.unbuffered_preconnected &&
961 (s->fd == STDIN_FILENO
962 || s->fd == STDOUT_FILENO
01cd2c93 963 || s->fd == STDERR_FILENO))
964 || isatty (s->fd))
65f15010 965 raw_init (s);
966 else
967 buf_init (s);
4ee9c684 968
969 return (stream *) s;
970}
971
972
771c1b50 973/* Given the Fortran unit number, convert it to a C file descriptor. */
974
975int
60c514ba 976unit_to_fd (int unit)
771c1b50 977{
771c1b50 978 gfc_unit *us;
60c514ba 979 int fd;
771c1b50 980
60c514ba 981 us = find_unit (unit);
771c1b50 982 if (us == NULL)
983 return -1;
984
60c514ba 985 fd = ((unix_stream *) us->s)->fd;
986 unlock_unit (us);
987 return fd;
771c1b50 988}
989
990
4ee9c684 991/* unpack_filename()-- Given a fortran string and a pointer to a
992 * buffer that is PATH_MAX characters, convert the fortran string to a
993 * C string in the buffer. Returns nonzero if this is not possible. */
994
1dc95e51 995int
4ee9c684 996unpack_filename (char *cstring, const char *fstring, int len)
997{
d6e40722 998 if (fstring == NULL)
999 return 1;
4ee9c684 1000 len = fstrlen (fstring, len);
1001 if (len >= PATH_MAX)
1002 return 1;
1003
1004 memmove (cstring, fstring, len);
1005 cstring[len] = '\0';
1006
1007 return 0;
1008}
1009
1010
1011/* tempfile()-- Generate a temporary filename for a scratch file and
1012 * open it. mkstemp() opens the file for reading and writing, but the
1013 * library mode prevents anything that is not allowed. The descriptor
7dfba97b 1014 * is returned, which is -1 on error. The template is pointed to by
60c514ba 1015 * opp->file, which is copied into the unit structure
4ee9c684 1016 * and freed later. */
1017
1018static int
60c514ba 1019tempfile (st_parameter_open *opp)
4ee9c684 1020{
1021 const char *tempdir;
1022 char *template;
db23ac43 1023 const char *slash = "/";
4ee9c684 1024 int fd;
d06c5aaa 1025 size_t tempdirlen;
1026
1027#ifndef HAVE_MKSTEMP
1028 int count;
1029 size_t slashlen;
1030#endif
4ee9c684 1031
1032 tempdir = getenv ("GFORTRAN_TMPDIR");
db23ac43 1033#ifdef __MINGW32__
1034 if (tempdir == NULL)
1035 {
1036 char buffer[MAX_PATH + 1];
1037 DWORD ret;
1038 ret = GetTempPath (MAX_PATH, buffer);
1039 /* If we are not able to get a temp-directory, we use
1040 current directory. */
1041 if (ret > MAX_PATH || !ret)
1042 buffer[0] = 0;
1043 else
1044 buffer[ret] = 0;
1045 tempdir = strdup (buffer);
1046 }
1047#else
4ee9c684 1048 if (tempdir == NULL)
1049 tempdir = getenv ("TMP");
ac09d5cc 1050 if (tempdir == NULL)
1051 tempdir = getenv ("TEMP");
4ee9c684 1052 if (tempdir == NULL)
1053 tempdir = DEFAULT_TEMPDIR;
db23ac43 1054#endif
d06c5aaa 1055
db23ac43 1056 /* Check for special case that tempdir contains slash
1057 or backslash at end. */
d06c5aaa 1058 tempdirlen = strlen (tempdir);
1059 if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/'
db23ac43 1060#ifdef __MINGW32__
d06c5aaa 1061 || tempdir[tempdirlen - 1] == '\\'
db23ac43 1062#endif
1063 )
1064 slash = "";
4ee9c684 1065
d06c5aaa 1066 // Take care that the template is longer in the mktemp() branch.
1067 template = get_mem (tempdirlen + 23);
4ee9c684 1068
7dfba97b 1069#ifdef HAVE_MKSTEMP
db23ac43 1070 sprintf (template, "%s%sgfortrantmpXXXXXX", tempdir, slash);
4ee9c684 1071
1072 fd = mkstemp (template);
1073
7dfba97b 1074#else /* HAVE_MKSTEMP */
726fd258 1075 fd = -1;
d06c5aaa 1076 count = 0;
1077 slashlen = strlen (slash);
726fd258 1078 do
1079 {
d06c5aaa 1080 sprintf (template, "%s%sgfortrantmpaaaXXXXXX", tempdir, slash);
1081 if (count > 0)
1082 {
1083 int c = count;
1084 template[tempdirlen + slashlen + 13] = 'a' + (c% 26);
1085 c /= 26;
1086 template[tempdirlen + slashlen + 12] = 'a' + (c % 26);
1087 c /= 26;
1088 template[tempdirlen + slashlen + 11] = 'a' + (c % 26);
1089 if (c >= 26)
1090 break;
1091 }
1092
726fd258 1093 if (!mktemp (template))
d06c5aaa 1094 {
1095 errno = EEXIST;
1096 count++;
1097 continue;
1098 }
1099
cf6a3896 1100#if defined(HAVE_CRLF) && defined(O_BINARY)
cf55c3cf 1101 fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
84d33b91 1102 S_IREAD | S_IWRITE);
cf55c3cf 1103#else
ac09d5cc 1104 fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
cf55c3cf 1105#endif
726fd258 1106 }
1107 while (fd == -1 && errno == EEXIST);
7dfba97b 1108#endif /* HAVE_MKSTEMP */
1109
e213d8e0 1110 opp->file = template;
1111 opp->file_len = strlen (template); /* Don't include trailing nul */
4ee9c684 1112
1113 return fd;
1114}
1115
1116
6d12c489 1117/* regular_file()-- Open a regular file.
2d6ba0f9 1118 * Change flags->action if it is ACTION_UNSPECIFIED on entry,
1119 * unless an error occurs.
6d12c489 1120 * Returns the descriptor, which is less than zero on error. */
4ee9c684 1121
1122static int
60c514ba 1123regular_file (st_parameter_open *opp, unit_flags *flags)
4ee9c684 1124{
1125 char path[PATH_MAX + 1];
4ee9c684 1126 int mode;
6d12c489 1127 int rwflag;
2d6ba0f9 1128 int crflag;
6d12c489 1129 int fd;
4ee9c684 1130
60c514ba 1131 if (unpack_filename (path, opp->file, opp->file_len))
4ee9c684 1132 {
1133 errno = ENOENT; /* Fake an OS error */
1134 return -1;
1135 }
1136
3d17984e 1137#ifdef __CYGWIN__
1138 if (opp->file_len == 7)
1139 {
1140 if (strncmp (path, "CONOUT$", 7) == 0
1141 || strncmp (path, "CONERR$", 7) == 0)
1142 {
1143 fd = open ("/dev/conout", O_WRONLY);
1144 flags->action = ACTION_WRITE;
1145 return fd;
1146 }
1147 }
1148
1149 if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
1150 {
1151 fd = open ("/dev/conin", O_RDONLY);
1152 flags->action = ACTION_READ;
1153 return fd;
1154 }
1155#endif
1156
2058bc7e 1157
1158#ifdef __MINGW32__
1159 if (opp->file_len == 7)
1160 {
1161 if (strncmp (path, "CONOUT$", 7) == 0
1162 || strncmp (path, "CONERR$", 7) == 0)
1163 {
1164 fd = open ("CONOUT$", O_WRONLY);
1165 flags->action = ACTION_WRITE;
1166 return fd;
1167 }
1168 }
1169
1170 if (opp->file_len == 6 && strncmp (path, "CONIN$", 6) == 0)
1171 {
1172 fd = open ("CONIN$", O_RDONLY);
1173 flags->action = ACTION_READ;
1174 return fd;
1175 }
1176#endif
1177
6d12c489 1178 rwflag = 0;
4ee9c684 1179
6d12c489 1180 switch (flags->action)
4ee9c684 1181 {
1182 case ACTION_READ:
6d12c489 1183 rwflag = O_RDONLY;
4ee9c684 1184 break;
1185
1186 case ACTION_WRITE:
6d12c489 1187 rwflag = O_WRONLY;
4ee9c684 1188 break;
1189
1190 case ACTION_READWRITE:
6d12c489 1191 case ACTION_UNSPECIFIED:
1192 rwflag = O_RDWR;
4ee9c684 1193 break;
1194
1195 default:
60c514ba 1196 internal_error (&opp->common, "regular_file(): Bad action");
4ee9c684 1197 }
1198
6d12c489 1199 switch (flags->status)
4ee9c684 1200 {
1201 case STATUS_NEW:
2d6ba0f9 1202 crflag = O_CREAT | O_EXCL;
4ee9c684 1203 break;
1204
2d6ba0f9 1205 case STATUS_OLD: /* open will fail if the file does not exist*/
1206 crflag = 0;
4ee9c684 1207 break;
1208
1209 case STATUS_UNKNOWN:
1210 case STATUS_SCRATCH:
2d6ba0f9 1211 crflag = O_CREAT;
4ee9c684 1212 break;
1213
1214 case STATUS_REPLACE:
a638be8f 1215 crflag = O_CREAT | O_TRUNC;
4ee9c684 1216 break;
1217
1218 default:
60c514ba 1219 internal_error (&opp->common, "regular_file(): Bad status");
4ee9c684 1220 }
1221
6d12c489 1222 /* rwflag |= O_LARGEFILE; */
4ee9c684 1223
cf6a3896 1224#if defined(HAVE_CRLF) && defined(O_BINARY)
cf55c3cf 1225 crflag |= O_BINARY;
1226#endif
1227
6d12c489 1228 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
2d6ba0f9 1229 fd = open (path, rwflag | crflag, mode);
1230 if (flags->action != ACTION_UNSPECIFIED)
a638be8f 1231 return fd;
2d6ba0f9 1232
1233 if (fd >= 0)
6d12c489 1234 {
2d6ba0f9 1235 flags->action = ACTION_READWRITE;
1236 return fd;
6d12c489 1237 }
a638be8f 1238 if (errno != EACCES && errno != EROFS)
2d6ba0f9 1239 return fd;
1240
1241 /* retry for read-only access */
1242 rwflag = O_RDONLY;
1243 fd = open (path, rwflag | crflag, mode);
1244 if (fd >=0)
1245 {
1246 flags->action = ACTION_READ;
84d33b91 1247 return fd; /* success */
2d6ba0f9 1248 }
1249
1250 if (errno != EACCES)
84d33b91 1251 return fd; /* failure */
2d6ba0f9 1252
1253 /* retry for write-only access */
1254 rwflag = O_WRONLY;
1255 fd = open (path, rwflag | crflag, mode);
1256 if (fd >=0)
1257 {
1258 flags->action = ACTION_WRITE;
84d33b91 1259 return fd; /* success */
2d6ba0f9 1260 }
84d33b91 1261 return fd; /* failure */
4ee9c684 1262}
1263
1264
1265/* open_external()-- Open an external file, unix specific version.
6d12c489 1266 * Change flags->action if it is ACTION_UNSPECIFIED on entry.
4ee9c684 1267 * Returns NULL on operating system error. */
1268
1269stream *
60c514ba 1270open_external (st_parameter_open *opp, unit_flags *flags)
4ee9c684 1271{
aadbd4ae 1272 int fd;
4ee9c684 1273
6d12c489 1274 if (flags->status == STATUS_SCRATCH)
1275 {
60c514ba 1276 fd = tempfile (opp);
6d12c489 1277 if (flags->action == ACTION_UNSPECIFIED)
84d33b91 1278 flags->action = ACTION_READWRITE;
1dc95e51 1279
1280#if HAVE_UNLINK_OPEN_FILE
6d12c489 1281 /* We can unlink scratch files now and it will go away when closed. */
60c514ba 1282 if (fd >= 0)
1283 unlink (opp->file);
1dc95e51 1284#endif
6d12c489 1285 }
1286 else
1287 {
2d6ba0f9 1288 /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
1289 * if it succeeds */
60c514ba 1290 fd = regular_file (opp, flags);
6d12c489 1291 }
4ee9c684 1292
1293 if (fd < 0)
1294 return NULL;
1295 fd = fix_fd (fd);
1296
aadbd4ae 1297 return fd_to_stream (fd);
4ee9c684 1298}
1299
1300
1301/* input_stream()-- Return a stream pointer to the default input stream.
1302 * Called on initialization. */
1303
1304stream *
1305input_stream (void)
1306{
aadbd4ae 1307 return fd_to_stream (STDIN_FILENO);
4ee9c684 1308}
1309
1310
ff81ee3b 1311/* output_stream()-- Return a stream pointer to the default output stream.
4ee9c684 1312 * Called on initialization. */
1313
1314stream *
1315output_stream (void)
1316{
3e45a719 1317 stream * s;
1318
e693d7f1 1319#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1320 setmode (STDOUT_FILENO, O_BINARY);
1321#endif
3e45a719 1322
aadbd4ae 1323 s = fd_to_stream (STDOUT_FILENO);
3e45a719 1324 return s;
4ee9c684 1325}
1326
1327
ff81ee3b 1328/* error_stream()-- Return a stream pointer to the default error stream.
1329 * Called on initialization. */
1330
1331stream *
1332error_stream (void)
1333{
3e45a719 1334 stream * s;
1335
e693d7f1 1336#if defined(HAVE_CRLF) && defined(HAVE_SETMODE)
1337 setmode (STDERR_FILENO, O_BINARY);
1338#endif
3e45a719 1339
aadbd4ae 1340 s = fd_to_stream (STDERR_FILENO);
3e45a719 1341 return s;
ff81ee3b 1342}
1343
4ee9c684 1344
5a037dbd 1345/* st_vprintf()-- vprintf function for error output. To avoid buffer
1346 overruns, we limit the length of the buffer to ST_VPRINTF_SIZE. 2k
1347 is big enough to completely fill a 80x25 terminal, so it shuld be
1348 OK. We use a direct write() because it is simpler and least likely
0e80ec22 1349 to be clobbered by memory corruption. Writing an error message
1350 longer than that is an error. */
4ee9c684 1351
5a037dbd 1352#define ST_VPRINTF_SIZE 2048
4ee9c684 1353
5a037dbd 1354int
1355st_vprintf (const char *format, va_list ap)
1356{
1357 static char buffer[ST_VPRINTF_SIZE];
1358 int written;
1359 int fd;
4ee9c684 1360
5a037dbd 1361 fd = options.use_stderr ? STDERR_FILENO : STDOUT_FILENO;
1362#ifdef HAVE_VSNPRINTF
1363 written = vsnprintf(buffer, ST_VPRINTF_SIZE, format, ap);
1364#else
0e80ec22 1365 written = vsprintf(buffer, format, ap);
1366
1367 if (written >= ST_VPRINTF_SIZE-1)
1368 {
1369 /* The error message was longer than our buffer. Ouch. Because
1370 we may have messed up things badly, report the error and
1371 quit. */
1372#define ERROR_MESSAGE "Internal error: buffer overrun in st_vprintf()\n"
1373 write (fd, buffer, ST_VPRINTF_SIZE-1);
1374 write (fd, ERROR_MESSAGE, strlen(ERROR_MESSAGE));
1375 sys_exit(2);
1376#undef ERROR_MESSAGE
1377
1378 }
5a037dbd 1379#endif
0e80ec22 1380
5a037dbd 1381 written = write (fd, buffer, written);
1382 return written;
4ee9c684 1383}
1384
5a037dbd 1385/* st_printf()-- printf() function for error output. This just calls
1386 st_vprintf() to do the actual work. */
76c0a846 1387
1388int
1389st_printf (const char *format, ...)
1390{
5a037dbd 1391 int written;
1392 va_list ap;
1393 va_start (ap, format);
1394 written = st_vprintf(format, ap);
1395 va_end (ap);
1396 return written;
76c0a846 1397}
1398
4ee9c684 1399
1400/* compare_file_filename()-- Given an open stream and a fortran string
1401 * that is a filename, figure out if the file is the same as the
1402 * filename. */
1403
1404int
daad4fd5 1405compare_file_filename (gfc_unit *u, const char *name, int len)
4ee9c684 1406{
1407 char path[PATH_MAX + 1];
01cd2c93 1408 gfstat_t st;
daad4fd5 1409#ifdef HAVE_WORKING_STAT
01cd2c93 1410 unix_stream *s;
c0ecd33c 1411#else
1412# ifdef __MINGW32__
1413 uint64_t id1, id2;
1414# endif
daad4fd5 1415#endif
4ee9c684 1416
1417 if (unpack_filename (path, name, len))
1418 return 0; /* Can't be the same */
1419
1420 /* If the filename doesn't exist, then there is no match with the
1421 * existing file. */
1422
01cd2c93 1423 if (stat (path, &st) < 0)
4ee9c684 1424 return 0;
1425
daad4fd5 1426#ifdef HAVE_WORKING_STAT
01cd2c93 1427 s = (unix_stream *) (u->s);
1428 return (st.st_dev == s->st_dev) && (st.st_ino == s->st_ino);
daad4fd5 1429#else
c0ecd33c 1430
1431# ifdef __MINGW32__
1432 /* We try to match files by a unique ID. On some filesystems (network
1433 fs and FAT), we can't generate this unique ID, and will simply compare
1434 filenames. */
1435 id1 = id_from_path (path);
1436 id2 = id_from_fd (((unix_stream *) (u->s))->fd);
1437 if (id1 || id2)
1438 return (id1 == id2);
1439# endif
1440
daad4fd5 1441 if (len != u->file_len)
1442 return 0;
1443 return (memcmp(path, u->file, len) == 0);
1444#endif
4ee9c684 1445}
1446
1447
60c514ba 1448#ifdef HAVE_WORKING_STAT
7a4491a4 1449# define FIND_FILE0_DECL gfstat_t *st
60c514ba 1450# define FIND_FILE0_ARGS st
1451#else
c0ecd33c 1452# define FIND_FILE0_DECL uint64_t id, const char *file, gfc_charlen_type file_len
1453# define FIND_FILE0_ARGS id, file, file_len
60c514ba 1454#endif
1455
4ee9c684 1456/* find_file0()-- Recursive work function for find_file() */
1457
f02dd226 1458static gfc_unit *
60c514ba 1459find_file0 (gfc_unit *u, FIND_FILE0_DECL)
4ee9c684 1460{
f02dd226 1461 gfc_unit *v;
c0ecd33c 1462#if defined(__MINGW32__) && !HAVE_WORKING_STAT
1463 uint64_t id1;
1464#endif
4ee9c684 1465
1466 if (u == NULL)
1467 return NULL;
1468
daad4fd5 1469#ifdef HAVE_WORKING_STAT
01cd2c93 1470 if (u->s != NULL)
1471 {
1472 unix_stream *s = (unix_stream *) (u->s);
1473 if (st[0].st_dev == s->st_dev && st[0].st_ino == s->st_ino)
1474 return u;
1475 }
daad4fd5 1476#else
c0ecd33c 1477# ifdef __MINGW32__
1478 if (u->s && ((id1 = id_from_fd (((unix_stream *) u->s)->fd)) || id1))
1479 {
1480 if (id == id1)
1481 return u;
1482 }
1483 else
1484# endif
1485 if (compare_string (u->file_len, u->file, file_len, file) == 0)
1486 return u;
daad4fd5 1487#endif
4ee9c684 1488
60c514ba 1489 v = find_file0 (u->left, FIND_FILE0_ARGS);
4ee9c684 1490 if (v != NULL)
1491 return v;
1492
60c514ba 1493 v = find_file0 (u->right, FIND_FILE0_ARGS);
4ee9c684 1494 if (v != NULL)
1495 return v;
1496
1497 return NULL;
1498}
1499
1500
1501/* find_file()-- Take the current filename and see if there is a unit
1502 * that has the file already open. Returns a pointer to the unit if so. */
1503
f02dd226 1504gfc_unit *
60c514ba 1505find_file (const char *file, gfc_charlen_type file_len)
4ee9c684 1506{
1507 char path[PATH_MAX + 1];
01cd2c93 1508 gfstat_t st[1];
60c514ba 1509 gfc_unit *u;
c12dc7d7 1510#if defined(__MINGW32__) && !HAVE_WORKING_STAT
1511 uint64_t id = 0ULL;
1512#endif
4ee9c684 1513
60c514ba 1514 if (unpack_filename (path, file, file_len))
4ee9c684 1515 return NULL;
1516
60c514ba 1517 if (stat (path, &st[0]) < 0)
4ee9c684 1518 return NULL;
1519
c0ecd33c 1520#if defined(__MINGW32__) && !HAVE_WORKING_STAT
c12dc7d7 1521 id = id_from_path (path);
c0ecd33c 1522#endif
1523
60c514ba 1524 __gthread_mutex_lock (&unit_lock);
1525retry:
1526 u = find_file0 (unit_root, FIND_FILE0_ARGS);
1527 if (u != NULL)
1528 {
1529 /* Fast path. */
1530 if (! __gthread_mutex_trylock (&u->lock))
1531 {
1532 /* assert (u->closed == 0); */
1533 __gthread_mutex_unlock (&unit_lock);
1534 return u;
1535 }
1536
1537 inc_waiting_locked (u);
1538 }
1539 __gthread_mutex_unlock (&unit_lock);
1540 if (u != NULL)
1541 {
1542 __gthread_mutex_lock (&u->lock);
1543 if (u->closed)
1544 {
1545 __gthread_mutex_lock (&unit_lock);
1546 __gthread_mutex_unlock (&u->lock);
1547 if (predec_waiting_locked (u) == 0)
5e62a3cc 1548 free (u);
60c514ba 1549 goto retry;
1550 }
1551
1552 dec_waiting_unlocked (u);
1553 }
1554 return u;
1555}
1556
1557static gfc_unit *
1558flush_all_units_1 (gfc_unit *u, int min_unit)
1559{
1560 while (u != NULL)
1561 {
1562 if (u->unit_number > min_unit)
1563 {
1564 gfc_unit *r = flush_all_units_1 (u->left, min_unit);
1565 if (r != NULL)
1566 return r;
1567 }
1568 if (u->unit_number >= min_unit)
1569 {
1570 if (__gthread_mutex_trylock (&u->lock))
1571 return u;
1572 if (u->s)
65f15010 1573 sflush (u->s);
60c514ba 1574 __gthread_mutex_unlock (&u->lock);
1575 }
1576 u = u->right;
1577 }
1578 return NULL;
1579}
1580
1581void
1582flush_all_units (void)
1583{
1584 gfc_unit *u;
1585 int min_unit = 0;
1586
1587 __gthread_mutex_lock (&unit_lock);
1588 do
1589 {
1590 u = flush_all_units_1 (unit_root, min_unit);
1591 if (u != NULL)
1592 inc_waiting_locked (u);
1593 __gthread_mutex_unlock (&unit_lock);
1594 if (u == NULL)
1595 return;
1596
1597 __gthread_mutex_lock (&u->lock);
1598
1599 min_unit = u->unit_number + 1;
1600
1601 if (u->closed == 0)
1602 {
65f15010 1603 sflush (u->s);
60c514ba 1604 __gthread_mutex_lock (&unit_lock);
1605 __gthread_mutex_unlock (&u->lock);
1606 (void) predec_waiting_locked (u);
1607 }
1608 else
1609 {
1610 __gthread_mutex_lock (&unit_lock);
1611 __gthread_mutex_unlock (&u->lock);
1612 if (predec_waiting_locked (u) == 0)
5e62a3cc 1613 free (u);
60c514ba 1614 }
1615 }
1616 while (1);
4ee9c684 1617}
1618
1619
4ee9c684 1620/* delete_file()-- Given a unit structure, delete the file associated
1621 * with the unit. Returns nonzero if something went wrong. */
1622
1623int
f02dd226 1624delete_file (gfc_unit * u)
4ee9c684 1625{
1626 char path[PATH_MAX + 1];
1627
1628 if (unpack_filename (path, u->file, u->file_len))
1629 { /* Shouldn't be possible */
1630 errno = ENOENT;
1631 return 1;
1632 }
1633
1634 return unlink (path);
1635}
1636
1637
1638/* file_exists()-- Returns nonzero if the current filename exists on
1639 * the system */
1640
1641int
60c514ba 1642file_exists (const char *file, gfc_charlen_type file_len)
4ee9c684 1643{
1644 char path[PATH_MAX + 1];
4ee9c684 1645
60c514ba 1646 if (unpack_filename (path, file, file_len))
4ee9c684 1647 return 0;
1648
fb053cd1 1649 return !(access (path, F_OK));
4ee9c684 1650}
1651
1652
f4e9c676 1653/* file_size()-- Returns the size of the file. */
1654
1655GFC_IO_INT
1656file_size (const char *file, gfc_charlen_type file_len)
1657{
1658 char path[PATH_MAX + 1];
1659 gfstat_t statbuf;
1660
1661 if (unpack_filename (path, file, file_len))
1662 return -1;
1663
1664 if (stat (path, &statbuf) < 0)
1665 return -1;
1666
1667 return (GFC_IO_INT) statbuf.st_size;
1668}
4ee9c684 1669
fb35179a 1670static const char yes[] = "YES", no[] = "NO", unknown[] = "UNKNOWN";
4ee9c684 1671
1672/* inquire_sequential()-- Given a fortran string, determine if the
1673 * file is suitable for sequential access. Returns a C-style
1674 * string. */
1675
1676const char *
1677inquire_sequential (const char *string, int len)
1678{
1679 char path[PATH_MAX + 1];
7a4491a4 1680 gfstat_t statbuf;
4ee9c684 1681
1682 if (string == NULL ||
1683 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1684 return unknown;
1685
1686 if (S_ISREG (statbuf.st_mode) ||
1687 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
2e1fa727 1688 return unknown;
4ee9c684 1689
1690 if (S_ISDIR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
1691 return no;
1692
1693 return unknown;
1694}
1695
1696
1697/* inquire_direct()-- Given a fortran string, determine if the file is
1698 * suitable for direct access. Returns a C-style string. */
1699
1700const char *
1701inquire_direct (const char *string, int len)
1702{
1703 char path[PATH_MAX + 1];
7a4491a4 1704 gfstat_t statbuf;
4ee9c684 1705
1706 if (string == NULL ||
1707 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1708 return unknown;
1709
1710 if (S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
2e1fa727 1711 return unknown;
4ee9c684 1712
1713 if (S_ISDIR (statbuf.st_mode) ||
1714 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
1715 return no;
1716
1717 return unknown;
1718}
1719
1720
1721/* inquire_formatted()-- Given a fortran string, determine if the file
1722 * is suitable for formatted form. Returns a C-style string. */
1723
1724const char *
1725inquire_formatted (const char *string, int len)
1726{
1727 char path[PATH_MAX + 1];
7a4491a4 1728 gfstat_t statbuf;
4ee9c684 1729
1730 if (string == NULL ||
1731 unpack_filename (path, string, len) || stat (path, &statbuf) < 0)
1732 return unknown;
1733
1734 if (S_ISREG (statbuf.st_mode) ||
1735 S_ISBLK (statbuf.st_mode) ||
1736 S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode))
2e1fa727 1737 return unknown;
4ee9c684 1738
1739 if (S_ISDIR (statbuf.st_mode))
1740 return no;
1741
1742 return unknown;
1743}
1744
1745
1746/* inquire_unformatted()-- Given a fortran string, determine if the file
1747 * is suitable for unformatted form. Returns a C-style string. */
1748
1749const char *
1750inquire_unformatted (const char *string, int len)
1751{
4ee9c684 1752 return inquire_formatted (string, len);
1753}
1754
1755
1756/* inquire_access()-- Given a fortran string, determine if the file is
1757 * suitable for access. */
1758
1759static const char *
1760inquire_access (const char *string, int len, int mode)
1761{
1762 char path[PATH_MAX + 1];
1763
1764 if (string == NULL || unpack_filename (path, string, len) ||
1765 access (path, mode) < 0)
1766 return no;
1767
1768 return yes;
1769}
1770
1771
1772/* inquire_read()-- Given a fortran string, determine if the file is
1773 * suitable for READ access. */
1774
1775const char *
1776inquire_read (const char *string, int len)
1777{
4ee9c684 1778 return inquire_access (string, len, R_OK);
1779}
1780
1781
1782/* inquire_write()-- Given a fortran string, determine if the file is
1783 * suitable for READ access. */
1784
1785const char *
1786inquire_write (const char *string, int len)
1787{
4ee9c684 1788 return inquire_access (string, len, W_OK);
1789}
1790
1791
1792/* inquire_readwrite()-- Given a fortran string, determine if the file is
1793 * suitable for read and write access. */
1794
1795const char *
1796inquire_readwrite (const char *string, int len)
1797{
4ee9c684 1798 return inquire_access (string, len, R_OK | W_OK);
1799}
1800
1801
1802/* file_length()-- Return the file length in bytes, -1 if unknown */
1803
b093181d 1804gfc_offset
4ee9c684 1805file_length (stream * s)
1806{
4dbc0658 1807 gfc_offset curr, end;
65f15010 1808 if (!is_seekable (s))
1809 return -1;
1810 curr = stell (s);
1811 if (curr == -1)
1812 return curr;
1813 end = sseek (s, 0, SEEK_END);
1814 sseek (s, curr, SEEK_SET);
1815 return end;
4ee9c684 1816}
1817
1818
1819/* is_seekable()-- Return nonzero if the stream is seekable, zero if
1820 * it is not */
1821
1822int
6e34b5c4 1823is_seekable (stream *s)
4ee9c684 1824{
b2a112ca 1825 /* By convention, if file_length == -1, the file is not
1826 seekable. */
5a78b88f 1827 return ((unix_stream *) s)->file_length!=-1;
4ee9c684 1828}
1829
6e34b5c4 1830
1831/* is_special()-- Return nonzero if the stream is not a regular file. */
1832
09478184 1833int
6e34b5c4 1834is_special (stream *s)
1835{
1836 return ((unix_stream *) s)->special_file;
1837}
1838
1839
60d77e0d 1840int
1841stream_isatty (stream *s)
1842{
1843 return isatty (((unix_stream *) s)->fd);
1844}
1845
57f34837 1846int
1847stream_ttyname (stream *s __attribute__ ((unused)),
1848 char * buf __attribute__ ((unused)),
1849 size_t buflen __attribute__ ((unused)))
1850{
1851#ifdef HAVE_TTYNAME_R
1852 return ttyname_r (((unix_stream *) s)->fd, buf, buflen);
1853#elif defined HAVE_TTYNAME
1854 char *p;
1855 size_t plen;
1856 p = ttyname (((unix_stream *) s)->fd);
1857 if (!p)
1858 return errno;
1859 plen = strlen (p);
1860 if (buflen < plen)
1861 plen = buflen;
1862 memcpy (buf, p, plen);
1863 return 0;
f2c0a16d 1864#else
57f34837 1865 return ENOSYS;
3479b863 1866#endif
57f34837 1867}
1868
3479b863 1869
60d77e0d 1870
4ee9c684 1871
1872/* How files are stored: This is an operating-system specific issue,
1873 and therefore belongs here. There are three cases to consider.
1874
1875 Direct Access:
1876 Records are written as block of bytes corresponding to the record
1877 length of the file. This goes for both formatted and unformatted
1878 records. Positioning is done explicitly for each data transfer,
1879 so positioning is not much of an issue.
1880
1881 Sequential Formatted:
1882 Records are separated by newline characters. The newline character
1883 is prohibited from appearing in a string. If it does, this will be
1884 messed up on the next read. End of file is also the end of a record.
1885
1886 Sequential Unformatted:
1887 In this case, we are merely copying bytes to and from main storage,
1888 yet we need to keep track of varying record lengths. We adopt
1889 the solution used by f2c. Each record contains a pair of length
1890 markers:
1891
84d33b91 1892 Length of record n in bytes
1893 Data of record n
1894 Length of record n in bytes
4ee9c684 1895
84d33b91 1896 Length of record n+1 in bytes
1897 Data of record n+1
1898 Length of record n+1 in bytes
4ee9c684 1899
1900 The length is stored at the end of a record to allow backspacing to the
1901 previous record. Between data transfer statements, the file pointer
1902 is left pointing to the first length of the current record.
1903
1904 ENDFILE records are never explicitly stored.
1905
1906*/