diff --git a/flang/runtime/file.h b/flang/runtime/file.h --- a/flang/runtime/file.h +++ b/flang/runtime/file.h @@ -39,6 +39,7 @@ void set_mayPosition(bool yes) { mayPosition_ = yes; } FileOffset position() const { return position_; } bool isTerminal() const { return isTerminal_; } + std::optional knownSize() const { return knownSize_; } bool IsOpen() const { return fd_ >= 0; } void Open(OpenStatus, Position, IoErrorHandler &); @@ -94,5 +95,7 @@ int nextId_; OwningPtr pending_; }; + +bool IsATerminal(int fd); } // namespace Fortran::runtime::io #endif // FORTRAN_RUNTIME_FILE_H_ diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp --- a/flang/runtime/file.cpp +++ b/flang/runtime/file.cpp @@ -64,9 +64,11 @@ if (fd_ >= 0) { return; } + knownSize_.reset(); break; case OpenStatus::New: flags |= O_CREAT | O_EXCL; + knownSize_ = 0; break; case OpenStatus::Scratch: if (path_.get()) { @@ -74,15 +76,18 @@ path_.reset(); } fd_ = openfile_mkstemp(handler); + knownSize_ = 0; return; case OpenStatus::Replace: flags |= O_CREAT | O_TRUNC; + knownSize_ = 0; break; case OpenStatus::Unknown: if (fd_ >= 0) { return; } flags |= O_CREAT; + knownSize_.reset(); break; } // If we reach this point, we're opening a new file. @@ -104,7 +109,6 @@ handler.SignalErrno(); } pending_.reset(); - knownSize_.reset(); if (position == Position::Append && !RawSeekToEnd()) { handler.SignalErrno(); } @@ -152,17 +156,14 @@ if (!Seek(at, handler)) { return 0; } - if (maxBytes < minBytes) { - minBytes = maxBytes; - } + minBytes = std::min(minBytes, maxBytes); std::size_t got{0}; while (got < minBytes) { auto chunk{::read(fd_, buffer + got, maxBytes - got)}; if (chunk == 0) { handler.SignalEnd(); break; - } - if (chunk < 0) { + } else if (chunk < 0) { auto err{errno}; if (err != EAGAIN && err != EWOULDBLOCK && err != EINTR) { handler.SignalError(err); @@ -355,4 +356,6 @@ pending_ = New{terminator}(id, iostat, std::move(pending_)); return id; } + +bool IsATerminal(int fd) { return ::isatty(fd); } } // namespace Fortran::runtime::io