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