LCOV - code coverage report
Current view: top level - lib/Support - Path.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 462 514 89.9 %
Date: 2017-09-14 15:23:50 Functions: 71 77 92.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- Path.cpp - Implement OS Path Concept ------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : //  This file implements the operating system Path API.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "llvm/Support/Path.h"
      15             : #include "llvm/ADT/ArrayRef.h"
      16             : #include "llvm/Support/Endian.h"
      17             : #include "llvm/Support/Errc.h"
      18             : #include "llvm/Support/ErrorHandling.h"
      19             : #include "llvm/Support/FileSystem.h"
      20             : #include "llvm/Support/Process.h"
      21             : #include <cctype>
      22             : #include <cstring>
      23             : 
      24             : #if !defined(_MSC_VER) && !defined(__MINGW32__)
      25             : #include <unistd.h>
      26             : #else
      27             : #include <io.h>
      28             : #endif
      29             : 
      30             : using namespace llvm;
      31             : using namespace llvm::support::endian;
      32             : 
      33             : namespace {
      34             :   using llvm::StringRef;
      35             :   using llvm::sys::path::is_separator;
      36             :   using llvm::sys::path::Style;
      37             : 
      38             :   inline Style real_style(Style style) {
      39             : #ifdef LLVM_ON_WIN32
      40             :     return (style == Style::posix) ? Style::posix : Style::windows;
      41             : #else
      42    62965364 :     return (style == Style::windows) ? Style::windows : Style::posix;
      43             : #endif
      44             :   }
      45             : 
      46             :   inline const char *separators(Style style) {
      47    10212126 :     if (real_style(style) == Style::windows)
      48             :       return "\\/";
      49             :     return "/";
      50             :   }
      51             : 
      52             :   inline char preferred_separator(Style style) {
      53     2684350 :     if (real_style(style) == Style::windows)
      54             :       return '\\';
      55             :     return '/';
      56             :   }
      57             : 
      58     7959410 :   StringRef find_first_component(StringRef path, Style style) {
      59             :     // Look for this first component in the following order.
      60             :     // * empty (in this case we return an empty string)
      61             :     // * either C: or {//,\\}net.
      62             :     // * {/,\}
      63             :     // * {file,directory}name
      64             : 
      65     7959410 :     if (path.empty())
      66      368637 :       return path;
      67             : 
      68          41 :     if (real_style(style) == Style::windows) {
      69             :       // C:
      70          75 :       if (path.size() >= 2 &&
      71          79 :           std::isalpha(static_cast<unsigned char>(path[0])) && path[1] == ':')
      72             :         return path.substr(0, 2);
      73             :     }
      74             : 
      75             :     // //net
      76    25167412 :     if ((path.size() > 2) && is_separator(path[0], style) &&
      77    16688870 :         path[0] == path[1] && !is_separator(path[2], style)) {
      78             :       // Find the next directory separator.
      79        1164 :       size_t end = path.find_first_of(separators(style), 2);
      80             :       return path.substr(0, end);
      81             :     }
      82             : 
      83             :     // {/,\}
      84    15180384 :     if (is_separator(path[0], style))
      85             :       return path.substr(0, 1);
      86             : 
      87             :     // * {file,directory}name
      88     9101006 :     size_t end = path.find_first_of(separators(style));
      89             :     return path.substr(0, end);
      90             :   }
      91             : 
      92     1577560 :   size_t filename_pos(StringRef str, Style style) {
      93     1577655 :     if (str.size() == 2 && is_separator(str[0], style) && str[0] == str[1])
      94             :       return 0;
      95             : 
      96     2888366 :     if (str.size() > 0 && is_separator(str[str.size() - 1], style))
      97       79198 :       return str.size() - 1;
      98             : 
      99     4495086 :     size_t pos = str.find_last_of(separators(style), str.size() - 1);
     100             : 
     101           9 :     if (real_style(style) == Style::windows) {
     102           9 :       if (pos == StringRef::npos)
     103           0 :         pos = str.find_last_of(':', str.size() - 2);
     104             :     }
     105             : 
     106     1498812 :     if (pos == StringRef::npos || (pos == 1 && is_separator(str[0], style)))
     107             :       return 0;
     108             : 
     109     1153275 :     return pos + 1;
     110             :   }
     111             : 
     112     1647852 :   size_t root_dir_start(StringRef str, Style style) {
     113             :     // case "c:/"
     114          15 :     if (real_style(style) == Style::windows) {
     115          37 :       if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style))
     116             :         return 2;
     117             :     }
     118             : 
     119             :     // case "//"
     120     1648277 :     if (str.size() == 2 && is_separator(str[0], style) && str[0] == str[1])
     121             :       return StringRef::npos;
     122             : 
     123             :     // case "//net"
     124     5371363 :     if (str.size() > 3 && is_separator(str[0], style) && str[0] == str[1] &&
     125         456 :         !is_separator(str[2], style)) {
     126         392 :       return str.find_first_of(separators(style), 2);
     127             :     }
     128             : 
     129             :     // case "/"
     130     4332491 :     if (str.size() > 0 && is_separator(str[0], style))
     131             :       return 0;
     132             : 
     133             :     return StringRef::npos;
     134             :   }
     135             : 
     136      522228 :   size_t parent_path_end(StringRef path, Style style) {
     137      522228 :     size_t end_pos = filename_pos(path, style);
     138             : 
     139             :     bool filename_was_sep =
     140     1039105 :         path.size() > 0 && is_separator(path[end_pos], style);
     141             : 
     142             :     // Skip separators except for root dir.
     143      522228 :     size_t root_dir_pos = root_dir_start(path.substr(0, end_pos), style);
     144             : 
     145     1791832 :     while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
     146     1742606 :            is_separator(path[end_pos - 1], style))
     147             :       --end_pos;
     148             : 
     149      522228 :     if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
     150             :       return StringRef::npos;
     151             : 
     152      522228 :     return end_pos;
     153             :   }
     154             : } // end unnamed namespace
     155             : 
     156             : enum FSEntity {
     157             :   FS_Dir,
     158             :   FS_File,
     159             :   FS_Name
     160             : };
     161             : 
     162       14358 : static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,
     163             :                                           SmallVectorImpl<char> &ResultPath,
     164             :                                           bool MakeAbsolute, unsigned Mode,
     165             :                                           FSEntity Type) {
     166       28716 :   SmallString<128> ModelStorage;
     167       14358 :   Model.toVector(ModelStorage);
     168             : 
     169       14358 :   if (MakeAbsolute) {
     170             :     // Make model absolute by prepending a temp directory if it's not already.
     171        4667 :     if (!sys::path::is_absolute(Twine(ModelStorage))) {
     172        9334 :       SmallString<128> TDir;
     173        4667 :       sys::path::system_temp_directory(true, TDir);
     174       18668 :       sys::path::append(TDir, Twine(ModelStorage));
     175        4667 :       ModelStorage.swap(TDir);
     176             :     }
     177             :   }
     178             : 
     179             :   // From here on, DO NOT modify model. It may be needed if the randomly chosen
     180             :   // path already exists.
     181       14358 :   ResultPath = ModelStorage;
     182             :   // Null terminate.
     183       14358 :   ResultPath.push_back(0);
     184       14358 :   ResultPath.pop_back();
     185             : 
     186             : retry_random_path:
     187             :   // Replace '%' with random chars.
     188     1547053 :   for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
     189     3036674 :     if (ModelStorage[i] == '%')
     190      201452 :       ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
     191             :   }
     192             : 
     193             :   // Try to open + create the file.
     194       14358 :   switch (Type) {
     195        9686 :   case FS_File: {
     196        9686 :     if (std::error_code EC =
     197       38744 :             sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
     198       29058 :                                       sys::fs::F_RW | sys::fs::F_Excl, Mode)) {
     199          71 :       if (EC == errc::file_exists)
     200             :         goto retry_random_path;
     201          71 :       return EC;
     202             :     }
     203             : 
     204        9615 :     return std::error_code();
     205             :   }
     206             : 
     207        4640 :   case FS_Name: {
     208             :     std::error_code EC =
     209       13920 :         sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
     210        9280 :     if (EC == errc::no_such_file_or_directory)
     211        4640 :       return std::error_code();
     212           0 :     if (EC)
     213           0 :       return EC;
     214           0 :     goto retry_random_path;
     215             :   }
     216             : 
     217          32 :   case FS_Dir: {
     218          32 :     if (std::error_code EC =
     219          96 :             sys::fs::create_directory(ResultPath.begin(), false)) {
     220           0 :       if (EC == errc::file_exists)
     221             :         goto retry_random_path;
     222           0 :       return EC;
     223             :     }
     224          32 :     return std::error_code();
     225             :   }
     226             :   }
     227           0 :   llvm_unreachable("Invalid Type");
     228             : }
     229             : 
     230             : namespace llvm {
     231             : namespace sys  {
     232             : namespace path {
     233             : 
     234     7959410 : const_iterator begin(StringRef path, Style style) {
     235     7959410 :   const_iterator i;
     236     7959410 :   i.Path      = path;
     237     7959410 :   i.Component = find_first_component(path, style);
     238     7959414 :   i.Position  = 0;
     239     7959414 :   i.S = style;
     240     7959414 :   return i;
     241             : }
     242             : 
     243     7959187 : const_iterator end(StringRef path) {
     244     7959187 :   const_iterator i;
     245     7959187 :   i.Path      = path;
     246     7959187 :   i.Position  = path.size();
     247     7959187 :   return i;
     248             : }
     249             : 
     250     4303338 : const_iterator &const_iterator::operator++() {
     251             :   assert(Position < Path.size() && "Tried to increment past end!");
     252             : 
     253             :   // Increment Position to past the current component
     254     8606676 :   Position += Component.size();
     255             : 
     256             :   // Check for end.
     257     8606676 :   if (Position == Path.size()) {
     258      927747 :     Component = StringRef();
     259      927747 :     return *this;
     260             :   }
     261             : 
     262             :   // Both POSIX and Windows treat paths that begin with exactly two separators
     263             :   // specially.
     264     8365330 :   bool was_net = Component.size() > 2 && is_separator(Component[0], S) &&
     265     3378416 :                  Component[1] == Component[0] && !is_separator(Component[2], S);
     266             : 
     267             :   // Handle separators.
     268     6751182 :   if (is_separator(Path[Position], S)) {
     269             :     // Root dir.
     270     2807870 :     if (was_net ||
     271             :         // c:/
     272     2807333 :         (real_style(S) == Style::windows && Component.endswith(":"))) {
     273        1132 :       Component = Path.substr(Position, 1);
     274         566 :       return *this;
     275             :     }
     276             : 
     277             :     // Skip extra separators.
     278    19652190 :     while (Position != Path.size() && is_separator(Path[Position], S)) {
     279     2807577 :       ++Position;
     280             :     }
     281             : 
     282             :     // Treat trailing '/' as a '.'.
     283     5614608 :     if (Position == Path.size()) {
     284          30 :       --Position;
     285          30 :       Component = ".";
     286          30 :       return *this;
     287             :     }
     288             :   }
     289             : 
     290             :   // Find next component.
     291    10124985 :   size_t end_pos = Path.find_first_of(separators(S), Position);
     292     6749990 :   Component = Path.slice(Position, end_pos);
     293             : 
     294     3374995 :   return *this;
     295             : }
     296             : 
     297    11111716 : bool const_iterator::operator==(const const_iterator &RHS) const {
     298    11111716 :   return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
     299             : }
     300             : 
     301         239 : ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
     302         239 :   return Position - RHS.Position;
     303             : }
     304             : 
     305     1040822 : reverse_iterator rbegin(StringRef Path, Style style) {
     306     1040822 :   reverse_iterator I;
     307     1040822 :   I.Path = Path;
     308     1040822 :   I.Position = Path.size();
     309     1040822 :   I.S = style;
     310     1040822 :   return ++I;
     311             : }
     312             : 
     313       53922 : reverse_iterator rend(StringRef Path) {
     314       53922 :   reverse_iterator I;
     315       53922 :   I.Path = Path;
     316       53922 :   I.Component = Path.substr(0, 0);
     317       53922 :   I.Position = 0;
     318       53922 :   return I;
     319             : }
     320             : 
     321     1125623 : reverse_iterator &reverse_iterator::operator++() {
     322             :   // If we're at the end and the previous char was a '/', return '.' unless
     323             :   // we are the root path.
     324     1125623 :   size_t root_dir_pos = root_dir_start(Path, S);
     325     3027953 :   if (Position == Path.size() && Path.size() > root_dir_pos + 1 &&
     326     1553410 :       is_separator(Path[Position - 1], S)) {
     327       74778 :     --Position;
     328       74778 :     Component = ".";
     329       74778 :     return *this;
     330             :   }
     331             : 
     332             :   // Skip separators unless it's the root directory.
     333     1050846 :   size_t end_pos = Position;
     334             : 
     335     2004385 :   while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
     336     1739348 :          is_separator(Path[end_pos - 1], S))
     337             :     --end_pos;
     338             : 
     339             :   // Find next separator.
     340     2101692 :   size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
     341     2101692 :   Component = Path.slice(start_pos, end_pos);
     342     1050846 :   Position = start_pos;
     343     1050846 :   return *this;
     344             : }
     345             : 
     346       84977 : bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
     347       85134 :   return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
     348       85134 :          Position == RHS.Position;
     349             : }
     350             : 
     351           3 : ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
     352           3 :   return Position - RHS.Position;
     353             : }
     354             : 
     355     2051922 : StringRef root_path(StringRef path, Style style) {
     356     2051922 :   const_iterator b = begin(path, style), pos = b, e = end(path);
     357     2051923 :   if (b != e) {
     358             :     bool has_net =
     359     4096537 :         b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
     360     1899996 :     bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
     361             : 
     362     1899964 :     if (has_net || has_drive) {
     363         860 :       if ((++pos != e) && is_separator((*pos)[0], style)) {
     364             :         // {C:/,//net/}, so get the first two components.
     365        1136 :         return path.substr(0, b->size() + pos->size());
     366             :       } else {
     367             :         // just {C:,//net}, return the first component.
     368           4 :         return *b;
     369             :       }
     370             :     }
     371             : 
     372             :     // POSIX style root directory.
     373     3799352 :     if (is_separator((*b)[0], style)) {
     374     1514620 :       return *b;
     375             :     }
     376             :   }
     377             : 
     378      537015 :   return StringRef();
     379             : }
     380             : 
     381     2827252 : StringRef root_name(StringRef path, Style style) {
     382     2827252 :   const_iterator b = begin(path, style), e = end(path);
     383     2827252 :   if (b != e) {
     384             :     bool has_net =
     385     8115071 :         b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
     386     2749074 :     bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
     387             : 
     388     2749048 :     if (has_net || has_drive) {
     389             :       // just {C:,//net}, return the first component.
     390           6 :       return *b;
     391             :     }
     392             :   }
     393             : 
     394             :   // No path or no name.
     395     2827247 :   return StringRef();
     396             : }
     397             : 
     398     1643256 : StringRef root_directory(StringRef path, Style style) {
     399     1643256 :   const_iterator b = begin(path, style), pos = b, e = end(path);
     400     1643257 :   if (b != e) {
     401             :     bool has_net =
     402     3557797 :         b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
     403     1525559 :     bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
     404             : 
     405     1525763 :     if ((has_net || has_drive) &&
     406             :         // {C:,//net}, skip to the next component.
     407     1526169 :         (++pos != e) && is_separator((*pos)[0], style)) {
     408         203 :       return *pos;
     409             :     }
     410             : 
     411             :     // POSIX style root directory.
     412     4576036 :     if (!has_net && is_separator((*b)[0], style)) {
     413      954180 :       return *b;
     414             :     }
     415             :   }
     416             : 
     417             :   // No path or no root.
     418      688875 :   return StringRef();
     419             : }
     420             : 
     421     1012495 : StringRef relative_path(StringRef path, Style style) {
     422     1012495 :   StringRef root = root_path(path, style);
     423     2024990 :   return path.substr(root.size());
     424             : }
     425             : 
     426     3558225 : void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
     427             :             const Twine &b, const Twine &c, const Twine &d) {
     428     7116448 :   SmallString<32> a_storage;
     429     7116448 :   SmallString<32> b_storage;
     430     7116448 :   SmallString<32> c_storage;
     431     7116448 :   SmallString<32> d_storage;
     432             : 
     433     7116448 :   SmallVector<StringRef, 4> components;
     434     3558202 :   if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
     435      385233 :   if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
     436      338195 :   if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
     437      158140 :   if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
     438             : 
     439    15114438 :   for (auto &component : components) {
     440             :     bool path_has_sep =
     441    12326937 :         !path.empty() && is_separator(path[path.size() - 1], style);
     442             :     if (path_has_sep) {
     443             :       // Strip separators from beginning of component.
     444     1575136 :       size_t loc = component.find_first_not_of(separators(style));
     445      787568 :       StringRef c = component.substr(loc);
     446             : 
     447             :       // Append it.
     448      787568 :       path.append(c.begin(), c.end());
     449      787567 :       continue;
     450             :     }
     451             : 
     452             :     bool component_has_sep =
     453    10059886 :         !component.empty() && is_separator(component[0], style);
     454     3352316 :     if (!component_has_sep &&
     455     6036676 :         !(path.empty() || has_root_name(component, style))) {
     456             :       // Add a separator.
     457     5368720 :       path.push_back(preferred_separator(style));
     458             :     }
     459             : 
     460     3652202 :     path.append(component.begin(), component.end());
     461             :   }
     462     3558223 : }
     463             : 
     464      989252 : void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
     465             :             const Twine &c, const Twine &d) {
     466      989252 :   append(path, Style::native, a, b, c, d);
     467      989252 : }
     468             : 
     469          39 : void append(SmallVectorImpl<char> &path, const_iterator begin,
     470             :             const_iterator end, Style style) {
     471         471 :   for (; begin != end; ++begin)
     472         864 :     path::append(path, style, *begin);
     473          39 : }
     474             : 
     475      505902 : StringRef parent_path(StringRef path, Style style) {
     476      505902 :   size_t end_pos = parent_path_end(path, style);
     477      505902 :   if (end_pos == StringRef::npos)
     478           0 :     return StringRef();
     479             :   else
     480             :     return path.substr(0, end_pos);
     481             : }
     482             : 
     483       16326 : void remove_filename(SmallVectorImpl<char> &path, Style style) {
     484       48978 :   size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
     485       16326 :   if (end_pos != StringRef::npos)
     486             :     path.set_size(end_pos);
     487       16326 : }
     488             : 
     489        4657 : void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
     490             :                        Style style) {
     491       13971 :   StringRef p(path.begin(), path.size());
     492        9314 :   SmallString<32> ext_storage;
     493        4657 :   StringRef ext = extension.toStringRef(ext_storage);
     494             : 
     495             :   // Erase existing extension.
     496        4657 :   size_t pos = p.find_last_of('.');
     497        4657 :   if (pos != StringRef::npos && pos >= filename_pos(p, style))
     498             :     path.set_size(pos);
     499             : 
     500             :   // Append '.' if needed.
     501        8931 :   if (ext.size() > 0 && ext[0] != '.')
     502        3965 :     path.push_back('.');
     503             : 
     504             :   // Append extension.
     505        4657 :   path.append(ext.begin(), ext.end());
     506        4657 : }
     507             : 
     508          19 : void replace_path_prefix(SmallVectorImpl<char> &Path,
     509             :                          const StringRef &OldPrefix, const StringRef &NewPrefix,
     510             :                          Style style) {
     511          20 :   if (OldPrefix.empty() && NewPrefix.empty())
     512           6 :     return;
     513             : 
     514          57 :   StringRef OrigPath(Path.begin(), Path.size());
     515             :   if (!OrigPath.startswith(OldPrefix))
     516             :     return;
     517             : 
     518             :   // If prefixes have the same size we can simply copy the new one over.
     519          32 :   if (OldPrefix.size() == NewPrefix.size()) {
     520           6 :     std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
     521             :     return;
     522             :   }
     523             : 
     524          26 :   StringRef RelPath = OrigPath.substr(OldPrefix.size());
     525          26 :   SmallString<256> NewPath;
     526          52 :   path::append(NewPath, style, NewPrefix);
     527          52 :   path::append(NewPath, style, RelPath);
     528          13 :   Path.swap(NewPath);
     529             : }
     530             : 
     531       19980 : void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
     532             :   assert((!path.isSingleStringRef() ||
     533             :           path.getSingleStringRef().data() != result.data()) &&
     534             :          "path and result are not allowed to overlap!");
     535             :   // Clear result.
     536       19980 :   result.clear();
     537       19980 :   path.toVector(result);
     538       19980 :   native(result, style);
     539       19980 : }
     540             : 
     541       22208 : void native(SmallVectorImpl<char> &Path, Style style) {
     542       22208 :   if (Path.empty())
     543             :     return;
     544             :   if (real_style(style) == Style::windows) {
     545         113 :     std::replace(Path.begin(), Path.end(), '/', '\\');
     546         226 :     if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
     547           0 :       SmallString<128> PathHome;
     548           0 :       home_directory(PathHome);
     549           0 :       PathHome.append(Path.begin() + 1, Path.end());
     550           0 :       Path = PathHome;
     551             :     }
     552             :   } else {
     553     4241582 :     for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
     554     2109744 :       if (*PI == '\\') {
     555          20 :         auto PN = PI + 1;
     556          20 :         if (PN < PE && *PN == '\\')
     557             :           ++PI; // increment once, the for loop will move over the escaped slash
     558             :         else
     559          19 :           *PI = '/';
     560             :       }
     561             :     }
     562             :   }
     563             : }
     564             : 
     565          93 : std::string convert_to_slash(StringRef path, Style style) {
     566          93 :   if (real_style(style) != Style::windows)
     567             :     return path;
     568             : 
     569           0 :   std::string s = path.str();
     570           0 :   std::replace(s.begin(), s.end(), '\\', '/');
     571           0 :   return s;
     572             : }
     573             : 
     574      986813 : StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
     575             : 
     576       39579 : StringRef stem(StringRef path, Style style) {
     577       39579 :   StringRef fname = filename(path, style);
     578       39579 :   size_t pos = fname.find_last_of('.');
     579       39579 :   if (pos == StringRef::npos)
     580       29880 :     return fname;
     581             :   else
     582       19366 :     if ((fname.size() == 1 && fname == ".") ||
     583        9675 :         (fname.size() == 2 && fname == ".."))
     584          40 :       return fname;
     585             :     else
     586             :       return fname.substr(0, pos);
     587             : }
     588             : 
     589       18345 : StringRef extension(StringRef path, Style style) {
     590       18345 :   StringRef fname = filename(path, style);
     591       18345 :   size_t pos = fname.find_last_of('.');
     592       18345 :   if (pos == StringRef::npos)
     593        7341 :     return StringRef();
     594             :   else
     595       21963 :     if ((fname.size() == 1 && fname == ".") ||
     596       10985 :         (fname.size() == 2 && fname == ".."))
     597          71 :       return StringRef();
     598             :     else
     599             :       return fname.substr(pos);
     600             : }
     601             : 
     602    47469624 : bool is_separator(char value, Style style) {
     603    47469624 :   if (value == '/')
     604             :     return true;
     605         294 :   if (real_style(style) == Style::windows)
     606         294 :     return value == '\\';
     607             :   return false;
     608             : }
     609             : 
     610       10130 : StringRef get_separator(Style style) {
     611       10130 :   if (real_style(style) == Style::windows)
     612          12 :     return "\\";
     613       10118 :   return "/";
     614             : }
     615             : 
     616     2684403 : bool has_root_name(const Twine &path, Style style) {
     617     5368806 :   SmallString<128> path_storage;
     618     2684403 :   StringRef p = path.toStringRef(path_storage);
     619             : 
     620     8053207 :   return !root_name(p, style).empty();
     621             : }
     622             : 
     623     1500452 : bool has_root_directory(const Twine &path, Style style) {
     624     3000906 :   SmallString<128> path_storage;
     625     1500452 :   StringRef p = path.toStringRef(path_storage);
     626             : 
     627     4501360 :   return !root_directory(p, style).empty();
     628             : }
     629             : 
     630          40 : bool has_root_path(const Twine &path, Style style) {
     631          80 :   SmallString<128> path_storage;
     632          40 :   StringRef p = path.toStringRef(path_storage);
     633             : 
     634         120 :   return !root_path(p, style).empty();
     635             : }
     636             : 
     637           0 : bool has_relative_path(const Twine &path, Style style) {
     638           0 :   SmallString<128> path_storage;
     639           0 :   StringRef p = path.toStringRef(path_storage);
     640             : 
     641           0 :   return !relative_path(p, style).empty();
     642             : }
     643             : 
     644          40 : bool has_filename(const Twine &path, Style style) {
     645          80 :   SmallString<128> path_storage;
     646          40 :   StringRef p = path.toStringRef(path_storage);
     647             : 
     648         120 :   return !filename(p, style).empty();
     649             : }
     650             : 
     651         206 : bool has_parent_path(const Twine &path, Style style) {
     652         412 :   SmallString<128> path_storage;
     653         206 :   StringRef p = path.toStringRef(path_storage);
     654             : 
     655         618 :   return !parent_path(p, style).empty();
     656             : }
     657             : 
     658          52 : bool has_stem(const Twine &path, Style style) {
     659         104 :   SmallString<128> path_storage;
     660          52 :   StringRef p = path.toStringRef(path_storage);
     661             : 
     662         156 :   return !stem(p, style).empty();
     663             : }
     664             : 
     665         414 : bool has_extension(const Twine &path, Style style) {
     666         828 :   SmallString<128> path_storage;
     667         414 :   StringRef p = path.toStringRef(path_storage);
     668             : 
     669        1242 :   return !extension(p, style).empty();
     670             : }
     671             : 
     672     1341510 : bool is_absolute(const Twine &path, Style style) {
     673     2683021 :   SmallString<128> path_storage;
     674     1341510 :   StringRef p = path.toStringRef(path_storage);
     675             : 
     676     1341509 :   bool rootDir = has_root_directory(p, style);
     677             :   bool rootName =
     678           6 :       (real_style(style) != Style::windows) || has_root_name(p, style);
     679             : 
     680     2683022 :   return rootDir && rootName;
     681             : }
     682             : 
     683       65888 : bool is_relative(const Twine &path, Style style) {
     684       65888 :   return !is_absolute(path, style);
     685             : }
     686             : 
     687        2780 : StringRef remove_leading_dotslash(StringRef Path, Style style) {
     688             :   // Remove leading "./" (or ".//" or "././" etc.)
     689        5563 :   while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
     690          13 :     Path = Path.substr(2);
     691          43 :     while (Path.size() > 0 && is_separator(Path[0], style))
     692           6 :       Path = Path.substr(1);
     693             :   }
     694        2780 :   return Path;
     695             : }
     696             : 
     697      726526 : static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
     698             :                                     Style style) {
     699     1453052 :   SmallVector<StringRef, 16> components;
     700             : 
     701             :   // Skip the root path, then look for traversal in the components.
     702      726526 :   StringRef rel = path::relative_path(path, style);
     703     2944515 :   for (StringRef C :
     704     5850619 :        llvm::make_range(path::begin(rel, style), path::end(rel))) {
     705     2976692 :     if (C == ".")
     706       32177 :       continue;
     707             :     // Leading ".." will remain in the path unless it's at the root.
     708     3199850 :     if (remove_dot_dot && C == "..") {
     709      343627 :       if (!components.empty() && components.back() != "..") {
     710       56115 :         components.pop_back();
     711       56115 :         continue;
     712             :       }
     713      462788 :       if (path::is_absolute(path, style))
     714      231391 :         continue;
     715             :     }
     716     2624832 :     components.push_back(C);
     717             :   }
     718             : 
     719     1453052 :   SmallString<256> buffer = path::root_path(path, style);
     720     4748295 :   for (StringRef C : components)
     721    10274868 :     path::append(buffer, style, C);
     722      726526 :   return buffer;
     723             : }
     724             : 
     725      726526 : bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
     726             :                  Style style) {
     727     2906104 :   StringRef p(path.data(), path.size());
     728             : 
     729     1453052 :   SmallString<256> result = remove_dots(p, remove_dot_dot, style);
     730      726526 :   if (result == path)
     731             :     return false;
     732             : 
     733      282034 :   path.swap(result);
     734      282034 :   return true;
     735             : }
     736             : 
     737             : } // end namespace path
     738             : 
     739             : namespace fs {
     740             : 
     741        3499 : std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
     742        3499 :   file_status Status;
     743        3499 :   std::error_code EC = status(Path, Status);
     744        3499 :   if (EC)
     745           0 :     return EC;
     746        3499 :   Result = Status.getUniqueID();
     747        3499 :   return std::error_code();
     748             : }
     749             : 
     750        9505 : std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
     751             :                                  SmallVectorImpl<char> &ResultPath,
     752             :                                  unsigned Mode) {
     753        9505 :   return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
     754             : }
     755             : 
     756         186 : std::error_code createUniqueFile(const Twine &Model,
     757             :                                  SmallVectorImpl<char> &ResultPath) {
     758             :   int Dummy;
     759         186 :   return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
     760             : }
     761             : 
     762             : static std::error_code
     763        4635 : createTemporaryFile(const Twine &Model, int &ResultFD,
     764             :                     llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
     765        9270 :   SmallString<128> Storage;
     766        4635 :   StringRef P = Model.toNullTerminatedStringRef(Storage);
     767             :   assert(P.find_first_of(separators(Style::native)) == StringRef::npos &&
     768             :          "Model must be a simple filename.");
     769             :   // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
     770             :   return createUniqueEntity(P.begin(), ResultFD, ResultPath,
     771       13905 :                             true, owner_read | owner_write, Type);
     772             : }
     773             : 
     774             : static std::error_code
     775        4635 : createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
     776             :                     llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
     777        4635 :   const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
     778       23175 :   return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
     779        9270 :                              Type);
     780             : }
     781             : 
     782         181 : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     783             :                                     int &ResultFD,
     784             :                                     SmallVectorImpl<char> &ResultPath) {
     785         181 :   return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
     786             : }
     787             : 
     788        4454 : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
     789             :                                     SmallVectorImpl<char> &ResultPath) {
     790             :   int Dummy;
     791        4454 :   return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
     792             : }
     793             : 
     794             : 
     795             : // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
     796             : // for consistency. We should try using mkdtemp.
     797          32 : std::error_code createUniqueDirectory(const Twine &Prefix,
     798             :                                       SmallVectorImpl<char> &ResultPath) {
     799             :   int Dummy;
     800          96 :   return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
     801          64 :                             true, 0, FS_Dir);
     802             : }
     803             : 
     804      158903 : static std::error_code make_absolute(const Twine &current_directory,
     805             :                                      SmallVectorImpl<char> &path,
     806             :                                      bool use_current_directory) {
     807      635612 :   StringRef p(path.data(), path.size());
     808             : 
     809      158903 :   bool rootDirectory = path::has_root_directory(p);
     810             :   bool rootName =
     811      158902 :       (real_style(Style::native) != Style::windows) || path::has_root_name(p);
     812             : 
     813             :   // Already absolute.
     814      158902 :   if (rootName && rootDirectory)
     815       16139 :     return std::error_code();
     816             : 
     817             :   // All of the following conditions will need the current directory.
     818      142763 :   SmallString<128> current_dir;
     819      142763 :   if (use_current_directory)
     820      136814 :     current_directory.toVector(current_dir);
     821        5949 :   else if (std::error_code ec = current_path(current_dir))
     822           0 :     return ec;
     823             : 
     824             :   // Relative path. Prepend the current directory.
     825             :   if (!rootName && !rootDirectory) {
     826             :     // Append path to the current directory.
     827             :     path::append(current_dir, p);
     828             :     // Set path to the result.
     829             :     path.swap(current_dir);
     830             :     return std::error_code();
     831             :   }
     832             : 
     833             :   if (!rootName && rootDirectory) {
     834             :     StringRef cdrn = path::root_name(current_dir);
     835             :     SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
     836             :     path::append(curDirRootName, p);
     837             :     // Set path to the result.
     838             :     path.swap(curDirRootName);
     839             :     return std::error_code();
     840             :   }
     841             : 
     842             :   if (rootName && !rootDirectory) {
     843      142764 :     StringRef pRootName      = path::root_name(p);
     844      142764 :     StringRef bRootDirectory = path::root_directory(current_dir);
     845      142764 :     StringRef bRelativePath  = path::relative_path(current_dir);
     846      142764 :     StringRef pRelativePath  = path::relative_path(p);
     847             : 
     848      285528 :     SmallString<128> res;
     849      571056 :     path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
     850      142764 :     path.swap(res);
     851      142764 :     return std::error_code();
     852             :   }
     853             : 
     854             :   llvm_unreachable("All rootName and rootDirectory combinations should have "
     855             :                    "occurred above!");
     856             : }
     857             : 
     858      136874 : std::error_code make_absolute(const Twine &current_directory,
     859             :                               SmallVectorImpl<char> &path) {
     860      136874 :   return make_absolute(current_directory, path, true);
     861             : }
     862             : 
     863       22029 : std::error_code make_absolute(SmallVectorImpl<char> &path) {
     864       22029 :   return make_absolute(Twine(), path, false);
     865             : }
     866             : 
     867        2003 : std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
     868             :                                    perms Perms) {
     869        4006 :   SmallString<128> PathStorage;
     870        2003 :   StringRef P = Path.toStringRef(PathStorage);
     871             : 
     872             :   // Be optimistic and try to create the directory
     873        4006 :   std::error_code EC = create_directory(P, IgnoreExisting, Perms);
     874             :   // If we succeeded, or had any error other than the parent not existing, just
     875             :   // return it.
     876        2452 :   if (EC != errc::no_such_file_or_directory)
     877        1554 :     return EC;
     878             : 
     879             :   // We failed because of a no_such_file_or_directory, try to create the
     880             :   // parent.
     881         449 :   StringRef Parent = path::parent_path(P);
     882         449 :   if (Parent.empty())
     883           0 :     return EC;
     884             : 
     885         898 :   if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
     886           0 :       return EC;
     887             : 
     888         898 :   return create_directory(P, IgnoreExisting, Perms);
     889             : }
     890             : 
     891         309 : std::error_code copy_file(const Twine &From, const Twine &To) {
     892             :   int ReadFD, WriteFD;
     893         309 :   if (std::error_code EC = openFileForRead(From, ReadFD))
     894           4 :     return EC;
     895         305 :   if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
     896           0 :     close(ReadFD);
     897           0 :     return EC;
     898             :   }
     899             : 
     900         305 :   const size_t BufSize = 4096;
     901         305 :   char *Buf = new char[BufSize];
     902         305 :   int BytesRead = 0, BytesWritten = 0;
     903             :   for (;;) {
     904         632 :     BytesRead = read(ReadFD, Buf, BufSize);
     905         632 :     if (BytesRead <= 0)
     906             :       break;
     907         981 :     while (BytesRead) {
     908         327 :       BytesWritten = write(WriteFD, Buf, BytesRead);
     909         327 :       if (BytesWritten < 0)
     910             :         break;
     911         327 :       BytesRead -= BytesWritten;
     912             :     }
     913         327 :     if (BytesWritten < 0)
     914             :       break;
     915             :   }
     916         305 :   close(ReadFD);
     917         305 :   close(WriteFD);
     918         305 :   delete[] Buf;
     919             : 
     920         305 :   if (BytesRead < 0 || BytesWritten < 0)
     921           0 :     return std::error_code(errno, std::generic_category());
     922         305 :   return std::error_code();
     923             : }
     924             : 
     925           1 : ErrorOr<MD5::MD5Result> md5_contents(int FD) {
     926           1 :   MD5 Hash;
     927             : 
     928           1 :   constexpr size_t BufSize = 4096;
     929           3 :   std::vector<uint8_t> Buf(BufSize);
     930           1 :   int BytesRead = 0;
     931             :   for (;;) {
     932           5 :     BytesRead = read(FD, Buf.data(), BufSize);
     933           2 :     if (BytesRead <= 0)
     934             :       break;
     935           3 :     Hash.update(makeArrayRef(Buf.data(), BytesRead));
     936             :   }
     937             : 
     938           1 :   if (BytesRead < 0)
     939           0 :     return std::error_code(errno, std::generic_category());
     940             :   MD5::MD5Result Result;
     941           1 :   Hash.final(Result);
     942             :   return Result;
     943             : }
     944             : 
     945           0 : ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
     946             :   int FD;
     947           0 :   if (auto EC = openFileForRead(Path, FD))
     948           0 :     return EC;
     949             : 
     950           0 :   auto Result = md5_contents(FD);
     951           0 :   close(FD);
     952           0 :   return Result;
     953             : }
     954             : 
     955        3314 : bool exists(file_status status) {
     956        3314 :   return status_known(status) && status.type() != file_type::file_not_found;
     957             : }
     958             : 
     959        3314 : bool status_known(file_status s) {
     960        3314 :   return s.type() != file_type::status_error;
     961             : }
     962             : 
     963           8 : file_type get_file_type(const Twine &Path, bool Follow) {
     964           8 :   file_status st;
     965           8 :   if (status(Path, st, Follow))
     966             :     return file_type::status_error;
     967           8 :   return st.type();
     968             : }
     969             : 
     970        3913 : bool is_directory(file_status status) {
     971        3913 :   return status.type() == file_type::directory_file;
     972             : }
     973             : 
     974        3945 : std::error_code is_directory(const Twine &path, bool &result) {
     975        3945 :   file_status st;
     976        3945 :   if (std::error_code ec = status(path, st))
     977         277 :     return ec;
     978        3668 :   result = is_directory(st);
     979        3668 :   return std::error_code();
     980             : }
     981             : 
     982        1299 : bool is_regular_file(file_status status) {
     983        1299 :   return status.type() == file_type::regular_file;
     984             : }
     985             : 
     986        2180 : std::error_code is_regular_file(const Twine &path, bool &result) {
     987        2180 :   file_status st;
     988        2180 :   if (std::error_code ec = status(path, st))
     989        1874 :     return ec;
     990         306 :   result = is_regular_file(st);
     991         306 :   return std::error_code();
     992             : }
     993             : 
     994           0 : bool is_symlink_file(file_status status) {
     995           0 :   return status.type() == file_type::symlink_file;
     996             : }
     997             : 
     998           0 : std::error_code is_symlink_file(const Twine &path, bool &result) {
     999           0 :   file_status st;
    1000           0 :   if (std::error_code ec = status(path, st, false))
    1001           0 :     return ec;
    1002           0 :   result = is_symlink_file(st);
    1003           0 :   return std::error_code();
    1004             : }
    1005             : 
    1006           0 : bool is_other(file_status status) {
    1007           0 :   return exists(status) &&
    1008           0 :          !is_regular_file(status) &&
    1009           0 :          !is_directory(status);
    1010             : }
    1011             : 
    1012           0 : std::error_code is_other(const Twine &Path, bool &Result) {
    1013           0 :   file_status FileStatus;
    1014           0 :   if (std::error_code EC = status(Path, FileStatus))
    1015           0 :     return EC;
    1016           0 :   Result = is_other(FileStatus);
    1017           0 :   return std::error_code();
    1018             : }
    1019             : 
    1020      112718 : void directory_entry::replace_filename(const Twine &filename, file_status st) {
    1021      450872 :   SmallString<128> path = path::parent_path(Path);
    1022      338154 :   path::append(path, filename);
    1023      338154 :   Path = path.str();
    1024      112718 :   Status = st;
    1025      112718 : }
    1026             : 
    1027      110200 : std::error_code directory_entry::status(file_status &result) const {
    1028      220400 :   return fs::status(Path, result, FollowSymlinks);
    1029             : }
    1030             : 
    1031          25 : ErrorOr<perms> getPermissions(const Twine &Path) {
    1032          25 :   file_status Status;
    1033          25 :   if (std::error_code EC = status(Path, Status))
    1034           0 :     return EC;
    1035             : 
    1036          50 :   return Status.permissions();
    1037             : }
    1038             : 
    1039             : } // end namespace fs
    1040             : } // end namespace sys
    1041             : } // end namespace llvm
    1042             : 
    1043             : // Include the truly platform-specific parts.
    1044             : #if defined(LLVM_ON_UNIX)
    1045             : #include "Unix/Path.inc"
    1046             : #endif
    1047             : #if defined(LLVM_ON_WIN32)
    1048             : #include "Windows/Path.inc"
    1049             : #endif
    1050             : 
    1051             : namespace llvm {
    1052             : namespace sys {
    1053             : namespace path {
    1054             : 
    1055           4 : bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
    1056             :                           const Twine &Path2, const Twine &Path3) {
    1057           4 :   if (getUserCacheDir(Result)) {
    1058           4 :     append(Result, Path1, Path2, Path3);
    1059           4 :     return true;
    1060             :   }
    1061             :   return false;
    1062             : }
    1063             : 
    1064             : } // end namespace path
    1065             : } // end namsspace sys
    1066             : } // end namespace llvm

Generated by: LCOV version 1.13