[PowerPC] Do not emit record-form rotates when record-form andi/andis suffices
[llvm-core.git] / lib / Support / Path.cpp
blob41f25648985404ff2a0eb2b33a51ab8f20f9a493
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.
12 //===----------------------------------------------------------------------===//
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>
26 #if !defined(_MSC_VER) && !defined(__MINGW32__)
27 #include <unistd.h>
28 #else
29 #include <io.h>
30 #endif
32 using namespace llvm;
33 using namespace llvm::support::endian;
35 namespace {
36 using llvm::StringRef;
37 using llvm::sys::path::is_separator;
38 using llvm::sys::path::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
48 inline const char *separators(Style style) {
49 if (real_style(style) == Style::windows)
50 return "\\/";
51 return "/";
54 inline char preferred_separator(Style style) {
55 if (real_style(style) == Style::windows)
56 return '\\';
57 return '/';
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
67 if (path.empty())
68 return path;
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);
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);
85 // {/,\}
86 if (is_separator(path[0], style))
87 return path.substr(0, 1);
89 // * {file,directory}name
90 size_t end = path.find_first_of(separators(style));
91 return path.substr(0, end);
94 // Returns the first character of the filename in str. For paths ending in
95 // '/', it returns the position of the '/'.
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;
100 size_t pos = str.find_last_of(separators(style), str.size() - 1);
102 if (real_style(style) == Style::windows) {
103 if (pos == StringRef::npos)
104 pos = str.find_last_of(':', str.size() - 2);
107 if (pos == StringRef::npos || (pos == 1 && is_separator(str[0], style)))
108 return 0;
110 return pos + 1;
113 // Returns the position of the root directory in str. If there is no root
114 // directory in str, it returns StringRef::npos.
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;
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);
128 // case "/"
129 if (str.size() > 0 && is_separator(str[0], style))
130 return 0;
132 return StringRef::npos;
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.
138 size_t parent_path_end(StringRef path, Style style) {
139 size_t end_pos = filename_pos(path, style);
141 bool filename_was_sep =
142 path.size() > 0 && is_separator(path[end_pos], style);
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;
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;
157 // Otherwise, just include before the last slash.
158 return end_pos;
160 } // end unnamed namespace
162 enum FSEntity {
163 FS_Dir,
164 FS_File,
165 FS_Name
168 static std::error_code
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);
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);
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();
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];
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;
219 return std::error_code();
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;
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;
238 return std::error_code();
241 llvm_unreachable("Invalid Type");
243 return EC;
246 namespace llvm {
247 namespace sys {
248 namespace path {
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;
259 const_iterator end(StringRef path) {
260 const_iterator i;
261 i.Path = path;
262 i.Position = path.size();
263 return i;
266 const_iterator &const_iterator::operator++() {
267 assert(Position < Path.size() && "Tried to increment past end!");
269 // Increment Position to past the current component
270 Position += Component.size();
272 // Check for end.
273 if (Position == Path.size()) {
274 Component = StringRef();
275 return *this;
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);
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;
293 // Skip extra separators.
294 while (Position != Path.size() && is_separator(Path[Position], S)) {
295 ++Position;
298 // Treat trailing '/' as a '.', unless it is the root dir.
299 if (Position == Path.size() && Component != "/") {
300 --Position;
301 Component = ".";
302 return *this;
306 // Find next component.
307 size_t end_pos = Path.find_first_of(separators(S), Position);
308 Component = Path.slice(Position, end_pos);
310 return *this;
313 bool const_iterator::operator==(const const_iterator &RHS) const {
314 return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
317 ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
318 return Position - RHS.Position;
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;
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;
337 reverse_iterator &reverse_iterator::operator++() {
338 size_t root_dir_pos = root_dir_start(Path, S);
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;
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;
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;
362 bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
363 return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
364 Position == RHS.Position;
367 ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
368 return Position - RHS.Position;
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(":");
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;
388 // POSIX style root directory.
389 if (is_separator((*b)[0], style)) {
390 return *b;
394 return StringRef();
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(":");
404 if (has_net || has_drive) {
405 // just {C:,//net}, return the first component.
406 return *b;
410 // No path or no name.
411 return StringRef();
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(":");
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;
427 // POSIX style root directory.
428 if (!has_net && is_separator((*b)[0], style)) {
429 return *b;
433 // No path or no root.
434 return StringRef();
437 StringRef relative_path(StringRef path, Style style) {
438 StringRef root = root_path(path, style);
439 return path.substr(root.size());
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;
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));
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);
463 // Append it.
464 path.append(c.begin(), c.end());
465 continue;
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));
476 path.append(component.begin(), component.end());
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);
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);
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);
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);
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);
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);
516 // Append '.' if needed.
517 if (ext.size() > 0 && ext[0] != '.')
518 path.push_back('.');
520 // Append extension.
521 path.append(ext.begin(), ext.end());
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;
530 StringRef OrigPath(Path.begin(), Path.size());
531 if (!OrigPath.startswith(OldPrefix))
532 return;
534 // If prefixes have the same size we can simply copy the new one over.
535 if (OldPrefix.size() == NewPrefix.size()) {
536 std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
537 return;
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);
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);
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;
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 = '/';
581 std::string convert_to_slash(StringRef path, Style style) {
582 if (real_style(style) != Style::windows)
583 return path;
585 std::string s = path.str();
586 std::replace(s.begin(), s.end(), '\\', '/');
587 return s;
590 StringRef filename(StringRef path, Style style) { return *rbegin(path, 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);
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);
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;
626 StringRef get_separator(Style style) {
627 if (real_style(style) == Style::windows)
628 return "\\";
629 return "/";
632 bool has_root_name(const Twine &path, Style style) {
633 SmallString<128> path_storage;
634 StringRef p = path.toStringRef(path_storage);
636 return !root_name(p, style).empty();
639 bool has_root_directory(const Twine &path, Style style) {
640 SmallString<128> path_storage;
641 StringRef p = path.toStringRef(path_storage);
643 return !root_directory(p, style).empty();
646 bool has_root_path(const Twine &path, Style style) {
647 SmallString<128> path_storage;
648 StringRef p = path.toStringRef(path_storage);
650 return !root_path(p, style).empty();
653 bool has_relative_path(const Twine &path, Style style) {
654 SmallString<128> path_storage;
655 StringRef p = path.toStringRef(path_storage);
657 return !relative_path(p, style).empty();
660 bool has_filename(const Twine &path, Style style) {
661 SmallString<128> path_storage;
662 StringRef p = path.toStringRef(path_storage);
664 return !filename(p, style).empty();
667 bool has_parent_path(const Twine &path, Style style) {
668 SmallString<128> path_storage;
669 StringRef p = path.toStringRef(path_storage);
671 return !parent_path(p, style).empty();
674 bool has_stem(const Twine &path, Style style) {
675 SmallString<128> path_storage;
676 StringRef p = path.toStringRef(path_storage);
678 return !stem(p, style).empty();
681 bool has_extension(const Twine &path, Style style) {
682 SmallString<128> path_storage;
683 StringRef p = path.toStringRef(path_storage);
685 return !extension(p, style).empty();
688 bool is_absolute(const Twine &path, Style style) {
689 SmallString<128> path_storage;
690 StringRef p = path.toStringRef(path_storage);
692 bool rootDir = has_root_directory(p, style);
693 bool rootName =
694 (real_style(style) != Style::windows) || has_root_name(p, style);
696 return rootDir && rootName;
699 bool is_relative(const Twine &path, Style style) {
700 return !is_absolute(path, 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);
710 return Path;
713 static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
714 Style style) {
715 SmallVector<StringRef, 16> components;
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;
729 if (path::is_absolute(path, style))
730 continue;
732 components.push_back(C);
735 SmallString<256> buffer = path::root_path(path, style);
736 for (StringRef C : components)
737 path::append(buffer, style, C);
738 return buffer;
741 bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
742 Style style) {
743 StringRef p(path.data(), path.size());
745 SmallString<256> result = remove_dots(p, remove_dot_dot, style);
746 if (result == path)
747 return false;
749 path.swap(result);
750 return true;
753 } // end namespace path
755 namespace fs {
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();
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);
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);
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;
791 static std::error_code
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);
803 static std::error_code
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);
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);
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;
829 // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
830 // for consistency. We should try using mkdtemp.
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);
838 std::error_code
839 getPotentiallyUniqueFileName(const Twine &Model,
840 SmallVectorImpl<char> &ResultPath) {
841 int Dummy;
842 return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
845 std::error_code
846 getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
847 SmallVectorImpl<char> &ResultPath) {
848 int Dummy;
849 return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
852 static std::error_code make_absolute(const Twine &current_directory,
853 SmallVectorImpl<char> &path,
854 bool use_current_directory) {
855 StringRef p(path.data(), path.size());
857 bool rootDirectory = path::has_root_directory(p);
858 bool rootName =
859 (real_style(Style::native) != Style::windows) || path::has_root_name(p);
861 // Already absolute.
862 if (rootName && rootDirectory)
863 return std::error_code();
865 // All of the following conditions will need the current directory.
866 SmallString<128> current_dir;
867 if (use_current_directory)
868 current_directory.toVector(current_dir);
869 else if (std::error_code ec = current_path(current_dir))
870 return ec;
872 // Relative path. Prepend the current directory.
873 if (!rootName && !rootDirectory) {
874 // Append path to the current directory.
875 path::append(current_dir, p);
876 // Set path to the result.
877 path.swap(current_dir);
878 return std::error_code();
881 if (!rootName && rootDirectory) {
882 StringRef cdrn = path::root_name(current_dir);
883 SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
884 path::append(curDirRootName, p);
885 // Set path to the result.
886 path.swap(curDirRootName);
887 return std::error_code();
890 if (rootName && !rootDirectory) {
891 StringRef pRootName = path::root_name(p);
892 StringRef bRootDirectory = path::root_directory(current_dir);
893 StringRef bRelativePath = path::relative_path(current_dir);
894 StringRef pRelativePath = path::relative_path(p);
896 SmallString<128> res;
897 path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
898 path.swap(res);
899 return std::error_code();
902 llvm_unreachable("All rootName and rootDirectory combinations should have "
903 "occurred above!");
906 std::error_code make_absolute(const Twine &current_directory,
907 SmallVectorImpl<char> &path) {
908 return make_absolute(current_directory, path, true);
911 std::error_code make_absolute(SmallVectorImpl<char> &path) {
912 return make_absolute(Twine(), path, false);
915 std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
916 perms Perms) {
917 SmallString<128> PathStorage;
918 StringRef P = Path.toStringRef(PathStorage);
920 // Be optimistic and try to create the directory
921 std::error_code EC = create_directory(P, IgnoreExisting, Perms);
922 // If we succeeded, or had any error other than the parent not existing, just
923 // return it.
924 if (EC != errc::no_such_file_or_directory)
925 return EC;
927 // We failed because of a no_such_file_or_directory, try to create the
928 // parent.
929 StringRef Parent = path::parent_path(P);
930 if (Parent.empty())
931 return EC;
933 if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
934 return EC;
936 return create_directory(P, IgnoreExisting, Perms);
939 static std::error_code copy_file_internal(int ReadFD, int WriteFD) {
940 const size_t BufSize = 4096;
941 char *Buf = new char[BufSize];
942 int BytesRead = 0, BytesWritten = 0;
943 for (;;) {
944 BytesRead = read(ReadFD, Buf, BufSize);
945 if (BytesRead <= 0)
946 break;
947 while (BytesRead) {
948 BytesWritten = write(WriteFD, Buf, BytesRead);
949 if (BytesWritten < 0)
950 break;
951 BytesRead -= BytesWritten;
953 if (BytesWritten < 0)
954 break;
956 delete[] Buf;
958 if (BytesRead < 0 || BytesWritten < 0)
959 return std::error_code(errno, std::generic_category());
960 return std::error_code();
963 std::error_code copy_file(const Twine &From, const Twine &To) {
964 int ReadFD, WriteFD;
965 if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
966 return EC;
967 if (std::error_code EC =
968 openFileForWrite(To, WriteFD, CD_CreateAlways, OF_None)) {
969 close(ReadFD);
970 return EC;
973 std::error_code EC = copy_file_internal(ReadFD, WriteFD);
975 close(ReadFD);
976 close(WriteFD);
978 return EC;
981 std::error_code copy_file(const Twine &From, int ToFD) {
982 int ReadFD;
983 if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
984 return EC;
986 std::error_code EC = copy_file_internal(ReadFD, ToFD);
988 close(ReadFD);
990 return EC;
993 ErrorOr<MD5::MD5Result> md5_contents(int FD) {
994 MD5 Hash;
996 constexpr size_t BufSize = 4096;
997 std::vector<uint8_t> Buf(BufSize);
998 int BytesRead = 0;
999 for (;;) {
1000 BytesRead = read(FD, Buf.data(), BufSize);
1001 if (BytesRead <= 0)
1002 break;
1003 Hash.update(makeArrayRef(Buf.data(), BytesRead));
1006 if (BytesRead < 0)
1007 return std::error_code(errno, std::generic_category());
1008 MD5::MD5Result Result;
1009 Hash.final(Result);
1010 return Result;
1013 ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
1014 int FD;
1015 if (auto EC = openFileForRead(Path, FD, OF_None))
1016 return EC;
1018 auto Result = md5_contents(FD);
1019 close(FD);
1020 return Result;
1023 bool exists(const basic_file_status &status) {
1024 return status_known(status) && status.type() != file_type::file_not_found;
1027 bool status_known(const basic_file_status &s) {
1028 return s.type() != file_type::status_error;
1031 file_type get_file_type(const Twine &Path, bool Follow) {
1032 file_status st;
1033 if (status(Path, st, Follow))
1034 return file_type::status_error;
1035 return st.type();
1038 bool is_directory(const basic_file_status &status) {
1039 return status.type() == file_type::directory_file;
1042 std::error_code is_directory(const Twine &path, bool &result) {
1043 file_status st;
1044 if (std::error_code ec = status(path, st))
1045 return ec;
1046 result = is_directory(st);
1047 return std::error_code();
1050 bool is_regular_file(const basic_file_status &status) {
1051 return status.type() == file_type::regular_file;
1054 std::error_code is_regular_file(const Twine &path, bool &result) {
1055 file_status st;
1056 if (std::error_code ec = status(path, st))
1057 return ec;
1058 result = is_regular_file(st);
1059 return std::error_code();
1062 bool is_symlink_file(const basic_file_status &status) {
1063 return status.type() == file_type::symlink_file;
1066 std::error_code is_symlink_file(const Twine &path, bool &result) {
1067 file_status st;
1068 if (std::error_code ec = status(path, st, false))
1069 return ec;
1070 result = is_symlink_file(st);
1071 return std::error_code();
1074 bool is_other(const basic_file_status &status) {
1075 return exists(status) &&
1076 !is_regular_file(status) &&
1077 !is_directory(status);
1080 std::error_code is_other(const Twine &Path, bool &Result) {
1081 file_status FileStatus;
1082 if (std::error_code EC = status(Path, FileStatus))
1083 return EC;
1084 Result = is_other(FileStatus);
1085 return std::error_code();
1088 void directory_entry::replace_filename(const Twine &Filename, file_type Type,
1089 basic_file_status Status) {
1090 SmallString<128> PathStr = path::parent_path(Path);
1091 path::append(PathStr, Filename);
1092 this->Path = PathStr.str();
1093 this->Type = Type;
1094 this->Status = Status;
1097 ErrorOr<perms> getPermissions(const Twine &Path) {
1098 file_status Status;
1099 if (std::error_code EC = status(Path, Status))
1100 return EC;
1102 return Status.permissions();
1105 } // end namespace fs
1106 } // end namespace sys
1107 } // end namespace llvm
1109 // Include the truly platform-specific parts.
1110 #if defined(LLVM_ON_UNIX)
1111 #include "Unix/Path.inc"
1112 #endif
1113 #if defined(_WIN32)
1114 #include "Windows/Path.inc"
1115 #endif
1117 namespace llvm {
1118 namespace sys {
1119 namespace fs {
1120 TempFile::TempFile(StringRef Name, int FD) : TmpName(Name), FD(FD) {}
1121 TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
1122 TempFile &TempFile::operator=(TempFile &&Other) {
1123 TmpName = std::move(Other.TmpName);
1124 FD = Other.FD;
1125 Other.Done = true;
1126 return *this;
1129 TempFile::~TempFile() { assert(Done); }
1131 Error TempFile::discard() {
1132 Done = true;
1133 std::error_code RemoveEC;
1134 // On windows closing will remove the file.
1135 #ifndef _WIN32
1136 // Always try to close and remove.
1137 if (!TmpName.empty()) {
1138 RemoveEC = fs::remove(TmpName);
1139 sys::DontRemoveFileOnSignal(TmpName);
1141 #endif
1143 if (!RemoveEC)
1144 TmpName = "";
1146 if (FD != -1 && close(FD) == -1) {
1147 std::error_code EC = std::error_code(errno, std::generic_category());
1148 return errorCodeToError(EC);
1150 FD = -1;
1152 return errorCodeToError(RemoveEC);
1155 Error TempFile::keep(const Twine &Name) {
1156 assert(!Done);
1157 Done = true;
1158 // Always try to close and rename.
1159 #ifdef _WIN32
1160 // If we can't cancel the delete don't rename.
1161 auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1162 std::error_code RenameEC = setDeleteDisposition(H, false);
1163 if (!RenameEC) {
1164 RenameEC = rename_fd(FD, Name);
1165 // If rename failed because it's cross-device, copy instead
1166 if (RenameEC ==
1167 std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) {
1168 RenameEC = copy_file(TmpName, Name);
1169 setDeleteDisposition(H, true);
1173 // If we can't rename, discard the temporary file.
1174 if (RenameEC)
1175 setDeleteDisposition(H, true);
1176 #else
1177 std::error_code RenameEC = fs::rename(TmpName, Name);
1178 if (RenameEC) {
1179 // If we can't rename, try to copy to work around cross-device link issues.
1180 RenameEC = sys::fs::copy_file(TmpName, Name);
1181 // If we can't rename or copy, discard the temporary file.
1182 if (RenameEC)
1183 remove(TmpName);
1185 sys::DontRemoveFileOnSignal(TmpName);
1186 #endif
1188 if (!RenameEC)
1189 TmpName = "";
1191 if (close(FD) == -1) {
1192 std::error_code EC(errno, std::generic_category());
1193 return errorCodeToError(EC);
1195 FD = -1;
1197 return errorCodeToError(RenameEC);
1200 Error TempFile::keep() {
1201 assert(!Done);
1202 Done = true;
1204 #ifdef _WIN32
1205 auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1206 if (std::error_code EC = setDeleteDisposition(H, false))
1207 return errorCodeToError(EC);
1208 #else
1209 sys::DontRemoveFileOnSignal(TmpName);
1210 #endif
1212 TmpName = "";
1214 if (close(FD) == -1) {
1215 std::error_code EC(errno, std::generic_category());
1216 return errorCodeToError(EC);
1218 FD = -1;
1220 return Error::success();
1223 Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) {
1224 int FD;
1225 SmallString<128> ResultPath;
1226 if (std::error_code EC =
1227 createUniqueFile(Model, FD, ResultPath, Mode, OF_Delete))
1228 return errorCodeToError(EC);
1230 TempFile Ret(ResultPath, FD);
1231 #ifndef _WIN32
1232 if (sys::RemoveFileOnSignal(ResultPath)) {
1233 // Make sure we delete the file when RemoveFileOnSignal fails.
1234 consumeError(Ret.discard());
1235 std::error_code EC(errc::operation_not_permitted);
1236 return errorCodeToError(EC);
1238 #endif
1239 return std::move(Ret);
1243 namespace path {
1245 bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
1246 const Twine &Path2, const Twine &Path3) {
1247 if (getUserCacheDir(Result)) {
1248 append(Result, Path1, Path2, Path3);
1249 return true;
1251 return false;
1254 } // end namespace path
1255 } // end namsspace sys
1256 } // end namespace llvm