LLVM API Documentation

PathV2.cpp
Go to the documentation of this file.
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