1//===-- Path.cpp - Implement OS Path Concept ------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the operating system Path API. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/Support/Errc.h" 15#include "llvm/Support/Path.h" 16#include "llvm/Support/Endian.h" 17#include "llvm/Support/ErrorHandling.h" 18#include "llvm/Support/FileSystem.h" 19#include "llvm/Support/Process.h" 20#include <cctype> 21#include <cstdio> 22#include <cstring> 23#include <fcntl.h> 24 25#if !defined(_MSC_VER) && !defined(__MINGW32__) 26#include <unistd.h> 27#else 28#include <io.h> 29#endif 30 31using namespace llvm; 32 33namespace { 34 using llvm::StringRef; 35 using llvm::sys::path::is_separator; 36 37#ifdef LLVM_ON_WIN32 38 const char *separators = "\\/"; 39 const char preferred_separator = '\\'; 40#else 41 const char separators = '/'; 42 const char preferred_separator = '/'; 43#endif 44 45 StringRef find_first_component(StringRef path) { 46 // Look for this first component in the following order. 47 // * empty (in this case we return an empty string) 48 // * either C: or {//,\\}net. 49 // * {/,\} 50 // * {.,..} 51 // * {file,directory}name 52 53 if (path.empty()) 54 return path; 55 56#ifdef LLVM_ON_WIN32 57 // C: 58 if (path.size() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) && 59 path[1] == ':') 60 return path.substr(0, 2); 61#endif 62 63 // //net 64 if ((path.size() > 2) && 65 is_separator(path[0]) && 66 path[0] == path[1] && 67 !is_separator(path[2])) { 68 // Find the next directory separator. 69 size_t end = path.find_first_of(separators, 2); 70 return path.substr(0, end); 71 } 72 73 // {/,\} 74 if (is_separator(path[0])) 75 return path.substr(0, 1); 76 77 if (path.startswith("..")) 78 return path.substr(0, 2); 79 80 if (path[0] == '.') 81 return path.substr(0, 1); 82 83 // * {file,directory}name 84 size_t end = path.find_first_of(separators); 85 return path.substr(0, end); 86 } 87 88 size_t filename_pos(StringRef str) { 89 if (str.size() == 2 && 90 is_separator(str[0]) && 91 str[0] == str[1]) 92 return 0; 93 94 if (str.size() > 0 && is_separator(str[str.size() - 1])) 95 return str.size() - 1; 96 97 size_t pos = str.find_last_of(separators, str.size() - 1); 98 99#ifdef LLVM_ON_WIN32 100 if (pos == StringRef::npos) 101 pos = str.find_last_of(':', str.size() - 2); 102#endif 103 104 if (pos == StringRef::npos || 105 (pos == 1 && is_separator(str[0]))) 106 return 0; 107 108 return pos + 1; 109 } 110 111 size_t root_dir_start(StringRef str) { 112 // case "c:/" 113#ifdef LLVM_ON_WIN32 114 if (str.size() > 2 && 115 str[1] == ':' && 116 is_separator(str[2])) 117 return 2; 118#endif 119 120 // case "//" 121 if (str.size() == 2 && 122 is_separator(str[0]) && 123 str[0] == str[1]) 124 return StringRef::npos; 125 126 // case "//net" 127 if (str.size() > 3 && 128 is_separator(str[0]) && 129 str[0] == str[1] && 130 !is_separator(str[2])) { 131 return str.find_first_of(separators, 2); 132 } 133 134 // case "/" 135 if (str.size() > 0 && is_separator(str[0])) 136 return 0; 137 138 return StringRef::npos; 139 } 140 141 size_t parent_path_end(StringRef path) { 142 size_t end_pos = filename_pos(path); 143 144 bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]); 145 146 // Skip separators except for root dir. 147 size_t root_dir_pos = root_dir_start(path.substr(0, end_pos)); 148 149 while(end_pos > 0 && 150 (end_pos - 1) != root_dir_pos && 151 is_separator(path[end_pos - 1])) 152 --end_pos; 153 154 if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) 155 return StringRef::npos; 156 157 return end_pos; 158 } 159} // end unnamed namespace 160 161enum FSEntity { 162 FS_Dir, 163 FS_File, 164 FS_Name 165}; 166 167// Implemented in Unix/Path.inc and Windows/Path.inc. 168static std::error_code TempDir(SmallVectorImpl<char> &result); 169 170static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, 171 SmallVectorImpl<char> &ResultPath, 172 bool MakeAbsolute, unsigned Mode, 173 FSEntity Type) { 174 SmallString<128> ModelStorage; 175 Model.toVector(ModelStorage); 176 177 if (MakeAbsolute) { 178 // Make model absolute by prepending a temp directory if it's not already. 179 if (!sys::path::is_absolute(Twine(ModelStorage))) { 180 SmallString<128> TDir; 181 if (std::error_code EC = TempDir(TDir)) 182 return EC; 183 sys::path::append(TDir, Twine(ModelStorage)); 184 ModelStorage.swap(TDir); 185 } 186 } 187 188 // From here on, DO NOT modify model. It may be needed if the randomly chosen 189 // path already exists. 190 ResultPath = ModelStorage; 191 // Null terminate. 192 ResultPath.push_back(0); 193 ResultPath.pop_back(); 194 195retry_random_path: 196 // Replace '%' with random chars. 197 for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) { 198 if (ModelStorage[i] == '%') 199 ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; 200 } 201 202 // Try to open + create the file. 203 switch (Type) { 204 case FS_File: { 205 if (std::error_code EC = 206 sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD, 207 sys::fs::F_RW | sys::fs::F_Excl, Mode)) { 208 if (EC == errc::file_exists) 209 goto retry_random_path; 210 return EC; 211 } 212 213 return std::error_code(); 214 } 215 216 case FS_Name: { 217 bool Exists; 218 std::error_code EC = sys::fs::exists(ResultPath.begin(), Exists); 219 if (EC) 220 return EC; 221 if (Exists) 222 goto retry_random_path; 223 return std::error_code(); 224 } 225 226 case FS_Dir: { 227 if (std::error_code EC = 228 sys::fs::create_directory(ResultPath.begin(), false)) { 229 if (EC == errc::file_exists) 230 goto retry_random_path; 231 return EC; 232 } 233 return std::error_code(); 234 } 235 } 236 llvm_unreachable("Invalid Type"); 237} 238 239namespace llvm { 240namespace sys { 241namespace path { 242 243const_iterator begin(StringRef path) { 244 const_iterator i; 245 i.Path = path; 246 i.Component = find_first_component(path); 247 i.Position = 0; 248 return i; 249} 250 251const_iterator end(StringRef path) { 252 const_iterator i; 253 i.Path = path; 254 i.Position = path.size(); 255 return i; 256} 257 258const_iterator &const_iterator::operator++() { 259 assert(Position < Path.size() && "Tried to increment past end!"); 260 261 // Increment Position to past the current component 262 Position += Component.size(); 263 264 // Check for end. 265 if (Position == Path.size()) { 266 Component = StringRef(); 267 return *this; 268 } 269 270 // Both POSIX and Windows treat paths that begin with exactly two separators 271 // specially. 272 bool was_net = Component.size() > 2 && 273 is_separator(Component[0]) && 274 Component[1] == Component[0] && 275 !is_separator(Component[2]); 276 277 // Handle separators. 278 if (is_separator(Path[Position])) { 279 // Root dir. 280 if (was_net 281#ifdef LLVM_ON_WIN32 282 // c:/ 283 || Component.endswith(":") 284#endif 285 ) { 286 Component = Path.substr(Position, 1); 287 return *this; 288 } 289 290 // Skip extra separators. 291 while (Position != Path.size() && 292 is_separator(Path[Position])) { 293 ++Position; 294 } 295 296 // Treat trailing '/' as a '.'. 297 if (Position == Path.size()) { 298 --Position; 299 Component = "."; 300 return *this; 301 } 302 } 303 304 // Find next component. 305 size_t end_pos = Path.find_first_of(separators, Position); 306 Component = Path.slice(Position, end_pos); 307 308 return *this; 309} 310 311const_iterator &const_iterator::operator--() { 312 // If we're at the end and the previous char was a '/', return '.' unless 313 // we are the root path. 314 size_t root_dir_pos = root_dir_start(Path); 315 if (Position == Path.size() && 316 Path.size() > root_dir_pos + 1 && 317 is_separator(Path[Position - 1])) { 318 --Position; 319 Component = "."; 320 return *this; 321 } 322 323 // Skip separators unless it's the root directory. 324 size_t end_pos = Position; 325 326 while(end_pos > 0 && 327 (end_pos - 1) != root_dir_pos && 328 is_separator(Path[end_pos - 1])) 329 --end_pos; 330 331 // Find next separator. 332 size_t start_pos = filename_pos(Path.substr(0, end_pos)); 333 Component = Path.slice(start_pos, end_pos); 334 Position = start_pos; 335 return *this; 336} 337 338bool const_iterator::operator==(const const_iterator &RHS) const { 339 return Path.begin() == RHS.Path.begin() && 340 Position == RHS.Position; 341} 342 343bool const_iterator::operator!=(const const_iterator &RHS) const { 344 return !(*this == RHS); 345} 346 347ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { 348 return Position - RHS.Position; 349} 350 351const StringRef root_path(StringRef path) { 352 const_iterator b = begin(path), 353 pos = b, 354 e = end(path); 355 if (b != e) { 356 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 357 bool has_drive = 358#ifdef LLVM_ON_WIN32 359 b->endswith(":"); 360#else 361 false; 362#endif 363 364 if (has_net || has_drive) { 365 if ((++pos != e) && is_separator((*pos)[0])) { 366 // {C:/,//net/}, so get the first two components. 367 return path.substr(0, b->size() + pos->size()); 368 } else { 369 // just {C:,//net}, return the first component. 370 return *b; 371 } 372 } 373 374 // POSIX style root directory. 375 if (is_separator((*b)[0])) { 376 return *b; 377 } 378 } 379 380 return StringRef(); 381} 382 383const StringRef root_name(StringRef path) { 384 const_iterator b = begin(path), 385 e = end(path); 386 if (b != e) { 387 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 388 bool has_drive = 389#ifdef LLVM_ON_WIN32 390 b->endswith(":"); 391#else 392 false; 393#endif 394 395 if (has_net || has_drive) { 396 // just {C:,//net}, return the first component. 397 return *b; 398 } 399 } 400 401 // No path or no name. 402 return StringRef(); 403} 404 405const StringRef root_directory(StringRef path) { 406 const_iterator b = begin(path), 407 pos = b, 408 e = end(path); 409 if (b != e) { 410 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 411 bool has_drive = 412#ifdef LLVM_ON_WIN32 413 b->endswith(":"); 414#else 415 false; 416#endif 417 418 if ((has_net || has_drive) && 419 // {C:,//net}, skip to the next component. 420 (++pos != e) && is_separator((*pos)[0])) { 421 return *pos; 422 } 423 424 // POSIX style root directory. 425 if (!has_net && is_separator((*b)[0])) { 426 return *b; 427 } 428 } 429 430 // No path or no root. 431 return StringRef(); 432} 433 434const StringRef relative_path(StringRef path) { 435 StringRef root = root_path(path); 436 return path.substr(root.size()); 437} 438 439void append(SmallVectorImpl<char> &path, const Twine &a, 440 const Twine &b, 441 const Twine &c, 442 const Twine &d) { 443 SmallString<32> a_storage; 444 SmallString<32> b_storage; 445 SmallString<32> c_storage; 446 SmallString<32> d_storage; 447 448 SmallVector<StringRef, 4> components; 449 if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage)); 450 if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage)); 451 if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage)); 452 if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage)); 453 454 for (SmallVectorImpl<StringRef>::const_iterator i = components.begin(), 455 e = components.end(); 456 i != e; ++i) { 457 bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]); 458 bool component_has_sep = !i->empty() && is_separator((*i)[0]); 459 bool is_root_name = has_root_name(*i); 460 461 if (path_has_sep) { 462 // Strip separators from beginning of component. 463 size_t loc = i->find_first_not_of(separators); 464 StringRef c = i->substr(loc); 465 466 // Append it. 467 path.append(c.begin(), c.end()); 468 continue; 469 } 470 471 if (!component_has_sep && !(path.empty() || is_root_name)) { 472 // Add a separator. 473 path.push_back(preferred_separator); 474 } 475 476 path.append(i->begin(), i->end()); 477 } 478} 479 480void append(SmallVectorImpl<char> &path, 481 const_iterator begin, const_iterator end) { 482 for (; begin != end; ++begin) 483 path::append(path, *begin); 484} 485 486const StringRef parent_path(StringRef path) { 487 size_t end_pos = parent_path_end(path); 488 if (end_pos == StringRef::npos) 489 return StringRef(); 490 else 491 return path.substr(0, end_pos); 492} 493 494void remove_filename(SmallVectorImpl<char> &path) { 495 size_t end_pos = parent_path_end(StringRef(path.begin(), path.size())); 496 if (end_pos != StringRef::npos) 497 path.set_size(end_pos); 498} 499 500void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) { 501 StringRef p(path.begin(), path.size()); 502 SmallString<32> ext_storage; 503 StringRef ext = extension.toStringRef(ext_storage); 504 505 // Erase existing extension. 506 size_t pos = p.find_last_of('.'); 507 if (pos != StringRef::npos && pos >= filename_pos(p)) 508 path.set_size(pos); 509 510 // Append '.' if needed. 511 if (ext.size() > 0 && ext[0] != '.') 512 path.push_back('.'); 513 514 // Append extension. 515 path.append(ext.begin(), ext.end()); 516} 517 518void native(const Twine &path, SmallVectorImpl<char> &result) { 519 assert((!path.isSingleStringRef() || 520 path.getSingleStringRef().data() != result.data()) && 521 "path and result are not allowed to overlap!"); 522 // Clear result. 523 result.clear(); 524 path.toVector(result); 525 native(result); 526} 527 528void native(SmallVectorImpl<char> &path) { 529#ifdef LLVM_ON_WIN32 530 std::replace(path.begin(), path.end(), '/', '\\'); 531#endif 532} 533 534const StringRef filename(StringRef path) { 535 return *(--end(path)); 536} 537 538const StringRef stem(StringRef path) { 539 StringRef fname = filename(path); 540 size_t pos = fname.find_last_of('.'); 541 if (pos == StringRef::npos) 542 return fname; 543 else 544 if ((fname.size() == 1 && fname == ".") || 545 (fname.size() == 2 && fname == "..")) 546 return fname; 547 else 548 return fname.substr(0, pos); 549} 550 551const StringRef extension(StringRef path) { 552 StringRef fname = filename(path); 553 size_t pos = fname.find_last_of('.'); 554 if (pos == StringRef::npos) 555 return StringRef(); 556 else 557 if ((fname.size() == 1 && fname == ".") || 558 (fname.size() == 2 && fname == "..")) 559 return StringRef(); 560 else 561 return fname.substr(pos); 562} 563 564bool is_separator(char value) { 565 switch(value) { 566#ifdef LLVM_ON_WIN32 567 case '\\': // fall through 568#endif 569 case '/': return true; 570 default: return false; 571 } 572} 573 574static const char preferred_separator_string[] = { preferred_separator, '\0' }; 575 576const StringRef get_separator() { 577 return preferred_separator_string; 578} 579 580void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) { 581 result.clear(); 582 583#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) 584 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. 585 // macros defined in <unistd.h> on darwin >= 9 586 int ConfName = erasedOnReboot? _CS_DARWIN_USER_TEMP_DIR 587 : _CS_DARWIN_USER_CACHE_DIR; 588 size_t ConfLen = confstr(ConfName, nullptr, 0); 589 if (ConfLen > 0) { 590 do { 591 result.resize(ConfLen); 592 ConfLen = confstr(ConfName, result.data(), result.size()); 593 } while (ConfLen > 0 && ConfLen != result.size()); 594 595 if (ConfLen > 0) { 596 assert(result.back() == 0); 597 result.pop_back(); 598 return; 599 } 600 601 result.clear(); 602 } 603#endif 604 605 // Check whether the temporary directory is specified by an environment 606 // variable. 607 const char *EnvironmentVariable; 608#ifdef LLVM_ON_WIN32 609 EnvironmentVariable = "TEMP"; 610#else 611 EnvironmentVariable = "TMPDIR"; 612#endif 613 if (char *RequestedDir = getenv(EnvironmentVariable)) { 614 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 615 return; 616 } 617 618 // Fall back to a system default. 619 const char *DefaultResult; 620#ifdef LLVM_ON_WIN32 621 (void)erasedOnReboot; 622 DefaultResult = "C:\\TEMP"; 623#else 624 if (erasedOnReboot) 625 DefaultResult = "/tmp"; 626 else 627 DefaultResult = "/var/tmp"; 628#endif 629 result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); 630} 631 632bool has_root_name(const Twine &path) { 633 SmallString<128> path_storage; 634 StringRef p = path.toStringRef(path_storage); 635 636 return !root_name(p).empty(); 637} 638 639bool has_root_directory(const Twine &path) { 640 SmallString<128> path_storage; 641 StringRef p = path.toStringRef(path_storage); 642 643 return !root_directory(p).empty(); 644} 645 646bool has_root_path(const Twine &path) { 647 SmallString<128> path_storage; 648 StringRef p = path.toStringRef(path_storage); 649 650 return !root_path(p).empty(); 651} 652 653bool has_relative_path(const Twine &path) { 654 SmallString<128> path_storage; 655 StringRef p = path.toStringRef(path_storage); 656 657 return !relative_path(p).empty(); 658} 659 660bool has_filename(const Twine &path) { 661 SmallString<128> path_storage; 662 StringRef p = path.toStringRef(path_storage); 663 664 return !filename(p).empty(); 665} 666 667bool has_parent_path(const Twine &path) { 668 SmallString<128> path_storage; 669 StringRef p = path.toStringRef(path_storage); 670 671 return !parent_path(p).empty(); 672} 673 674bool has_stem(const Twine &path) { 675 SmallString<128> path_storage; 676 StringRef p = path.toStringRef(path_storage); 677 678 return !stem(p).empty(); 679} 680 681bool has_extension(const Twine &path) { 682 SmallString<128> path_storage; 683 StringRef p = path.toStringRef(path_storage); 684 685 return !extension(p).empty(); 686} 687 688bool is_absolute(const Twine &path) { 689 SmallString<128> path_storage; 690 StringRef p = path.toStringRef(path_storage); 691 692 bool rootDir = has_root_directory(p), 693#ifdef LLVM_ON_WIN32 694 rootName = has_root_name(p); 695#else 696 rootName = true; 697#endif 698 699 return rootDir && rootName; 700} 701 702bool is_relative(const Twine &path) { 703 return !is_absolute(path); 704} 705 706} // end namespace path 707 708namespace fs { 709 710std::error_code getUniqueID(const Twine Path, UniqueID &Result) { 711 file_status Status; 712 std::error_code EC = status(Path, Status); 713 if (EC) 714 return EC; 715 Result = Status.getUniqueID(); 716 return std::error_code(); 717} 718 719std::error_code createUniqueFile(const Twine &Model, int &ResultFd, 720 SmallVectorImpl<char> &ResultPath, 721 unsigned Mode) { 722 return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File); 723} 724 725std::error_code createUniqueFile(const Twine &Model, 726 SmallVectorImpl<char> &ResultPath) { 727 int Dummy; 728 return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name); 729} 730 731static std::error_code 732createTemporaryFile(const Twine &Model, int &ResultFD, 733 llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) { 734 SmallString<128> Storage; 735 StringRef P = Model.toNullTerminatedStringRef(Storage); 736 assert(P.find_first_of(separators) == StringRef::npos && 737 "Model must be a simple filename."); 738 // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage. 739 return createUniqueEntity(P.begin(), ResultFD, ResultPath, 740 true, owner_read | owner_write, Type); 741} 742 743static std::error_code 744createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, 745 llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) { 746 const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%."; 747 return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath, 748 Type); 749} 750 751std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 752 int &ResultFD, 753 SmallVectorImpl<char> &ResultPath) { 754 return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File); 755} 756 757std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 758 SmallVectorImpl<char> &ResultPath) { 759 int Dummy; 760 return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name); 761} 762 763 764// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly 765// for consistency. We should try using mkdtemp. 766std::error_code createUniqueDirectory(const Twine &Prefix, 767 SmallVectorImpl<char> &ResultPath) { 768 int Dummy; 769 return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, 770 true, 0, FS_Dir); 771} 772 773std::error_code make_absolute(SmallVectorImpl<char> &path) { 774 StringRef p(path.data(), path.size()); 775 776 bool rootDirectory = path::has_root_directory(p), 777#ifdef LLVM_ON_WIN32 778 rootName = path::has_root_name(p); 779#else 780 rootName = true; 781#endif 782 783 // Already absolute. 784 if (rootName && rootDirectory) 785 return std::error_code(); 786 787 // All of the following conditions will need the current directory. 788 SmallString<128> current_dir; 789 if (std::error_code ec = current_path(current_dir)) 790 return ec; 791 792 // Relative path. Prepend the current directory. 793 if (!rootName && !rootDirectory) { 794 // Append path to the current directory. 795 path::append(current_dir, p); 796 // Set path to the result. 797 path.swap(current_dir); 798 return std::error_code(); 799 } 800 801 if (!rootName && rootDirectory) { 802 StringRef cdrn = path::root_name(current_dir); 803 SmallString<128> curDirRootName(cdrn.begin(), cdrn.end()); 804 path::append(curDirRootName, p); 805 // Set path to the result. 806 path.swap(curDirRootName); 807 return std::error_code(); 808 } 809 810 if (rootName && !rootDirectory) { 811 StringRef pRootName = path::root_name(p); 812 StringRef bRootDirectory = path::root_directory(current_dir); 813 StringRef bRelativePath = path::relative_path(current_dir); 814 StringRef pRelativePath = path::relative_path(p); 815 816 SmallString<128> res; 817 path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath); 818 path.swap(res); 819 return std::error_code(); 820 } 821 822 llvm_unreachable("All rootName and rootDirectory combinations should have " 823 "occurred above!"); 824} 825 826std::error_code create_directories(const Twine &Path, bool IgnoreExisting) { 827 SmallString<128> PathStorage; 828 StringRef P = Path.toStringRef(PathStorage); 829 830 // Be optimistic and try to create the directory 831 std::error_code EC = create_directory(P, IgnoreExisting); 832 // If we succeeded, or had any error other than the parent not existing, just 833 // return it. 834 if (EC != errc::no_such_file_or_directory) 835 return EC; 836 837 // We failed because of a no_such_file_or_directory, try to create the 838 // parent. 839 StringRef Parent = path::parent_path(P); 840 if (Parent.empty()) 841 return EC; 842 843 if ((EC = create_directories(Parent))) 844 return EC; 845 846 return create_directory(P, IgnoreExisting); 847} 848 849std::error_code copy_file(const Twine &From, const Twine &To) { 850 int ReadFD, WriteFD; 851 if (std::error_code EC = openFileForRead(From, ReadFD)) 852 return EC; 853 if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) { 854 close(ReadFD); 855 return EC; 856 } 857 858 const size_t BufSize = 4096; 859 char *Buf = new char[BufSize]; 860 int BytesRead = 0, BytesWritten = 0; 861 for (;;) { 862 BytesRead = read(ReadFD, Buf, BufSize); 863 if (BytesRead <= 0) 864 break; 865 while (BytesRead) { 866 BytesWritten = write(WriteFD, Buf, BytesRead); 867 if (BytesWritten < 0) 868 break; 869 BytesRead -= BytesWritten; 870 } 871 if (BytesWritten < 0) 872 break; 873 } 874 close(ReadFD); 875 close(WriteFD); 876 delete[] Buf; 877 878 if (BytesRead < 0 || BytesWritten < 0) 879 return std::error_code(errno, std::generic_category()); 880 return std::error_code(); 881} 882 883bool exists(file_status status) { 884 return status_known(status) && status.type() != file_type::file_not_found; 885} 886 887bool status_known(file_status s) { 888 return s.type() != file_type::status_error; 889} 890 891bool is_directory(file_status status) { 892 return status.type() == file_type::directory_file; 893} 894 895std::error_code is_directory(const Twine &path, bool &result) { 896 file_status st; 897 if (std::error_code ec = status(path, st)) 898 return ec; 899 result = is_directory(st); 900 return std::error_code(); 901} 902 903bool is_regular_file(file_status status) { 904 return status.type() == file_type::regular_file; 905} 906 907std::error_code is_regular_file(const Twine &path, bool &result) { 908 file_status st; 909 if (std::error_code ec = status(path, st)) 910 return ec; 911 result = is_regular_file(st); 912 return std::error_code(); 913} 914 915bool is_other(file_status status) { 916 return exists(status) && 917 !is_regular_file(status) && 918 !is_directory(status); 919} 920 921void directory_entry::replace_filename(const Twine &filename, file_status st) { 922 SmallString<128> path(Path.begin(), Path.end()); 923 path::remove_filename(path); 924 path::append(path, filename); 925 Path = path.str(); 926 Status = st; 927} 928 929/// @brief Identify the magic in magic. 930file_magic identify_magic(StringRef Magic) { 931 if (Magic.size() < 4) 932 return file_magic::unknown; 933 switch ((unsigned char)Magic[0]) { 934 case 0x00: { 935 // COFF short import library file 936 if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff && 937 Magic[3] == (char)0xff) 938 return file_magic::coff_import_library; 939 // Windows resource file 940 const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' }; 941 if (Magic.size() >= sizeof(Expected) && 942 memcmp(Magic.data(), Expected, sizeof(Expected)) == 0) 943 return file_magic::windows_resource; 944 // 0x0000 = COFF unknown machine type 945 if (Magic[1] == 0) 946 return file_magic::coff_object; 947 break; 948 } 949 case 0xDE: // 0x0B17C0DE = BC wraper 950 if (Magic[1] == (char)0xC0 && Magic[2] == (char)0x17 && 951 Magic[3] == (char)0x0B) 952 return file_magic::bitcode; 953 break; 954 case 'B': 955 if (Magic[1] == 'C' && Magic[2] == (char)0xC0 && Magic[3] == (char)0xDE) 956 return file_magic::bitcode; 957 break; 958 case '!': 959 if (Magic.size() >= 8) 960 if (memcmp(Magic.data(),"!<arch>\n",8) == 0) 961 return file_magic::archive; 962 break; 963 964 case '\177': 965 if (Magic.size() >= 18 && Magic[1] == 'E' && Magic[2] == 'L' && 966 Magic[3] == 'F') { 967 bool Data2MSB = Magic[5] == 2; 968 unsigned high = Data2MSB ? 16 : 17; 969 unsigned low = Data2MSB ? 17 : 16; 970 if (Magic[high] == 0) 971 switch (Magic[low]) { 972 default: break; 973 case 1: return file_magic::elf_relocatable; 974 case 2: return file_magic::elf_executable; 975 case 3: return file_magic::elf_shared_object; 976 case 4: return file_magic::elf_core; 977 } 978 } 979 break; 980 981 case 0xCA: 982 if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) && 983 Magic[3] == char(0xBE)) { 984 // This is complicated by an overlap with Java class files. 985 // See the Mach-O section in /usr/share/file/magic for details. 986 if (Magic.size() >= 8 && Magic[7] < 43) 987 return file_magic::macho_universal_binary; 988 } 989 break; 990 991 // The two magic numbers for mach-o are: 992 // 0xfeedface - 32-bit mach-o 993 // 0xfeedfacf - 64-bit mach-o 994 case 0xFE: 995 case 0xCE: 996 case 0xCF: { 997 uint16_t type = 0; 998 if (Magic[0] == char(0xFE) && Magic[1] == char(0xED) && 999 Magic[2] == char(0xFA) && 1000 (Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) { 1001 /* Native endian */ 1002 if (Magic.size() >= 16) type = Magic[14] << 8 | Magic[15]; 1003 } else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) && 1004 Magic[1] == char(0xFA) && Magic[2] == char(0xED) && 1005 Magic[3] == char(0xFE)) { 1006 /* Reverse endian */ 1007 if (Magic.size() >= 14) type = Magic[13] << 8 | Magic[12]; 1008 } 1009 switch (type) { 1010 default: break; 1011 case 1: return file_magic::macho_object; 1012 case 2: return file_magic::macho_executable; 1013 case 3: return file_magic::macho_fixed_virtual_memory_shared_lib; 1014 case 4: return file_magic::macho_core; 1015 case 5: return file_magic::macho_preload_executable; 1016 case 6: return file_magic::macho_dynamically_linked_shared_lib; 1017 case 7: return file_magic::macho_dynamic_linker; 1018 case 8: return file_magic::macho_bundle; 1019 case 9: return file_magic::macho_dynamic_linker; 1020 case 10: return file_magic::macho_dsym_companion; 1021 } 1022 break; 1023 } 1024 case 0xF0: // PowerPC Windows 1025 case 0x83: // Alpha 32-bit 1026 case 0x84: // Alpha 64-bit 1027 case 0x66: // MPS R4000 Windows 1028 case 0x50: // mc68K 1029 case 0x4c: // 80386 Windows 1030 case 0xc4: // ARMNT Windows 1031 if (Magic[1] == 0x01) 1032 return file_magic::coff_object; 1033 1034 case 0x90: // PA-RISC Windows 1035 case 0x68: // mc68K Windows 1036 if (Magic[1] == 0x02) 1037 return file_magic::coff_object; 1038 break; 1039 1040 case 0x4d: // Possible MS-DOS stub on Windows PE file 1041 if (Magic[1] == 0x5a) { 1042 uint32_t off = 1043 *reinterpret_cast<const support::ulittle32_t*>(Magic.data() + 0x3c); 1044 // PE/COFF file, either EXE or DLL. 1045 if (off < Magic.size() && memcmp(Magic.data() + off, "PE\0\0",4) == 0) 1046 return file_magic::pecoff_executable; 1047 } 1048 break; 1049 1050 case 0x64: // x86-64 Windows. 1051 if (Magic[1] == char(0x86)) 1052 return file_magic::coff_object; 1053 break; 1054 1055 default: 1056 break; 1057 } 1058 return file_magic::unknown; 1059} 1060 1061std::error_code identify_magic(const Twine &Path, file_magic &Result) { 1062 int FD; 1063 if (std::error_code EC = openFileForRead(Path, FD)) 1064 return EC; 1065 1066 char Buffer[32]; 1067 int Length = read(FD, Buffer, sizeof(Buffer)); 1068 if (close(FD) != 0 || Length < 0) 1069 return std::error_code(errno, std::generic_category()); 1070 1071 Result = identify_magic(StringRef(Buffer, Length)); 1072 return std::error_code(); 1073} 1074 1075std::error_code directory_entry::status(file_status &result) const { 1076 return fs::status(Path, result); 1077} 1078 1079} // end namespace fs 1080} // end namespace sys 1081} // end namespace llvm 1082 1083// Include the truly platform-specific parts. 1084#if defined(LLVM_ON_UNIX) 1085#include "Unix/Path.inc" 1086#endif 1087#if defined(LLVM_ON_WIN32) 1088#include "Windows/Path.inc" 1089#endif 1090