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