|
25 | 25 | #include "lldb/Utility/UriParser.h" |
26 | 26 | #include "lldb/lldb-forward.h" |
27 | 27 | #include "llvm/ADT/ArrayRef.h" |
| 28 | +#include "llvm/ADT/DenseMap.h" |
28 | 29 | #include "llvm/ADT/ScopeExit.h" |
29 | 30 | #include "llvm/ADT/SmallVector.h" |
30 | 31 | #include "llvm/ADT/StringExtras.h" |
|
44 | 45 | #include "llvm/Support/WithColor.h" |
45 | 46 | #include "llvm/Support/raw_ostream.h" |
46 | 47 | #include <condition_variable> |
| 48 | +#include <cstddef> |
47 | 49 | #include <cstdio> |
48 | 50 | #include <cstdlib> |
| 51 | +#include <exception> |
49 | 52 | #include <fcntl.h> |
50 | 53 | #include <map> |
51 | 54 | #include <memory> |
@@ -146,52 +149,69 @@ static void PrintVersion() { |
146 | 149 | } |
147 | 150 |
|
148 | 151 | #if not defined(_WIN32) |
149 | | -static llvm::Error RedirectToFile(int fd, llvm::StringRef file, bool read, |
150 | | - bool write) { |
151 | | - if (!read && !write) |
| 152 | +struct FDGroup { |
| 153 | + int GetFlags() const { |
| 154 | + if (read && write) |
| 155 | + return O_NOCTTY | O_CREAT | O_RDWR; |
| 156 | + if (read) |
| 157 | + return O_NOCTTY | O_RDONLY; |
| 158 | + return O_NOCTTY | O_CREAT | O_WRONLY | O_TRUNC; |
| 159 | + } |
| 160 | + |
| 161 | + std::vector<int> fds; |
| 162 | + bool read = false; |
| 163 | + bool write = false; |
| 164 | +}; |
| 165 | + |
| 166 | +static llvm::Error RedirectToFile(const FDGroup &fdg, llvm::StringRef file) { |
| 167 | + if (!fdg.read && !fdg.write) |
152 | 168 | return llvm::Error::success(); |
153 | | - int flags = 0; |
154 | | - if (read && write) |
155 | | - flags = O_NOCTTY | O_CREAT | O_RDWR; |
156 | | - else if (read) |
157 | | - flags = O_NOCTTY | O_RDONLY; |
158 | | - else |
159 | | - flags = O_NOCTTY | O_CREAT | O_WRONLY | O_TRUNC; |
160 | | - int target_fd = lldb_private::FileSystem::Instance().Open(file.str().c_str(), |
161 | | - flags, 0666); |
| 169 | + int target_fd = lldb_private::FileSystem::Instance().Open( |
| 170 | + file.str().c_str(), fdg.GetFlags(), 0666); |
162 | 171 | if (target_fd == -1) |
163 | 172 | return llvm::errorCodeToError( |
164 | 173 | std::error_code(errno, std::generic_category())); |
165 | | - if (target_fd == fd) |
166 | | - return llvm::Error::success(); |
167 | | - if (dup2(target_fd, fd) == -1) |
168 | | - return llvm::errorCodeToError( |
169 | | - std::error_code(errno, std::generic_category())); |
170 | | - close(target_fd); |
| 174 | + for (int fd : fdg.fds) { |
| 175 | + if (target_fd == fd) |
| 176 | + continue; |
| 177 | + if (::dup2(target_fd, fd) == -1) |
| 178 | + return llvm::errorCodeToError( |
| 179 | + std::error_code(errno, std::generic_category())); |
| 180 | + } |
| 181 | + ::close(target_fd); |
171 | 182 | return llvm::Error::success(); |
172 | 183 | } |
173 | 184 |
|
174 | 185 | static llvm::Error |
175 | 186 | SetupIORedirection(const llvm::SmallVectorImpl<llvm::StringRef> &files) { |
176 | | - for (std::size_t i = 0; i < files.size(); i++) { |
| 187 | + llvm::SmallDenseMap<llvm::StringRef, FDGroup> groups; |
| 188 | + for (size_t i = 0; i < files.size(); i++) { |
177 | 189 | if (files[i].empty()) |
178 | 190 | continue; |
| 191 | + auto group = groups.find(files[i]); |
| 192 | + if (group == groups.end()) |
| 193 | + group = groups.insert({files[i], {{static_cast<int>(i)}}}).first; |
| 194 | + else |
| 195 | + group->second.fds.push_back(i); |
179 | 196 | switch (i) { |
180 | 197 | case 0: |
181 | | - if (llvm::Error err = RedirectToFile(i, files[i], true, false)) |
182 | | - return err; |
| 198 | + group->second.read = true; |
183 | 199 | break; |
184 | 200 | case 1: |
185 | 201 | case 2: |
186 | | - if (llvm::Error err = RedirectToFile(i, files[i], false, true)) |
187 | | - return err; |
| 202 | + group->second.write = true; |
188 | 203 | break; |
189 | 204 | default: |
190 | | - if (llvm::Error err = RedirectToFile(i, files[i], true, true)) |
191 | | - return err; |
| 205 | + group->second.read = true; |
| 206 | + group->second.write = true; |
192 | 207 | break; |
193 | 208 | } |
194 | 209 | } |
| 210 | + for (const auto &[file, group] : groups) { |
| 211 | + if (llvm::Error err = RedirectToFile(group, file)) |
| 212 | + return llvm::createStringError( |
| 213 | + llvm::formatv("{0}: {1}", file, llvm::toString(std::move(err)))); |
| 214 | + } |
195 | 215 | return llvm::Error::success(); |
196 | 216 | } |
197 | 217 | #endif |
|
0 commit comments