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 (is_style_windows(style)) { 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 (is_style_windows(style)) { 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 (is_style_windows(style)) { 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 (is_style_windows(S) && 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 = is_style_windows(style) && 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 = is_style_windows(style) && 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 = is_style_windows(style) && 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 (is_style_windows(style)) { 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 (is_style_windows(style)) { 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 (is_style_posix(style)) 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 (is_style_windows(style)) 599 return value == '\\'; 600 return false; 601 } 602 603 StringRef get_separator(Style style) { 604 if (is_style_windows(style)) 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 = is_style_posix(style) || has_root_name(p, style); 671 672 return rootDir && rootName; 673 } 674 675 bool is_absolute_gnu(const Twine &path, Style style) { 676 SmallString<128> path_storage; 677 StringRef p = path.toStringRef(path_storage); 678 679 // Handle '/' which is absolute for both Windows and POSIX systems. 680 // Handle '\\' on Windows. 681 if (!p.empty() && is_separator(p.front(), style)) 682 return true; 683 684 if (is_style_windows(style)) { 685 // Handle drive letter pattern (a character followed by ':') on Windows. 686 if (p.size() >= 2 && (p[0] && p[1] == ':')) 687 return true; 688 } 689 690 return false; 691 } 692 693 bool is_relative(const Twine &path, Style style) { 694 return !is_absolute(path, style); 695 } 696 697 StringRef remove_leading_dotslash(StringRef Path, Style style) { 698 // Remove leading "./" (or ".//" or "././" etc.) 699 while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) { 700 Path = Path.substr(2); 701 while (Path.size() > 0 && is_separator(Path[0], style)) 702 Path = Path.substr(1); 703 } 704 return Path; 705 } 706 707 // Remove path traversal components ("." and "..") when possible, and 708 // canonicalize slashes. 709 bool remove_dots(SmallVectorImpl<char> &the_path, bool remove_dot_dot, 710 Style style) { 711 style = real_style(style); 712 StringRef remaining(the_path.data(), the_path.size()); 713 bool needs_change = false; 714 SmallVector<StringRef, 16> components; 715 716 // Consume the root path, if present. 717 StringRef root = path::root_path(remaining, style); 718 bool absolute = !root.empty(); 719 if (absolute) 720 remaining = remaining.drop_front(root.size()); 721 722 // Loop over path components manually. This makes it easier to detect 723 // non-preferred slashes and double separators that must be canonicalized. 724 while (!remaining.empty()) { 725 size_t next_slash = remaining.find_first_of(separators(style)); 726 if (next_slash == StringRef::npos) 727 next_slash = remaining.size(); 728 StringRef component = remaining.take_front(next_slash); 729 remaining = remaining.drop_front(next_slash); 730 731 // Eat the slash, and check if it is the preferred separator. 732 if (!remaining.empty()) { 733 needs_change |= remaining.front() != preferred_separator(style); 734 remaining = remaining.drop_front(); 735 // The path needs to be rewritten if it has a trailing slash. 736 // FIXME: This is emergent behavior that could be removed. 737 needs_change |= remaining.empty(); 738 } 739 740 // Check for path traversal components or double separators. 741 if (component.empty() || component == ".") { 742 needs_change = true; 743 } else if (remove_dot_dot && component == "..") { 744 needs_change = true; 745 // Do not allow ".." to remove the root component. If this is the 746 // beginning of a relative path, keep the ".." component. 747 if (!components.empty() && components.back() != "..") { 748 components.pop_back(); 749 } else if (!absolute) { 750 components.push_back(component); 751 } 752 } else { 753 components.push_back(component); 754 } 755 } 756 757 // Avoid rewriting the path unless we have to. 758 if (!needs_change) 759 return false; 760 761 SmallString<256> buffer = root; 762 if (!components.empty()) { 763 buffer += components[0]; 764 for (StringRef C : makeArrayRef(components).drop_front()) { 765 buffer += preferred_separator(style); 766 buffer += C; 767 } 768 } 769 the_path.swap(buffer); 770 return true; 771 } 772 773 } // end namespace path 774 775 namespace fs { 776 777 std::error_code getUniqueID(const Twine Path, UniqueID &Result) { 778 file_status Status; 779 std::error_code EC = status(Path, Status); 780 if (EC) 781 return EC; 782 Result = Status.getUniqueID(); 783 return std::error_code(); 784 } 785 786 void createUniquePath(const Twine &Model, SmallVectorImpl<char> &ResultPath, 787 bool MakeAbsolute) { 788 SmallString<128> ModelStorage; 789 Model.toVector(ModelStorage); 790 791 if (MakeAbsolute) { 792 // Make model absolute by prepending a temp directory if it's not already. 793 if (!sys::path::is_absolute(Twine(ModelStorage))) { 794 SmallString<128> TDir; 795 sys::path::system_temp_directory(true, TDir); 796 sys::path::append(TDir, Twine(ModelStorage)); 797 ModelStorage.swap(TDir); 798 } 799 } 800 801 ResultPath = ModelStorage; 802 ResultPath.push_back(0); 803 ResultPath.pop_back(); 804 805 // Replace '%' with random chars. 806 for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) { 807 if (ModelStorage[i] == '%') 808 ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; 809 } 810 } 811 812 std::error_code createUniqueFile(const Twine &Model, int &ResultFd, 813 SmallVectorImpl<char> &ResultPath, 814 OpenFlags Flags, unsigned Mode) { 815 return createUniqueEntity(Model, ResultFd, ResultPath, false, FS_File, Flags, 816 Mode); 817 } 818 819 std::error_code createUniqueFile(const Twine &Model, 820 SmallVectorImpl<char> &ResultPath, 821 unsigned Mode) { 822 int FD; 823 auto EC = createUniqueFile(Model, FD, ResultPath, OF_None, Mode); 824 if (EC) 825 return EC; 826 // FD is only needed to avoid race conditions. Close it right away. 827 close(FD); 828 return EC; 829 } 830 831 static std::error_code 832 createTemporaryFile(const Twine &Model, int &ResultFD, 833 llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type, 834 sys::fs::OpenFlags Flags = sys::fs::OF_None) { 835 SmallString<128> Storage; 836 StringRef P = Model.toNullTerminatedStringRef(Storage); 837 assert(P.find_first_of(separators(Style::native)) == StringRef::npos && 838 "Model must be a simple filename."); 839 // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage. 840 return createUniqueEntity(P.begin(), ResultFD, ResultPath, true, Type, Flags, 841 owner_read | owner_write); 842 } 843 844 static std::error_code 845 createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, 846 llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type, 847 sys::fs::OpenFlags Flags = sys::fs::OF_None) { 848 const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%."; 849 return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath, 850 Type, Flags); 851 } 852 853 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 854 int &ResultFD, 855 SmallVectorImpl<char> &ResultPath, 856 sys::fs::OpenFlags Flags) { 857 return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File, 858 Flags); 859 } 860 861 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 862 SmallVectorImpl<char> &ResultPath, 863 sys::fs::OpenFlags Flags) { 864 int FD; 865 auto EC = createTemporaryFile(Prefix, Suffix, FD, ResultPath, Flags); 866 if (EC) 867 return EC; 868 // FD is only needed to avoid race conditions. Close it right away. 869 close(FD); 870 return EC; 871 } 872 873 // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly 874 // for consistency. We should try using mkdtemp. 875 std::error_code createUniqueDirectory(const Twine &Prefix, 876 SmallVectorImpl<char> &ResultPath) { 877 int Dummy; 878 return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, true, 879 FS_Dir); 880 } 881 882 std::error_code 883 getPotentiallyUniqueFileName(const Twine &Model, 884 SmallVectorImpl<char> &ResultPath) { 885 int Dummy; 886 return createUniqueEntity(Model, Dummy, ResultPath, false, FS_Name); 887 } 888 889 std::error_code 890 getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix, 891 SmallVectorImpl<char> &ResultPath) { 892 int Dummy; 893 return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name); 894 } 895 896 void make_absolute(const Twine ¤t_directory, 897 SmallVectorImpl<char> &path) { 898 StringRef p(path.data(), path.size()); 899 900 bool rootDirectory = path::has_root_directory(p); 901 bool rootName = path::has_root_name(p); 902 903 // Already absolute. 904 if ((rootName || is_style_posix(Style::native)) && rootDirectory) 905 return; 906 907 // All of the following conditions will need the current directory. 908 SmallString<128> current_dir; 909 current_directory.toVector(current_dir); 910 911 // Relative path. Prepend the current directory. 912 if (!rootName && !rootDirectory) { 913 // Append path to the current directory. 914 path::append(current_dir, p); 915 // Set path to the result. 916 path.swap(current_dir); 917 return; 918 } 919 920 if (!rootName && rootDirectory) { 921 StringRef cdrn = path::root_name(current_dir); 922 SmallString<128> curDirRootName(cdrn.begin(), cdrn.end()); 923 path::append(curDirRootName, p); 924 // Set path to the result. 925 path.swap(curDirRootName); 926 return; 927 } 928 929 if (rootName && !rootDirectory) { 930 StringRef pRootName = path::root_name(p); 931 StringRef bRootDirectory = path::root_directory(current_dir); 932 StringRef bRelativePath = path::relative_path(current_dir); 933 StringRef pRelativePath = path::relative_path(p); 934 935 SmallString<128> res; 936 path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath); 937 path.swap(res); 938 return; 939 } 940 941 llvm_unreachable("All rootName and rootDirectory combinations should have " 942 "occurred above!"); 943 } 944 945 std::error_code make_absolute(SmallVectorImpl<char> &path) { 946 if (path::is_absolute(path)) 947 return {}; 948 949 SmallString<128> current_dir; 950 if (std::error_code ec = current_path(current_dir)) 951 return ec; 952 953 make_absolute(current_dir, path); 954 return {}; 955 } 956 957 std::error_code create_directories(const Twine &Path, bool IgnoreExisting, 958 perms Perms) { 959 SmallString<128> PathStorage; 960 StringRef P = Path.toStringRef(PathStorage); 961 962 // Be optimistic and try to create the directory 963 std::error_code EC = create_directory(P, IgnoreExisting, Perms); 964 // If we succeeded, or had any error other than the parent not existing, just 965 // return it. 966 if (EC != errc::no_such_file_or_directory) 967 return EC; 968 969 // We failed because of a no_such_file_or_directory, try to create the 970 // parent. 971 StringRef Parent = path::parent_path(P); 972 if (Parent.empty()) 973 return EC; 974 975 if ((EC = create_directories(Parent, IgnoreExisting, Perms))) 976 return EC; 977 978 return create_directory(P, IgnoreExisting, Perms); 979 } 980 981 static std::error_code copy_file_internal(int ReadFD, int WriteFD) { 982 const size_t BufSize = 4096; 983 char *Buf = new char[BufSize]; 984 int BytesRead = 0, BytesWritten = 0; 985 for (;;) { 986 BytesRead = read(ReadFD, Buf, BufSize); 987 if (BytesRead <= 0) 988 break; 989 while (BytesRead) { 990 BytesWritten = write(WriteFD, Buf, BytesRead); 991 if (BytesWritten < 0) 992 break; 993 BytesRead -= BytesWritten; 994 } 995 if (BytesWritten < 0) 996 break; 997 } 998 delete[] Buf; 999 1000 if (BytesRead < 0 || BytesWritten < 0) 1001 return std::error_code(errno, std::generic_category()); 1002 return std::error_code(); 1003 } 1004 1005 #ifndef __APPLE__ 1006 std::error_code copy_file(const Twine &From, const Twine &To) { 1007 int ReadFD, WriteFD; 1008 if (std::error_code EC = openFileForRead(From, ReadFD, OF_None)) 1009 return EC; 1010 if (std::error_code EC = 1011 openFileForWrite(To, WriteFD, CD_CreateAlways, OF_None)) { 1012 close(ReadFD); 1013 return EC; 1014 } 1015 1016 std::error_code EC = copy_file_internal(ReadFD, WriteFD); 1017 1018 close(ReadFD); 1019 close(WriteFD); 1020 1021 return EC; 1022 } 1023 #endif 1024 1025 std::error_code copy_file(const Twine &From, int ToFD) { 1026 int ReadFD; 1027 if (std::error_code EC = openFileForRead(From, ReadFD, OF_None)) 1028 return EC; 1029 1030 std::error_code EC = copy_file_internal(ReadFD, ToFD); 1031 1032 close(ReadFD); 1033 1034 return EC; 1035 } 1036 1037 ErrorOr<MD5::MD5Result> md5_contents(int FD) { 1038 MD5 Hash; 1039 1040 constexpr size_t BufSize = 4096; 1041 std::vector<uint8_t> Buf(BufSize); 1042 int BytesRead = 0; 1043 for (;;) { 1044 BytesRead = read(FD, Buf.data(), BufSize); 1045 if (BytesRead <= 0) 1046 break; 1047 Hash.update(makeArrayRef(Buf.data(), BytesRead)); 1048 } 1049 1050 if (BytesRead < 0) 1051 return std::error_code(errno, std::generic_category()); 1052 MD5::MD5Result Result; 1053 Hash.final(Result); 1054 return Result; 1055 } 1056 1057 ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) { 1058 int FD; 1059 if (auto EC = openFileForRead(Path, FD, OF_None)) 1060 return EC; 1061 1062 auto Result = md5_contents(FD); 1063 close(FD); 1064 return Result; 1065 } 1066 1067 bool exists(const basic_file_status &status) { 1068 return status_known(status) && status.type() != file_type::file_not_found; 1069 } 1070 1071 bool status_known(const basic_file_status &s) { 1072 return s.type() != file_type::status_error; 1073 } 1074 1075 file_type get_file_type(const Twine &Path, bool Follow) { 1076 file_status st; 1077 if (status(Path, st, Follow)) 1078 return file_type::status_error; 1079 return st.type(); 1080 } 1081 1082 bool is_directory(const basic_file_status &status) { 1083 return status.type() == file_type::directory_file; 1084 } 1085 1086 std::error_code is_directory(const Twine &path, bool &result) { 1087 file_status st; 1088 if (std::error_code ec = status(path, st)) 1089 return ec; 1090 result = is_directory(st); 1091 return std::error_code(); 1092 } 1093 1094 bool is_regular_file(const basic_file_status &status) { 1095 return status.type() == file_type::regular_file; 1096 } 1097 1098 std::error_code is_regular_file(const Twine &path, bool &result) { 1099 file_status st; 1100 if (std::error_code ec = status(path, st)) 1101 return ec; 1102 result = is_regular_file(st); 1103 return std::error_code(); 1104 } 1105 1106 bool is_symlink_file(const basic_file_status &status) { 1107 return status.type() == file_type::symlink_file; 1108 } 1109 1110 std::error_code is_symlink_file(const Twine &path, bool &result) { 1111 file_status st; 1112 if (std::error_code ec = status(path, st, false)) 1113 return ec; 1114 result = is_symlink_file(st); 1115 return std::error_code(); 1116 } 1117 1118 bool is_other(const basic_file_status &status) { 1119 return exists(status) && 1120 !is_regular_file(status) && 1121 !is_directory(status); 1122 } 1123 1124 std::error_code is_other(const Twine &Path, bool &Result) { 1125 file_status FileStatus; 1126 if (std::error_code EC = status(Path, FileStatus)) 1127 return EC; 1128 Result = is_other(FileStatus); 1129 return std::error_code(); 1130 } 1131 1132 void directory_entry::replace_filename(const Twine &Filename, file_type Type, 1133 basic_file_status Status) { 1134 SmallString<128> PathStr = path::parent_path(Path); 1135 path::append(PathStr, Filename); 1136 this->Path = std::string(PathStr.str()); 1137 this->Type = Type; 1138 this->Status = Status; 1139 } 1140 1141 ErrorOr<perms> getPermissions(const Twine &Path) { 1142 file_status Status; 1143 if (std::error_code EC = status(Path, Status)) 1144 return EC; 1145 1146 return Status.permissions(); 1147 } 1148 1149 size_t mapped_file_region::size() const { 1150 assert(Mapping && "Mapping failed but used anyway!"); 1151 return Size; 1152 } 1153 1154 char *mapped_file_region::data() const { 1155 assert(Mapping && "Mapping failed but used anyway!"); 1156 return reinterpret_cast<char *>(Mapping); 1157 } 1158 1159 const char *mapped_file_region::const_data() const { 1160 assert(Mapping && "Mapping failed but used anyway!"); 1161 return reinterpret_cast<const char *>(Mapping); 1162 } 1163 1164 } // end namespace fs 1165 } // end namespace sys 1166 } // end namespace llvm 1167 1168 // Include the truly platform-specific parts. 1169 #if defined(LLVM_ON_UNIX) 1170 #include "Unix/Path.inc" 1171 #endif 1172 #if defined(_WIN32) 1173 #include "Windows/Path.inc" 1174 #endif 1175 1176 namespace llvm { 1177 namespace sys { 1178 namespace fs { 1179 TempFile::TempFile(StringRef Name, int FD) 1180 : TmpName(std::string(Name)), FD(FD) {} 1181 TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); } 1182 TempFile &TempFile::operator=(TempFile &&Other) { 1183 TmpName = std::move(Other.TmpName); 1184 FD = Other.FD; 1185 Other.Done = true; 1186 Other.FD = -1; 1187 #ifdef _WIN32 1188 RemoveOnClose = Other.RemoveOnClose; 1189 Other.RemoveOnClose = false; 1190 #endif 1191 return *this; 1192 } 1193 1194 TempFile::~TempFile() { assert(Done); } 1195 1196 Error TempFile::discard() { 1197 Done = true; 1198 if (FD != -1 && close(FD) == -1) { 1199 std::error_code EC = std::error_code(errno, std::generic_category()); 1200 return errorCodeToError(EC); 1201 } 1202 FD = -1; 1203 1204 #ifdef _WIN32 1205 // On Windows, closing will remove the file, if we set the delete 1206 // disposition. If not, remove it manually. 1207 bool Remove = RemoveOnClose; 1208 #else 1209 // Always try to remove the file. 1210 bool Remove = true; 1211 #endif 1212 std::error_code RemoveEC; 1213 if (Remove && !TmpName.empty()) { 1214 RemoveEC = fs::remove(TmpName); 1215 #ifndef _WIN32 1216 sys::DontRemoveFileOnSignal(TmpName); 1217 #endif 1218 if (!RemoveEC) 1219 TmpName = ""; 1220 } else { 1221 TmpName = ""; 1222 } 1223 return errorCodeToError(RemoveEC); 1224 } 1225 1226 Error TempFile::keep(const Twine &Name) { 1227 assert(!Done); 1228 Done = true; 1229 // Always try to close and rename. 1230 #ifdef _WIN32 1231 // If we can't cancel the delete don't rename. 1232 auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); 1233 std::error_code RenameEC = setDeleteDisposition(H, false); 1234 bool ShouldDelete = false; 1235 if (!RenameEC) { 1236 RenameEC = rename_handle(H, Name); 1237 // If rename failed because it's cross-device, copy instead 1238 if (RenameEC == 1239 std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) { 1240 RenameEC = copy_file(TmpName, Name); 1241 ShouldDelete = true; 1242 } 1243 } 1244 1245 // If we can't rename or copy, discard the temporary file. 1246 if (RenameEC) 1247 ShouldDelete = true; 1248 if (ShouldDelete) { 1249 if (!RemoveOnClose) 1250 setDeleteDisposition(H, true); 1251 else 1252 remove(TmpName); 1253 } 1254 #else 1255 std::error_code RenameEC = fs::rename(TmpName, Name); 1256 if (RenameEC) { 1257 // If we can't rename, try to copy to work around cross-device link issues. 1258 RenameEC = sys::fs::copy_file(TmpName, Name); 1259 // If we can't rename or copy, discard the temporary file. 1260 if (RenameEC) 1261 remove(TmpName); 1262 } 1263 sys::DontRemoveFileOnSignal(TmpName); 1264 #endif 1265 1266 if (!RenameEC) 1267 TmpName = ""; 1268 1269 if (close(FD) == -1) { 1270 std::error_code EC(errno, std::generic_category()); 1271 return errorCodeToError(EC); 1272 } 1273 FD = -1; 1274 1275 return errorCodeToError(RenameEC); 1276 } 1277 1278 Error TempFile::keep() { 1279 assert(!Done); 1280 Done = true; 1281 1282 #ifdef _WIN32 1283 auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); 1284 if (std::error_code EC = setDeleteDisposition(H, false)) 1285 return errorCodeToError(EC); 1286 #else 1287 sys::DontRemoveFileOnSignal(TmpName); 1288 #endif 1289 1290 TmpName = ""; 1291 1292 if (close(FD) == -1) { 1293 std::error_code EC(errno, std::generic_category()); 1294 return errorCodeToError(EC); 1295 } 1296 FD = -1; 1297 1298 return Error::success(); 1299 } 1300 1301 Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode, 1302 OpenFlags ExtraFlags) { 1303 int FD; 1304 SmallString<128> ResultPath; 1305 if (std::error_code EC = 1306 createUniqueFile(Model, FD, ResultPath, OF_Delete | ExtraFlags, Mode)) 1307 return errorCodeToError(EC); 1308 1309 TempFile Ret(ResultPath, FD); 1310 #ifdef _WIN32 1311 auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); 1312 if (std::error_code EC = setDeleteDisposition(H, true)) { 1313 Ret.RemoveOnClose = true; 1314 } 1315 #else 1316 if (sys::RemoveFileOnSignal(ResultPath)) { 1317 // Make sure we delete the file when RemoveFileOnSignal fails. 1318 consumeError(Ret.discard()); 1319 std::error_code EC(errc::operation_not_permitted); 1320 return errorCodeToError(EC); 1321 } 1322 #endif 1323 return std::move(Ret); 1324 } 1325 } // namespace fs 1326 1327 } // namespace sys 1328 } // namespace llvm 1329