1 //===-- Path.cpp - Implement OS Path Concept ------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
26 #if !defined(_MSC_VER) && !defined(__MINGW32__)
33 using namespace llvm::support::endian
;
36 using llvm::StringRef
;
37 using llvm::sys::path::is_separator
;
38 using llvm::sys::path::Style
;
40 inline Style
real_style(Style style
) {
42 return (style
== Style::posix
) ? Style::posix
: Style::windows
;
44 return (style
== Style::windows
) ? Style::windows
: Style::posix
;
48 inline const char *separators(Style style
) {
49 if (real_style(style
) == Style::windows
)
54 inline char preferred_separator(Style style
) {
55 if (real_style(style
) == Style::windows
)
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.
65 // * {file,directory}name
70 if (real_style(style
) == Style::windows
) {
72 if (path
.size() >= 2 &&
73 std::isalpha(static_cast<unsigned char>(path
[0])) && path
[1] == ':')
74 return path
.substr(0, 2);
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
);
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
)))
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
) {
117 if (real_style(style
) == Style::windows
) {
118 if (str
.size() > 2 && str
[1] == ':' && is_separator(str
[2], style
))
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);
129 if (str
.size() > 0 && is_separator(str
[0], style
))
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
))
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.
160 } // end unnamed namespace
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
);
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
;
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.
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
] == '%')
203 "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
206 // Try to open + create the file.
209 EC
= sys::fs::openFileForReadWrite(Twine(ResultPath
.begin()), ResultFD
,
210 sys::fs::CD_CreateNew
, Flags
, Mode
);
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
)
219 return std::error_code();
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();
232 EC
= sys::fs::create_directory(ResultPath
.begin(), false);
234 if (EC
== errc::file_exists
)
238 return std::error_code();
241 llvm_unreachable("Invalid Type");
250 const_iterator
begin(StringRef path
, Style style
) {
253 i
.Component
= find_first_component(path
, style
);
259 const_iterator
end(StringRef path
) {
262 i
.Position
= path
.size();
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();
273 if (Position
== Path
.size()) {
274 Component
= StringRef();
278 // Both POSIX and Windows treat paths that begin with exactly two separators
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
)) {
288 (real_style(S
) == Style::windows
&& Component
.endswith(":"))) {
289 Component
= Path
.substr(Position
, 1);
293 // Skip extra separators.
294 while (Position
!= Path
.size() && is_separator(Path
[Position
], S
)) {
298 // Treat trailing '/' as a '.', unless it is the root dir.
299 if (Position
== Path
.size() && Component
!= "/") {
306 // Find next component.
307 size_t end_pos
= Path
.find_first_of(separators(S
), Position
);
308 Component
= Path
.slice(Position
, end_pos
);
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
) {
324 I
.Position
= Path
.size();
329 reverse_iterator
rend(StringRef Path
) {
332 I
.Component
= Path
.substr(0, 0);
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
))
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
)) {
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
;
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
);
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());
383 // just {C:,//net}, return the first component.
388 // POSIX style root directory.
389 if (is_separator((*b
)[0], style
)) {
397 StringRef
root_name(StringRef path
, Style style
) {
398 const_iterator b
= begin(path
, style
), e
= end(path
);
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.
410 // No path or no name.
414 StringRef
root_directory(StringRef path
, Style style
) {
415 const_iterator b
= begin(path
, style
), pos
= b
, e
= end(path
);
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
)) {
427 // POSIX style root directory.
428 if (!has_net
&& is_separator((*b
)[0], style
)) {
433 // No path or no root.
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
) {
457 !path
.empty() && is_separator(path
[path
.size() - 1], style
);
459 // Strip separators from beginning of component.
460 size_t loc
= component
.find_first_not_of(separators(style
));
461 StringRef c
= component
.substr(loc
);
464 path
.append(c
.begin(), c
.end());
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
))) {
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
)
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
,
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
))
516 // Append '.' if needed.
517 if (ext
.size() > 0 && ext
[0] != '.')
521 path
.append(ext
.begin(), ext
.end());
524 void replace_path_prefix(SmallVectorImpl
<char> &Path
,
525 const StringRef
&OldPrefix
, const StringRef
&NewPrefix
,
527 if (OldPrefix
.empty() && NewPrefix
.empty())
530 StringRef
OrigPath(Path
.begin(), Path
.size());
531 if (!OrigPath
.startswith(OldPrefix
))
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());
540 StringRef RelPath
= OrigPath
.substr(OldPrefix
.size());
541 SmallString
<256> NewPath
;
542 path::append(NewPath
, style
, NewPrefix
);
543 path::append(NewPath
, style
, RelPath
);
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!");
553 path
.toVector(result
);
554 native(result
, style
);
557 void native(SmallVectorImpl
<char> &Path
, Style style
) {
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());
569 for (auto PI
= Path
.begin(), PE
= Path
.end(); PI
< PE
; ++PI
) {
572 if (PN
< PE
&& *PN
== '\\')
573 ++PI
; // increment once, the for loop will move over the escaped slash
581 std::string
convert_to_slash(StringRef path
, Style style
) {
582 if (real_style(style
) != Style::windows
)
585 std::string s
= path
.str();
586 std::replace(s
.begin(), s
.end(), '\\', '/');
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
)
598 if ((fname
.size() == 1 && fname
== ".") ||
599 (fname
.size() == 2 && fname
== ".."))
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
)
611 if ((fname
.size() == 1 && fname
== ".") ||
612 (fname
.size() == 2 && fname
== ".."))
615 return fname
.substr(pos
);
618 bool is_separator(char value
, Style style
) {
621 if (real_style(style
) == Style::windows
)
622 return value
== '\\';
626 StringRef
get_separator(Style style
) {
627 if (real_style(style
) == Style::windows
)
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
);
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);
713 static SmallString
<256> remove_dots(StringRef path
, bool remove_dot_dot
,
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
);
720 llvm::make_range(path::begin(rel
, style
), path::end(rel
))) {
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();
729 if (path::is_absolute(path
, style
))
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
);
741 bool remove_dots(SmallVectorImpl
<char> &path
, bool remove_dot_dot
,
743 StringRef
p(path
.data(), path
.size());
745 SmallString
<256> result
= remove_dots(p
, remove_dot_dot
, style
);
753 } // end namespace path
757 std::error_code
getUniqueID(const Twine Path
, UniqueID
&Result
) {
759 std::error_code EC
= status(Path
, Status
);
762 Result
= Status
.getUniqueID();
763 return std::error_code();
766 std::error_code
createUniqueFile(const Twine
&Model
, int &ResultFd
,
767 SmallVectorImpl
<char> &ResultPath
,
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
,
779 std::error_code
createUniqueFile(const Twine
&Model
,
780 SmallVectorImpl
<char> &ResultPath
,
783 auto EC
= createUniqueFile(Model
, FD
, ResultPath
, Mode
);
786 // FD is only needed to avoid race conditions. Close it right away.
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
,
811 std::error_code
createTemporaryFile(const Twine
&Prefix
, StringRef Suffix
,
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
) {
820 auto EC
= createTemporaryFile(Prefix
, Suffix
, FD
, ResultPath
);
823 // FD is only needed to avoid race conditions. Close it right away.
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
) {
834 return createUniqueEntity(Prefix
+ "-%%%%%%", Dummy
, ResultPath
, true, 0,
839 getPotentiallyUniqueFileName(const Twine
&Model
,
840 SmallVectorImpl
<char> &ResultPath
) {
842 return createUniqueEntity(Model
, Dummy
, ResultPath
, false, 0, FS_Name
);
846 getPotentiallyUniqueTempFileName(const Twine
&Prefix
, StringRef Suffix
,
847 SmallVectorImpl
<char> &ResultPath
) {
849 return createTemporaryFile(Prefix
, Suffix
, Dummy
, ResultPath
, FS_Name
);
852 static std::error_code
make_absolute(const Twine
¤t_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
);
859 (real_style(Style::native
) != Style::windows
) || path::has_root_name(p
);
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
))
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
);
899 return std::error_code();
902 llvm_unreachable("All rootName and rootDirectory combinations should have "
906 std::error_code
make_absolute(const Twine
¤t_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
,
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
924 if (EC
!= errc::no_such_file_or_directory
)
927 // We failed because of a no_such_file_or_directory, try to create the
929 StringRef Parent
= path::parent_path(P
);
933 if ((EC
= create_directories(Parent
, IgnoreExisting
, Perms
)))
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;
944 BytesRead
= read(ReadFD
, Buf
, BufSize
);
948 BytesWritten
= write(WriteFD
, Buf
, BytesRead
);
949 if (BytesWritten
< 0)
951 BytesRead
-= BytesWritten
;
953 if (BytesWritten
< 0)
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
) {
965 if (std::error_code EC
= openFileForRead(From
, ReadFD
, OF_None
))
967 if (std::error_code EC
=
968 openFileForWrite(To
, WriteFD
, CD_CreateAlways
, OF_None
)) {
973 std::error_code EC
= copy_file_internal(ReadFD
, WriteFD
);
981 std::error_code
copy_file(const Twine
&From
, int ToFD
) {
983 if (std::error_code EC
= openFileForRead(From
, ReadFD
, OF_None
))
986 std::error_code EC
= copy_file_internal(ReadFD
, ToFD
);
993 ErrorOr
<MD5::MD5Result
> md5_contents(int FD
) {
996 constexpr size_t BufSize
= 4096;
997 std::vector
<uint8_t> Buf(BufSize
);
1000 BytesRead
= read(FD
, Buf
.data(), BufSize
);
1003 Hash
.update(makeArrayRef(Buf
.data(), BytesRead
));
1007 return std::error_code(errno
, std::generic_category());
1008 MD5::MD5Result Result
;
1013 ErrorOr
<MD5::MD5Result
> md5_contents(const Twine
&Path
) {
1015 if (auto EC
= openFileForRead(Path
, FD
, OF_None
))
1018 auto Result
= md5_contents(FD
);
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
) {
1033 if (status(Path
, st
, Follow
))
1034 return file_type::status_error
;
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
) {
1044 if (std::error_code ec
= status(path
, st
))
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
) {
1056 if (std::error_code ec
= status(path
, st
))
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
) {
1068 if (std::error_code ec
= status(path
, st
, false))
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
))
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();
1094 this->Status
= Status
;
1097 ErrorOr
<perms
> getPermissions(const Twine
&Path
) {
1099 if (std::error_code EC
= status(Path
, Status
))
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"
1114 #include "Windows/Path.inc"
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
);
1129 TempFile::~TempFile() { assert(Done
); }
1131 Error
TempFile::discard() {
1133 std::error_code RemoveEC
;
1134 // On windows closing will remove the file.
1136 // Always try to close and remove.
1137 if (!TmpName
.empty()) {
1138 RemoveEC
= fs::remove(TmpName
);
1139 sys::DontRemoveFileOnSignal(TmpName
);
1146 if (FD
!= -1 && close(FD
) == -1) {
1147 std::error_code EC
= std::error_code(errno
, std::generic_category());
1148 return errorCodeToError(EC
);
1152 return errorCodeToError(RemoveEC
);
1155 Error
TempFile::keep(const Twine
&Name
) {
1158 // Always try to close and rename.
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);
1164 RenameEC
= rename_fd(FD
, Name
);
1165 // If rename failed because it's cross-device, copy instead
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.
1175 setDeleteDisposition(H
, true);
1177 std::error_code RenameEC
= fs::rename(TmpName
, Name
);
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.
1185 sys::DontRemoveFileOnSignal(TmpName
);
1191 if (close(FD
) == -1) {
1192 std::error_code
EC(errno
, std::generic_category());
1193 return errorCodeToError(EC
);
1197 return errorCodeToError(RenameEC
);
1200 Error
TempFile::keep() {
1205 auto H
= reinterpret_cast<HANDLE
>(_get_osfhandle(FD
));
1206 if (std::error_code EC
= setDeleteDisposition(H
, false))
1207 return errorCodeToError(EC
);
1209 sys::DontRemoveFileOnSignal(TmpName
);
1214 if (close(FD
) == -1) {
1215 std::error_code
EC(errno
, std::generic_category());
1216 return errorCodeToError(EC
);
1220 return Error::success();
1223 Expected
<TempFile
> TempFile::create(const Twine
&Model
, unsigned Mode
) {
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
);
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
);
1239 return std::move(Ret
);
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
);
1254 } // end namespace path
1255 } // end namsspace sys
1256 } // end namespace llvm