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