LLVM API Documentation
00001 //===-- PathV2.cpp - Implement OS Path Concept ------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the operating system PathV2 API. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/Support/PathV2.h" 00015 #include "llvm/Support/Endian.h" 00016 #include "llvm/Support/ErrorHandling.h" 00017 #include "llvm/Support/FileSystem.h" 00018 #include <cctype> 00019 #include <cstdio> 00020 #include <cstring> 00021 #ifdef __APPLE__ 00022 #include <unistd.h> 00023 #endif 00024 00025 namespace { 00026 using llvm::StringRef; 00027 using llvm::sys::path::is_separator; 00028 00029 #ifdef LLVM_ON_WIN32 00030 const char *separators = "\\/"; 00031 const char prefered_separator = '\\'; 00032 #else 00033 const char separators = '/'; 00034 const char prefered_separator = '/'; 00035 #endif 00036 00037 StringRef find_first_component(StringRef path) { 00038 // Look for this first component in the following order. 00039 // * empty (in this case we return an empty string) 00040 // * either C: or {//,\\}net. 00041 // * {/,\} 00042 // * {.,..} 00043 // * {file,directory}name 00044 00045 if (path.empty()) 00046 return path; 00047 00048 #ifdef LLVM_ON_WIN32 00049 // C: 00050 if (path.size() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) && 00051 path[1] == ':') 00052 return path.substr(0, 2); 00053 #endif 00054 00055 // //net 00056 if ((path.size() > 2) && 00057 is_separator(path[0]) && 00058 path[0] == path[1] && 00059 !is_separator(path[2])) { 00060 // Find the next directory separator. 00061 size_t end = path.find_first_of(separators, 2); 00062 return path.substr(0, end); 00063 } 00064 00065 // {/,\} 00066 if (is_separator(path[0])) 00067 return path.substr(0, 1); 00068 00069 if (path.startswith("..")) 00070 return path.substr(0, 2); 00071 00072 if (path[0] == '.') 00073 return path.substr(0, 1); 00074 00075 // * {file,directory}name 00076 size_t end = path.find_first_of(separators, 2); 00077 return path.substr(0, end); 00078 } 00079 00080 size_t filename_pos(StringRef str) { 00081 if (str.size() == 2 && 00082 is_separator(str[0]) && 00083 str[0] == str[1]) 00084 return 0; 00085 00086 if (str.size() > 0 && is_separator(str[str.size() - 1])) 00087 return str.size() - 1; 00088 00089 size_t pos = str.find_last_of(separators, str.size() - 1); 00090 00091 #ifdef LLVM_ON_WIN32 00092 if (pos == StringRef::npos) 00093 pos = str.find_last_of(':', str.size() - 2); 00094 #endif 00095 00096 if (pos == StringRef::npos || 00097 (pos == 1 && is_separator(str[0]))) 00098 return 0; 00099 00100 return pos + 1; 00101 } 00102 00103 size_t root_dir_start(StringRef str) { 00104 // case "c:/" 00105 #ifdef LLVM_ON_WIN32 00106 if (str.size() > 2 && 00107 str[1] == ':' && 00108 is_separator(str[2])) 00109 return 2; 00110 #endif 00111 00112 // case "//" 00113 if (str.size() == 2 && 00114 is_separator(str[0]) && 00115 str[0] == str[1]) 00116 return StringRef::npos; 00117 00118 // case "//net" 00119 if (str.size() > 3 && 00120 is_separator(str[0]) && 00121 str[0] == str[1] && 00122 !is_separator(str[2])) { 00123 return str.find_first_of(separators, 2); 00124 } 00125 00126 // case "/" 00127 if (str.size() > 0 && is_separator(str[0])) 00128 return 0; 00129 00130 return StringRef::npos; 00131 } 00132 00133 size_t parent_path_end(StringRef path) { 00134 size_t end_pos = filename_pos(path); 00135 00136 bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]); 00137 00138 // Skip separators except for root dir. 00139 size_t root_dir_pos = root_dir_start(path.substr(0, end_pos)); 00140 00141 while(end_pos > 0 && 00142 (end_pos - 1) != root_dir_pos && 00143 is_separator(path[end_pos - 1])) 00144 --end_pos; 00145 00146 if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) 00147 return StringRef::npos; 00148 00149 return end_pos; 00150 } 00151 } // end unnamed namespace 00152 00153 namespace llvm { 00154 namespace sys { 00155 namespace path { 00156 00157 const_iterator begin(StringRef path) { 00158 const_iterator i; 00159 i.Path = path; 00160 i.Component = find_first_component(path); 00161 i.Position = 0; 00162 return i; 00163 } 00164 00165 const_iterator end(StringRef path) { 00166 const_iterator i; 00167 i.Path = path; 00168 i.Position = path.size(); 00169 return i; 00170 } 00171 00172 const_iterator &const_iterator::operator++() { 00173 assert(Position < Path.size() && "Tried to increment past end!"); 00174 00175 // Increment Position to past the current component 00176 Position += Component.size(); 00177 00178 // Check for end. 00179 if (Position == Path.size()) { 00180 Component = StringRef(); 00181 return *this; 00182 } 00183 00184 // Both POSIX and Windows treat paths that begin with exactly two separators 00185 // specially. 00186 bool was_net = Component.size() > 2 && 00187 is_separator(Component[0]) && 00188 Component[1] == Component[0] && 00189 !is_separator(Component[2]); 00190 00191 // Handle separators. 00192 if (is_separator(Path[Position])) { 00193 // Root dir. 00194 if (was_net 00195 #ifdef LLVM_ON_WIN32 00196 // c:/ 00197 || Component.endswith(":") 00198 #endif 00199 ) { 00200 Component = Path.substr(Position, 1); 00201 return *this; 00202 } 00203 00204 // Skip extra separators. 00205 while (Position != Path.size() && 00206 is_separator(Path[Position])) { 00207 ++Position; 00208 } 00209 00210 // Treat trailing '/' as a '.'. 00211 if (Position == Path.size()) { 00212 --Position; 00213 Component = "."; 00214 return *this; 00215 } 00216 } 00217 00218 // Find next component. 00219 size_t end_pos = Path.find_first_of(separators, Position); 00220 Component = Path.slice(Position, end_pos); 00221 00222 return *this; 00223 } 00224 00225 const_iterator &const_iterator::operator--() { 00226 // If we're at the end and the previous char was a '/', return '.'. 00227 if (Position == Path.size() && 00228 Path.size() > 1 && 00229 is_separator(Path[Position - 1]) 00230 #ifdef LLVM_ON_WIN32 00231 && Path[Position - 2] != ':' 00232 #endif 00233 ) { 00234 --Position; 00235 Component = "."; 00236 return *this; 00237 } 00238 00239 // Skip separators unless it's the root directory. 00240 size_t root_dir_pos = root_dir_start(Path); 00241 size_t end_pos = Position; 00242 00243 while(end_pos > 0 && 00244 (end_pos - 1) != root_dir_pos && 00245 is_separator(Path[end_pos - 1])) 00246 --end_pos; 00247 00248 // Find next separator. 00249 size_t start_pos = filename_pos(Path.substr(0, end_pos)); 00250 Component = Path.slice(start_pos, end_pos); 00251 Position = start_pos; 00252 return *this; 00253 } 00254 00255 bool const_iterator::operator==(const const_iterator &RHS) const { 00256 return Path.begin() == RHS.Path.begin() && 00257 Position == RHS.Position; 00258 } 00259 00260 bool const_iterator::operator!=(const const_iterator &RHS) const { 00261 return !(*this == RHS); 00262 } 00263 00264 ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { 00265 return Position - RHS.Position; 00266 } 00267 00268 const StringRef root_path(StringRef path) { 00269 const_iterator b = begin(path), 00270 pos = b, 00271 e = end(path); 00272 if (b != e) { 00273 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 00274 bool has_drive = 00275 #ifdef LLVM_ON_WIN32 00276 b->endswith(":"); 00277 #else 00278 false; 00279 #endif 00280 00281 if (has_net || has_drive) { 00282 if ((++pos != e) && is_separator((*pos)[0])) { 00283 // {C:/,//net/}, so get the first two components. 00284 return path.substr(0, b->size() + pos->size()); 00285 } else { 00286 // just {C:,//net}, return the first component. 00287 return *b; 00288 } 00289 } 00290 00291 // POSIX style root directory. 00292 if (is_separator((*b)[0])) { 00293 return *b; 00294 } 00295 } 00296 00297 return StringRef(); 00298 } 00299 00300 const StringRef root_name(StringRef path) { 00301 const_iterator b = begin(path), 00302 e = end(path); 00303 if (b != e) { 00304 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 00305 bool has_drive = 00306 #ifdef LLVM_ON_WIN32 00307 b->endswith(":"); 00308 #else 00309 false; 00310 #endif 00311 00312 if (has_net || has_drive) { 00313 // just {C:,//net}, return the first component. 00314 return *b; 00315 } 00316 } 00317 00318 // No path or no name. 00319 return StringRef(); 00320 } 00321 00322 const StringRef root_directory(StringRef path) { 00323 const_iterator b = begin(path), 00324 pos = b, 00325 e = end(path); 00326 if (b != e) { 00327 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; 00328 bool has_drive = 00329 #ifdef LLVM_ON_WIN32 00330 b->endswith(":"); 00331 #else 00332 false; 00333 #endif 00334 00335 if ((has_net || has_drive) && 00336 // {C:,//net}, skip to the next component. 00337 (++pos != e) && is_separator((*pos)[0])) { 00338 return *pos; 00339 } 00340 00341 // POSIX style root directory. 00342 if (!has_net && is_separator((*b)[0])) { 00343 return *b; 00344 } 00345 } 00346 00347 // No path or no root. 00348 return StringRef(); 00349 } 00350 00351 const StringRef relative_path(StringRef path) { 00352 StringRef root = root_path(path); 00353 return path.substr(root.size()); 00354 } 00355 00356 void append(SmallVectorImpl<char> &path, const Twine &a, 00357 const Twine &b, 00358 const Twine &c, 00359 const Twine &d) { 00360 SmallString<32> a_storage; 00361 SmallString<32> b_storage; 00362 SmallString<32> c_storage; 00363 SmallString<32> d_storage; 00364 00365 SmallVector<StringRef, 4> components; 00366 if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage)); 00367 if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage)); 00368 if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage)); 00369 if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage)); 00370 00371 for (SmallVectorImpl<StringRef>::const_iterator i = components.begin(), 00372 e = components.end(); 00373 i != e; ++i) { 00374 bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]); 00375 bool component_has_sep = !i->empty() && is_separator((*i)[0]); 00376 bool is_root_name = has_root_name(*i); 00377 00378 if (path_has_sep) { 00379 // Strip separators from beginning of component. 00380 size_t loc = i->find_first_not_of(separators); 00381 StringRef c = i->substr(loc); 00382 00383 // Append it. 00384 path.append(c.begin(), c.end()); 00385 continue; 00386 } 00387 00388 if (!component_has_sep && !(path.empty() || is_root_name)) { 00389 // Add a separator. 00390 path.push_back(prefered_separator); 00391 } 00392 00393 path.append(i->begin(), i->end()); 00394 } 00395 } 00396 00397 void append(SmallVectorImpl<char> &path, 00398 const_iterator begin, const_iterator end) { 00399 for (; begin != end; ++begin) 00400 path::append(path, *begin); 00401 } 00402 00403 const StringRef parent_path(StringRef path) { 00404 size_t end_pos = parent_path_end(path); 00405 if (end_pos == StringRef::npos) 00406 return StringRef(); 00407 else 00408 return path.substr(0, end_pos); 00409 } 00410 00411 void remove_filename(SmallVectorImpl<char> &path) { 00412 size_t end_pos = parent_path_end(StringRef(path.begin(), path.size())); 00413 if (end_pos != StringRef::npos) 00414 path.set_size(end_pos); 00415 } 00416 00417 void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) { 00418 StringRef p(path.begin(), path.size()); 00419 SmallString<32> ext_storage; 00420 StringRef ext = extension.toStringRef(ext_storage); 00421 00422 // Erase existing extension. 00423 size_t pos = p.find_last_of('.'); 00424 if (pos != StringRef::npos && pos >= filename_pos(p)) 00425 path.set_size(pos); 00426 00427 // Append '.' if needed. 00428 if (ext.size() > 0 && ext[0] != '.') 00429 path.push_back('.'); 00430 00431 // Append extension. 00432 path.append(ext.begin(), ext.end()); 00433 } 00434 00435 void native(const Twine &path, SmallVectorImpl<char> &result) { 00436 // Clear result. 00437 result.clear(); 00438 #ifdef LLVM_ON_WIN32 00439 SmallString<128> path_storage; 00440 StringRef p = path.toStringRef(path_storage); 00441 result.reserve(p.size()); 00442 for (StringRef::const_iterator i = p.begin(), 00443 e = p.end(); 00444 i != e; 00445 ++i) { 00446 if (*i == '/') 00447 result.push_back('\\'); 00448 else 00449 result.push_back(*i); 00450 } 00451 #else 00452 path.toVector(result); 00453 #endif 00454 } 00455 00456 const StringRef filename(StringRef path) { 00457 return *(--end(path)); 00458 } 00459 00460 const StringRef stem(StringRef path) { 00461 StringRef fname = filename(path); 00462 size_t pos = fname.find_last_of('.'); 00463 if (pos == StringRef::npos) 00464 return fname; 00465 else 00466 if ((fname.size() == 1 && fname == ".") || 00467 (fname.size() == 2 && fname == "..")) 00468 return fname; 00469 else 00470 return fname.substr(0, pos); 00471 } 00472 00473 const StringRef extension(StringRef path) { 00474 StringRef fname = filename(path); 00475 size_t pos = fname.find_last_of('.'); 00476 if (pos == StringRef::npos) 00477 return StringRef(); 00478 else 00479 if ((fname.size() == 1 && fname == ".") || 00480 (fname.size() == 2 && fname == "..")) 00481 return StringRef(); 00482 else 00483 return fname.substr(pos); 00484 } 00485 00486 bool is_separator(char value) { 00487 switch(value) { 00488 #ifdef LLVM_ON_WIN32 00489 case '\\': // fall through 00490 #endif 00491 case '/': return true; 00492 default: return false; 00493 } 00494 } 00495 00496 void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) { 00497 result.clear(); 00498 00499 #ifdef __APPLE__ 00500 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. 00501 int ConfName = erasedOnReboot? _CS_DARWIN_USER_TEMP_DIR 00502 : _CS_DARWIN_USER_CACHE_DIR; 00503 size_t ConfLen = confstr(ConfName, 0, 0); 00504 if (ConfLen > 0) { 00505 do { 00506 result.resize(ConfLen); 00507 ConfLen = confstr(ConfName, result.data(), result.size()); 00508 } while (ConfLen > 0 && ConfLen != result.size()); 00509 00510 if (ConfLen > 0) { 00511 assert(result.back() == 0); 00512 result.pop_back(); 00513 return; 00514 } 00515 00516 result.clear(); 00517 } 00518 #endif 00519 00520 // Check whether the temporary directory is specified by an environment 00521 // variable. 00522 const char *EnvironmentVariable; 00523 #ifdef LLVM_ON_WIN32 00524 EnvironmentVariable = "TEMP"; 00525 #else 00526 EnvironmentVariable = "TMPDIR"; 00527 #endif 00528 if (char *RequestedDir = getenv(EnvironmentVariable)) { 00529 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 00530 return; 00531 } 00532 00533 // Fall back to a system default. 00534 const char *DefaultResult; 00535 #ifdef LLVM_ON_WIN32 00536 (void)erasedOnReboot; 00537 DefaultResult = "C:\\TEMP"; 00538 #else 00539 if (erasedOnReboot) 00540 DefaultResult = "/tmp"; 00541 else 00542 DefaultResult = "/var/tmp"; 00543 #endif 00544 result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); 00545 } 00546 00547 bool has_root_name(const Twine &path) { 00548 SmallString<128> path_storage; 00549 StringRef p = path.toStringRef(path_storage); 00550 00551 return !root_name(p).empty(); 00552 } 00553 00554 bool has_root_directory(const Twine &path) { 00555 SmallString<128> path_storage; 00556 StringRef p = path.toStringRef(path_storage); 00557 00558 return !root_directory(p).empty(); 00559 } 00560 00561 bool has_root_path(const Twine &path) { 00562 SmallString<128> path_storage; 00563 StringRef p = path.toStringRef(path_storage); 00564 00565 return !root_path(p).empty(); 00566 } 00567 00568 bool has_relative_path(const Twine &path) { 00569 SmallString<128> path_storage; 00570 StringRef p = path.toStringRef(path_storage); 00571 00572 return !relative_path(p).empty(); 00573 } 00574 00575 bool has_filename(const Twine &path) { 00576 SmallString<128> path_storage; 00577 StringRef p = path.toStringRef(path_storage); 00578 00579 return !filename(p).empty(); 00580 } 00581 00582 bool has_parent_path(const Twine &path) { 00583 SmallString<128> path_storage; 00584 StringRef p = path.toStringRef(path_storage); 00585 00586 return !parent_path(p).empty(); 00587 } 00588 00589 bool has_stem(const Twine &path) { 00590 SmallString<128> path_storage; 00591 StringRef p = path.toStringRef(path_storage); 00592 00593 return !stem(p).empty(); 00594 } 00595 00596 bool has_extension(const Twine &path) { 00597 SmallString<128> path_storage; 00598 StringRef p = path.toStringRef(path_storage); 00599 00600 return !extension(p).empty(); 00601 } 00602 00603 bool is_absolute(const Twine &path) { 00604 SmallString<128> path_storage; 00605 StringRef p = path.toStringRef(path_storage); 00606 00607 bool rootDir = has_root_directory(p), 00608 #ifdef LLVM_ON_WIN32 00609 rootName = has_root_name(p); 00610 #else 00611 rootName = true; 00612 #endif 00613 00614 return rootDir && rootName; 00615 } 00616 00617 bool is_relative(const Twine &path) { 00618 return !is_absolute(path); 00619 } 00620 00621 } // end namespace path 00622 00623 namespace fs { 00624 00625 error_code make_absolute(SmallVectorImpl<char> &path) { 00626 StringRef p(path.data(), path.size()); 00627 00628 bool rootDirectory = path::has_root_directory(p), 00629 #ifdef LLVM_ON_WIN32 00630 rootName = path::has_root_name(p); 00631 #else 00632 rootName = true; 00633 #endif 00634 00635 // Already absolute. 00636 if (rootName && rootDirectory) 00637 return error_code::success(); 00638 00639 // All of the following conditions will need the current directory. 00640 SmallString<128> current_dir; 00641 if (error_code ec = current_path(current_dir)) return ec; 00642 00643 // Relative path. Prepend the current directory. 00644 if (!rootName && !rootDirectory) { 00645 // Append path to the current directory. 00646 path::append(current_dir, p); 00647 // Set path to the result. 00648 path.swap(current_dir); 00649 return error_code::success(); 00650 } 00651 00652 if (!rootName && rootDirectory) { 00653 StringRef cdrn = path::root_name(current_dir); 00654 SmallString<128> curDirRootName(cdrn.begin(), cdrn.end()); 00655 path::append(curDirRootName, p); 00656 // Set path to the result. 00657 path.swap(curDirRootName); 00658 return error_code::success(); 00659 } 00660 00661 if (rootName && !rootDirectory) { 00662 StringRef pRootName = path::root_name(p); 00663 StringRef bRootDirectory = path::root_directory(current_dir); 00664 StringRef bRelativePath = path::relative_path(current_dir); 00665 StringRef pRelativePath = path::relative_path(p); 00666 00667 SmallString<128> res; 00668 path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath); 00669 path.swap(res); 00670 return error_code::success(); 00671 } 00672 00673 llvm_unreachable("All rootName and rootDirectory combinations should have " 00674 "occurred above!"); 00675 } 00676 00677 error_code create_directories(const Twine &path, bool &existed) { 00678 SmallString<128> path_storage; 00679 StringRef p = path.toStringRef(path_storage); 00680 00681 StringRef parent = path::parent_path(p); 00682 if (!parent.empty()) { 00683 bool parent_exists; 00684 if (error_code ec = fs::exists(parent, parent_exists)) return ec; 00685 00686 if (!parent_exists) 00687 if (error_code ec = create_directories(parent, existed)) return ec; 00688 } 00689 00690 return create_directory(p, existed); 00691 } 00692 00693 bool exists(file_status status) { 00694 return status_known(status) && status.type() != file_type::file_not_found; 00695 } 00696 00697 bool status_known(file_status s) { 00698 return s.type() != file_type::status_error; 00699 } 00700 00701 bool is_directory(file_status status) { 00702 return status.type() == file_type::directory_file; 00703 } 00704 00705 error_code is_directory(const Twine &path, bool &result) { 00706 file_status st; 00707 if (error_code ec = status(path, st)) 00708 return ec; 00709 result = is_directory(st); 00710 return error_code::success(); 00711 } 00712 00713 bool is_regular_file(file_status status) { 00714 return status.type() == file_type::regular_file; 00715 } 00716 00717 error_code is_regular_file(const Twine &path, bool &result) { 00718 file_status st; 00719 if (error_code ec = status(path, st)) 00720 return ec; 00721 result = is_regular_file(st); 00722 return error_code::success(); 00723 } 00724 00725 bool is_symlink(file_status status) { 00726 return status.type() == file_type::symlink_file; 00727 } 00728 00729 error_code is_symlink(const Twine &path, bool &result) { 00730 file_status st; 00731 if (error_code ec = status(path, st)) 00732 return ec; 00733 result = is_symlink(st); 00734 return error_code::success(); 00735 } 00736 00737 bool is_other(file_status status) { 00738 return exists(status) && 00739 !is_regular_file(status) && 00740 !is_directory(status) && 00741 !is_symlink(status); 00742 } 00743 00744 void directory_entry::replace_filename(const Twine &filename, file_status st) { 00745 SmallString<128> path(Path.begin(), Path.end()); 00746 path::remove_filename(path); 00747 path::append(path, filename); 00748 Path = path.str(); 00749 Status = st; 00750 } 00751 00752 error_code has_magic(const Twine &path, const Twine &magic, bool &result) { 00753 SmallString<32> MagicStorage; 00754 StringRef Magic = magic.toStringRef(MagicStorage); 00755 SmallString<32> Buffer; 00756 00757 if (error_code ec = get_magic(path, Magic.size(), Buffer)) { 00758 if (ec == errc::value_too_large) { 00759 // Magic.size() > file_size(Path). 00760 result = false; 00761 return error_code::success(); 00762 } 00763 return ec; 00764 } 00765 00766 result = Magic == Buffer; 00767 return error_code::success(); 00768 } 00769 00770 /// @brief Identify the magic in magic. 00771 file_magic identify_magic(StringRef magic) { 00772 if (magic.size() < 4) 00773 return file_magic::unknown; 00774 switch ((unsigned char)magic[0]) { 00775 case 0xDE: // 0x0B17C0DE = BC wraper 00776 if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 && 00777 magic[3] == (char)0x0B) 00778 return file_magic::bitcode; 00779 break; 00780 case 'B': 00781 if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE) 00782 return file_magic::bitcode; 00783 break; 00784 case '!': 00785 if (magic.size() >= 8) 00786 if (memcmp(magic.data(),"!<arch>\n",8) == 0) 00787 return file_magic::archive; 00788 break; 00789 00790 case '\177': 00791 if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') { 00792 bool Data2MSB = magic[5] == 2; 00793 unsigned high = Data2MSB ? 16 : 17; 00794 unsigned low = Data2MSB ? 17 : 16; 00795 if (magic.size() >= 18 && magic[high] == 0) 00796 switch (magic[low]) { 00797 default: break; 00798 case 1: return file_magic::elf_relocatable; 00799 case 2: return file_magic::elf_executable; 00800 case 3: return file_magic::elf_shared_object; 00801 case 4: return file_magic::elf_core; 00802 } 00803 } 00804 break; 00805 00806 case 0xCA: 00807 if (magic[1] == char(0xFE) && magic[2] == char(0xBA) && 00808 magic[3] == char(0xBE)) { 00809 // This is complicated by an overlap with Java class files. 00810 // See the Mach-O section in /usr/share/file/magic for details. 00811 if (magic.size() >= 8 && magic[7] < 43) 00812 // FIXME: Universal Binary of any type. 00813 return file_magic::macho_dynamically_linked_shared_lib; 00814 } 00815 break; 00816 00817 // The two magic numbers for mach-o are: 00818 // 0xfeedface - 32-bit mach-o 00819 // 0xfeedfacf - 64-bit mach-o 00820 case 0xFE: 00821 case 0xCE: 00822 case 0xCF: { 00823 uint16_t type = 0; 00824 if (magic[0] == char(0xFE) && magic[1] == char(0xED) && 00825 magic[2] == char(0xFA) && 00826 (magic[3] == char(0xCE) || magic[3] == char(0xCF))) { 00827 /* Native endian */ 00828 if (magic.size() >= 16) type = magic[14] << 8 | magic[15]; 00829 } else if ((magic[0] == char(0xCE) || magic[0] == char(0xCF)) && 00830 magic[1] == char(0xFA) && magic[2] == char(0xED) && 00831 magic[3] == char(0xFE)) { 00832 /* Reverse endian */ 00833 if (magic.size() >= 14) type = magic[13] << 8 | magic[12]; 00834 } 00835 switch (type) { 00836 default: break; 00837 case 1: return file_magic::macho_object; 00838 case 2: return file_magic::macho_executable; 00839 case 3: return file_magic::macho_fixed_virtual_memory_shared_lib; 00840 case 4: return file_magic::macho_core; 00841 case 5: return file_magic::macho_preload_executabl; 00842 case 6: return file_magic::macho_dynamically_linked_shared_lib; 00843 case 7: return file_magic::macho_dynamic_linker; 00844 case 8: return file_magic::macho_bundle; 00845 case 9: return file_magic::macho_dynamic_linker; 00846 case 10: return file_magic::macho_dsym_companion; 00847 } 00848 break; 00849 } 00850 case 0xF0: // PowerPC Windows 00851 case 0x83: // Alpha 32-bit 00852 case 0x84: // Alpha 64-bit 00853 case 0x66: // MPS R4000 Windows 00854 case 0x50: // mc68K 00855 case 0x4c: // 80386 Windows 00856 if (magic[1] == 0x01) 00857 return file_magic::coff_object; 00858 00859 case 0x90: // PA-RISC Windows 00860 case 0x68: // mc68K Windows 00861 if (magic[1] == 0x02) 00862 return file_magic::coff_object; 00863 break; 00864 00865 case 0x4d: // Possible MS-DOS stub on Windows PE file 00866 if (magic[1] == 0x5a) { 00867 uint32_t off = 00868 *reinterpret_cast<const support::ulittle32_t*>(magic.data() + 0x3c); 00869 // PE/COFF file, either EXE or DLL. 00870 if (off < magic.size() && memcmp(magic.data() + off, "PE\0\0",4) == 0) 00871 return file_magic::pecoff_executable; 00872 } 00873 break; 00874 00875 case 0x64: // x86-64 Windows. 00876 if (magic[1] == char(0x86)) 00877 return file_magic::coff_object; 00878 break; 00879 00880 default: 00881 break; 00882 } 00883 return file_magic::unknown; 00884 } 00885 00886 error_code identify_magic(const Twine &path, file_magic &result) { 00887 SmallString<32> Magic; 00888 error_code ec = get_magic(path, Magic.capacity(), Magic); 00889 if (ec && ec != errc::value_too_large) 00890 return ec; 00891 00892 result = identify_magic(Magic); 00893 return error_code::success(); 00894 } 00895 00896 namespace { 00897 error_code remove_all_r(StringRef path, file_type ft, uint32_t &count) { 00898 if (ft == file_type::directory_file) { 00899 // This code would be a lot better with exceptions ;/. 00900 error_code ec; 00901 directory_iterator i(path, ec); 00902 if (ec) return ec; 00903 for (directory_iterator e; i != e; i.increment(ec)) { 00904 if (ec) return ec; 00905 file_status st; 00906 if (error_code ec = i->status(st)) return ec; 00907 if (error_code ec = remove_all_r(i->path(), st.type(), count)) return ec; 00908 } 00909 bool obviously_this_exists; 00910 if (error_code ec = remove(path, obviously_this_exists)) return ec; 00911 assert(obviously_this_exists); 00912 ++count; // Include the directory itself in the items removed. 00913 } else { 00914 bool obviously_this_exists; 00915 if (error_code ec = remove(path, obviously_this_exists)) return ec; 00916 assert(obviously_this_exists); 00917 ++count; 00918 } 00919 00920 return error_code::success(); 00921 } 00922 } // end unnamed namespace 00923 00924 error_code remove_all(const Twine &path, uint32_t &num_removed) { 00925 SmallString<128> path_storage; 00926 StringRef p = path.toStringRef(path_storage); 00927 00928 file_status fs; 00929 if (error_code ec = status(path, fs)) 00930 return ec; 00931 num_removed = 0; 00932 return remove_all_r(p, fs.type(), num_removed); 00933 } 00934 00935 error_code directory_entry::status(file_status &result) const { 00936 return fs::status(Path, result); 00937 } 00938 00939 } // end namespace fs 00940 } // end namespace sys 00941 } // end namespace llvm 00942 00943 // Include the truly platform-specific parts. 00944 #if defined(LLVM_ON_UNIX) 00945 #include "Unix/PathV2.inc" 00946 #endif 00947 #if defined(LLVM_ON_WIN32) 00948 #include "Windows/PathV2.inc" 00949 #endif