LLVM API Documentation

Path.cpp
Go to the documentation of this file.
00001 //===-- Path.cpp - Implement OS Path Concept ------------------------------===//
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 Path API.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Support/Errc.h"
00015 #include "llvm/Support/Path.h"
00016 #include "llvm/Support/Endian.h"
00017 #include "llvm/Support/ErrorHandling.h"
00018 #include "llvm/Support/FileSystem.h"
00019 #include "llvm/Support/Process.h"
00020 #include <cctype>
00021 #include <cstdio>
00022 #include <cstring>
00023 #include <fcntl.h>
00024 
00025 #if !defined(_MSC_VER) && !defined(__MINGW32__)
00026 #include <unistd.h>
00027 #else
00028 #include <io.h>
00029 #endif
00030 
00031 using namespace llvm;
00032 
00033 namespace {
00034   using llvm::StringRef;
00035   using llvm::sys::path::is_separator;
00036 
00037 #ifdef LLVM_ON_WIN32
00038   const char *separators = "\\/";
00039   const char preferred_separator = '\\';
00040 #else
00041   const char  separators = '/';
00042   const char preferred_separator = '/';
00043 #endif
00044 
00045   StringRef find_first_component(StringRef path) {
00046     // Look for this first component in the following order.
00047     // * empty (in this case we return an empty string)
00048     // * either C: or {//,\\}net.
00049     // * {/,\}
00050     // * {.,..}
00051     // * {file,directory}name
00052 
00053     if (path.empty())
00054       return path;
00055 
00056 #ifdef LLVM_ON_WIN32
00057     // C:
00058     if (path.size() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) &&
00059         path[1] == ':')
00060       return path.substr(0, 2);
00061 #endif
00062 
00063     // //net
00064     if ((path.size() > 2) &&
00065         is_separator(path[0]) &&
00066         path[0] == path[1] &&
00067         !is_separator(path[2])) {
00068       // Find the next directory separator.
00069       size_t end = path.find_first_of(separators, 2);
00070       return path.substr(0, end);
00071     }
00072 
00073     // {/,\}
00074     if (is_separator(path[0]))
00075       return path.substr(0, 1);
00076 
00077     if (path.startswith(".."))
00078       return path.substr(0, 2);
00079 
00080     if (path[0] == '.')
00081       return path.substr(0, 1);
00082 
00083     // * {file,directory}name
00084     size_t end = path.find_first_of(separators);
00085     return path.substr(0, end);
00086   }
00087 
00088   size_t filename_pos(StringRef str) {
00089     if (str.size() == 2 &&
00090         is_separator(str[0]) &&
00091         str[0] == str[1])
00092       return 0;
00093 
00094     if (str.size() > 0 && is_separator(str[str.size() - 1]))
00095       return str.size() - 1;
00096 
00097     size_t pos = str.find_last_of(separators, str.size() - 1);
00098 
00099 #ifdef LLVM_ON_WIN32
00100     if (pos == StringRef::npos)
00101       pos = str.find_last_of(':', str.size() - 2);
00102 #endif
00103 
00104     if (pos == StringRef::npos ||
00105         (pos == 1 && is_separator(str[0])))
00106       return 0;
00107 
00108     return pos + 1;
00109   }
00110 
00111   size_t root_dir_start(StringRef str) {
00112     // case "c:/"
00113 #ifdef LLVM_ON_WIN32
00114     if (str.size() > 2 &&
00115         str[1] == ':' &&
00116         is_separator(str[2]))
00117       return 2;
00118 #endif
00119 
00120     // case "//"
00121     if (str.size() == 2 &&
00122         is_separator(str[0]) &&
00123         str[0] == str[1])
00124       return StringRef::npos;
00125 
00126     // case "//net"
00127     if (str.size() > 3 &&
00128         is_separator(str[0]) &&
00129         str[0] == str[1] &&
00130         !is_separator(str[2])) {
00131       return str.find_first_of(separators, 2);
00132     }
00133 
00134     // case "/"
00135     if (str.size() > 0 && is_separator(str[0]))
00136       return 0;
00137 
00138     return StringRef::npos;
00139   }
00140 
00141   size_t parent_path_end(StringRef path) {
00142     size_t end_pos = filename_pos(path);
00143 
00144     bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]);
00145 
00146     // Skip separators except for root dir.
00147     size_t root_dir_pos = root_dir_start(path.substr(0, end_pos));
00148 
00149     while(end_pos > 0 &&
00150           (end_pos - 1) != root_dir_pos &&
00151           is_separator(path[end_pos - 1]))
00152       --end_pos;
00153 
00154     if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
00155       return StringRef::npos;
00156 
00157     return end_pos;
00158   }
00159 } // end unnamed namespace
00160 
00161 enum FSEntity {
00162   FS_Dir,
00163   FS_File,
00164   FS_Name
00165 };
00166 
00167 // Implemented in Unix/Path.inc and Windows/Path.inc.
00168 static std::error_code TempDir(SmallVectorImpl<char> &result);
00169 
00170 static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,
00171                                           SmallVectorImpl<char> &ResultPath,
00172                                           bool MakeAbsolute, unsigned Mode,
00173                                           FSEntity Type) {
00174   SmallString<128> ModelStorage;
00175   Model.toVector(ModelStorage);
00176 
00177   if (MakeAbsolute) {
00178     // Make model absolute by prepending a temp directory if it's not already.
00179     if (!sys::path::is_absolute(Twine(ModelStorage))) {
00180       SmallString<128> TDir;
00181       if (std::error_code EC = TempDir(TDir))
00182         return EC;
00183       sys::path::append(TDir, Twine(ModelStorage));
00184       ModelStorage.swap(TDir);
00185     }
00186   }
00187 
00188   // From here on, DO NOT modify model. It may be needed if the randomly chosen
00189   // path already exists.
00190   ResultPath = ModelStorage;
00191   // Null terminate.
00192   ResultPath.push_back(0);
00193   ResultPath.pop_back();
00194 
00195 retry_random_path:
00196   // Replace '%' with random chars.
00197   for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
00198     if (ModelStorage[i] == '%')
00199       ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
00200   }
00201 
00202   // Try to open + create the file.
00203   switch (Type) {
00204   case FS_File: {
00205     if (std::error_code EC =
00206             sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
00207                                       sys::fs::F_RW | sys::fs::F_Excl, Mode)) {
00208       if (EC == errc::file_exists)
00209         goto retry_random_path;
00210       return EC;
00211     }
00212 
00213     return std::error_code();
00214   }
00215 
00216   case FS_Name: {
00217     bool Exists;
00218     std::error_code EC = sys::fs::exists(ResultPath.begin(), Exists);
00219     if (EC)
00220       return EC;
00221     if (Exists)
00222       goto retry_random_path;
00223     return std::error_code();
00224   }
00225 
00226   case FS_Dir: {
00227     if (std::error_code EC =
00228             sys::fs::create_directory(ResultPath.begin(), false)) {
00229       if (EC == errc::file_exists)
00230         goto retry_random_path;
00231       return EC;
00232     }
00233     return std::error_code();
00234   }
00235   }
00236   llvm_unreachable("Invalid Type");
00237 }
00238 
00239 namespace llvm {
00240 namespace sys  {
00241 namespace path {
00242 
00243 const_iterator begin(StringRef path) {
00244   const_iterator i;
00245   i.Path      = path;
00246   i.Component = find_first_component(path);
00247   i.Position  = 0;
00248   return i;
00249 }
00250 
00251 const_iterator end(StringRef path) {
00252   const_iterator i;
00253   i.Path      = path;
00254   i.Position  = path.size();
00255   return i;
00256 }
00257 
00258 const_iterator &const_iterator::operator++() {
00259   assert(Position < Path.size() && "Tried to increment past end!");
00260 
00261   // Increment Position to past the current component
00262   Position += Component.size();
00263 
00264   // Check for end.
00265   if (Position == Path.size()) {
00266     Component = StringRef();
00267     return *this;
00268   }
00269 
00270   // Both POSIX and Windows treat paths that begin with exactly two separators
00271   // specially.
00272   bool was_net = Component.size() > 2 &&
00273     is_separator(Component[0]) &&
00274     Component[1] == Component[0] &&
00275     !is_separator(Component[2]);
00276 
00277   // Handle separators.
00278   if (is_separator(Path[Position])) {
00279     // Root dir.
00280     if (was_net
00281 #ifdef LLVM_ON_WIN32
00282         // c:/
00283         || Component.endswith(":")
00284 #endif
00285         ) {
00286       Component = Path.substr(Position, 1);
00287       return *this;
00288     }
00289 
00290     // Skip extra separators.
00291     while (Position != Path.size() &&
00292            is_separator(Path[Position])) {
00293       ++Position;
00294     }
00295 
00296     // Treat trailing '/' as a '.'.
00297     if (Position == Path.size()) {
00298       --Position;
00299       Component = ".";
00300       return *this;
00301     }
00302   }
00303 
00304   // Find next component.
00305   size_t end_pos = Path.find_first_of(separators, Position);
00306   Component = Path.slice(Position, end_pos);
00307 
00308   return *this;
00309 }
00310 
00311 bool const_iterator::operator==(const const_iterator &RHS) const {
00312   return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
00313 }
00314 
00315 ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
00316   return Position - RHS.Position;
00317 }
00318 
00319 reverse_iterator rbegin(StringRef Path) {
00320   reverse_iterator I;
00321   I.Path = Path;
00322   I.Position = Path.size();
00323   return ++I;
00324 }
00325 
00326 reverse_iterator rend(StringRef Path) {
00327   reverse_iterator I;
00328   I.Path = Path;
00329   I.Component = Path.substr(0, 0);
00330   I.Position = 0;
00331   return I;
00332 }
00333 
00334 reverse_iterator &reverse_iterator::operator++() {
00335   // If we're at the end and the previous char was a '/', return '.' unless
00336   // we are the root path.
00337   size_t root_dir_pos = root_dir_start(Path);
00338   if (Position == Path.size() &&
00339       Path.size() > root_dir_pos + 1 &&
00340       is_separator(Path[Position - 1])) {
00341     --Position;
00342     Component = ".";
00343     return *this;
00344   }
00345 
00346   // Skip separators unless it's the root directory.
00347   size_t end_pos = Position;
00348 
00349   while(end_pos > 0 &&
00350         (end_pos - 1) != root_dir_pos &&
00351         is_separator(Path[end_pos - 1]))
00352     --end_pos;
00353 
00354   // Find next separator.
00355   size_t start_pos = filename_pos(Path.substr(0, end_pos));
00356   Component = Path.slice(start_pos, end_pos);
00357   Position = start_pos;
00358   return *this;
00359 }
00360 
00361 bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
00362   return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
00363          Position == RHS.Position;
00364 }
00365 
00366 const StringRef root_path(StringRef path) {
00367   const_iterator b = begin(path),
00368                  pos = b,
00369                  e = end(path);
00370   if (b != e) {
00371     bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
00372     bool has_drive =
00373 #ifdef LLVM_ON_WIN32
00374       b->endswith(":");
00375 #else
00376       false;
00377 #endif
00378 
00379     if (has_net || has_drive) {
00380       if ((++pos != e) && is_separator((*pos)[0])) {
00381         // {C:/,//net/}, so get the first two components.
00382         return path.substr(0, b->size() + pos->size());
00383       } else {
00384         // just {C:,//net}, return the first component.
00385         return *b;
00386       }
00387     }
00388 
00389     // POSIX style root directory.
00390     if (is_separator((*b)[0])) {
00391       return *b;
00392     }
00393   }
00394 
00395   return StringRef();
00396 }
00397 
00398 const StringRef root_name(StringRef path) {
00399   const_iterator b = begin(path),
00400                  e = end(path);
00401   if (b != e) {
00402     bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
00403     bool has_drive =
00404 #ifdef LLVM_ON_WIN32
00405       b->endswith(":");
00406 #else
00407       false;
00408 #endif
00409 
00410     if (has_net || has_drive) {
00411       // just {C:,//net}, return the first component.
00412       return *b;
00413     }
00414   }
00415 
00416   // No path or no name.
00417   return StringRef();
00418 }
00419 
00420 const StringRef root_directory(StringRef path) {
00421   const_iterator b = begin(path),
00422                  pos = b,
00423                  e = end(path);
00424   if (b != e) {
00425     bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
00426     bool has_drive =
00427 #ifdef LLVM_ON_WIN32
00428       b->endswith(":");
00429 #else
00430       false;
00431 #endif
00432 
00433     if ((has_net || has_drive) &&
00434         // {C:,//net}, skip to the next component.
00435         (++pos != e) && is_separator((*pos)[0])) {
00436       return *pos;
00437     }
00438 
00439     // POSIX style root directory.
00440     if (!has_net && is_separator((*b)[0])) {
00441       return *b;
00442     }
00443   }
00444 
00445   // No path or no root.
00446   return StringRef();
00447 }
00448 
00449 const StringRef relative_path(StringRef path) {
00450   StringRef root = root_path(path);
00451   return path.substr(root.size());
00452 }
00453 
00454 void append(SmallVectorImpl<char> &path, const Twine &a,
00455                                          const Twine &b,
00456                                          const Twine &c,
00457                                          const Twine &d) {
00458   SmallString<32> a_storage;
00459   SmallString<32> b_storage;
00460   SmallString<32> c_storage;
00461   SmallString<32> d_storage;
00462 
00463   SmallVector<StringRef, 4> components;
00464   if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
00465   if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
00466   if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
00467   if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
00468 
00469   for (SmallVectorImpl<StringRef>::const_iterator i = components.begin(),
00470                                                   e = components.end();
00471                                                   i != e; ++i) {
00472     bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]);
00473     bool component_has_sep = !i->empty() && is_separator((*i)[0]);
00474     bool is_root_name = has_root_name(*i);
00475 
00476     if (path_has_sep) {
00477       // Strip separators from beginning of component.
00478       size_t loc = i->find_first_not_of(separators);
00479       StringRef c = i->substr(loc);
00480 
00481       // Append it.
00482       path.append(c.begin(), c.end());
00483       continue;
00484     }
00485 
00486     if (!component_has_sep && !(path.empty() || is_root_name)) {
00487       // Add a separator.
00488       path.push_back(preferred_separator);
00489     }
00490 
00491     path.append(i->begin(), i->end());
00492   }
00493 }
00494 
00495 void append(SmallVectorImpl<char> &path,
00496             const_iterator begin, const_iterator end) {
00497   for (; begin != end; ++begin)
00498     path::append(path, *begin);
00499 }
00500 
00501 const StringRef parent_path(StringRef path) {
00502   size_t end_pos = parent_path_end(path);
00503   if (end_pos == StringRef::npos)
00504     return StringRef();
00505   else
00506     return path.substr(0, end_pos);
00507 }
00508 
00509 void remove_filename(SmallVectorImpl<char> &path) {
00510   size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()));
00511   if (end_pos != StringRef::npos)
00512     path.set_size(end_pos);
00513 }
00514 
00515 void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) {
00516   StringRef p(path.begin(), path.size());
00517   SmallString<32> ext_storage;
00518   StringRef ext = extension.toStringRef(ext_storage);
00519 
00520   // Erase existing extension.
00521   size_t pos = p.find_last_of('.');
00522   if (pos != StringRef::npos && pos >= filename_pos(p))
00523     path.set_size(pos);
00524 
00525   // Append '.' if needed.
00526   if (ext.size() > 0 && ext[0] != '.')
00527     path.push_back('.');
00528 
00529   // Append extension.
00530   path.append(ext.begin(), ext.end());
00531 }
00532 
00533 void native(const Twine &path, SmallVectorImpl<char> &result) {
00534   assert((!path.isSingleStringRef() ||
00535           path.getSingleStringRef().data() != result.data()) &&
00536          "path and result are not allowed to overlap!");
00537   // Clear result.
00538   result.clear();
00539   path.toVector(result);
00540   native(result);
00541 }
00542 
00543 void native(SmallVectorImpl<char> &Path) {
00544 #ifdef LLVM_ON_WIN32
00545   std::replace(Path.begin(), Path.end(), '/', '\\');
00546 #else
00547   for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
00548     if (*PI == '\\') {
00549       auto PN = PI + 1;
00550       if (PN < PE && *PN == '\\')
00551         ++PI; // increment once, the for loop will move over the escaped slash
00552       else
00553         *PI = '/';
00554     }
00555   }
00556 #endif
00557 }
00558 
00559 const StringRef filename(StringRef path) {
00560   return *rbegin(path);
00561 }
00562 
00563 const StringRef stem(StringRef path) {
00564   StringRef fname = filename(path);
00565   size_t pos = fname.find_last_of('.');
00566   if (pos == StringRef::npos)
00567     return fname;
00568   else
00569     if ((fname.size() == 1 && fname == ".") ||
00570         (fname.size() == 2 && fname == ".."))
00571       return fname;
00572     else
00573       return fname.substr(0, pos);
00574 }
00575 
00576 const StringRef extension(StringRef path) {
00577   StringRef fname = filename(path);
00578   size_t pos = fname.find_last_of('.');
00579   if (pos == StringRef::npos)
00580     return StringRef();
00581   else
00582     if ((fname.size() == 1 && fname == ".") ||
00583         (fname.size() == 2 && fname == ".."))
00584       return StringRef();
00585     else
00586       return fname.substr(pos);
00587 }
00588 
00589 bool is_separator(char value) {
00590   switch(value) {
00591 #ifdef LLVM_ON_WIN32
00592     case '\\': // fall through
00593 #endif
00594     case '/': return true;
00595     default: return false;
00596   }
00597 }
00598 
00599 static const char preferred_separator_string[] = { preferred_separator, '\0' };
00600 
00601 const StringRef get_separator() {
00602   return preferred_separator_string;
00603 }
00604 
00605 void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) {
00606   result.clear();
00607 
00608 #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR)
00609   // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR.
00610   // macros defined in <unistd.h> on darwin >= 9
00611   int ConfName = erasedOnReboot? _CS_DARWIN_USER_TEMP_DIR
00612                                : _CS_DARWIN_USER_CACHE_DIR;
00613   size_t ConfLen = confstr(ConfName, nullptr, 0);
00614   if (ConfLen > 0) {
00615     do {
00616       result.resize(ConfLen);
00617       ConfLen = confstr(ConfName, result.data(), result.size());
00618     } while (ConfLen > 0 && ConfLen != result.size());
00619 
00620     if (ConfLen > 0) {
00621       assert(result.back() == 0);
00622       result.pop_back();
00623       return;
00624     }
00625 
00626     result.clear();
00627   }
00628 #endif
00629 
00630   // Check whether the temporary directory is specified by an environment
00631   // variable.
00632   const char *EnvironmentVariable;
00633 #ifdef LLVM_ON_WIN32
00634   EnvironmentVariable = "TEMP";
00635 #else
00636   EnvironmentVariable = "TMPDIR";
00637 #endif
00638   if (char *RequestedDir = getenv(EnvironmentVariable)) {
00639     result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
00640     return;
00641   }
00642 
00643   // Fall back to a system default.
00644   const char *DefaultResult;
00645 #ifdef LLVM_ON_WIN32
00646   (void)erasedOnReboot;
00647   DefaultResult = "C:\\TEMP";
00648 #else
00649   if (erasedOnReboot)
00650     DefaultResult = "/tmp";
00651   else
00652     DefaultResult = "/var/tmp";
00653 #endif
00654   result.append(DefaultResult, DefaultResult + strlen(DefaultResult));
00655 }
00656 
00657 bool has_root_name(const Twine &path) {
00658   SmallString<128> path_storage;
00659   StringRef p = path.toStringRef(path_storage);
00660 
00661   return !root_name(p).empty();
00662 }
00663 
00664 bool has_root_directory(const Twine &path) {
00665   SmallString<128> path_storage;
00666   StringRef p = path.toStringRef(path_storage);
00667 
00668   return !root_directory(p).empty();
00669 }
00670 
00671 bool has_root_path(const Twine &path) {
00672   SmallString<128> path_storage;
00673   StringRef p = path.toStringRef(path_storage);
00674 
00675   return !root_path(p).empty();
00676 }
00677 
00678 bool has_relative_path(const Twine &path) {
00679   SmallString<128> path_storage;
00680   StringRef p = path.toStringRef(path_storage);
00681 
00682   return !relative_path(p).empty();
00683 }
00684 
00685 bool has_filename(const Twine &path) {
00686   SmallString<128> path_storage;
00687   StringRef p = path.toStringRef(path_storage);
00688 
00689   return !filename(p).empty();
00690 }
00691 
00692 bool has_parent_path(const Twine &path) {
00693   SmallString<128> path_storage;
00694   StringRef p = path.toStringRef(path_storage);
00695 
00696   return !parent_path(p).empty();
00697 }
00698 
00699 bool has_stem(const Twine &path) {
00700   SmallString<128> path_storage;
00701   StringRef p = path.toStringRef(path_storage);
00702 
00703   return !stem(p).empty();
00704 }
00705 
00706 bool has_extension(const Twine &path) {
00707   SmallString<128> path_storage;
00708   StringRef p = path.toStringRef(path_storage);
00709 
00710   return !extension(p).empty();
00711 }
00712 
00713 bool is_absolute(const Twine &path) {
00714   SmallString<128> path_storage;
00715   StringRef p = path.toStringRef(path_storage);
00716 
00717   bool rootDir = has_root_directory(p),
00718 #ifdef LLVM_ON_WIN32
00719        rootName = has_root_name(p);
00720 #else
00721        rootName = true;
00722 #endif
00723 
00724   return rootDir && rootName;
00725 }
00726 
00727 bool is_relative(const Twine &path) {
00728   return !is_absolute(path);
00729 }
00730 
00731 } // end namespace path
00732 
00733 namespace fs {
00734 
00735 std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
00736   file_status Status;
00737   std::error_code EC = status(Path, Status);
00738   if (EC)
00739     return EC;
00740   Result = Status.getUniqueID();
00741   return std::error_code();
00742 }
00743 
00744 std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
00745                                  SmallVectorImpl<char> &ResultPath,
00746                                  unsigned Mode) {
00747   return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
00748 }
00749 
00750 std::error_code createUniqueFile(const Twine &Model,
00751                                  SmallVectorImpl<char> &ResultPath) {
00752   int Dummy;
00753   return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
00754 }
00755 
00756 static std::error_code
00757 createTemporaryFile(const Twine &Model, int &ResultFD,
00758                     llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
00759   SmallString<128> Storage;
00760   StringRef P = Model.toNullTerminatedStringRef(Storage);
00761   assert(P.find_first_of(separators) == StringRef::npos &&
00762          "Model must be a simple filename.");
00763   // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
00764   return createUniqueEntity(P.begin(), ResultFD, ResultPath,
00765                             true, owner_read | owner_write, Type);
00766 }
00767 
00768 static std::error_code
00769 createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
00770                     llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
00771   const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
00772   return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
00773                              Type);
00774 }
00775 
00776 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
00777                                     int &ResultFD,
00778                                     SmallVectorImpl<char> &ResultPath) {
00779   return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
00780 }
00781 
00782 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
00783                                     SmallVectorImpl<char> &ResultPath) {
00784   int Dummy;
00785   return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
00786 }
00787 
00788 
00789 // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
00790 // for consistency. We should try using mkdtemp.
00791 std::error_code createUniqueDirectory(const Twine &Prefix,
00792                                       SmallVectorImpl<char> &ResultPath) {
00793   int Dummy;
00794   return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
00795                             true, 0, FS_Dir);
00796 }
00797 
00798 std::error_code make_absolute(SmallVectorImpl<char> &path) {
00799   StringRef p(path.data(), path.size());
00800 
00801   bool rootDirectory = path::has_root_directory(p),
00802 #ifdef LLVM_ON_WIN32
00803        rootName = path::has_root_name(p);
00804 #else
00805        rootName = true;
00806 #endif
00807 
00808   // Already absolute.
00809   if (rootName && rootDirectory)
00810     return std::error_code();
00811 
00812   // All of the following conditions will need the current directory.
00813   SmallString<128> current_dir;
00814   if (std::error_code ec = current_path(current_dir))
00815     return ec;
00816 
00817   // Relative path. Prepend the current directory.
00818   if (!rootName && !rootDirectory) {
00819     // Append path to the current directory.
00820     path::append(current_dir, p);
00821     // Set path to the result.
00822     path.swap(current_dir);
00823     return std::error_code();
00824   }
00825 
00826   if (!rootName && rootDirectory) {
00827     StringRef cdrn = path::root_name(current_dir);
00828     SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
00829     path::append(curDirRootName, p);
00830     // Set path to the result.
00831     path.swap(curDirRootName);
00832     return std::error_code();
00833   }
00834 
00835   if (rootName && !rootDirectory) {
00836     StringRef pRootName      = path::root_name(p);
00837     StringRef bRootDirectory = path::root_directory(current_dir);
00838     StringRef bRelativePath  = path::relative_path(current_dir);
00839     StringRef pRelativePath  = path::relative_path(p);
00840 
00841     SmallString<128> res;
00842     path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
00843     path.swap(res);
00844     return std::error_code();
00845   }
00846 
00847   llvm_unreachable("All rootName and rootDirectory combinations should have "
00848                    "occurred above!");
00849 }
00850 
00851 std::error_code create_directories(const Twine &Path, bool IgnoreExisting) {
00852   SmallString<128> PathStorage;
00853   StringRef P = Path.toStringRef(PathStorage);
00854 
00855   // Be optimistic and try to create the directory
00856   std::error_code EC = create_directory(P, IgnoreExisting);
00857   // If we succeeded, or had any error other than the parent not existing, just
00858   // return it.
00859   if (EC != errc::no_such_file_or_directory)
00860     return EC;
00861 
00862   // We failed because of a no_such_file_or_directory, try to create the
00863   // parent.
00864   StringRef Parent = path::parent_path(P);
00865   if (Parent.empty())
00866     return EC;
00867 
00868   if ((EC = create_directories(Parent)))
00869       return EC;
00870 
00871   return create_directory(P, IgnoreExisting);
00872 }
00873 
00874 std::error_code copy_file(const Twine &From, const Twine &To) {
00875   int ReadFD, WriteFD;
00876   if (std::error_code EC = openFileForRead(From, ReadFD))
00877     return EC;
00878   if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
00879     close(ReadFD);
00880     return EC;
00881   }
00882 
00883   const size_t BufSize = 4096;
00884   char *Buf = new char[BufSize];
00885   int BytesRead = 0, BytesWritten = 0;
00886   for (;;) {
00887     BytesRead = read(ReadFD, Buf, BufSize);
00888     if (BytesRead <= 0)
00889       break;
00890     while (BytesRead) {
00891       BytesWritten = write(WriteFD, Buf, BytesRead);
00892       if (BytesWritten < 0)
00893         break;
00894       BytesRead -= BytesWritten;
00895     }
00896     if (BytesWritten < 0)
00897       break;
00898   }
00899   close(ReadFD);
00900   close(WriteFD);
00901   delete[] Buf;
00902 
00903   if (BytesRead < 0 || BytesWritten < 0)
00904     return std::error_code(errno, std::generic_category());
00905   return std::error_code();
00906 }
00907 
00908 bool exists(file_status status) {
00909   return status_known(status) && status.type() != file_type::file_not_found;
00910 }
00911 
00912 bool status_known(file_status s) {
00913   return s.type() != file_type::status_error;
00914 }
00915 
00916 bool is_directory(file_status status) {
00917   return status.type() == file_type::directory_file;
00918 }
00919 
00920 std::error_code is_directory(const Twine &path, bool &result) {
00921   file_status st;
00922   if (std::error_code ec = status(path, st))
00923     return ec;
00924   result = is_directory(st);
00925   return std::error_code();
00926 }
00927 
00928 bool is_regular_file(file_status status) {
00929   return status.type() == file_type::regular_file;
00930 }
00931 
00932 std::error_code is_regular_file(const Twine &path, bool &result) {
00933   file_status st;
00934   if (std::error_code ec = status(path, st))
00935     return ec;
00936   result = is_regular_file(st);
00937   return std::error_code();
00938 }
00939 
00940 bool is_other(file_status status) {
00941   return exists(status) &&
00942          !is_regular_file(status) &&
00943          !is_directory(status);
00944 }
00945 
00946 void directory_entry::replace_filename(const Twine &filename, file_status st) {
00947   SmallString<128> path(Path.begin(), Path.end());
00948   path::remove_filename(path);
00949   path::append(path, filename);
00950   Path = path.str();
00951   Status = st;
00952 }
00953 
00954 /// @brief Identify the magic in magic.
00955 file_magic identify_magic(StringRef Magic) {
00956   if (Magic.size() < 4)
00957     return file_magic::unknown;
00958   switch ((unsigned char)Magic[0]) {
00959     case 0x00: {
00960       // COFF short import library file
00961       if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff &&
00962           Magic[3] == (char)0xff)
00963         return file_magic::coff_import_library;
00964       // Windows resource file
00965       const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' };
00966       if (Magic.size() >= sizeof(Expected) &&
00967           memcmp(Magic.data(), Expected, sizeof(Expected)) == 0)
00968         return file_magic::windows_resource;
00969       // 0x0000 = COFF unknown machine type
00970       if (Magic[1] == 0)
00971         return file_magic::coff_object;
00972       break;
00973     }
00974     case 0xDE:  // 0x0B17C0DE = BC wraper
00975       if (Magic[1] == (char)0xC0 && Magic[2] == (char)0x17 &&
00976           Magic[3] == (char)0x0B)
00977         return file_magic::bitcode;
00978       break;
00979     case 'B':
00980       if (Magic[1] == 'C' && Magic[2] == (char)0xC0 && Magic[3] == (char)0xDE)
00981         return file_magic::bitcode;
00982       break;
00983     case '!':
00984       if (Magic.size() >= 8)
00985         if (memcmp(Magic.data(),"!<arch>\n",8) == 0)
00986           return file_magic::archive;
00987       break;
00988 
00989     case '\177':
00990       if (Magic.size() >= 18 && Magic[1] == 'E' && Magic[2] == 'L' &&
00991           Magic[3] == 'F') {
00992         bool Data2MSB = Magic[5] == 2;
00993         unsigned high = Data2MSB ? 16 : 17;
00994         unsigned low  = Data2MSB ? 17 : 16;
00995         if (Magic[high] == 0)
00996           switch (Magic[low]) {
00997             default: break;
00998             case 1: return file_magic::elf_relocatable;
00999             case 2: return file_magic::elf_executable;
01000             case 3: return file_magic::elf_shared_object;
01001             case 4: return file_magic::elf_core;
01002           }
01003       }
01004       break;
01005 
01006     case 0xCA:
01007       if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) &&
01008           Magic[3] == char(0xBE)) {
01009         // This is complicated by an overlap with Java class files.
01010         // See the Mach-O section in /usr/share/file/magic for details.
01011         if (Magic.size() >= 8 && Magic[7] < 43)
01012           return file_magic::macho_universal_binary;
01013       }
01014       break;
01015 
01016       // The two magic numbers for mach-o are:
01017       // 0xfeedface - 32-bit mach-o
01018       // 0xfeedfacf - 64-bit mach-o
01019     case 0xFE:
01020     case 0xCE:
01021     case 0xCF: {
01022       uint16_t type = 0;
01023       if (Magic[0] == char(0xFE) && Magic[1] == char(0xED) &&
01024           Magic[2] == char(0xFA) &&
01025           (Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) {
01026         /* Native endian */
01027         if (Magic.size() >= 16) type = Magic[14] << 8 | Magic[15];
01028       } else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) &&
01029                  Magic[1] == char(0xFA) && Magic[2] == char(0xED) &&
01030                  Magic[3] == char(0xFE)) {
01031         /* Reverse endian */
01032         if (Magic.size() >= 14) type = Magic[13] << 8 | Magic[12];
01033       }
01034       switch (type) {
01035         default: break;
01036         case 1: return file_magic::macho_object;
01037         case 2: return file_magic::macho_executable;
01038         case 3: return file_magic::macho_fixed_virtual_memory_shared_lib;
01039         case 4: return file_magic::macho_core;
01040         case 5: return file_magic::macho_preload_executable;
01041         case 6: return file_magic::macho_dynamically_linked_shared_lib;
01042         case 7: return file_magic::macho_dynamic_linker;
01043         case 8: return file_magic::macho_bundle;
01044         case 9: return file_magic::macho_dynamic_linker;
01045         case 10: return file_magic::macho_dsym_companion;
01046       }
01047       break;
01048     }
01049     case 0xF0: // PowerPC Windows
01050     case 0x83: // Alpha 32-bit
01051     case 0x84: // Alpha 64-bit
01052     case 0x66: // MPS R4000 Windows
01053     case 0x50: // mc68K
01054     case 0x4c: // 80386 Windows
01055     case 0xc4: // ARMNT Windows
01056       if (Magic[1] == 0x01)
01057         return file_magic::coff_object;
01058 
01059     case 0x90: // PA-RISC Windows
01060     case 0x68: // mc68K Windows
01061       if (Magic[1] == 0x02)
01062         return file_magic::coff_object;
01063       break;
01064 
01065     case 0x4d: // Possible MS-DOS stub on Windows PE file
01066       if (Magic[1] == 0x5a) {
01067         uint32_t off =
01068           *reinterpret_cast<const support::ulittle32_t*>(Magic.data() + 0x3c);
01069         // PE/COFF file, either EXE or DLL.
01070         if (off < Magic.size() && memcmp(Magic.data() + off, "PE\0\0",4) == 0)
01071           return file_magic::pecoff_executable;
01072       }
01073       break;
01074 
01075     case 0x64: // x86-64 Windows.
01076       if (Magic[1] == char(0x86))
01077         return file_magic::coff_object;
01078       break;
01079 
01080     default:
01081       break;
01082   }
01083   return file_magic::unknown;
01084 }
01085 
01086 std::error_code identify_magic(const Twine &Path, file_magic &Result) {
01087   int FD;
01088   if (std::error_code EC = openFileForRead(Path, FD))
01089     return EC;
01090 
01091   char Buffer[32];
01092   int Length = read(FD, Buffer, sizeof(Buffer));
01093   if (close(FD) != 0 || Length < 0)
01094     return std::error_code(errno, std::generic_category());
01095 
01096   Result = identify_magic(StringRef(Buffer, Length));
01097   return std::error_code();
01098 }
01099 
01100 std::error_code directory_entry::status(file_status &result) const {
01101   return fs::status(Path, result);
01102 }
01103 
01104 } // end namespace fs
01105 } // end namespace sys
01106 } // end namespace llvm
01107 
01108 // Include the truly platform-specific parts.
01109 #if defined(LLVM_ON_UNIX)
01110 #include "Unix/Path.inc"
01111 #endif
01112 #if defined(LLVM_ON_WIN32)
01113 #include "Windows/Path.inc"
01114 #endif