annotate flang/runtime/file.cpp @ 266:00f31e85ec16 default tip

Added tag current for changeset 31d058e83c98
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 14 Oct 2023 10:13:55 +0900
parents c4bab56944e8
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
1 //===-- runtime/file.cpp --------------------------------------------------===//
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 //
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 //
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
8
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 #include "file.h"
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
10 #include "flang/Runtime/magic-numbers.h"
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
11 #include "flang/Runtime/memory.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
12 #include <algorithm>
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 #include <cerrno>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 #include <cstring>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 #include <fcntl.h>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 #include <stdlib.h>
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
17 #include <sys/stat.h>
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 #ifdef _WIN32
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
19 #define NOMINMAX
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #include <io.h>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include <windows.h>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #else
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 #include <unistd.h>
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 #endif
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
25
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 namespace Fortran::runtime::io {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
27
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 void OpenFile::set_path(OwningPtr<char> &&path, std::size_t bytes) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 path_ = std::move(path);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 pathLength_ = bytes;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
32
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 static int openfile_mkstemp(IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 #ifdef _WIN32
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 const unsigned int uUnique{0};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 // GetTempFileNameA needs a directory name < MAX_PATH-14 characters in length.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamea
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 char tempDirName[MAX_PATH - 14];
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 char tempFileName[MAX_PATH];
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 unsigned long nBufferLength{sizeof(tempDirName)};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 nBufferLength = ::GetTempPathA(nBufferLength, tempDirName);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 if (nBufferLength > sizeof(tempDirName) || nBufferLength == 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 return -1;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 if (::GetTempFileNameA(tempDirName, "Fortran", uUnique, tempFileName) == 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 return -1;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 }
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
48 int fd{::_open(tempFileName, _O_CREAT | _O_BINARY | _O_TEMPORARY | _O_RDWR,
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
49 _S_IREAD | _S_IWRITE)};
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 #else
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 char path[]{"/tmp/Fortran-Scratch-XXXXXX"};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 int fd{::mkstemp(path)};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 #endif
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 if (fd < 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 handler.SignalErrno();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 #ifndef _WIN32
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 ::unlink(path);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 #endif
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 return fd;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
62
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
63 void OpenFile::Open(OpenStatus status, std::optional<Action> action,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
64 Position position, IoErrorHandler &handler) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
65 if (fd_ >= 0 &&
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
66 (status == OpenStatus::Old || status == OpenStatus::Unknown)) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
67 return;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
68 }
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
69 CloseFd(handler);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
70 if (status == OpenStatus::Scratch) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 if (path_.get()) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 handler.SignalError("FILE= must not appear with STATUS='SCRATCH'");
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 path_.reset();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
75 if (!action) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
76 action = Action::ReadWrite;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
77 }
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 fd_ = openfile_mkstemp(handler);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
79 } else {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
80 if (!path_.get()) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
81 handler.SignalError("FILE= is required");
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 return;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
84 int flags{0};
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
85 #ifdef _WIN32
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
86 // We emit explicit CR+LF line endings and cope with them on input
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
87 // for formatted files, since we can't yet always know now at OPEN
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
88 // time whether the file is formatted or not.
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
89 flags |= O_BINARY;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
90 #endif
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
91 if (status != OpenStatus::Old) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
92 flags |= O_CREAT;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
93 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
94 if (status == OpenStatus::New) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
95 flags |= O_EXCL;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
96 } else if (status == OpenStatus::Replace) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
97 flags |= O_TRUNC;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
98 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
99 if (!action) {
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
100 // Try to open read/write, back off to read-only or even write-only
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
101 // on failure
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
102 fd_ = ::open(path_.get(), flags | O_RDWR, 0600);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
103 if (fd_ >= 0) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
104 action = Action::ReadWrite;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
105 } else {
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
106 fd_ = ::open(path_.get(), flags | O_RDONLY, 0600);
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
107 if (fd_ >= 0) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
108 action = Action::Read;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
109 } else {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
110 action = Action::Write;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
111 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
112 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
113 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
114 if (fd_ < 0) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
115 switch (*action) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
116 case Action::Read:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
117 flags |= O_RDONLY;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
118 break;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
119 case Action::Write:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
120 flags |= O_WRONLY;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
121 break;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
122 case Action::ReadWrite:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
123 flags |= O_RDWR;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
124 break;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
125 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
126 fd_ = ::open(path_.get(), flags, 0600);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
127 if (fd_ < 0) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
128 handler.SignalErrno();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
129 }
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
132 RUNTIME_CHECK(handler, action.has_value());
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 pending_.reset();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 if (position == Position::Append && !RawSeekToEnd()) {
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
135 handler.SignalError(IostatOpenBadAppend);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 }
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
137 isTerminal_ = IsATerminal(fd_) == 1;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
138 mayRead_ = *action != Action::Write;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
139 mayWrite_ = *action != Action::Read;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
140 if (status == OpenStatus::Old || status == OpenStatus::Unknown) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
141 knownSize_.reset();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
142 #ifndef _WIN32
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
143 struct stat buf;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
144 if (::fstat(fd_, &buf) == 0) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
145 mayPosition_ = S_ISREG(buf.st_mode);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
146 knownSize_ = buf.st_size;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
147 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
148 #else // TODO: _WIN32
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
149 mayPosition_ = true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
150 #endif
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
151 } else {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
152 knownSize_ = 0;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
153 mayPosition_ = true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
154 }
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
155 openPosition_ = position; // for INQUIRE(POSITION=)
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
157
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 void OpenFile::Predefine(int fd) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 fd_ = fd;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 path_.reset();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 pathLength_ = 0;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 position_ = 0;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 knownSize_.reset();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 nextId_ = 0;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 pending_.reset();
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
166 isTerminal_ = IsATerminal(fd_) == 1;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
167 mayRead_ = fd == 0;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
168 mayWrite_ = fd != 0;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
169 mayPosition_ = false;
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
170 #ifdef _WIN32
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
171 isWindowsTextFile_ = true;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
172 #endif
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
174
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 void OpenFile::Close(CloseStatus status, IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 pending_.reset();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 knownSize_.reset();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 switch (status) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 case CloseStatus::Keep:
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 case CloseStatus::Delete:
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 if (path_.get()) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 ::unlink(path_.get());
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
186 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 path_.reset();
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
188 CloseFd(handler);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
190
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 std::size_t OpenFile::Read(FileOffset at, char *buffer, std::size_t minBytes,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 std::size_t maxBytes, IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 if (maxBytes == 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 return 0;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 CheckOpen(handler);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 if (!Seek(at, handler)) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 return 0;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
200 minBytes = std::min(minBytes, maxBytes);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 std::size_t got{0};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 while (got < minBytes) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 auto chunk{::read(fd_, buffer + got, maxBytes - got)};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 if (chunk == 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 break;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
206 } else if (chunk < 0) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 auto err{errno};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 if (err != EAGAIN && err != EWOULDBLOCK && err != EINTR) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 handler.SignalError(err);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 } else {
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
213 SetPosition(position_ + chunk);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 got += chunk;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 return got;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
219
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 std::size_t OpenFile::Write(FileOffset at, const char *buffer,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 std::size_t bytes, IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 if (bytes == 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 return 0;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
224 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
225 CheckOpen(handler);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 if (!Seek(at, handler)) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 return 0;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 std::size_t put{0};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 while (put < bytes) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 auto chunk{::write(fd_, buffer + put, bytes - put)};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 if (chunk >= 0) {
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
233 SetPosition(position_ + chunk);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 put += chunk;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 } else {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 auto err{errno};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 if (err != EAGAIN && err != EWOULDBLOCK && err != EINTR) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 handler.SignalError(err);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 if (knownSize_ && position_ > *knownSize_) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 knownSize_ = position_;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 return put;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
248
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 inline static int openfile_ftruncate(int fd, OpenFile::FileOffset at) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 #ifdef _WIN32
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
251 return ::_chsize(fd, at);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 #else
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 return ::ftruncate(fd, at);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 #endif
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
256
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 void OpenFile::Truncate(FileOffset at, IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 CheckOpen(handler);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 if (!knownSize_ || *knownSize_ != at) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 if (openfile_ftruncate(fd_, at) != 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
261 handler.SignalErrno();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 knownSize_ = at;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
266
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 // The operation is performed immediately; the results are saved
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 // to be claimed by a later WAIT statement.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 // TODO: True asynchronicity
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 int OpenFile::ReadAsynchronously(
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 FileOffset at, char *buffer, std::size_t bytes, IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 CheckOpen(handler);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 int iostat{0};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 for (std::size_t got{0}; got < bytes;) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 #if _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809L
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 auto chunk{::pread(fd_, buffer + got, bytes - got, at)};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 #else
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 auto chunk{Seek(at, handler) ? ::read(fd_, buffer + got, bytes - got) : -1};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 #endif
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 if (chunk == 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 iostat = FORTRAN_RUNTIME_IOSTAT_END;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 if (chunk < 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 auto err{errno};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
286 if (err != EAGAIN && err != EWOULDBLOCK && err != EINTR) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 iostat = err;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
290 } else {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 at += chunk;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 got += chunk;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
294 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 return PendingResult(handler, iostat);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
296 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
297
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
298 // TODO: True asynchronicity
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
299 int OpenFile::WriteAsynchronously(FileOffset at, const char *buffer,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 std::size_t bytes, IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
301 CheckOpen(handler);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
302 int iostat{0};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 for (std::size_t put{0}; put < bytes;) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 #if _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809L
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 auto chunk{::pwrite(fd_, buffer + put, bytes - put, at)};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 #else
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 auto chunk{
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 Seek(at, handler) ? ::write(fd_, buffer + put, bytes - put) : -1};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 #endif
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
310 if (chunk >= 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 at += chunk;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 put += chunk;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
313 } else {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 auto err{errno};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 if (err != EAGAIN && err != EWOULDBLOCK && err != EINTR) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 iostat = err;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
321 return PendingResult(handler, iostat);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
323
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 void OpenFile::Wait(int id, IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
325 std::optional<int> ioStat;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 Pending *prev{nullptr};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
327 for (Pending *p{pending_.get()}; p; p = (prev = p)->next.get()) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 if (p->id == id) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 ioStat = p->ioStat;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 if (prev) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
331 prev->next.reset(p->next.release());
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 } else {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 pending_.reset(p->next.release());
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 break;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 if (ioStat) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 handler.SignalError(*ioStat);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
342
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 void OpenFile::WaitAll(IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 while (true) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 int ioStat;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 if (pending_) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 ioStat = pending_->ioStat;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 pending_.reset(pending_->next.release());
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 } else {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 return;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 handler.SignalError(ioStat);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
355
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
356 Position OpenFile::InquirePosition() const {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
357 if (openPosition_) { // from OPEN statement
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
358 return *openPosition_;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
359 } else { // unit has been repositioned since opening
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
360 if (position_ == knownSize_.value_or(position_ + 1)) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
361 return Position::Append;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
362 } else if (position_ == 0 && mayPosition_) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
363 return Position::Rewind;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
364 } else {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
365 return Position::AsIs; // processor-dependent & no common behavior
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
366 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
367 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
368 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
369
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 void OpenFile::CheckOpen(const Terminator &terminator) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
371 RUNTIME_CHECK(terminator, fd_ >= 0);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
372 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
373
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
374 bool OpenFile::Seek(FileOffset at, IoErrorHandler &handler) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
375 if (at == position_) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
376 return true;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
377 } else if (RawSeek(at)) {
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
378 SetPosition(at);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
379 return true;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 } else {
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
381 handler.SignalError(IostatCannotReposition);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
382 return false;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
383 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
384 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
385
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
386 bool OpenFile::RawSeek(FileOffset at) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 #ifdef _LARGEFILE64_SOURCE
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 return ::lseek64(fd_, at, SEEK_SET) == at;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
389 #else
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 return ::lseek(fd_, at, SEEK_SET) == at;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 #endif
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
392 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
393
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 bool OpenFile::RawSeekToEnd() {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 #ifdef _LARGEFILE64_SOURCE
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
396 std::int64_t at{::lseek64(fd_, 0, SEEK_END)};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 #else
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
398 std::int64_t at{::lseek(fd_, 0, SEEK_END)};
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 #endif
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
400 if (at >= 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
401 knownSize_ = at;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 return true;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
403 } else {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
404 return false;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
405 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
406 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
407
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
408 int OpenFile::PendingResult(const Terminator &terminator, int iostat) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 int id{nextId_++};
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
410 pending_ = New<Pending>{terminator}(id, iostat, std::move(pending_));
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 return id;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
413
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
414 void OpenFile::CloseFd(IoErrorHandler &handler) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
415 if (fd_ >= 0) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
416 if (fd_ <= 2) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
417 // don't actually close a standard file descriptor, we might need it
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
418 } else {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
419 if (::close(fd_) != 0) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
420 handler.SignalErrno();
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
421 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
422 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
423 fd_ = -1;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
424 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
425 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
426
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
427 bool IsATerminal(int fd) { return ::isatty(fd); }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
428
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
429 #if defined(_WIN32) && !defined(F_OK)
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
430 // Access flags are normally defined in unistd.h, which unavailable under
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
431 // Windows. Instead, define the flags as documented at
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
432 // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/access-waccess
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
433 // On Mingw, io.h does define these same constants - so check whether they
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
434 // already are defined before defining these.
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
435 #define F_OK 00
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
436 #define W_OK 02
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
437 #define R_OK 04
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
438 #endif
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
439
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
440 bool IsExtant(const char *path) { return ::access(path, F_OK) == 0; }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
441 bool MayRead(const char *path) { return ::access(path, R_OK) == 0; }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
442 bool MayWrite(const char *path) { return ::access(path, W_OK) == 0; }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
443 bool MayReadAndWrite(const char *path) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
444 return ::access(path, R_OK | W_OK) == 0;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
445 }
236
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
446
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
447 std::int64_t SizeInBytes(const char *path) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
448 #ifndef _WIN32
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
449 struct stat buf;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
450 if (::stat(path, &buf) == 0) {
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
451 return buf.st_size;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
452 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
453 #else // TODO: _WIN32
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
454 #endif
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
455 // No Fortran compiler signals an error
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
456 return -1;
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
457 }
c4bab56944e8 LLVM 16
kono
parents: 232
diff changeset
458
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
459 } // namespace Fortran::runtime::io