1 //===-- runtime/file.h ------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // Raw system I/O wrappers 10 11 #ifndef FORTRAN_RUNTIME_FILE_H_ 12 #define FORTRAN_RUNTIME_FILE_H_ 13 14 #include "io-error.h" 15 #include "memory.h" 16 #include <cinttypes> 17 #include <optional> 18 19 namespace Fortran::runtime::io { 20 21 enum class OpenStatus { Old, New, Scratch, Replace, Unknown }; 22 enum class CloseStatus { Keep, Delete }; 23 enum class Position { AsIs, Rewind, Append }; 24 enum class Action { Read, Write, ReadWrite }; 25 26 class OpenFile { 27 public: 28 using FileOffset = std::int64_t; 29 path()30 const char *path() const { return path_.get(); } 31 void set_path(OwningPtr<char> &&, std::size_t bytes); pathLength()32 std::size_t pathLength() const { return pathLength_; } mayRead()33 bool mayRead() const { return mayRead_; } mayWrite()34 bool mayWrite() const { return mayWrite_; } mayPosition()35 bool mayPosition() const { return mayPosition_; } mayAsynchronous()36 bool mayAsynchronous() const { return mayAsynchronous_; } set_mayAsynchronous(bool yes)37 void set_mayAsynchronous(bool yes) { mayAsynchronous_ = yes; } position()38 FileOffset position() const { return position_; } isTerminal()39 bool isTerminal() const { return isTerminal_; } knownSize()40 std::optional<FileOffset> knownSize() const { return knownSize_; } 41 IsOpen()42 bool IsOpen() const { return fd_ >= 0; } 43 void Open(OpenStatus, std::optional<Action>, Position, IoErrorHandler &); 44 void Predefine(int fd); 45 void Close(CloseStatus, IoErrorHandler &); 46 47 // Reads data into memory; returns amount acquired. Synchronous. 48 // Partial reads (less than minBytes) signify end-of-file. If the 49 // buffer is larger than minBytes, and extra returned data will be 50 // preserved for future consumption, set maxBytes larger than minBytes 51 // to reduce system calls This routine handles EAGAIN/EWOULDBLOCK and EINTR. 52 std::size_t Read(FileOffset, char *, std::size_t minBytes, 53 std::size_t maxBytes, IoErrorHandler &); 54 55 // Writes data. Synchronous. Partial writes indicate program-handled 56 // error conditions. 57 std::size_t Write(FileOffset, const char *, std::size_t, IoErrorHandler &); 58 59 // Truncates the file 60 void Truncate(FileOffset, IoErrorHandler &); 61 62 // Asynchronous transfers 63 int ReadAsynchronously(FileOffset, char *, std::size_t, IoErrorHandler &); 64 int WriteAsynchronously( 65 FileOffset, const char *, std::size_t, IoErrorHandler &); 66 void Wait(int id, IoErrorHandler &); 67 void WaitAll(IoErrorHandler &); 68 69 private: 70 struct Pending { 71 int id; 72 int ioStat{0}; 73 OwningPtr<Pending> next; 74 }; 75 76 void CheckOpen(const Terminator &); 77 bool Seek(FileOffset, IoErrorHandler &); 78 bool RawSeek(FileOffset); 79 bool RawSeekToEnd(); 80 int PendingResult(const Terminator &, int); 81 82 int fd_{-1}; 83 OwningPtr<char> path_; 84 std::size_t pathLength_; 85 bool mayRead_{false}; 86 bool mayWrite_{false}; 87 bool mayPosition_{false}; 88 bool mayAsynchronous_{false}; 89 FileOffset position_{0}; 90 std::optional<FileOffset> knownSize_; 91 bool isTerminal_{false}; 92 93 int nextId_; 94 OwningPtr<Pending> pending_; 95 }; 96 97 bool IsATerminal(int fd); 98 bool IsExtant(const char *path); 99 bool MayRead(const char *path); 100 bool MayWrite(const char *path); 101 bool MayReadAndWrite(const char *path); 102 } // namespace Fortran::runtime::io 103 #endif // FORTRAN_RUNTIME_FILE_H_ 104