1 //===-- Path.cpp - Implement OS Path Concept ------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the operating system Path API.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/Path.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/Config/llvm-config.h"
17 #include "llvm/Support/Endian.h"
18 #include "llvm/Support/Errc.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/FileSystem.h"
21 #include "llvm/Support/Process.h"
22 #include "llvm/Support/Signals.h"
23 #include <cctype>
24 #include <cstring>
25
26 #if !defined(_MSC_VER) && !defined(__MINGW32__)
27 #include <unistd.h>
28 #else
29 #include <io.h>
30 #endif
31
32 using namespace llvm;
33 using namespace llvm::support::endian;
34
35 namespace {
36 using llvm::StringRef;
37 using llvm::sys::path::is_separator;
38 using llvm::sys::path::Style;
39
real_style(Style style)40 inline Style real_style(Style style) {
41 #ifdef _WIN32
42 return (style == Style::posix) ? Style::posix : Style::windows;
43 #else
44 return (style == Style::windows) ? Style::windows : Style::posix;
45 #endif
46 }
47
separators(Style style)48 inline const char *separators(Style style) {
49 if (real_style(style) == Style::windows)
50 return "\\/";
51 return "/";
52 }
53
preferred_separator(Style style)54 inline char preferred_separator(Style style) {
55 if (real_style(style) == Style::windows)
56 return '\\';
57 return '/';
58 }
59
find_first_component(StringRef path,Style style)60 StringRef find_first_component(StringRef path, Style style) {
61 // Look for this first component in the following order.
62 // * empty (in this case we return an empty string)
63 // * either C: or {//,\\}net.
64 // * {/,\}
65 // * {file,directory}name
66
67 if (path.empty())
68 return path;
69
70 if (real_style(style) == Style::windows) {
71 // C:
72 if (path.size() >= 2 &&
73 std::isalpha(static_cast<unsigned char>(path[0])) && path[1] == ':')
74 return path.substr(0, 2);
75 }
76
77 // //net
78 if ((path.size() > 2) && is_separator(path[0], style) &&
79 path[0] == path[1] && !is_separator(path[2], style)) {
80 // Find the next directory separator.
81 size_t end = path.find_first_of(separators(style), 2);
82 return path.substr(0, end);
83 }
84
85 // {/,\}
86 if (is_separator(path[0], style))
87 return path.substr(0, 1);
88
89 // * {file,directory}name
90 size_t end = path.find_first_of(separators(style));
91 return path.substr(0, end);
92 }
93
94 // Returns the first character of the filename in str. For paths ending in
95 // '/', it returns the position of the '/'.
filename_pos(StringRef str,Style style)96 size_t filename_pos(StringRef str, Style style) {
97 if (str.size() > 0 && is_separator(str[str.size() - 1], style))
98 return str.size() - 1;
99
100 size_t pos = str.find_last_of(separators(style), str.size() - 1);
101
102 if (real_style(style) == Style::windows) {
103 if (pos == StringRef::npos)
104 pos = str.find_last_of(':', str.size() - 2);
105 }
106
107 if (pos == StringRef::npos || (pos == 1 && is_separator(str[0], style)))
108 return 0;
109
110 return pos + 1;
111 }
112
113 // Returns the position of the root directory in str. If there is no root
114 // directory in str, it returns StringRef::npos.
root_dir_start(StringRef str,Style style)115 size_t root_dir_start(StringRef str, Style style) {
116 // case "c:/"
117 if (real_style(style) == Style::windows) {
118 if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style))
119 return 2;
120 }
121
122 // case "//net"
123 if (str.size() > 3 && is_separator(str[0], style) && str[0] == str[1] &&
124 !is_separator(str[2], style)) {
125 return str.find_first_of(separators(style), 2);
126 }
127
128 // case "/"
129 if (str.size() > 0 && is_separator(str[0], style))
130 return 0;
131
132 return StringRef::npos;
133 }
134
135 // Returns the position past the end of the "parent path" of path. The parent
136 // path will not end in '/', unless the parent is the root directory. If the
137 // path has no parent, 0 is returned.
parent_path_end(StringRef path,Style style)138 size_t parent_path_end(StringRef path, Style style) {
139 size_t end_pos = filename_pos(path, style);
140
141 bool filename_was_sep =
142 path.size() > 0 && is_separator(path[end_pos], style);
143
144 // Skip separators until we reach root dir (or the start of the string).
145 size_t root_dir_pos = root_dir_start(path, style);
146 while (end_pos > 0 &&
147 (root_dir_pos == StringRef::npos || end_pos > root_dir_pos) &&
148 is_separator(path[end_pos - 1], style))
149 --end_pos;
150
151 if (end_pos == root_dir_pos && !filename_was_sep) {
152 // We've reached the root dir and the input path was *not* ending in a
153 // sequence of slashes. Include the root dir in the parent path.
154 return root_dir_pos + 1;
155 }
156
157 // Otherwise, just include before the last slash.
158 return end_pos;
159 }
160 } // end unnamed namespace
161
162 enum FSEntity {
163 FS_Dir,
164 FS_File,
165 FS_Name
166 };
167
168 static std::error_code
createUniqueEntity(const Twine & Model,int & ResultFD,SmallVectorImpl<char> & ResultPath,bool MakeAbsolute,unsigned Mode,FSEntity Type,sys::fs::OpenFlags Flags=sys::fs::OF_None)169 createUniqueEntity(const Twine &Model, int &ResultFD,
170 SmallVectorImpl<char> &ResultPath, bool MakeAbsolute,
171 unsigned Mode, FSEntity Type,
172 sys::fs::OpenFlags Flags = sys::fs::OF_None) {
173 SmallString<128> ModelStorage;
174 Model.toVector(ModelStorage);
175
176 if (MakeAbsolute) {
177 // Make model absolute by prepending a temp directory if it's not already.
178 if (!sys::path::is_absolute(Twine(ModelStorage))) {
179 SmallString<128> TDir;
180 sys::path::system_temp_directory(true, TDir);
181 sys::path::append(TDir, Twine(ModelStorage));
182 ModelStorage.swap(TDir);
183 }
184 }
185
186 // From here on, DO NOT modify model. It may be needed if the randomly chosen
187 // path already exists.
188 ResultPath = ModelStorage;
189 // Null terminate.
190 ResultPath.push_back(0);
191 ResultPath.pop_back();
192
193 // Limit the number of attempts we make, so that we don't infinite loop. E.g.
194 // "permission denied" could be for a specific file (so we retry with a
195 // different name) or for the whole directory (retry would always fail).
196 // Checking which is racy, so we try a number of times, then give up.
197 std::error_code EC;
198 for (int Retries = 128; Retries > 0; --Retries) {
199 // Replace '%' with random chars.
200 for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
201 if (ModelStorage[i] == '%')
202 ResultPath[i] =
203 "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
204 }
205
206 // Try to open + create the file.
207 switch (Type) {
208 case FS_File: {
209 EC = sys::fs::openFileForReadWrite(Twine(ResultPath.begin()), ResultFD,
210 sys::fs::CD_CreateNew, Flags, Mode);
211 if (EC) {
212 // errc::permission_denied happens on Windows when we try to open a file
213 // that has been marked for deletion.
214 if (EC == errc::file_exists || EC == errc::permission_denied)
215 continue;
216 return EC;
217 }
218
219 return std::error_code();
220 }
221
222 case FS_Name: {
223 EC = sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
224 if (EC == errc::no_such_file_or_directory)
225 return std::error_code();
226 if (EC)
227 return EC;
228 continue;
229 }
230
231 case FS_Dir: {
232 EC = sys::fs::create_directory(ResultPath.begin(), false);
233 if (EC) {
234 if (EC == errc::file_exists)
235 continue;
236 return EC;
237 }
238 return std::error_code();
239 }
240 }
241 llvm_unreachable("Invalid Type");
242 }
243 return EC;
244 }
245
246 namespace llvm {
247 namespace sys {
248 namespace path {
249
begin(StringRef path,Style style)250 const_iterator begin(StringRef path, Style style) {
251 const_iterator i;
252 i.Path = path;
253 i.Component = find_first_component(path, style);
254 i.Position = 0;
255 i.S = style;
256 return i;
257 }
258
end(StringRef path)259 const_iterator end(StringRef path) {
260 const_iterator i;
261 i.Path = path;
262 i.Position = path.size();
263 return i;
264 }
265
operator ++()266 const_iterator &const_iterator::operator++() {
267 assert(Position < Path.size() && "Tried to increment past end!");
268
269 // Increment Position to past the current component
270 Position += Component.size();
271
272 // Check for end.
273 if (Position == Path.size()) {
274 Component = StringRef();
275 return *this;
276 }
277
278 // Both POSIX and Windows treat paths that begin with exactly two separators
279 // specially.
280 bool was_net = Component.size() > 2 && is_separator(Component[0], S) &&
281 Component[1] == Component[0] && !is_separator(Component[2], S);
282
283 // Handle separators.
284 if (is_separator(Path[Position], S)) {
285 // Root dir.
286 if (was_net ||
287 // c:/
288 (real_style(S) == Style::windows && Component.endswith(":"))) {
289 Component = Path.substr(Position, 1);
290 return *this;
291 }
292
293 // Skip extra separators.
294 while (Position != Path.size() && is_separator(Path[Position], S)) {
295 ++Position;
296 }
297
298 // Treat trailing '/' as a '.', unless it is the root dir.
299 if (Position == Path.size() && Component != "/") {
300 --Position;
301 Component = ".";
302 return *this;
303 }
304 }
305
306 // Find next component.
307 size_t end_pos = Path.find_first_of(separators(S), Position);
308 Component = Path.slice(Position, end_pos);
309
310 return *this;
311 }
312
operator ==(const const_iterator & RHS) const313 bool const_iterator::operator==(const const_iterator &RHS) const {
314 return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
315 }
316
operator -(const const_iterator & RHS) const317 ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
318 return Position - RHS.Position;
319 }
320
rbegin(StringRef Path,Style style)321 reverse_iterator rbegin(StringRef Path, Style style) {
322 reverse_iterator I;
323 I.Path = Path;
324 I.Position = Path.size();
325 I.S = style;
326 return ++I;
327 }
328
rend(StringRef Path)329 reverse_iterator rend(StringRef Path) {
330 reverse_iterator I;
331 I.Path = Path;
332 I.Component = Path.substr(0, 0);
333 I.Position = 0;
334 return I;
335 }
336
operator ++()337 reverse_iterator &reverse_iterator::operator++() {
338 size_t root_dir_pos = root_dir_start(Path, S);
339
340 // Skip separators unless it's the root directory.
341 size_t end_pos = Position;
342 while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
343 is_separator(Path[end_pos - 1], S))
344 --end_pos;
345
346 // Treat trailing '/' as a '.', unless it is the root dir.
347 if (Position == Path.size() && !Path.empty() &&
348 is_separator(Path.back(), S) &&
349 (root_dir_pos == StringRef::npos || end_pos - 1 > root_dir_pos)) {
350 --Position;
351 Component = ".";
352 return *this;
353 }
354
355 // Find next separator.
356 size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
357 Component = Path.slice(start_pos, end_pos);
358 Position = start_pos;
359 return *this;
360 }
361
operator ==(const reverse_iterator & RHS) const362 bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
363 return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
364 Position == RHS.Position;
365 }
366
operator -(const reverse_iterator & RHS) const367 ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
368 return Position - RHS.Position;
369 }
370
root_path(StringRef path,Style style)371 StringRef root_path(StringRef path, Style style) {
372 const_iterator b = begin(path, style), pos = b, e = end(path);
373 if (b != e) {
374 bool has_net =
375 b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
376 bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
377
378 if (has_net || has_drive) {
379 if ((++pos != e) && is_separator((*pos)[0], style)) {
380 // {C:/,//net/}, so get the first two components.
381 return path.substr(0, b->size() + pos->size());
382 } else {
383 // just {C:,//net}, return the first component.
384 return *b;
385 }
386 }
387
388 // POSIX style root directory.
389 if (is_separator((*b)[0], style)) {
390 return *b;
391 }
392 }
393
394 return StringRef();
395 }
396
root_name(StringRef path,Style style)397 StringRef root_name(StringRef path, Style style) {
398 const_iterator b = begin(path, style), e = end(path);
399 if (b != e) {
400 bool has_net =
401 b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
402 bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
403
404 if (has_net || has_drive) {
405 // just {C:,//net}, return the first component.
406 return *b;
407 }
408 }
409
410 // No path or no name.
411 return StringRef();
412 }
413
root_directory(StringRef path,Style style)414 StringRef root_directory(StringRef path, Style style) {
415 const_iterator b = begin(path, style), pos = b, e = end(path);
416 if (b != e) {
417 bool has_net =
418 b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
419 bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
420
421 if ((has_net || has_drive) &&
422 // {C:,//net}, skip to the next component.
423 (++pos != e) && is_separator((*pos)[0], style)) {
424 return *pos;
425 }
426
427 // POSIX style root directory.
428 if (!has_net && is_separator((*b)[0], style)) {
429 return *b;
430 }
431 }
432
433 // No path or no root.
434 return StringRef();
435 }
436
relative_path(StringRef path,Style style)437 StringRef relative_path(StringRef path, Style style) {
438 StringRef root = root_path(path, style);
439 return path.substr(root.size());
440 }
441
append(SmallVectorImpl<char> & path,Style style,const Twine & a,const Twine & b,const Twine & c,const Twine & d)442 void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
443 const Twine &b, const Twine &c, const Twine &d) {
444 SmallString<32> a_storage;
445 SmallString<32> b_storage;
446 SmallString<32> c_storage;
447 SmallString<32> d_storage;
448
449 SmallVector<StringRef, 4> components;
450 if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
451 if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
452 if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
453 if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
454
455 for (auto &component : components) {
456 bool path_has_sep =
457 !path.empty() && is_separator(path[path.size() - 1], style);
458 if (path_has_sep) {
459 // Strip separators from beginning of component.
460 size_t loc = component.find_first_not_of(separators(style));
461 StringRef c = component.substr(loc);
462
463 // Append it.
464 path.append(c.begin(), c.end());
465 continue;
466 }
467
468 bool component_has_sep =
469 !component.empty() && is_separator(component[0], style);
470 if (!component_has_sep &&
471 !(path.empty() || has_root_name(component, style))) {
472 // Add a separator.
473 path.push_back(preferred_separator(style));
474 }
475
476 path.append(component.begin(), component.end());
477 }
478 }
479
append(SmallVectorImpl<char> & path,const Twine & a,const Twine & b,const Twine & c,const Twine & d)480 void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
481 const Twine &c, const Twine &d) {
482 append(path, Style::native, a, b, c, d);
483 }
484
append(SmallVectorImpl<char> & path,const_iterator begin,const_iterator end,Style style)485 void append(SmallVectorImpl<char> &path, const_iterator begin,
486 const_iterator end, Style style) {
487 for (; begin != end; ++begin)
488 path::append(path, style, *begin);
489 }
490
parent_path(StringRef path,Style style)491 StringRef parent_path(StringRef path, Style style) {
492 size_t end_pos = parent_path_end(path, style);
493 if (end_pos == StringRef::npos)
494 return StringRef();
495 else
496 return path.substr(0, end_pos);
497 }
498
remove_filename(SmallVectorImpl<char> & path,Style style)499 void remove_filename(SmallVectorImpl<char> &path, Style style) {
500 size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
501 if (end_pos != StringRef::npos)
502 path.set_size(end_pos);
503 }
504
replace_extension(SmallVectorImpl<char> & path,const Twine & extension,Style style)505 void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
506 Style style) {
507 StringRef p(path.begin(), path.size());
508 SmallString<32> ext_storage;
509 StringRef ext = extension.toStringRef(ext_storage);
510
511 // Erase existing extension.
512 size_t pos = p.find_last_of('.');
513 if (pos != StringRef::npos && pos >= filename_pos(p, style))
514 path.set_size(pos);
515
516 // Append '.' if needed.
517 if (ext.size() > 0 && ext[0] != '.')
518 path.push_back('.');
519
520 // Append extension.
521 path.append(ext.begin(), ext.end());
522 }
523
replace_path_prefix(SmallVectorImpl<char> & Path,const StringRef & OldPrefix,const StringRef & NewPrefix,Style style)524 void replace_path_prefix(SmallVectorImpl<char> &Path,
525 const StringRef &OldPrefix, const StringRef &NewPrefix,
526 Style style) {
527 if (OldPrefix.empty() && NewPrefix.empty())
528 return;
529
530 StringRef OrigPath(Path.begin(), Path.size());
531 if (!OrigPath.startswith(OldPrefix))
532 return;
533
534 // If prefixes have the same size we can simply copy the new one over.
535 if (OldPrefix.size() == NewPrefix.size()) {
536 llvm::copy(NewPrefix, Path.begin());
537 return;
538 }
539
540 StringRef RelPath = OrigPath.substr(OldPrefix.size());
541 SmallString<256> NewPath;
542 path::append(NewPath, style, NewPrefix);
543 path::append(NewPath, style, RelPath);
544 Path.swap(NewPath);
545 }
546
native(const Twine & path,SmallVectorImpl<char> & result,Style style)547 void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
548 assert((!path.isSingleStringRef() ||
549 path.getSingleStringRef().data() != result.data()) &&
550 "path and result are not allowed to overlap!");
551 // Clear result.
552 result.clear();
553 path.toVector(result);
554 native(result, style);
555 }
556
native(SmallVectorImpl<char> & Path,Style style)557 void native(SmallVectorImpl<char> &Path, Style style) {
558 if (Path.empty())
559 return;
560 if (real_style(style) == Style::windows) {
561 std::replace(Path.begin(), Path.end(), '/', '\\');
562 if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
563 SmallString<128> PathHome;
564 home_directory(PathHome);
565 PathHome.append(Path.begin() + 1, Path.end());
566 Path = PathHome;
567 }
568 } else {
569 for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
570 if (*PI == '\\') {
571 auto PN = PI + 1;
572 if (PN < PE && *PN == '\\')
573 ++PI; // increment once, the for loop will move over the escaped slash
574 else
575 *PI = '/';
576 }
577 }
578 }
579 }
580
convert_to_slash(StringRef path,Style style)581 std::string convert_to_slash(StringRef path, Style style) {
582 if (real_style(style) != Style::windows)
583 return path;
584
585 std::string s = path.str();
586 std::replace(s.begin(), s.end(), '\\', '/');
587 return s;
588 }
589
filename(StringRef path,Style style)590 StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
591
stem(StringRef path,Style style)592 StringRef stem(StringRef path, Style style) {
593 StringRef fname = filename(path, style);
594 size_t pos = fname.find_last_of('.');
595 if (pos == StringRef::npos)
596 return fname;
597 else
598 if ((fname.size() == 1 && fname == ".") ||
599 (fname.size() == 2 && fname == ".."))
600 return fname;
601 else
602 return fname.substr(0, pos);
603 }
604
extension(StringRef path,Style style)605 StringRef extension(StringRef path, Style style) {
606 StringRef fname = filename(path, style);
607 size_t pos = fname.find_last_of('.');
608 if (pos == StringRef::npos)
609 return StringRef();
610 else
611 if ((fname.size() == 1 && fname == ".") ||
612 (fname.size() == 2 && fname == ".."))
613 return StringRef();
614 else
615 return fname.substr(pos);
616 }
617
is_separator(char value,Style style)618 bool is_separator(char value, Style style) {
619 if (value == '/')
620 return true;
621 if (real_style(style) == Style::windows)
622 return value == '\\';
623 return false;
624 }
625
get_separator(Style style)626 StringRef get_separator(Style style) {
627 if (real_style(style) == Style::windows)
628 return "\\";
629 return "/";
630 }
631
has_root_name(const Twine & path,Style style)632 bool has_root_name(const Twine &path, Style style) {
633 SmallString<128> path_storage;
634 StringRef p = path.toStringRef(path_storage);
635
636 return !root_name(p, style).empty();
637 }
638
has_root_directory(const Twine & path,Style style)639 bool has_root_directory(const Twine &path, Style style) {
640 SmallString<128> path_storage;
641 StringRef p = path.toStringRef(path_storage);
642
643 return !root_directory(p, style).empty();
644 }
645
has_root_path(const Twine & path,Style style)646 bool has_root_path(const Twine &path, Style style) {
647 SmallString<128> path_storage;
648 StringRef p = path.toStringRef(path_storage);
649
650 return !root_path(p, style).empty();
651 }
652
has_relative_path(const Twine & path,Style style)653 bool has_relative_path(const Twine &path, Style style) {
654 SmallString<128> path_storage;
655 StringRef p = path.toStringRef(path_storage);
656
657 return !relative_path(p, style).empty();
658 }
659
has_filename(const Twine & path,Style style)660 bool has_filename(const Twine &path, Style style) {
661 SmallString<128> path_storage;
662 StringRef p = path.toStringRef(path_storage);
663
664 return !filename(p, style).empty();
665 }
666
has_parent_path(const Twine & path,Style style)667 bool has_parent_path(const Twine &path, Style style) {
668 SmallString<128> path_storage;
669 StringRef p = path.toStringRef(path_storage);
670
671 return !parent_path(p, style).empty();
672 }
673
has_stem(const Twine & path,Style style)674 bool has_stem(const Twine &path, Style style) {
675 SmallString<128> path_storage;
676 StringRef p = path.toStringRef(path_storage);
677
678 return !stem(p, style).empty();
679 }
680
has_extension(const Twine & path,Style style)681 bool has_extension(const Twine &path, Style style) {
682 SmallString<128> path_storage;
683 StringRef p = path.toStringRef(path_storage);
684
685 return !extension(p, style).empty();
686 }
687
is_absolute(const Twine & path,Style style)688 bool is_absolute(const Twine &path, Style style) {
689 SmallString<128> path_storage;
690 StringRef p = path.toStringRef(path_storage);
691
692 bool rootDir = has_root_directory(p, style);
693 bool rootName =
694 (real_style(style) != Style::windows) || has_root_name(p, style);
695
696 return rootDir && rootName;
697 }
698
is_relative(const Twine & path,Style style)699 bool is_relative(const Twine &path, Style style) {
700 return !is_absolute(path, style);
701 }
702
remove_leading_dotslash(StringRef Path,Style style)703 StringRef remove_leading_dotslash(StringRef Path, Style style) {
704 // Remove leading "./" (or ".//" or "././" etc.)
705 while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
706 Path = Path.substr(2);
707 while (Path.size() > 0 && is_separator(Path[0], style))
708 Path = Path.substr(1);
709 }
710 return Path;
711 }
712
remove_dots(StringRef path,bool remove_dot_dot,Style style)713 static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
714 Style style) {
715 SmallVector<StringRef, 16> components;
716
717 // Skip the root path, then look for traversal in the components.
718 StringRef rel = path::relative_path(path, style);
719 for (StringRef C :
720 llvm::make_range(path::begin(rel, style), path::end(rel))) {
721 if (C == ".")
722 continue;
723 // Leading ".." will remain in the path unless it's at the root.
724 if (remove_dot_dot && C == "..") {
725 if (!components.empty() && components.back() != "..") {
726 components.pop_back();
727 continue;
728 }
729 if (path::is_absolute(path, style))
730 continue;
731 }
732 components.push_back(C);
733 }
734
735 SmallString<256> buffer = path::root_path(path, style);
736 for (StringRef C : components)
737 path::append(buffer, style, C);
738 return buffer;
739 }
740
remove_dots(SmallVectorImpl<char> & path,bool remove_dot_dot,Style style)741 bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
742 Style style) {
743 StringRef p(path.data(), path.size());
744
745 SmallString<256> result = remove_dots(p, remove_dot_dot, style);
746 if (result == path)
747 return false;
748
749 path.swap(result);
750 return true;
751 }
752
753 } // end namespace path
754
755 namespace fs {
756
getUniqueID(const Twine Path,UniqueID & Result)757 std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
758 file_status Status;
759 std::error_code EC = status(Path, Status);
760 if (EC)
761 return EC;
762 Result = Status.getUniqueID();
763 return std::error_code();
764 }
765
createUniqueFile(const Twine & Model,int & ResultFd,SmallVectorImpl<char> & ResultPath,unsigned Mode)766 std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
767 SmallVectorImpl<char> &ResultPath,
768 unsigned Mode) {
769 return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
770 }
771
createUniqueFile(const Twine & Model,int & ResultFd,SmallVectorImpl<char> & ResultPath,unsigned Mode,OpenFlags Flags)772 static std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
773 SmallVectorImpl<char> &ResultPath,
774 unsigned Mode, OpenFlags Flags) {
775 return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File,
776 Flags);
777 }
778
createUniqueFile(const Twine & Model,SmallVectorImpl<char> & ResultPath,unsigned Mode)779 std::error_code createUniqueFile(const Twine &Model,
780 SmallVectorImpl<char> &ResultPath,
781 unsigned Mode) {
782 int FD;
783 auto EC = createUniqueFile(Model, FD, ResultPath, Mode);
784 if (EC)
785 return EC;
786 // FD is only needed to avoid race conditions. Close it right away.
787 close(FD);
788 return EC;
789 }
790
791 static std::error_code
createTemporaryFile(const Twine & Model,int & ResultFD,llvm::SmallVectorImpl<char> & ResultPath,FSEntity Type)792 createTemporaryFile(const Twine &Model, int &ResultFD,
793 llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
794 SmallString<128> Storage;
795 StringRef P = Model.toNullTerminatedStringRef(Storage);
796 assert(P.find_first_of(separators(Style::native)) == StringRef::npos &&
797 "Model must be a simple filename.");
798 // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
799 return createUniqueEntity(P.begin(), ResultFD, ResultPath, true,
800 owner_read | owner_write, Type);
801 }
802
803 static std::error_code
createTemporaryFile(const Twine & Prefix,StringRef Suffix,int & ResultFD,llvm::SmallVectorImpl<char> & ResultPath,FSEntity Type)804 createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
805 llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
806 const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
807 return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
808 Type);
809 }
810
createTemporaryFile(const Twine & Prefix,StringRef Suffix,int & ResultFD,SmallVectorImpl<char> & ResultPath)811 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
812 int &ResultFD,
813 SmallVectorImpl<char> &ResultPath) {
814 return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
815 }
816
createTemporaryFile(const Twine & Prefix,StringRef Suffix,SmallVectorImpl<char> & ResultPath)817 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
818 SmallVectorImpl<char> &ResultPath) {
819 int FD;
820 auto EC = createTemporaryFile(Prefix, Suffix, FD, ResultPath);
821 if (EC)
822 return EC;
823 // FD is only needed to avoid race conditions. Close it right away.
824 close(FD);
825 return EC;
826 }
827
828
829 // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
830 // for consistency. We should try using mkdtemp.
createUniqueDirectory(const Twine & Prefix,SmallVectorImpl<char> & ResultPath)831 std::error_code createUniqueDirectory(const Twine &Prefix,
832 SmallVectorImpl<char> &ResultPath) {
833 int Dummy;
834 return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, true, 0,
835 FS_Dir);
836 }
837
838 std::error_code
getPotentiallyUniqueFileName(const Twine & Model,SmallVectorImpl<char> & ResultPath)839 getPotentiallyUniqueFileName(const Twine &Model,
840 SmallVectorImpl<char> &ResultPath) {
841 int Dummy;
842 return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
843 }
844
845 std::error_code
getPotentiallyUniqueTempFileName(const Twine & Prefix,StringRef Suffix,SmallVectorImpl<char> & ResultPath)846 getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
847 SmallVectorImpl<char> &ResultPath) {
848 int Dummy;
849 return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
850 }
851
make_absolute(const Twine & current_directory,SmallVectorImpl<char> & path)852 void make_absolute(const Twine ¤t_directory,
853 SmallVectorImpl<char> &path) {
854 StringRef p(path.data(), path.size());
855
856 bool rootDirectory = path::has_root_directory(p);
857 bool rootName =
858 (real_style(Style::native) != Style::windows) || path::has_root_name(p);
859
860 // Already absolute.
861 if (rootName && rootDirectory)
862 return;
863
864 // All of the following conditions will need the current directory.
865 SmallString<128> current_dir;
866 current_directory.toVector(current_dir);
867
868 // Relative path. Prepend the current directory.
869 if (!rootName && !rootDirectory) {
870 // Append path to the current directory.
871 path::append(current_dir, p);
872 // Set path to the result.
873 path.swap(current_dir);
874 return;
875 }
876
877 if (!rootName && rootDirectory) {
878 StringRef cdrn = path::root_name(current_dir);
879 SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
880 path::append(curDirRootName, p);
881 // Set path to the result.
882 path.swap(curDirRootName);
883 return;
884 }
885
886 if (rootName && !rootDirectory) {
887 StringRef pRootName = path::root_name(p);
888 StringRef bRootDirectory = path::root_directory(current_dir);
889 StringRef bRelativePath = path::relative_path(current_dir);
890 StringRef pRelativePath = path::relative_path(p);
891
892 SmallString<128> res;
893 path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
894 path.swap(res);
895 return;
896 }
897
898 llvm_unreachable("All rootName and rootDirectory combinations should have "
899 "occurred above!");
900 }
901
make_absolute(SmallVectorImpl<char> & path)902 std::error_code make_absolute(SmallVectorImpl<char> &path) {
903 if (path::is_absolute(path))
904 return {};
905
906 SmallString<128> current_dir;
907 if (std::error_code ec = current_path(current_dir))
908 return ec;
909
910 make_absolute(current_dir, path);
911 return {};
912 }
913
create_directories(const Twine & Path,bool IgnoreExisting,perms Perms)914 std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
915 perms Perms) {
916 SmallString<128> PathStorage;
917 StringRef P = Path.toStringRef(PathStorage);
918
919 // Be optimistic and try to create the directory
920 std::error_code EC = create_directory(P, IgnoreExisting, Perms);
921 // If we succeeded, or had any error other than the parent not existing, just
922 // return it.
923 if (EC != errc::no_such_file_or_directory)
924 return EC;
925
926 // We failed because of a no_such_file_or_directory, try to create the
927 // parent.
928 StringRef Parent = path::parent_path(P);
929 if (Parent.empty())
930 return EC;
931
932 if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
933 return EC;
934
935 return create_directory(P, IgnoreExisting, Perms);
936 }
937
copy_file_internal(int ReadFD,int WriteFD)938 static std::error_code copy_file_internal(int ReadFD, int WriteFD) {
939 const size_t BufSize = 4096;
940 char *Buf = new char[BufSize];
941 int BytesRead = 0, BytesWritten = 0;
942 for (;;) {
943 BytesRead = read(ReadFD, Buf, BufSize);
944 if (BytesRead <= 0)
945 break;
946 while (BytesRead) {
947 BytesWritten = write(WriteFD, Buf, BytesRead);
948 if (BytesWritten < 0)
949 break;
950 BytesRead -= BytesWritten;
951 }
952 if (BytesWritten < 0)
953 break;
954 }
955 delete[] Buf;
956
957 if (BytesRead < 0 || BytesWritten < 0)
958 return std::error_code(errno, std::generic_category());
959 return std::error_code();
960 }
961
copy_file(const Twine & From,const Twine & To)962 std::error_code copy_file(const Twine &From, const Twine &To) {
963 int ReadFD, WriteFD;
964 if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
965 return EC;
966 if (std::error_code EC =
967 openFileForWrite(To, WriteFD, CD_CreateAlways, OF_None)) {
968 close(ReadFD);
969 return EC;
970 }
971
972 std::error_code EC = copy_file_internal(ReadFD, WriteFD);
973
974 close(ReadFD);
975 close(WriteFD);
976
977 return EC;
978 }
979
copy_file(const Twine & From,int ToFD)980 std::error_code copy_file(const Twine &From, int ToFD) {
981 int ReadFD;
982 if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
983 return EC;
984
985 std::error_code EC = copy_file_internal(ReadFD, ToFD);
986
987 close(ReadFD);
988
989 return EC;
990 }
991
md5_contents(int FD)992 ErrorOr<MD5::MD5Result> md5_contents(int FD) {
993 MD5 Hash;
994
995 constexpr size_t BufSize = 4096;
996 std::vector<uint8_t> Buf(BufSize);
997 int BytesRead = 0;
998 for (;;) {
999 BytesRead = read(FD, Buf.data(), BufSize);
1000 if (BytesRead <= 0)
1001 break;
1002 Hash.update(makeArrayRef(Buf.data(), BytesRead));
1003 }
1004
1005 if (BytesRead < 0)
1006 return std::error_code(errno, std::generic_category());
1007 MD5::MD5Result Result;
1008 Hash.final(Result);
1009 return Result;
1010 }
1011
md5_contents(const Twine & Path)1012 ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
1013 int FD;
1014 if (auto EC = openFileForRead(Path, FD, OF_None))
1015 return EC;
1016
1017 auto Result = md5_contents(FD);
1018 close(FD);
1019 return Result;
1020 }
1021
exists(const basic_file_status & status)1022 bool exists(const basic_file_status &status) {
1023 return status_known(status) && status.type() != file_type::file_not_found;
1024 }
1025
status_known(const basic_file_status & s)1026 bool status_known(const basic_file_status &s) {
1027 return s.type() != file_type::status_error;
1028 }
1029
get_file_type(const Twine & Path,bool Follow)1030 file_type get_file_type(const Twine &Path, bool Follow) {
1031 file_status st;
1032 if (status(Path, st, Follow))
1033 return file_type::status_error;
1034 return st.type();
1035 }
1036
is_directory(const basic_file_status & status)1037 bool is_directory(const basic_file_status &status) {
1038 return status.type() == file_type::directory_file;
1039 }
1040
is_directory(const Twine & path,bool & result)1041 std::error_code is_directory(const Twine &path, bool &result) {
1042 file_status st;
1043 if (std::error_code ec = status(path, st))
1044 return ec;
1045 result = is_directory(st);
1046 return std::error_code();
1047 }
1048
is_regular_file(const basic_file_status & status)1049 bool is_regular_file(const basic_file_status &status) {
1050 return status.type() == file_type::regular_file;
1051 }
1052
is_regular_file(const Twine & path,bool & result)1053 std::error_code is_regular_file(const Twine &path, bool &result) {
1054 file_status st;
1055 if (std::error_code ec = status(path, st))
1056 return ec;
1057 result = is_regular_file(st);
1058 return std::error_code();
1059 }
1060
is_symlink_file(const basic_file_status & status)1061 bool is_symlink_file(const basic_file_status &status) {
1062 return status.type() == file_type::symlink_file;
1063 }
1064
is_symlink_file(const Twine & path,bool & result)1065 std::error_code is_symlink_file(const Twine &path, bool &result) {
1066 file_status st;
1067 if (std::error_code ec = status(path, st, false))
1068 return ec;
1069 result = is_symlink_file(st);
1070 return std::error_code();
1071 }
1072
is_other(const basic_file_status & status)1073 bool is_other(const basic_file_status &status) {
1074 return exists(status) &&
1075 !is_regular_file(status) &&
1076 !is_directory(status);
1077 }
1078
is_other(const Twine & Path,bool & Result)1079 std::error_code is_other(const Twine &Path, bool &Result) {
1080 file_status FileStatus;
1081 if (std::error_code EC = status(Path, FileStatus))
1082 return EC;
1083 Result = is_other(FileStatus);
1084 return std::error_code();
1085 }
1086
replace_filename(const Twine & Filename,file_type Type,basic_file_status Status)1087 void directory_entry::replace_filename(const Twine &Filename, file_type Type,
1088 basic_file_status Status) {
1089 SmallString<128> PathStr = path::parent_path(Path);
1090 path::append(PathStr, Filename);
1091 this->Path = PathStr.str();
1092 this->Type = Type;
1093 this->Status = Status;
1094 }
1095
getPermissions(const Twine & Path)1096 ErrorOr<perms> getPermissions(const Twine &Path) {
1097 file_status Status;
1098 if (std::error_code EC = status(Path, Status))
1099 return EC;
1100
1101 return Status.permissions();
1102 }
1103
1104 } // end namespace fs
1105 } // end namespace sys
1106 } // end namespace llvm
1107
1108 // Include the truly platform-specific parts.
1109 #if defined(LLVM_ON_UNIX)
1110 #include "Unix/Path.inc"
1111 #endif
1112 #if defined(_WIN32)
1113 #include "Windows/Path.inc"
1114 #endif
1115
1116 namespace llvm {
1117 namespace sys {
1118 namespace fs {
TempFile(StringRef Name,int FD)1119 TempFile::TempFile(StringRef Name, int FD) : TmpName(Name), FD(FD) {}
TempFile(TempFile && Other)1120 TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
operator =(TempFile && Other)1121 TempFile &TempFile::operator=(TempFile &&Other) {
1122 TmpName = std::move(Other.TmpName);
1123 FD = Other.FD;
1124 Other.Done = true;
1125 return *this;
1126 }
1127
~TempFile()1128 TempFile::~TempFile() { assert(Done); }
1129
discard()1130 Error TempFile::discard() {
1131 Done = true;
1132 std::error_code RemoveEC;
1133 // On windows closing will remove the file.
1134 #ifndef _WIN32
1135 // Always try to close and remove.
1136 if (!TmpName.empty()) {
1137 RemoveEC = fs::remove(TmpName);
1138 sys::DontRemoveFileOnSignal(TmpName);
1139 }
1140 #endif
1141
1142 if (!RemoveEC)
1143 TmpName = "";
1144
1145 if (FD != -1 && close(FD) == -1) {
1146 std::error_code EC = std::error_code(errno, std::generic_category());
1147 return errorCodeToError(EC);
1148 }
1149 FD = -1;
1150
1151 return errorCodeToError(RemoveEC);
1152 }
1153
keep(const Twine & Name)1154 Error TempFile::keep(const Twine &Name) {
1155 assert(!Done);
1156 Done = true;
1157 // Always try to close and rename.
1158 #ifdef _WIN32
1159 // If we can't cancel the delete don't rename.
1160 auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1161 std::error_code RenameEC = setDeleteDisposition(H, false);
1162 if (!RenameEC) {
1163 RenameEC = rename_fd(FD, Name);
1164 // If rename failed because it's cross-device, copy instead
1165 if (RenameEC ==
1166 std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) {
1167 RenameEC = copy_file(TmpName, Name);
1168 setDeleteDisposition(H, true);
1169 }
1170 }
1171
1172 // If we can't rename, discard the temporary file.
1173 if (RenameEC)
1174 setDeleteDisposition(H, true);
1175 #else
1176 std::error_code RenameEC = fs::rename(TmpName, Name);
1177 if (RenameEC) {
1178 // If we can't rename, try to copy to work around cross-device link issues.
1179 RenameEC = sys::fs::copy_file(TmpName, Name);
1180 // If we can't rename or copy, discard the temporary file.
1181 if (RenameEC)
1182 remove(TmpName);
1183 }
1184 sys::DontRemoveFileOnSignal(TmpName);
1185 #endif
1186
1187 if (!RenameEC)
1188 TmpName = "";
1189
1190 if (close(FD) == -1) {
1191 std::error_code EC(errno, std::generic_category());
1192 return errorCodeToError(EC);
1193 }
1194 FD = -1;
1195
1196 return errorCodeToError(RenameEC);
1197 }
1198
keep()1199 Error TempFile::keep() {
1200 assert(!Done);
1201 Done = true;
1202
1203 #ifdef _WIN32
1204 auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1205 if (std::error_code EC = setDeleteDisposition(H, false))
1206 return errorCodeToError(EC);
1207 #else
1208 sys::DontRemoveFileOnSignal(TmpName);
1209 #endif
1210
1211 TmpName = "";
1212
1213 if (close(FD) == -1) {
1214 std::error_code EC(errno, std::generic_category());
1215 return errorCodeToError(EC);
1216 }
1217 FD = -1;
1218
1219 return Error::success();
1220 }
1221
create(const Twine & Model,unsigned Mode)1222 Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) {
1223 int FD;
1224 SmallString<128> ResultPath;
1225 if (std::error_code EC =
1226 createUniqueFile(Model, FD, ResultPath, Mode, OF_Delete))
1227 return errorCodeToError(EC);
1228
1229 TempFile Ret(ResultPath, FD);
1230 #ifndef _WIN32
1231 if (sys::RemoveFileOnSignal(ResultPath)) {
1232 // Make sure we delete the file when RemoveFileOnSignal fails.
1233 consumeError(Ret.discard());
1234 std::error_code EC(errc::operation_not_permitted);
1235 return errorCodeToError(EC);
1236 }
1237 #endif
1238 return std::move(Ret);
1239 }
1240 }
1241
1242 } // end namsspace sys
1243 } // end namespace llvm
1244