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 "flang/Common/optional.h" |
16 | #include "flang/Runtime/memory.h" |
17 | #include <cinttypes> |
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 | |
30 | const char *path() const { return path_.get(); } |
31 | std::size_t pathLength() const { return pathLength_; } |
32 | void set_path(OwningPtr<char> &&, std::size_t bytes); |
33 | bool mayRead() const { return mayRead_; } |
34 | bool mayWrite() const { return mayWrite_; } |
35 | bool mayPosition() const { return mayPosition_; } |
36 | bool mayAsynchronous() const { return mayAsynchronous_; } |
37 | void set_mayAsynchronous(bool yes) { mayAsynchronous_ = yes; } |
38 | bool isTerminal() const { return isTerminal_; } |
39 | bool isWindowsTextFile() const { return isWindowsTextFile_; } |
40 | Fortran::common::optional<FileOffset> knownSize() const { return knownSize_; } |
41 | |
42 | bool IsConnected() const { return fd_ >= 0; } |
43 | void Open(OpenStatus, Fortran::common::optional<Action>, Position, |
44 | IoErrorHandler &); |
45 | void Predefine(int fd); |
46 | void Close(CloseStatus, IoErrorHandler &); |
47 | |
48 | // Reads data into memory; returns amount acquired. Synchronous. |
49 | // Partial reads (less than minBytes) signify end-of-file. If the |
50 | // buffer is larger than minBytes, and extra returned data will be |
51 | // preserved for future consumption, set maxBytes larger than minBytes |
52 | // to reduce system calls This routine handles EAGAIN/EWOULDBLOCK and EINTR. |
53 | std::size_t Read(FileOffset, char *, std::size_t minBytes, |
54 | std::size_t maxBytes, IoErrorHandler &); |
55 | |
56 | // Writes data. Synchronous. Partial writes indicate program-handled |
57 | // error conditions. |
58 | std::size_t Write(FileOffset, const char *, std::size_t, IoErrorHandler &); |
59 | |
60 | // Truncates the file |
61 | void Truncate(FileOffset, IoErrorHandler &); |
62 | |
63 | // Asynchronous transfers |
64 | int ReadAsynchronously(FileOffset, char *, std::size_t, IoErrorHandler &); |
65 | int WriteAsynchronously( |
66 | FileOffset, const char *, std::size_t, IoErrorHandler &); |
67 | void Wait(int id, IoErrorHandler &); |
68 | void WaitAll(IoErrorHandler &); |
69 | |
70 | // INQUIRE(POSITION=) |
71 | Position InquirePosition() const; |
72 | |
73 | private: |
74 | struct Pending { |
75 | int id; |
76 | int ioStat{0}; |
77 | OwningPtr<Pending> next; |
78 | }; |
79 | |
80 | void CheckOpen(const Terminator &); |
81 | bool Seek(FileOffset, IoErrorHandler &); |
82 | bool RawSeek(FileOffset); |
83 | bool RawSeekToEnd(); |
84 | int PendingResult(const Terminator &, int); |
85 | void SetPosition(FileOffset pos) { |
86 | position_ = pos; |
87 | openPosition_.reset(); |
88 | } |
89 | void CloseFd(IoErrorHandler &); |
90 | |
91 | int fd_{-1}; |
92 | OwningPtr<char> path_; |
93 | std::size_t pathLength_; |
94 | bool mayRead_{false}; |
95 | bool mayWrite_{false}; |
96 | bool mayPosition_{false}; |
97 | bool mayAsynchronous_{false}; |
98 | Fortran::common::optional<Position> |
99 | openPosition_; // from Open(); reset after positioning |
100 | FileOffset position_{0}; |
101 | Fortran::common::optional<FileOffset> knownSize_; |
102 | bool isTerminal_{false}; |
103 | bool isWindowsTextFile_{false}; // expands LF to CR+LF on write |
104 | |
105 | int nextId_; |
106 | OwningPtr<Pending> pending_; |
107 | }; |
108 | |
109 | RT_API_ATTRS bool IsATerminal(int fd); |
110 | RT_API_ATTRS bool IsExtant(const char *path); |
111 | RT_API_ATTRS bool MayRead(const char *path); |
112 | RT_API_ATTRS bool MayWrite(const char *path); |
113 | RT_API_ATTRS bool MayReadAndWrite(const char *path); |
114 | RT_API_ATTRS std::int64_t SizeInBytes(const char *path); |
115 | } // namespace Fortran::runtime::io |
116 | #endif // FORTRAN_RUNTIME_FILE_H_ |
117 | |