[flang] Track known file size, add IsATerminal (ext. I/O work part 5)
authorpeter klausler <pklausler@nvidia.com>
Fri, 3 Jul 2020 17:56:08 +0000 (10:56 -0700)
committerpeter klausler <pklausler@nvidia.com>
Fri, 3 Jul 2020 20:04:18 +0000 (13:04 -0700)
Add a data member knownSize_ and an accessor to allow the size of
an external file to be tracked when known.  Also add a wrapper for
::isatty() here in the filesystem encapsulation module.  These
features are needed for the external I/O rework changes still
to come.

Reviewed By: sscalpone

Differential Revision: https://reviews.llvm.org/D83141

flang/runtime/file.cpp
flang/runtime/file.h

index fdd7ea6..120c1ce 100644 (file)
@@ -64,9 +64,11 @@ void OpenFile::Open(
     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 @@ void OpenFile::Open(
       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 @@ void OpenFile::Open(
     handler.SignalErrno();
   }
   pending_.reset();
-  knownSize_.reset();
   if (position == Position::Append && !RawSeekToEnd()) {
     handler.SignalErrno();
   }
@@ -152,17 +156,14 @@ std::size_t OpenFile::Read(FileOffset at, char *buffer, std::size_t minBytes,
   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 @@ int OpenFile::PendingResult(const Terminator &terminator, int iostat) {
   pending_ = New<Pending>{terminator}(id, iostat, std::move(pending_));
   return id;
 }
+
+bool IsATerminal(int fd) { return ::isatty(fd); }
 } // namespace Fortran::runtime::io
index 741a0bc..17a5e91 100644 (file)
@@ -39,6 +39,7 @@ public:
   void set_mayPosition(bool yes) { mayPosition_ = yes; }
   FileOffset position() const { return position_; }
   bool isTerminal() const { return isTerminal_; }
+  std::optional<FileOffset> knownSize() const { return knownSize_; }
 
   bool IsOpen() const { return fd_ >= 0; }
   void Open(OpenStatus, Position, IoErrorHandler &);
@@ -94,5 +95,7 @@ private:
   int nextId_;
   OwningPtr<Pending> pending_;
 };
+
+bool IsATerminal(int fd);
 } // namespace Fortran::runtime::io
 #endif // FORTRAN_RUNTIME_FILE_H_