Skip to content

Commit c53792b

Browse files
authored
[flang][runtime] OPEN(existingUnit,POSITION=) (#153688)
Ensure that when a connected unit is reopened with POSITION='REWIND' or 'APPEND', and a STATUS='OLD' or unspecified, that it is actually repositioned as requested. Fixes #153426.
1 parent 2cf982c commit c53792b

File tree

4 files changed

+29
-17
lines changed

4 files changed

+29
-17
lines changed

flang-rt/include/flang-rt/runtime/file.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class OpenFile {
6868
void WaitAll(IoErrorHandler &);
6969

7070
// INQUIRE(POSITION=)
71-
Position InquirePosition() const;
71+
Position InquirePosition(FileOffset offset) const;
7272

7373
private:
7474
struct Pending {
@@ -80,7 +80,7 @@ class OpenFile {
8080
void CheckOpen(const Terminator &);
8181
bool Seek(FileOffset, IoErrorHandler &);
8282
bool RawSeek(FileOffset);
83-
bool RawSeekToEnd();
83+
bool SeekToEnd(IoErrorHandler &);
8484
int PendingResult(const Terminator &, int);
8585
void SetPosition(FileOffset pos) {
8686
position_ = pos;

flang-rt/lib/runtime/external-unit.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ ExternalFileUnit *ExternalFileUnit::LookUpOrCreate(
5757
}
5858

5959
ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
60-
Direction dir, Fortran::common::optional<bool> isUnformatted,
60+
Direction dir, common::optional<bool> isUnformatted,
6161
IoErrorHandler &handler) {
6262
// Make sure that the returned anonymous unit has been opened,
6363
// not just created in the unitMap.
@@ -109,8 +109,8 @@ ExternalFileUnit &ExternalFileUnit::NewUnit(
109109
return unit;
110110
}
111111

112-
bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
113-
Fortran::common::optional<Action> action, Position position,
112+
bool ExternalFileUnit::OpenUnit(common::optional<OpenStatus> status,
113+
common::optional<Action> action, Position position,
114114
OwningPtr<char> &&newPath, std::size_t newPathLength, Convert convert,
115115
IoErrorHandler &handler) {
116116
if (convert == Convert::Unknown) {
@@ -131,6 +131,7 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
131131
if (!newPath.get() || isSamePath) {
132132
// OPEN of existing unit, STATUS='OLD' or unspecified, not new FILE=
133133
newPath.reset();
134+
Open(status.value_or(OpenStatus::Old), action, position, handler);
134135
return impliedClose;
135136
}
136137
// Otherwise, OPEN on open unit with new FILE= implies CLOSE
@@ -194,10 +195,9 @@ bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status,
194195
return impliedClose;
195196
}
196197

197-
bool ExternalFileUnit::OpenAnonymousUnit(
198-
Fortran::common::optional<OpenStatus> status,
199-
Fortran::common::optional<Action> action, Position position,
200-
Convert convert, IoErrorHandler &handler) {
198+
bool ExternalFileUnit::OpenAnonymousUnit(common::optional<OpenStatus> status,
199+
common::optional<Action> action, Position position, Convert convert,
200+
IoErrorHandler &handler) {
201201
// I/O to an unconnected unit reads/creates a local file, e.g. fort.7
202202
std::size_t pathMaxLen{32};
203203
auto path{SizedNew<char>{handler}(pathMaxLen)};

flang-rt/lib/runtime/file.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,16 @@ static int openfile_mkstemp(IoErrorHandler &handler) {
6060
return fd;
6161
}
6262

63-
void OpenFile::Open(OpenStatus status, Fortran::common::optional<Action> action,
63+
void OpenFile::Open(OpenStatus status, common::optional<Action> action,
6464
Position position, IoErrorHandler &handler) {
6565
if (fd_ >= 0 &&
6666
(status == OpenStatus::Old || status == OpenStatus::Unknown)) {
67+
if (position == Position::Rewind) {
68+
Seek(0, handler);
69+
} else if (position == Position::Append) {
70+
SeekToEnd(handler);
71+
}
72+
openPosition_ = position; // for INQUIRE(POSITION=)
6773
return;
6874
}
6975
CloseFd(handler);
@@ -131,8 +137,8 @@ void OpenFile::Open(OpenStatus status, Fortran::common::optional<Action> action,
131137
}
132138
RUNTIME_CHECK(handler, action.has_value());
133139
pending_.reset();
134-
if (fd_ >= 0 && position == Position::Append && !RawSeekToEnd()) {
135-
handler.SignalError(IostatOpenBadAppend);
140+
if (fd_ >= 0 && position == Position::Append) {
141+
SeekToEnd(handler);
136142
}
137143
isTerminal_ = fd_ >= 0 && IsATerminal(fd_);
138144
mayRead_ = *action != Action::Write;
@@ -322,7 +328,7 @@ int OpenFile::WriteAsynchronously(FileOffset at, const char *buffer,
322328
}
323329

324330
void OpenFile::Wait(int id, IoErrorHandler &handler) {
325-
Fortran::common::optional<int> ioStat;
331+
common::optional<int> ioStat;
326332
Pending *prev{nullptr};
327333
for (Pending *p{pending_.get()}; p; p = (prev = p)->next.get()) {
328334
if (p->id == id) {
@@ -353,13 +359,13 @@ void OpenFile::WaitAll(IoErrorHandler &handler) {
353359
}
354360
}
355361

356-
Position OpenFile::InquirePosition() const {
362+
Position OpenFile::InquirePosition(FileOffset offset) const {
357363
if (openPosition_) { // from OPEN statement
358364
return *openPosition_;
359365
} else { // unit has been repositioned since opening
360-
if (position_ == knownSize_.value_or(position_ + 1)) {
366+
if (offset == knownSize_.value_or(offset + 1)) {
361367
return Position::Append;
362-
} else if (position_ == 0 && mayPosition_) {
368+
} else if (offset == 0 && mayPosition_) {
363369
return Position::Rewind;
364370
} else {
365371
return Position::AsIs; // processor-dependent & no common behavior
@@ -391,16 +397,18 @@ bool OpenFile::RawSeek(FileOffset at) {
391397
#endif
392398
}
393399

394-
bool OpenFile::RawSeekToEnd() {
400+
bool OpenFile::SeekToEnd(IoErrorHandler &handler) {
395401
#ifdef _LARGEFILE64_SOURCE
396402
std::int64_t at{::lseek64(fd_, 0, SEEK_END)};
397403
#else
398404
std::int64_t at{::lseek(fd_, 0, SEEK_END)};
399405
#endif
400406
if (at >= 0) {
401407
knownSize_ = at;
408+
SetPosition(at);
402409
return true;
403410
} else {
411+
handler.SignalError(IostatOpenBadAppend);
404412
return false;
405413
}
406414
}

flang-rt/lib/runtime/unit.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ class ExternalFileUnit : public ConnectionState,
197197

198198
RT_API_ATTRS int GetAsynchronousId(IoErrorHandler &);
199199
RT_API_ATTRS bool Wait(int);
200+
RT_API_ATTRS Position InquirePosition() const {
201+
return OpenFile::InquirePosition(
202+
static_cast<FileOffset>(frameOffsetInFile_ + recordOffsetInFrame_));
203+
}
200204

201205
private:
202206
static RT_API_ATTRS UnitMap &CreateUnitMap();

0 commit comments

Comments
 (0)