1 //===-- Path.cpp - Implement OS Path Concept ------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the operating system Path API.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Support/Path.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/ScopeExit.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/Config/config.h"
18 #include "llvm/Config/llvm-config.h"
19 #include "llvm/Support/Endian.h"
20 #include "llvm/Support/Errc.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/Process.h"
24 #include "llvm/Support/Signals.h"
28 #if !defined(_MSC_VER) && !defined(__MINGW32__)
35 using namespace llvm::support::endian
;
38 using llvm::StringRef
;
39 using llvm::sys::path::is_separator
;
40 using llvm::sys::path::Style
;
42 inline Style
real_style(Style style
) {
43 if (style
!= Style::native
)
45 if (is_style_posix(style
))
47 return LLVM_WINDOWS_PREFER_FORWARD_SLASH
? Style::windows_slash
48 : Style::windows_backslash
;
51 inline const char *separators(Style style
) {
52 if (is_style_windows(style
))
57 inline char preferred_separator(Style style
) {
58 if (real_style(style
) == Style::windows
)
63 StringRef
find_first_component(StringRef path
, Style style
) {
64 // Look for this first component in the following order.
65 // * empty (in this case we return an empty string)
66 // * either C: or {//,\\}net.
68 // * {file,directory}name
73 if (is_style_windows(style
)) {
75 if (path
.size() >= 2 &&
76 std::isalpha(static_cast<unsigned char>(path
[0])) && path
[1] == ':')
77 return path
.substr(0, 2);
81 if ((path
.size() > 2) && is_separator(path
[0], style
) &&
82 path
[0] == path
[1] && !is_separator(path
[2], style
)) {
83 // Find the next directory separator.
84 size_t end
= path
.find_first_of(separators(style
), 2);
85 return path
.substr(0, end
);
89 if (is_separator(path
[0], style
))
90 return path
.substr(0, 1);
92 // * {file,directory}name
93 size_t end
= path
.find_first_of(separators(style
));
94 return path
.substr(0, end
);
97 // Returns the first character of the filename in str. For paths ending in
98 // '/', it returns the position of the '/'.
99 size_t filename_pos(StringRef str
, Style style
) {
100 if (str
.size() > 0 && is_separator(str
[str
.size() - 1], style
))
101 return str
.size() - 1;
103 size_t pos
= str
.find_last_of(separators(style
), str
.size() - 1);
105 if (is_style_windows(style
)) {
106 if (pos
== StringRef::npos
)
107 pos
= str
.find_last_of(':', str
.size() - 1);
110 if (pos
== StringRef::npos
|| (pos
== 1 && is_separator(str
[0], style
)))
116 // Returns the position of the root directory in str. If there is no root
117 // directory in str, it returns StringRef::npos.
118 size_t root_dir_start(StringRef str
, Style style
) {
120 if (is_style_windows(style
)) {
121 if (str
.size() > 2 && str
[1] == ':' && is_separator(str
[2], style
))
126 if (str
.size() > 3 && is_separator(str
[0], style
) && str
[0] == str
[1] &&
127 !is_separator(str
[2], style
)) {
128 return str
.find_first_of(separators(style
), 2);
132 if (str
.size() > 0 && is_separator(str
[0], style
))
135 return StringRef::npos
;
138 // Returns the position past the end of the "parent path" of path. The parent
139 // path will not end in '/', unless the parent is the root directory. If the
140 // path has no parent, 0 is returned.
141 size_t parent_path_end(StringRef path
, Style style
) {
142 size_t end_pos
= filename_pos(path
, style
);
144 bool filename_was_sep
=
145 path
.size() > 0 && is_separator(path
[end_pos
], style
);
147 // Skip separators until we reach root dir (or the start of the string).
148 size_t root_dir_pos
= root_dir_start(path
, style
);
149 while (end_pos
> 0 &&
150 (root_dir_pos
== StringRef::npos
|| end_pos
> root_dir_pos
) &&
151 is_separator(path
[end_pos
- 1], style
))
154 if (end_pos
== root_dir_pos
&& !filename_was_sep
) {
155 // We've reached the root dir and the input path was *not* ending in a
156 // sequence of slashes. Include the root dir in the parent path.
157 return root_dir_pos
+ 1;
160 // Otherwise, just include before the last slash.
163 } // end unnamed namespace
171 static std::error_code
172 createUniqueEntity(const Twine
&Model
, int &ResultFD
,
173 SmallVectorImpl
<char> &ResultPath
, bool MakeAbsolute
,
174 FSEntity Type
, sys::fs::OpenFlags Flags
= sys::fs::OF_None
,
177 // Limit the number of attempts we make, so that we don't infinite loop. E.g.
178 // "permission denied" could be for a specific file (so we retry with a
179 // different name) or for the whole directory (retry would always fail).
180 // Checking which is racy, so we try a number of times, then give up.
182 for (int Retries
= 128; Retries
> 0; --Retries
) {
183 sys::fs::createUniquePath(Model
, ResultPath
, MakeAbsolute
);
184 // Try to open + create the file.
187 EC
= sys::fs::openFileForReadWrite(Twine(ResultPath
.begin()), ResultFD
,
188 sys::fs::CD_CreateNew
, Flags
, Mode
);
190 // errc::permission_denied happens on Windows when we try to open a file
191 // that has been marked for deletion.
192 if (EC
== errc::file_exists
|| EC
== errc::permission_denied
)
197 return std::error_code();
201 EC
= sys::fs::access(ResultPath
.begin(), sys::fs::AccessMode::Exist
);
202 if (EC
== errc::no_such_file_or_directory
)
203 return std::error_code();
210 EC
= sys::fs::create_directory(ResultPath
.begin(), false);
212 if (EC
== errc::file_exists
)
216 return std::error_code();
219 llvm_unreachable("Invalid Type");
228 const_iterator
begin(StringRef path
, Style style
) {
231 i
.Component
= find_first_component(path
, style
);
237 const_iterator
end(StringRef path
) {
240 i
.Position
= path
.size();
244 const_iterator
&const_iterator::operator++() {
245 assert(Position
< Path
.size() && "Tried to increment past end!");
247 // Increment Position to past the current component
248 Position
+= Component
.size();
251 if (Position
== Path
.size()) {
252 Component
= StringRef();
256 // Both POSIX and Windows treat paths that begin with exactly two separators
258 bool was_net
= Component
.size() > 2 && is_separator(Component
[0], S
) &&
259 Component
[1] == Component
[0] && !is_separator(Component
[2], S
);
261 // Handle separators.
262 if (is_separator(Path
[Position
], S
)) {
266 (is_style_windows(S
) && Component
.ends_with(":"))) {
267 Component
= Path
.substr(Position
, 1);
271 // Skip extra separators.
272 while (Position
!= Path
.size() && is_separator(Path
[Position
], S
)) {
276 // Treat trailing '/' as a '.', unless it is the root dir.
277 if (Position
== Path
.size() && Component
!= "/") {
284 // Find next component.
285 size_t end_pos
= Path
.find_first_of(separators(S
), Position
);
286 Component
= Path
.slice(Position
, end_pos
);
291 bool const_iterator::operator==(const const_iterator
&RHS
) const {
292 return Path
.begin() == RHS
.Path
.begin() && Position
== RHS
.Position
;
295 ptrdiff_t const_iterator::operator-(const const_iterator
&RHS
) const {
296 return Position
- RHS
.Position
;
299 reverse_iterator
rbegin(StringRef Path
, Style style
) {
302 I
.Position
= Path
.size();
308 reverse_iterator
rend(StringRef Path
) {
311 I
.Component
= Path
.substr(0, 0);
316 reverse_iterator
&reverse_iterator::operator++() {
317 size_t root_dir_pos
= root_dir_start(Path
, S
);
319 // Skip separators unless it's the root directory.
320 size_t end_pos
= Position
;
321 while (end_pos
> 0 && (end_pos
- 1) != root_dir_pos
&&
322 is_separator(Path
[end_pos
- 1], S
))
325 // Treat trailing '/' as a '.', unless it is the root dir.
326 if (Position
== Path
.size() && !Path
.empty() &&
327 is_separator(Path
.back(), S
) &&
328 (root_dir_pos
== StringRef::npos
|| end_pos
- 1 > root_dir_pos
)) {
334 // Find next separator.
335 size_t start_pos
= filename_pos(Path
.substr(0, end_pos
), S
);
336 Component
= Path
.slice(start_pos
, end_pos
);
337 Position
= start_pos
;
341 bool reverse_iterator::operator==(const reverse_iterator
&RHS
) const {
342 return Path
.begin() == RHS
.Path
.begin() && Component
== RHS
.Component
&&
343 Position
== RHS
.Position
;
346 ptrdiff_t reverse_iterator::operator-(const reverse_iterator
&RHS
) const {
347 return Position
- RHS
.Position
;
350 StringRef
root_path(StringRef path
, Style style
) {
351 const_iterator b
= begin(path
, style
), pos
= b
, e
= end(path
);
354 b
->size() > 2 && is_separator((*b
)[0], style
) && (*b
)[1] == (*b
)[0];
355 bool has_drive
= is_style_windows(style
) && b
->ends_with(":");
357 if (has_net
|| has_drive
) {
358 if ((++pos
!= e
) && is_separator((*pos
)[0], style
)) {
359 // {C:/,//net/}, so get the first two components.
360 return path
.substr(0, b
->size() + pos
->size());
362 // just {C:,//net}, return the first component.
366 // POSIX style root directory.
367 if (is_separator((*b
)[0], style
)) {
375 StringRef
root_name(StringRef path
, Style style
) {
376 const_iterator b
= begin(path
, style
), e
= end(path
);
379 b
->size() > 2 && is_separator((*b
)[0], style
) && (*b
)[1] == (*b
)[0];
380 bool has_drive
= is_style_windows(style
) && b
->ends_with(":");
382 if (has_net
|| has_drive
) {
383 // just {C:,//net}, return the first component.
388 // No path or no name.
392 StringRef
root_directory(StringRef path
, Style style
) {
393 const_iterator b
= begin(path
, style
), pos
= b
, e
= end(path
);
396 b
->size() > 2 && is_separator((*b
)[0], style
) && (*b
)[1] == (*b
)[0];
397 bool has_drive
= is_style_windows(style
) && b
->ends_with(":");
399 if ((has_net
|| has_drive
) &&
400 // {C:,//net}, skip to the next component.
401 (++pos
!= e
) && is_separator((*pos
)[0], style
)) {
405 // POSIX style root directory.
406 if (!has_net
&& is_separator((*b
)[0], style
)) {
411 // No path or no root.
415 StringRef
relative_path(StringRef path
, Style style
) {
416 StringRef root
= root_path(path
, style
);
417 return path
.substr(root
.size());
420 void append(SmallVectorImpl
<char> &path
, Style style
, const Twine
&a
,
421 const Twine
&b
, const Twine
&c
, const Twine
&d
) {
422 SmallString
<32> a_storage
;
423 SmallString
<32> b_storage
;
424 SmallString
<32> c_storage
;
425 SmallString
<32> d_storage
;
427 SmallVector
<StringRef
, 4> components
;
428 if (!a
.isTriviallyEmpty()) components
.push_back(a
.toStringRef(a_storage
));
429 if (!b
.isTriviallyEmpty()) components
.push_back(b
.toStringRef(b_storage
));
430 if (!c
.isTriviallyEmpty()) components
.push_back(c
.toStringRef(c_storage
));
431 if (!d
.isTriviallyEmpty()) components
.push_back(d
.toStringRef(d_storage
));
433 for (auto &component
: components
) {
435 !path
.empty() && is_separator(path
[path
.size() - 1], style
);
437 // Strip separators from beginning of component.
438 size_t loc
= component
.find_first_not_of(separators(style
));
439 StringRef c
= component
.substr(loc
);
442 path
.append(c
.begin(), c
.end());
446 bool component_has_sep
=
447 !component
.empty() && is_separator(component
[0], style
);
448 if (!component_has_sep
&&
449 !(path
.empty() || has_root_name(component
, style
))) {
451 path
.push_back(preferred_separator(style
));
454 path
.append(component
.begin(), component
.end());
458 void append(SmallVectorImpl
<char> &path
, const Twine
&a
, const Twine
&b
,
459 const Twine
&c
, const Twine
&d
) {
460 append(path
, Style::native
, a
, b
, c
, d
);
463 void append(SmallVectorImpl
<char> &path
, const_iterator begin
,
464 const_iterator end
, Style style
) {
465 for (; begin
!= end
; ++begin
)
466 path::append(path
, style
, *begin
);
469 StringRef
parent_path(StringRef path
, Style style
) {
470 size_t end_pos
= parent_path_end(path
, style
);
471 if (end_pos
== StringRef::npos
)
473 return path
.substr(0, end_pos
);
476 void remove_filename(SmallVectorImpl
<char> &path
, Style style
) {
477 size_t end_pos
= parent_path_end(StringRef(path
.begin(), path
.size()), style
);
478 if (end_pos
!= StringRef::npos
)
479 path
.truncate(end_pos
);
482 void replace_extension(SmallVectorImpl
<char> &path
, const Twine
&extension
,
484 StringRef
p(path
.begin(), path
.size());
485 SmallString
<32> ext_storage
;
486 StringRef ext
= extension
.toStringRef(ext_storage
);
488 // Erase existing extension.
489 size_t pos
= p
.find_last_of('.');
490 if (pos
!= StringRef::npos
&& pos
>= filename_pos(p
, style
))
493 // Append '.' if needed.
494 if (ext
.size() > 0 && ext
[0] != '.')
498 path
.append(ext
.begin(), ext
.end());
501 static bool starts_with(StringRef Path
, StringRef Prefix
,
502 Style style
= Style::native
) {
503 // Windows prefix matching : case and separator insensitive
504 if (is_style_windows(style
)) {
505 if (Path
.size() < Prefix
.size())
507 for (size_t I
= 0, E
= Prefix
.size(); I
!= E
; ++I
) {
508 bool SepPath
= is_separator(Path
[I
], style
);
509 bool SepPrefix
= is_separator(Prefix
[I
], style
);
510 if (SepPath
!= SepPrefix
)
512 if (!SepPath
&& toLower(Path
[I
]) != toLower(Prefix
[I
]))
517 return Path
.starts_with(Prefix
);
520 bool replace_path_prefix(SmallVectorImpl
<char> &Path
, StringRef OldPrefix
,
521 StringRef NewPrefix
, Style style
) {
522 if (OldPrefix
.empty() && NewPrefix
.empty())
525 StringRef
OrigPath(Path
.begin(), Path
.size());
526 if (!starts_with(OrigPath
, OldPrefix
, style
))
529 // If prefixes have the same size we can simply copy the new one over.
530 if (OldPrefix
.size() == NewPrefix
.size()) {
531 llvm::copy(NewPrefix
, Path
.begin());
535 StringRef RelPath
= OrigPath
.substr(OldPrefix
.size());
536 SmallString
<256> NewPath
;
537 (Twine(NewPrefix
) + RelPath
).toVector(NewPath
);
542 void native(const Twine
&path
, SmallVectorImpl
<char> &result
, Style style
) {
543 assert((!path
.isSingleStringRef() ||
544 path
.getSingleStringRef().data() != result
.data()) &&
545 "path and result are not allowed to overlap!");
548 path
.toVector(result
);
549 native(result
, style
);
552 void native(SmallVectorImpl
<char> &Path
, Style style
) {
555 if (is_style_windows(style
)) {
556 for (char &Ch
: Path
)
557 if (is_separator(Ch
, style
))
558 Ch
= preferred_separator(style
);
559 if (Path
[0] == '~' && (Path
.size() == 1 || is_separator(Path
[1], style
))) {
560 SmallString
<128> PathHome
;
561 home_directory(PathHome
);
562 PathHome
.append(Path
.begin() + 1, Path
.end());
566 std::replace(Path
.begin(), Path
.end(), '\\', '/');
570 std::string
convert_to_slash(StringRef path
, Style style
) {
571 if (is_style_posix(style
))
572 return std::string(path
);
574 std::string s
= path
.str();
575 std::replace(s
.begin(), s
.end(), '\\', '/');
579 StringRef
filename(StringRef path
, Style style
) { return *rbegin(path
, style
); }
581 StringRef
stem(StringRef path
, Style style
) {
582 StringRef fname
= filename(path
, style
);
583 size_t pos
= fname
.find_last_of('.');
584 if (pos
== StringRef::npos
)
586 if ((fname
.size() == 1 && fname
== ".") ||
587 (fname
.size() == 2 && fname
== ".."))
589 return fname
.substr(0, pos
);
592 StringRef
extension(StringRef path
, Style style
) {
593 StringRef fname
= filename(path
, style
);
594 size_t pos
= fname
.find_last_of('.');
595 if (pos
== StringRef::npos
)
597 if ((fname
.size() == 1 && fname
== ".") ||
598 (fname
.size() == 2 && fname
== ".."))
600 return fname
.substr(pos
);
603 bool is_separator(char value
, Style style
) {
606 if (is_style_windows(style
))
607 return value
== '\\';
611 StringRef
get_separator(Style style
) {
612 if (real_style(style
) == Style::windows
)
617 bool has_root_name(const Twine
&path
, Style style
) {
618 SmallString
<128> path_storage
;
619 StringRef p
= path
.toStringRef(path_storage
);
621 return !root_name(p
, style
).empty();
624 bool has_root_directory(const Twine
&path
, Style style
) {
625 SmallString
<128> path_storage
;
626 StringRef p
= path
.toStringRef(path_storage
);
628 return !root_directory(p
, style
).empty();
631 bool has_root_path(const Twine
&path
, Style style
) {
632 SmallString
<128> path_storage
;
633 StringRef p
= path
.toStringRef(path_storage
);
635 return !root_path(p
, style
).empty();
638 bool has_relative_path(const Twine
&path
, Style style
) {
639 SmallString
<128> path_storage
;
640 StringRef p
= path
.toStringRef(path_storage
);
642 return !relative_path(p
, style
).empty();
645 bool has_filename(const Twine
&path
, Style style
) {
646 SmallString
<128> path_storage
;
647 StringRef p
= path
.toStringRef(path_storage
);
649 return !filename(p
, style
).empty();
652 bool has_parent_path(const Twine
&path
, Style style
) {
653 SmallString
<128> path_storage
;
654 StringRef p
= path
.toStringRef(path_storage
);
656 return !parent_path(p
, style
).empty();
659 bool has_stem(const Twine
&path
, Style style
) {
660 SmallString
<128> path_storage
;
661 StringRef p
= path
.toStringRef(path_storage
);
663 return !stem(p
, style
).empty();
666 bool has_extension(const Twine
&path
, Style style
) {
667 SmallString
<128> path_storage
;
668 StringRef p
= path
.toStringRef(path_storage
);
670 return !extension(p
, style
).empty();
673 bool is_absolute(const Twine
&path
, Style style
) {
674 SmallString
<128> path_storage
;
675 StringRef p
= path
.toStringRef(path_storage
);
677 bool rootDir
= has_root_directory(p
, style
);
678 bool rootName
= is_style_posix(style
) || has_root_name(p
, style
);
680 return rootDir
&& rootName
;
683 bool is_absolute_gnu(const Twine
&path
, Style style
) {
684 SmallString
<128> path_storage
;
685 StringRef p
= path
.toStringRef(path_storage
);
687 // Handle '/' which is absolute for both Windows and POSIX systems.
688 // Handle '\\' on Windows.
689 if (!p
.empty() && is_separator(p
.front(), style
))
692 if (is_style_windows(style
)) {
693 // Handle drive letter pattern (a character followed by ':') on Windows.
694 if (p
.size() >= 2 && (p
[0] && p
[1] == ':'))
701 bool is_relative(const Twine
&path
, Style style
) {
702 return !is_absolute(path
, style
);
705 StringRef
remove_leading_dotslash(StringRef Path
, Style style
) {
706 // Remove leading "./" (or ".//" or "././" etc.)
707 while (Path
.size() > 2 && Path
[0] == '.' && is_separator(Path
[1], style
)) {
708 Path
= Path
.substr(2);
709 while (Path
.size() > 0 && is_separator(Path
[0], style
))
710 Path
= Path
.substr(1);
715 // Remove path traversal components ("." and "..") when possible, and
716 // canonicalize slashes.
717 bool remove_dots(SmallVectorImpl
<char> &the_path
, bool remove_dot_dot
,
719 style
= real_style(style
);
720 StringRef
remaining(the_path
.data(), the_path
.size());
721 bool needs_change
= false;
722 SmallVector
<StringRef
, 16> components
;
724 // Consume the root path, if present.
725 StringRef root
= path::root_path(remaining
, style
);
726 bool absolute
= !root
.empty();
728 remaining
= remaining
.drop_front(root
.size());
730 // Loop over path components manually. This makes it easier to detect
731 // non-preferred slashes and double separators that must be canonicalized.
732 while (!remaining
.empty()) {
733 size_t next_slash
= remaining
.find_first_of(separators(style
));
734 if (next_slash
== StringRef::npos
)
735 next_slash
= remaining
.size();
736 StringRef component
= remaining
.take_front(next_slash
);
737 remaining
= remaining
.drop_front(next_slash
);
739 // Eat the slash, and check if it is the preferred separator.
740 if (!remaining
.empty()) {
741 needs_change
|= remaining
.front() != preferred_separator(style
);
742 remaining
= remaining
.drop_front();
743 // The path needs to be rewritten if it has a trailing slash.
744 // FIXME: This is emergent behavior that could be removed.
745 needs_change
|= remaining
.empty();
748 // Check for path traversal components or double separators.
749 if (component
.empty() || component
== ".") {
751 } else if (remove_dot_dot
&& component
== "..") {
753 // Do not allow ".." to remove the root component. If this is the
754 // beginning of a relative path, keep the ".." component.
755 if (!components
.empty() && components
.back() != "..") {
756 components
.pop_back();
757 } else if (!absolute
) {
758 components
.push_back(component
);
761 components
.push_back(component
);
765 SmallString
<256> buffer
= root
;
766 // "root" could be "/", which may need to be translated into "\".
767 make_preferred(buffer
, style
);
768 needs_change
|= root
!= buffer
;
770 // Avoid rewriting the path unless we have to.
774 if (!components
.empty()) {
775 buffer
+= components
[0];
776 for (StringRef C
: ArrayRef(components
).drop_front()) {
777 buffer
+= preferred_separator(style
);
781 the_path
.swap(buffer
);
785 } // end namespace path
789 std::error_code
getUniqueID(const Twine Path
, UniqueID
&Result
) {
791 std::error_code EC
= status(Path
, Status
);
794 Result
= Status
.getUniqueID();
795 return std::error_code();
798 void createUniquePath(const Twine
&Model
, SmallVectorImpl
<char> &ResultPath
,
800 SmallString
<128> ModelStorage
;
801 Model
.toVector(ModelStorage
);
804 // Make model absolute by prepending a temp directory if it's not already.
805 if (!sys::path::is_absolute(Twine(ModelStorage
))) {
806 SmallString
<128> TDir
;
807 sys::path::system_temp_directory(true, TDir
);
808 sys::path::append(TDir
, Twine(ModelStorage
));
809 ModelStorage
.swap(TDir
);
813 ResultPath
= ModelStorage
;
814 ResultPath
.push_back(0);
815 ResultPath
.pop_back();
817 // Replace '%' with random chars.
818 for (unsigned i
= 0, e
= ModelStorage
.size(); i
!= e
; ++i
) {
819 if (ModelStorage
[i
] == '%')
820 ResultPath
[i
] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
824 std::error_code
createUniqueFile(const Twine
&Model
, int &ResultFd
,
825 SmallVectorImpl
<char> &ResultPath
,
826 OpenFlags Flags
, unsigned Mode
) {
827 return createUniqueEntity(Model
, ResultFd
, ResultPath
, false, FS_File
, Flags
,
831 std::error_code
createUniqueFile(const Twine
&Model
,
832 SmallVectorImpl
<char> &ResultPath
,
835 auto EC
= createUniqueFile(Model
, FD
, ResultPath
, OF_None
, Mode
);
838 // FD is only needed to avoid race conditions. Close it right away.
843 static std::error_code
844 createTemporaryFile(const Twine
&Model
, int &ResultFD
,
845 llvm::SmallVectorImpl
<char> &ResultPath
, FSEntity Type
,
846 sys::fs::OpenFlags Flags
= sys::fs::OF_None
) {
847 SmallString
<128> Storage
;
848 StringRef P
= Model
.toNullTerminatedStringRef(Storage
);
849 assert(P
.find_first_of(separators(Style::native
)) == StringRef::npos
&&
850 "Model must be a simple filename.");
851 // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
852 return createUniqueEntity(P
.begin(), ResultFD
, ResultPath
, true, Type
, Flags
,
853 owner_read
| owner_write
);
856 static std::error_code
857 createTemporaryFile(const Twine
&Prefix
, StringRef Suffix
, int &ResultFD
,
858 llvm::SmallVectorImpl
<char> &ResultPath
, FSEntity Type
,
859 sys::fs::OpenFlags Flags
= sys::fs::OF_None
) {
860 const char *Middle
= Suffix
.empty() ? "-%%%%%%" : "-%%%%%%.";
861 return createTemporaryFile(Prefix
+ Middle
+ Suffix
, ResultFD
, ResultPath
,
865 std::error_code
createTemporaryFile(const Twine
&Prefix
, StringRef Suffix
,
867 SmallVectorImpl
<char> &ResultPath
,
868 sys::fs::OpenFlags Flags
) {
869 return createTemporaryFile(Prefix
, Suffix
, ResultFD
, ResultPath
, FS_File
,
873 std::error_code
createTemporaryFile(const Twine
&Prefix
, StringRef Suffix
,
874 SmallVectorImpl
<char> &ResultPath
,
875 sys::fs::OpenFlags Flags
) {
877 auto EC
= createTemporaryFile(Prefix
, Suffix
, FD
, ResultPath
, Flags
);
880 // FD is only needed to avoid race conditions. Close it right away.
885 // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
886 // for consistency. We should try using mkdtemp.
887 std::error_code
createUniqueDirectory(const Twine
&Prefix
,
888 SmallVectorImpl
<char> &ResultPath
) {
890 return createUniqueEntity(Prefix
+ "-%%%%%%", Dummy
, ResultPath
, true,
895 getPotentiallyUniqueFileName(const Twine
&Model
,
896 SmallVectorImpl
<char> &ResultPath
) {
898 return createUniqueEntity(Model
, Dummy
, ResultPath
, false, FS_Name
);
902 getPotentiallyUniqueTempFileName(const Twine
&Prefix
, StringRef Suffix
,
903 SmallVectorImpl
<char> &ResultPath
) {
905 return createTemporaryFile(Prefix
, Suffix
, Dummy
, ResultPath
, FS_Name
);
908 void make_absolute(const Twine
¤t_directory
,
909 SmallVectorImpl
<char> &path
) {
910 StringRef
p(path
.data(), path
.size());
912 bool rootDirectory
= path::has_root_directory(p
);
913 bool rootName
= path::has_root_name(p
);
916 if ((rootName
|| is_style_posix(Style::native
)) && rootDirectory
)
919 // All of the following conditions will need the current directory.
920 SmallString
<128> current_dir
;
921 current_directory
.toVector(current_dir
);
923 // Relative path. Prepend the current directory.
924 if (!rootName
&& !rootDirectory
) {
925 // Append path to the current directory.
926 path::append(current_dir
, p
);
927 // Set path to the result.
928 path
.swap(current_dir
);
932 if (!rootName
&& rootDirectory
) {
933 StringRef cdrn
= path::root_name(current_dir
);
934 SmallString
<128> curDirRootName(cdrn
.begin(), cdrn
.end());
935 path::append(curDirRootName
, p
);
936 // Set path to the result.
937 path
.swap(curDirRootName
);
941 if (rootName
&& !rootDirectory
) {
942 StringRef pRootName
= path::root_name(p
);
943 StringRef bRootDirectory
= path::root_directory(current_dir
);
944 StringRef bRelativePath
= path::relative_path(current_dir
);
945 StringRef pRelativePath
= path::relative_path(p
);
947 SmallString
<128> res
;
948 path::append(res
, pRootName
, bRootDirectory
, bRelativePath
, pRelativePath
);
953 llvm_unreachable("All rootName and rootDirectory combinations should have "
957 std::error_code
make_absolute(SmallVectorImpl
<char> &path
) {
958 if (path::is_absolute(path
))
961 SmallString
<128> current_dir
;
962 if (std::error_code ec
= current_path(current_dir
))
965 make_absolute(current_dir
, path
);
969 std::error_code
create_directories(const Twine
&Path
, bool IgnoreExisting
,
971 SmallString
<128> PathStorage
;
972 StringRef P
= Path
.toStringRef(PathStorage
);
974 // Be optimistic and try to create the directory
975 std::error_code EC
= create_directory(P
, IgnoreExisting
, Perms
);
976 // If we succeeded, or had any error other than the parent not existing, just
978 if (EC
!= errc::no_such_file_or_directory
)
981 // We failed because of a no_such_file_or_directory, try to create the
983 StringRef Parent
= path::parent_path(P
);
987 if ((EC
= create_directories(Parent
, IgnoreExisting
, Perms
)))
990 return create_directory(P
, IgnoreExisting
, Perms
);
993 static std::error_code
copy_file_internal(int ReadFD
, int WriteFD
) {
994 const size_t BufSize
= 4096;
995 char *Buf
= new char[BufSize
];
996 int BytesRead
= 0, BytesWritten
= 0;
998 BytesRead
= read(ReadFD
, Buf
, BufSize
);
1002 BytesWritten
= write(WriteFD
, Buf
, BytesRead
);
1003 if (BytesWritten
< 0)
1005 BytesRead
-= BytesWritten
;
1007 if (BytesWritten
< 0)
1012 if (BytesRead
< 0 || BytesWritten
< 0)
1013 return std::error_code(errno
, std::generic_category());
1014 return std::error_code();
1018 std::error_code
copy_file(const Twine
&From
, const Twine
&To
) {
1019 int ReadFD
, WriteFD
;
1020 if (std::error_code EC
= openFileForRead(From
, ReadFD
, OF_None
))
1022 if (std::error_code EC
=
1023 openFileForWrite(To
, WriteFD
, CD_CreateAlways
, OF_None
)) {
1028 std::error_code EC
= copy_file_internal(ReadFD
, WriteFD
);
1037 std::error_code
copy_file(const Twine
&From
, int ToFD
) {
1039 if (std::error_code EC
= openFileForRead(From
, ReadFD
, OF_None
))
1042 std::error_code EC
= copy_file_internal(ReadFD
, ToFD
);
1049 ErrorOr
<MD5::MD5Result
> md5_contents(int FD
) {
1052 constexpr size_t BufSize
= 4096;
1053 std::vector
<uint8_t> Buf(BufSize
);
1056 BytesRead
= read(FD
, Buf
.data(), BufSize
);
1059 Hash
.update(ArrayRef(Buf
.data(), BytesRead
));
1063 return std::error_code(errno
, std::generic_category());
1064 MD5::MD5Result Result
;
1069 ErrorOr
<MD5::MD5Result
> md5_contents(const Twine
&Path
) {
1071 if (auto EC
= openFileForRead(Path
, FD
, OF_None
))
1074 auto Result
= md5_contents(FD
);
1079 bool exists(const basic_file_status
&status
) {
1080 return status_known(status
) && status
.type() != file_type::file_not_found
;
1083 bool status_known(const basic_file_status
&s
) {
1084 return s
.type() != file_type::status_error
;
1087 file_type
get_file_type(const Twine
&Path
, bool Follow
) {
1089 if (status(Path
, st
, Follow
))
1090 return file_type::status_error
;
1094 bool is_directory(const basic_file_status
&status
) {
1095 return status
.type() == file_type::directory_file
;
1098 std::error_code
is_directory(const Twine
&path
, bool &result
) {
1100 if (std::error_code ec
= status(path
, st
))
1102 result
= is_directory(st
);
1103 return std::error_code();
1106 bool is_regular_file(const basic_file_status
&status
) {
1107 return status
.type() == file_type::regular_file
;
1110 std::error_code
is_regular_file(const Twine
&path
, bool &result
) {
1112 if (std::error_code ec
= status(path
, st
))
1114 result
= is_regular_file(st
);
1115 return std::error_code();
1118 bool is_symlink_file(const basic_file_status
&status
) {
1119 return status
.type() == file_type::symlink_file
;
1122 std::error_code
is_symlink_file(const Twine
&path
, bool &result
) {
1124 if (std::error_code ec
= status(path
, st
, false))
1126 result
= is_symlink_file(st
);
1127 return std::error_code();
1130 bool is_other(const basic_file_status
&status
) {
1131 return exists(status
) &&
1132 !is_regular_file(status
) &&
1133 !is_directory(status
);
1136 std::error_code
is_other(const Twine
&Path
, bool &Result
) {
1137 file_status FileStatus
;
1138 if (std::error_code EC
= status(Path
, FileStatus
))
1140 Result
= is_other(FileStatus
);
1141 return std::error_code();
1144 void directory_entry::replace_filename(const Twine
&Filename
, file_type Type
,
1145 basic_file_status Status
) {
1146 SmallString
<128> PathStr
= path::parent_path(Path
);
1147 path::append(PathStr
, Filename
);
1148 this->Path
= std::string(PathStr
);
1150 this->Status
= Status
;
1153 ErrorOr
<perms
> getPermissions(const Twine
&Path
) {
1155 if (std::error_code EC
= status(Path
, Status
))
1158 return Status
.permissions();
1161 size_t mapped_file_region::size() const {
1162 assert(Mapping
&& "Mapping failed but used anyway!");
1166 char *mapped_file_region::data() const {
1167 assert(Mapping
&& "Mapping failed but used anyway!");
1168 return reinterpret_cast<char *>(Mapping
);
1171 const char *mapped_file_region::const_data() const {
1172 assert(Mapping
&& "Mapping failed but used anyway!");
1173 return reinterpret_cast<const char *>(Mapping
);
1176 Error
readNativeFileToEOF(file_t FileHandle
, SmallVectorImpl
<char> &Buffer
,
1177 ssize_t ChunkSize
) {
1178 // Install a handler to truncate the buffer to the correct size on exit.
1179 size_t Size
= Buffer
.size();
1180 auto TruncateOnExit
= make_scope_exit([&]() { Buffer
.truncate(Size
); });
1182 // Read into Buffer until we hit EOF.
1184 Buffer
.resize_for_overwrite(Size
+ ChunkSize
);
1185 Expected
<size_t> ReadBytes
= readNativeFile(
1186 FileHandle
, MutableArrayRef(Buffer
.begin() + Size
, ChunkSize
));
1188 return ReadBytes
.takeError();
1189 if (*ReadBytes
== 0)
1190 return Error::success();
1195 } // end namespace fs
1196 } // end namespace sys
1197 } // end namespace llvm
1199 // Include the truly platform-specific parts.
1200 #if defined(LLVM_ON_UNIX)
1201 #include "Unix/Path.inc"
1204 #include "Windows/Path.inc"
1211 TempFile::TempFile(StringRef Name
, int FD
)
1212 : TmpName(std::string(Name
)), FD(FD
) {}
1213 TempFile::TempFile(TempFile
&&Other
) { *this = std::move(Other
); }
1214 TempFile
&TempFile::operator=(TempFile
&&Other
) {
1215 TmpName
= std::move(Other
.TmpName
);
1220 RemoveOnClose
= Other
.RemoveOnClose
;
1221 Other
.RemoveOnClose
= false;
1226 TempFile::~TempFile() { assert(Done
); }
1228 Error
TempFile::discard() {
1230 if (FD
!= -1 && close(FD
) == -1) {
1231 std::error_code EC
= std::error_code(errno
, std::generic_category());
1232 return errorCodeToError(EC
);
1237 // On Windows, closing will remove the file, if we set the delete
1238 // disposition. If not, remove it manually.
1239 bool Remove
= RemoveOnClose
;
1241 // Always try to remove the file.
1244 std::error_code RemoveEC
;
1245 if (Remove
&& !TmpName
.empty()) {
1246 RemoveEC
= fs::remove(TmpName
);
1247 sys::DontRemoveFileOnSignal(TmpName
);
1253 return errorCodeToError(RemoveEC
);
1256 Error
TempFile::keep(const Twine
&Name
) {
1259 // Always try to close and rename.
1261 // If we can't cancel the delete don't rename.
1262 auto H
= reinterpret_cast<HANDLE
>(_get_osfhandle(FD
));
1263 std::error_code RenameEC
=
1264 RemoveOnClose
? std::error_code() : setDeleteDisposition(H
, false);
1265 bool ShouldDelete
= false;
1267 RenameEC
= rename_handle(H
, Name
);
1268 // If rename failed because it's cross-device, copy instead
1270 std::error_code(ERROR_NOT_SAME_DEVICE
, std::system_category())) {
1271 RenameEC
= copy_file(TmpName
, Name
);
1272 ShouldDelete
= true;
1276 // If we can't rename or copy, discard the temporary file.
1278 ShouldDelete
= true;
1281 setDeleteDisposition(H
, true);
1286 std::error_code RenameEC
= fs::rename(TmpName
, Name
);
1288 // If we can't rename, try to copy to work around cross-device link issues.
1289 RenameEC
= sys::fs::copy_file(TmpName
, Name
);
1290 // If we can't rename or copy, discard the temporary file.
1295 sys::DontRemoveFileOnSignal(TmpName
);
1300 if (close(FD
) == -1) {
1301 std::error_code
EC(errno
, std::generic_category());
1302 return errorCodeToError(EC
);
1306 return errorCodeToError(RenameEC
);
1309 Error
TempFile::keep() {
1314 auto H
= reinterpret_cast<HANDLE
>(_get_osfhandle(FD
));
1315 if (std::error_code EC
= setDeleteDisposition(H
, false))
1316 return errorCodeToError(EC
);
1318 sys::DontRemoveFileOnSignal(TmpName
);
1322 if (close(FD
) == -1) {
1323 std::error_code
EC(errno
, std::generic_category());
1324 return errorCodeToError(EC
);
1328 return Error::success();
1331 Expected
<TempFile
> TempFile::create(const Twine
&Model
, unsigned Mode
,
1332 OpenFlags ExtraFlags
) {
1334 SmallString
<128> ResultPath
;
1335 if (std::error_code EC
=
1336 createUniqueFile(Model
, FD
, ResultPath
, OF_Delete
| ExtraFlags
, Mode
))
1337 return errorCodeToError(EC
);
1339 TempFile
Ret(ResultPath
, FD
);
1341 auto H
= reinterpret_cast<HANDLE
>(_get_osfhandle(FD
));
1342 bool SetSignalHandler
= false;
1343 if (std::error_code EC
= setDeleteDisposition(H
, true)) {
1344 Ret
.RemoveOnClose
= true;
1345 SetSignalHandler
= true;
1348 bool SetSignalHandler
= true;
1350 if (SetSignalHandler
&& sys::RemoveFileOnSignal(ResultPath
)) {
1351 // Make sure we delete the file when RemoveFileOnSignal fails.
1352 consumeError(Ret
.discard());
1353 std::error_code
EC(errc::operation_not_permitted
);
1354 return errorCodeToError(EC
);
1356 return std::move(Ret
);