LLVM  6.0.0svn
Path.cpp
Go to the documentation of this file.
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"
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;
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  return (style == Style::windows) ? Style::windows : Style::posix;
43 #endif
44  }
45 
46  inline const char *separators(Style style) {
47  if (real_style(style) == Style::windows)
48  return "\\/";
49  return "/";
50  }
51 
52  inline char preferred_separator(Style style) {
53  if (real_style(style) == Style::windows)
54  return '\\';
55  return '/';
56  }
57 
58  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  if (path.empty())
66  return path;
67 
68  if (real_style(style) == Style::windows) {
69  // C:
70  if (path.size() >= 2 &&
71  std::isalpha(static_cast<unsigned char>(path[0])) && path[1] == ':')
72  return path.substr(0, 2);
73  }
74 
75  // //net
76  if ((path.size() > 2) && is_separator(path[0], style) &&
77  path[0] == path[1] && !is_separator(path[2], style)) {
78  // Find the next directory separator.
79  size_t end = path.find_first_of(separators(style), 2);
80  return path.substr(0, end);
81  }
82 
83  // {/,\}
84  if (is_separator(path[0], style))
85  return path.substr(0, 1);
86 
87  // * {file,directory}name
88  size_t end = path.find_first_of(separators(style));
89  return path.substr(0, end);
90  }
91 
92  size_t filename_pos(StringRef str, Style style) {
93  if (str.size() == 2 && is_separator(str[0], style) && str[0] == str[1])
94  return 0;
95 
96  if (str.size() > 0 && is_separator(str[str.size() - 1], style))
97  return str.size() - 1;
98 
99  size_t pos = str.find_last_of(separators(style), str.size() - 1);
100 
101  if (real_style(style) == Style::windows) {
102  if (pos == StringRef::npos)
103  pos = str.find_last_of(':', str.size() - 2);
104  }
105 
106  if (pos == StringRef::npos || (pos == 1 && is_separator(str[0], style)))
107  return 0;
108 
109  return pos + 1;
110  }
111 
112  size_t root_dir_start(StringRef str, Style style) {
113  // case "c:/"
114  if (real_style(style) == Style::windows) {
115  if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style))
116  return 2;
117  }
118 
119  // case "//"
120  if (str.size() == 2 && is_separator(str[0], style) && str[0] == str[1])
121  return StringRef::npos;
122 
123  // case "//net"
124  if (str.size() > 3 && is_separator(str[0], style) && str[0] == str[1] &&
125  !is_separator(str[2], style)) {
126  return str.find_first_of(separators(style), 2);
127  }
128 
129  // case "/"
130  if (str.size() > 0 && is_separator(str[0], style))
131  return 0;
132 
133  return StringRef::npos;
134  }
135 
136  size_t parent_path_end(StringRef path, Style style) {
137  size_t end_pos = filename_pos(path, style);
138 
139  bool filename_was_sep =
140  path.size() > 0 && is_separator(path[end_pos], style);
141 
142  // Skip separators except for root dir.
143  size_t root_dir_pos = root_dir_start(path.substr(0, end_pos), style);
144 
145  while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
146  is_separator(path[end_pos - 1], style))
147  --end_pos;
148 
149  if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
150  return StringRef::npos;
151 
152  return end_pos;
153  }
154 } // end unnamed namespace
155 
156 enum FSEntity {
160 };
161 
162 static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,
163  SmallVectorImpl<char> &ResultPath,
164  bool MakeAbsolute, unsigned Mode,
165  FSEntity Type) {
166  SmallString<128> ModelStorage;
167  Model.toVector(ModelStorage);
168 
169  if (MakeAbsolute) {
170  // Make model absolute by prepending a temp directory if it's not already.
171  if (!sys::path::is_absolute(Twine(ModelStorage))) {
172  SmallString<128> TDir;
174  sys::path::append(TDir, Twine(ModelStorage));
175  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  ResultPath = ModelStorage;
182  // Null terminate.
183  ResultPath.push_back(0);
184  ResultPath.pop_back();
185 
186 retry_random_path:
187  // Replace '%' with random chars.
188  for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
189  if (ModelStorage[i] == '%')
190  ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
191  }
192 
193  // Try to open + create the file.
194  switch (Type) {
195  case FS_File: {
196  if (std::error_code EC =
197  sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
198  sys::fs::F_RW | sys::fs::F_Excl, Mode)) {
199  if (EC == errc::file_exists)
200  goto retry_random_path;
201  return EC;
202  }
203 
204  return std::error_code();
205  }
206 
207  case FS_Name: {
208  std::error_code EC =
211  return std::error_code();
212  if (EC)
213  return EC;
214  goto retry_random_path;
215  }
216 
217  case FS_Dir: {
218  if (std::error_code EC =
219  sys::fs::create_directory(ResultPath.begin(), false)) {
220  if (EC == errc::file_exists)
221  goto retry_random_path;
222  return EC;
223  }
224  return std::error_code();
225  }
226  }
227  llvm_unreachable("Invalid Type");
228 }
229 
230 namespace llvm {
231 namespace sys {
232 namespace path {
233 
235  const_iterator i;
236  i.Path = path;
237  i.Component = find_first_component(path, style);
238  i.Position = 0;
239  i.S = style;
240  return i;
241 }
242 
244  const_iterator i;
245  i.Path = path;
246  i.Position = path.size();
247  return i;
248 }
249 
250 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  Position += Component.size();
255 
256  // Check for end.
257  if (Position == Path.size()) {
258  Component = StringRef();
259  return *this;
260  }
261 
262  // Both POSIX and Windows treat paths that begin with exactly two separators
263  // specially.
264  bool was_net = Component.size() > 2 && is_separator(Component[0], S) &&
265  Component[1] == Component[0] && !is_separator(Component[2], S);
266 
267  // Handle separators.
268  if (is_separator(Path[Position], S)) {
269  // Root dir.
270  if (was_net ||
271  // c:/
272  (real_style(S) == Style::windows && Component.endswith(":"))) {
273  Component = Path.substr(Position, 1);
274  return *this;
275  }
276 
277  // Skip extra separators.
278  while (Position != Path.size() && is_separator(Path[Position], S)) {
279  ++Position;
280  }
281 
282  // Treat trailing '/' as a '.'.
283  if (Position == Path.size()) {
284  --Position;
285  Component = ".";
286  return *this;
287  }
288  }
289 
290  // Find next component.
291  size_t end_pos = Path.find_first_of(separators(S), Position);
292  Component = Path.slice(Position, end_pos);
293 
294  return *this;
295 }
296 
298  return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
299 }
300 
302  return Position - RHS.Position;
303 }
304 
307  I.Path = Path;
308  I.Position = Path.size();
309  I.S = style;
310  return ++I;
311 }
312 
315  I.Path = Path;
316  I.Component = Path.substr(0, 0);
317  I.Position = 0;
318  return I;
319 }
320 
321 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  size_t root_dir_pos = root_dir_start(Path, S);
325  if (Position == Path.size() && Path.size() > root_dir_pos + 1 &&
326  is_separator(Path[Position - 1], S)) {
327  --Position;
328  Component = ".";
329  return *this;
330  }
331 
332  // Skip separators unless it's the root directory.
333  size_t end_pos = Position;
334 
335  while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
336  is_separator(Path[end_pos - 1], S))
337  --end_pos;
338 
339  // Find next separator.
340  size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
341  Component = Path.slice(start_pos, end_pos);
342  Position = start_pos;
343  return *this;
344 }
345 
347  return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
348  Position == RHS.Position;
349 }
350 
352  return Position - RHS.Position;
353 }
354 
356  const_iterator b = begin(path, style), pos = b, e = end(path);
357  if (b != e) {
358  bool has_net =
359  b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
360  bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
361 
362  if (has_net || has_drive) {
363  if ((++pos != e) && is_separator((*pos)[0], style)) {
364  // {C:/,//net/}, so get the first two components.
365  return path.substr(0, b->size() + pos->size());
366  } else {
367  // just {C:,//net}, return the first component.
368  return *b;
369  }
370  }
371 
372  // POSIX style root directory.
373  if (is_separator((*b)[0], style)) {
374  return *b;
375  }
376  }
377 
378  return StringRef();
379 }
380 
382  const_iterator b = begin(path, style), e = end(path);
383  if (b != e) {
384  bool has_net =
385  b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
386  bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
387 
388  if (has_net || has_drive) {
389  // just {C:,//net}, return the first component.
390  return *b;
391  }
392  }
393 
394  // No path or no name.
395  return StringRef();
396 }
397 
399  const_iterator b = begin(path, style), pos = b, e = end(path);
400  if (b != e) {
401  bool has_net =
402  b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
403  bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
404 
405  if ((has_net || has_drive) &&
406  // {C:,//net}, skip to the next component.
407  (++pos != e) && is_separator((*pos)[0], style)) {
408  return *pos;
409  }
410 
411  // POSIX style root directory.
412  if (!has_net && is_separator((*b)[0], style)) {
413  return *b;
414  }
415  }
416 
417  // No path or no root.
418  return StringRef();
419 }
420 
422  StringRef root = root_path(path, style);
423  return path.substr(root.size());
424 }
425 
426 void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
427  const Twine &b, const Twine &c, const Twine &d) {
428  SmallString<32> a_storage;
429  SmallString<32> b_storage;
430  SmallString<32> c_storage;
431  SmallString<32> d_storage;
432 
433  SmallVector<StringRef, 4> components;
434  if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
435  if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
436  if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
437  if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
438 
439  for (auto &component : components) {
440  bool path_has_sep =
441  !path.empty() && is_separator(path[path.size() - 1], style);
442  bool component_has_sep =
443  !component.empty() && is_separator(component[0], style);
444  bool is_root_name = has_root_name(component, style);
445 
446  if (path_has_sep) {
447  // Strip separators from beginning of component.
448  size_t loc = component.find_first_not_of(separators(style));
449  StringRef c = component.substr(loc);
450 
451  // Append it.
452  path.append(c.begin(), c.end());
453  continue;
454  }
455 
456  if (!component_has_sep && !(path.empty() || is_root_name)) {
457  // Add a separator.
458  path.push_back(preferred_separator(style));
459  }
460 
461  path.append(component.begin(), component.end());
462  }
463 }
464 
465 void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
466  const Twine &c, const Twine &d) {
467  append(path, Style::native, a, b, c, d);
468 }
469 
471  const_iterator end, Style style) {
472  for (; begin != end; ++begin)
473  path::append(path, style, *begin);
474 }
475 
477  size_t end_pos = parent_path_end(path, style);
478  if (end_pos == StringRef::npos)
479  return StringRef();
480  else
481  return path.substr(0, end_pos);
482 }
483 
485  size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
486  if (end_pos != StringRef::npos)
487  path.set_size(end_pos);
488 }
489 
491  Style style) {
492  StringRef p(path.begin(), path.size());
493  SmallString<32> ext_storage;
494  StringRef ext = extension.toStringRef(ext_storage);
495 
496  // Erase existing extension.
497  size_t pos = p.find_last_of('.');
498  if (pos != StringRef::npos && pos >= filename_pos(p, style))
499  path.set_size(pos);
500 
501  // Append '.' if needed.
502  if (ext.size() > 0 && ext[0] != '.')
503  path.push_back('.');
504 
505  // Append extension.
506  path.append(ext.begin(), ext.end());
507 }
508 
510  const StringRef &OldPrefix, const StringRef &NewPrefix,
511  Style style) {
512  if (OldPrefix.empty() && NewPrefix.empty())
513  return;
514 
515  StringRef OrigPath(Path.begin(), Path.size());
516  if (!OrigPath.startswith(OldPrefix))
517  return;
518 
519  // If prefixes have the same size we can simply copy the new one over.
520  if (OldPrefix.size() == NewPrefix.size()) {
521  std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
522  return;
523  }
524 
525  StringRef RelPath = OrigPath.substr(OldPrefix.size());
526  SmallString<256> NewPath;
527  path::append(NewPath, style, NewPrefix);
528  path::append(NewPath, style, RelPath);
529  Path.swap(NewPath);
530 }
531 
532 void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
533  assert((!path.isSingleStringRef() ||
534  path.getSingleStringRef().data() != result.data()) &&
535  "path and result are not allowed to overlap!");
536  // Clear result.
537  result.clear();
538  path.toVector(result);
539  native(result, style);
540 }
541 
542 void native(SmallVectorImpl<char> &Path, Style style) {
543  if (Path.empty())
544  return;
545  if (real_style(style) == Style::windows) {
546  std::replace(Path.begin(), Path.end(), '/', '\\');
547  if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
548  SmallString<128> PathHome;
549  home_directory(PathHome);
550  PathHome.append(Path.begin() + 1, Path.end());
551  Path = PathHome;
552  }
553  } else {
554  for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
555  if (*PI == '\\') {
556  auto PN = PI + 1;
557  if (PN < PE && *PN == '\\')
558  ++PI; // increment once, the for loop will move over the escaped slash
559  else
560  *PI = '/';
561  }
562  }
563  }
564 }
565 
566 std::string convert_to_slash(StringRef path, Style style) {
567  if (real_style(style) != Style::windows)
568  return path;
569 
570  std::string s = path.str();
571  std::replace(s.begin(), s.end(), '\\', '/');
572  return s;
573 }
574 
575 StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
576 
578  StringRef fname = filename(path, style);
579  size_t pos = fname.find_last_of('.');
580  if (pos == StringRef::npos)
581  return fname;
582  else
583  if ((fname.size() == 1 && fname == ".") ||
584  (fname.size() == 2 && fname == ".."))
585  return fname;
586  else
587  return fname.substr(0, pos);
588 }
589 
591  StringRef fname = filename(path, style);
592  size_t pos = fname.find_last_of('.');
593  if (pos == StringRef::npos)
594  return StringRef();
595  else
596  if ((fname.size() == 1 && fname == ".") ||
597  (fname.size() == 2 && fname == ".."))
598  return StringRef();
599  else
600  return fname.substr(pos);
601 }
602 
603 bool is_separator(char value, Style style) {
604  if (value == '/')
605  return true;
606  if (real_style(style) == Style::windows)
607  return value == '\\';
608  return false;
609 }
610 
612  if (real_style(style) == Style::windows)
613  return "\\";
614  return "/";
615 }
616 
617 bool has_root_name(const Twine &path, Style style) {
618  SmallString<128> path_storage;
619  StringRef p = path.toStringRef(path_storage);
620 
621  return !root_name(p, style).empty();
622 }
623 
624 bool has_root_directory(const Twine &path, Style style) {
625  SmallString<128> path_storage;
626  StringRef p = path.toStringRef(path_storage);
627 
628  return !root_directory(p, style).empty();
629 }
630 
631 bool has_root_path(const Twine &path, Style style) {
632  SmallString<128> path_storage;
633  StringRef p = path.toStringRef(path_storage);
634 
635  return !root_path(p, style).empty();
636 }
637 
638 bool has_relative_path(const Twine &path, Style style) {
639  SmallString<128> path_storage;
640  StringRef p = path.toStringRef(path_storage);
641 
642  return !relative_path(p, style).empty();
643 }
644 
645 bool has_filename(const Twine &path, Style style) {
646  SmallString<128> path_storage;
647  StringRef p = path.toStringRef(path_storage);
648 
649  return !filename(p, style).empty();
650 }
651 
652 bool has_parent_path(const Twine &path, Style style) {
653  SmallString<128> path_storage;
654  StringRef p = path.toStringRef(path_storage);
655 
656  return !parent_path(p, style).empty();
657 }
658 
659 bool has_stem(const Twine &path, Style style) {
660  SmallString<128> path_storage;
661  StringRef p = path.toStringRef(path_storage);
662 
663  return !stem(p, style).empty();
664 }
665 
666 bool has_extension(const Twine &path, Style style) {
667  SmallString<128> path_storage;
668  StringRef p = path.toStringRef(path_storage);
669 
670  return !extension(p, style).empty();
671 }
672 
673 bool is_absolute(const Twine &path, Style style) {
674  SmallString<128> path_storage;
675  StringRef p = path.toStringRef(path_storage);
676 
677  bool rootDir = has_root_directory(p, style);
678  bool rootName =
679  (real_style(style) != Style::windows) || has_root_name(p, style);
680 
681  return rootDir && rootName;
682 }
683 
684 bool is_relative(const Twine &path, Style style) {
685  return !is_absolute(path, style);
686 }
687 
689  // Remove leading "./" (or ".//" or "././" etc.)
690  while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
691  Path = Path.substr(2);
692  while (Path.size() > 0 && is_separator(Path[0], style))
693  Path = Path.substr(1);
694  }
695  return Path;
696 }
697 
698 static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
699  Style style) {
700  SmallVector<StringRef, 16> components;
701 
702  // Skip the root path, then look for traversal in the components.
703  StringRef rel = path::relative_path(path, style);
704  for (StringRef C :
705  llvm::make_range(path::begin(rel, style), path::end(rel))) {
706  if (C == ".")
707  continue;
708  // Leading ".." will remain in the path unless it's at the root.
709  if (remove_dot_dot && C == "..") {
710  if (!components.empty() && components.back() != "..") {
711  components.pop_back();
712  continue;
713  }
714  if (path::is_absolute(path, style))
715  continue;
716  }
717  components.push_back(C);
718  }
719 
720  SmallString<256> buffer = path::root_path(path, style);
721  for (StringRef C : components)
722  path::append(buffer, style, C);
723  return buffer;
724 }
725 
726 bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
727  Style style) {
728  StringRef p(path.data(), path.size());
729 
730  SmallString<256> result = remove_dots(p, remove_dot_dot, style);
731  if (result == path)
732  return false;
733 
734  path.swap(result);
735  return true;
736 }
737 
738 } // end namespace path
739 
740 namespace fs {
741 
742 std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
743  file_status Status;
744  std::error_code EC = status(Path, Status);
745  if (EC)
746  return EC;
747  Result = Status.getUniqueID();
748  return std::error_code();
749 }
750 
751 std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
752  SmallVectorImpl<char> &ResultPath,
753  unsigned Mode) {
754  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
755 }
756 
757 std::error_code createUniqueFile(const Twine &Model,
758  SmallVectorImpl<char> &ResultPath) {
759  int Dummy;
760  return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
761 }
762 
763 static std::error_code
764 createTemporaryFile(const Twine &Model, int &ResultFD,
766  SmallString<128> Storage;
767  StringRef P = Model.toNullTerminatedStringRef(Storage);
769  "Model must be a simple filename.");
770  // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
771  return createUniqueEntity(P.begin(), ResultFD, ResultPath,
772  true, owner_read | owner_write, Type);
773 }
774 
775 static std::error_code
776 createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
778  const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
779  return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
780  Type);
781 }
782 
783 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
784  int &ResultFD,
785  SmallVectorImpl<char> &ResultPath) {
786  return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
787 }
788 
789 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
790  SmallVectorImpl<char> &ResultPath) {
791  int Dummy;
792  return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
793 }
794 
795 
796 // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
797 // for consistency. We should try using mkdtemp.
798 std::error_code createUniqueDirectory(const Twine &Prefix,
799  SmallVectorImpl<char> &ResultPath) {
800  int Dummy;
801  return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
802  true, 0, FS_Dir);
803 }
804 
805 static std::error_code make_absolute(const Twine &current_directory,
806  SmallVectorImpl<char> &path,
807  bool use_current_directory) {
808  StringRef p(path.data(), path.size());
809 
810  bool rootDirectory = path::has_root_directory(p);
811  bool rootName =
812  (real_style(Style::native) != Style::windows) || path::has_root_name(p);
813 
814  // Already absolute.
815  if (rootName && rootDirectory)
816  return std::error_code();
817 
818  // All of the following conditions will need the current directory.
819  SmallString<128> current_dir;
820  if (use_current_directory)
821  current_directory.toVector(current_dir);
822  else if (std::error_code ec = current_path(current_dir))
823  return ec;
824 
825  // Relative path. Prepend the current directory.
826  if (!rootName && !rootDirectory) {
827  // Append path to the current directory.
828  path::append(current_dir, p);
829  // Set path to the result.
830  path.swap(current_dir);
831  return std::error_code();
832  }
833 
834  if (!rootName && rootDirectory) {
835  StringRef cdrn = path::root_name(current_dir);
836  SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
837  path::append(curDirRootName, p);
838  // Set path to the result.
839  path.swap(curDirRootName);
840  return std::error_code();
841  }
842 
843  if (rootName && !rootDirectory) {
844  StringRef pRootName = path::root_name(p);
845  StringRef bRootDirectory = path::root_directory(current_dir);
846  StringRef bRelativePath = path::relative_path(current_dir);
847  StringRef pRelativePath = path::relative_path(p);
848 
849  SmallString<128> res;
850  path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
851  path.swap(res);
852  return std::error_code();
853  }
854 
855  llvm_unreachable("All rootName and rootDirectory combinations should have "
856  "occurred above!");
857 }
858 
859 std::error_code make_absolute(const Twine &current_directory,
860  SmallVectorImpl<char> &path) {
861  return make_absolute(current_directory, path, true);
862 }
863 
864 std::error_code make_absolute(SmallVectorImpl<char> &path) {
865  return make_absolute(Twine(), path, false);
866 }
867 
868 std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
869  perms Perms) {
870  SmallString<128> PathStorage;
871  StringRef P = Path.toStringRef(PathStorage);
872 
873  // Be optimistic and try to create the directory
874  std::error_code EC = create_directory(P, IgnoreExisting, Perms);
875  // If we succeeded, or had any error other than the parent not existing, just
876  // return it.
878  return EC;
879 
880  // We failed because of a no_such_file_or_directory, try to create the
881  // parent.
882  StringRef Parent = path::parent_path(P);
883  if (Parent.empty())
884  return EC;
885 
886  if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
887  return EC;
888 
889  return create_directory(P, IgnoreExisting, Perms);
890 }
891 
892 std::error_code copy_file(const Twine &From, const Twine &To) {
893  int ReadFD, WriteFD;
894  if (std::error_code EC = openFileForRead(From, ReadFD))
895  return EC;
896  if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
897  close(ReadFD);
898  return EC;
899  }
900 
901  const size_t BufSize = 4096;
902  char *Buf = new char[BufSize];
903  int BytesRead = 0, BytesWritten = 0;
904  for (;;) {
905  BytesRead = read(ReadFD, Buf, BufSize);
906  if (BytesRead <= 0)
907  break;
908  while (BytesRead) {
909  BytesWritten = write(WriteFD, Buf, BytesRead);
910  if (BytesWritten < 0)
911  break;
912  BytesRead -= BytesWritten;
913  }
914  if (BytesWritten < 0)
915  break;
916  }
917  close(ReadFD);
918  close(WriteFD);
919  delete[] Buf;
920 
921  if (BytesRead < 0 || BytesWritten < 0)
922  return std::error_code(errno, std::generic_category());
923  return std::error_code();
924 }
925 
927  MD5 Hash;
928 
929  constexpr size_t BufSize = 4096;
930  std::vector<uint8_t> Buf(BufSize);
931  int BytesRead = 0;
932  for (;;) {
933  BytesRead = read(FD, Buf.data(), BufSize);
934  if (BytesRead <= 0)
935  break;
936  Hash.update(makeArrayRef(Buf.data(), BytesRead));
937  }
938 
939  if (BytesRead < 0)
940  return std::error_code(errno, std::generic_category());
941  MD5::MD5Result Result;
942  Hash.final(Result);
943  return Result;
944 }
945 
947  int FD;
948  if (auto EC = openFileForRead(Path, FD))
949  return EC;
950 
951  auto Result = md5_contents(FD);
952  close(FD);
953  return Result;
954 }
955 
957  return status_known(status) && status.type() != file_type::file_not_found;
958 }
959 
961  return s.type() != file_type::status_error;
962 }
963 
964 file_type get_file_type(const Twine &Path, bool Follow) {
965  file_status st;
966  if (status(Path, st, Follow))
967  return file_type::status_error;
968  return st.type();
969 }
970 
972  return status.type() == file_type::directory_file;
973 }
974 
975 std::error_code is_directory(const Twine &path, bool &result) {
976  file_status st;
977  if (std::error_code ec = status(path, st))
978  return ec;
979  result = is_directory(st);
980  return std::error_code();
981 }
982 
984  return status.type() == file_type::regular_file;
985 }
986 
987 std::error_code is_regular_file(const Twine &path, bool &result) {
988  file_status st;
989  if (std::error_code ec = status(path, st))
990  return ec;
991  result = is_regular_file(st);
992  return std::error_code();
993 }
994 
996  return status.type() == file_type::symlink_file;
997 }
998 
999 std::error_code is_symlink_file(const Twine &path, bool &result) {
1000  file_status st;
1001  if (std::error_code ec = status(path, st, false))
1002  return ec;
1003  result = is_symlink_file(st);
1004  return std::error_code();
1005 }
1006 
1008  return exists(status) &&
1009  !is_regular_file(status) &&
1010  !is_directory(status);
1011 }
1012 
1013 std::error_code is_other(const Twine &Path, bool &Result) {
1014  file_status FileStatus;
1015  if (std::error_code EC = status(Path, FileStatus))
1016  return EC;
1017  Result = is_other(FileStatus);
1018  return std::error_code();
1019 }
1020 
1021 void directory_entry::replace_filename(const Twine &filename, file_status st) {
1022  SmallString<128> path = path::parent_path(Path);
1023  path::append(path, filename);
1024  Path = path.str();
1025  Status = st;
1026 }
1027 
1028 std::error_code directory_entry::status(file_status &result) const {
1029  return fs::status(Path, result, FollowSymlinks);
1030 }
1031 
1033  file_status Status;
1034  if (std::error_code EC = status(Path, Status))
1035  return EC;
1036 
1037  return Status.permissions();
1038 }
1039 
1040 } // end namespace fs
1041 } // end namespace sys
1042 } // end namespace llvm
1043 
1044 // Include the truly platform-specific parts.
1045 #if defined(LLVM_ON_UNIX)
1046 #include "Unix/Path.inc"
1047 #endif
1048 #if defined(LLVM_ON_WIN32)
1049 #include "Windows/Path.inc"
1050 #endif
1051 
1052 namespace llvm {
1053 namespace sys {
1054 namespace path {
1055 
1057  const Twine &Path2, const Twine &Path3) {
1058  if (getUserCacheDir(Result)) {
1059  append(Result, Path1, Path2, Path3);
1060  return true;
1061  }
1062  return false;
1063 }
1064 
1065 } // end namespace path
1066 } // end namsspace sys
1067 } // end namespace llvm
uint64_t CallInst * C
void push_back(const T &Elt)
Definition: SmallVector.h:212
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
Definition: Path.cpp:603
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition: Path.cpp:868
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:243
Represents either an error or a value T.
Definition: ErrorOr.h:69
void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)
Remove the last component from path unless it is the root dir.
Definition: Path.cpp:484
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:228
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:234
void replace_path_prefix(SmallVectorImpl< char > &Path, const StringRef &OldPrefix, const StringRef &NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
Definition: Path.cpp:509
SI Whole Quad Mode
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:136
std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, unsigned Mode=all_read|all_write)
Create a uniquely named file.
Definition: Path.cpp:751
std::error_code openFileForRead(const Twine &Name, int &ResultFD, SmallVectorImpl< char > *RealPath=nullptr)
F_Excl - When opening a file, this flag makes raw_fd_ostream report an error if the file already exis...
Definition: FileSystem.h:699
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
bool isTriviallyEmpty() const
Check if this twine is trivially empty; a false return value does not necessarily mean the twine is e...
Definition: Twine.h:408
StringRef toStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single StringRef if it can be represented as such.
Definition: Twine.h:463
static std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, llvm::SmallVectorImpl< char > &ResultPath, FSEntity Type)
Definition: Path.cpp:776
bool has_extension(const Twine &path, Style style=Style::native)
Has extension?
Definition: Path.cpp:666
LLVM_NODISCARD size_t find_last_of(char C, size_t From=npos) const
Find the last character in the string that is C, or npos if not found.
Definition: StringRef.h:421
std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
Definition: Path.cpp:566
StringRef remove_leading_dotslash(StringRef path, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
Definition: Path.cpp:688
static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute, unsigned Mode, FSEntity Type)
Definition: Path.cpp:162
file_status - Represents the result of a call to stat and friends.
Definition: FileSystem.h:146
Definition: Path.cpp:157
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
bool status_known(file_status s)
Is status available?
Definition: Path.cpp:960
ErrorOr< MD5::MD5Result > md5_contents(int FD)
Compute an MD5 hash of a file&#39;s contents.
Definition: Path.cpp:926
ErrorOr< perms > getPermissions(const Twine &Path)
Get file permissions.
Definition: Path.cpp:1032
bool has_stem(const Twine &path, Style style=Style::native)
Has stem?
Definition: Path.cpp:659
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:465
reverse_iterator rbegin(StringRef path, Style style=Style::native)
Get reverse begin iterator over path.
Definition: Path.cpp:305
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:451
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
Definition: MD5.cpp:189
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:673
StringRef root_path(StringRef path, Style style=Style::native)
Get root path.
Definition: Path.cpp:355
StringRef getSingleStringRef() const
This returns the twine as a single StringRef.
Definition: Twine.h:447
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:267
bool isSingleStringRef() const
Return true if this twine can be dynamically accessed as a single StringRef value with getSingleStrin...
Definition: Twine.h:414
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
Open the file for read and write.
Definition: FileSystem.h:711
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:598
bool is_symlink_file(file_status status)
Does status represent a symlink file?
Definition: Path.cpp:995
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:100
void append(in_iter S, in_iter E)
Append from an iterator pair.
Definition: SmallString.h:75
std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition: Path.cpp:892
#define P(N)
static SmallString< 256 > remove_dots(StringRef path, bool remove_dot_dot, Style style)
Definition: Path.cpp:698
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
void swap(SmallVectorImpl &RHS)
Definition: SmallVector.h:696
bool has_parent_path(const Twine &path, Style style=Style::native)
Has parent path?
Definition: Path.cpp:652
UniqueID getUniqueID() const
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:116
bool is_other(file_status status)
Does this status represent something that exists but is not a directory or regular file...
Definition: Path.cpp:1007
bool has_filename(const Twine &path, Style style=Style::native)
Has filename?
Definition: Path.cpp:645
StringRef toNullTerminatedStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single null terminated StringRef if it can be represented as such...
Definition: Twine.cpp:37
bool user_cache_directory(SmallVectorImpl< char > &Result, const Twine &Path1, const Twine &Path2="", const Twine &Path3="")
Get the user&#39;s cache directory.
Definition: Path.cpp:1056
std::error_code getUniqueID(const Twine Path, UniqueID &Result)
Definition: Path.cpp:742
file_type get_file_type(const Twine &Path, bool Follow=true)
Does status represent a directory?
Definition: Path.cpp:964
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:476
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
Definition: Twine.cpp:32
StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
Definition: Path.cpp:611
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool is_directory(file_status status)
Does status represent a directory?
Definition: Path.cpp:971
perms permissions() const
Definition: FileSystem.h:207
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:864
StringRef root_directory(StringRef path, Style style=Style::native)
Get root directory.
Definition: Path.cpp:398
void replace_extension(SmallVectorImpl< char > &path, const Twine &extension, Style style=Style::native)
Replace the file extension of path with extension.
Definition: Path.cpp:490
StringRef root_name(StringRef path, Style style=Style::native)
Get root name.
Definition: Path.cpp:381
std::error_code createUniqueDirectory(const Twine &Prefix, SmallVectorImpl< char > &ResultPath)
Definition: Path.cpp:798
bool is_regular_file(file_status status)
Does status represent a regular file?
Definition: Path.cpp:983
bool has_root_directory(const Twine &path, Style style=Style::native)
Has root directory?
Definition: Path.cpp:624
Path iterator.
Definition: Path.h:52
iterator begin() const
Definition: StringRef.h:106
Reverse path iterator.
Definition: Path.h:78
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:398
bool has_root_path(const Twine &path, Style style=Style::native)
Has root path?
Definition: Path.cpp:631
static unsigned GetRandomNumber()
Get the result of a process wide random number generator.
bool has_relative_path(const Twine &path, Style style=Style::native)
Has relative path?
Definition: Path.cpp:638
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:120
void set_size(size_type N)
Set the array size to N, which the current array must have enough capacity for.
Definition: SmallVector.h:689
Provides a library for accessing information about this process and other processes on the operating ...
pointer data()
Return a pointer to the vector&#39;s buffer, even if empty().
Definition: SmallVector.h:143
static const size_t npos
Definition: StringRef.h:51
file_type
An enumeration for the file system&#39;s view of the type.
Definition: FileSystem.h:56
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:575
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:61
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition: Endian.h:66
LLVM_NODISCARD size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
Definition: StringRef.h:395
#define I(x, y, z)
Definition: MD5.cpp:58
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
Definition: Path.cpp:684
APInt operator-(APInt)
Definition: APInt.h:2023
Definition: MD5.h:41
std::error_code create_directory(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create the directory in path.
reverse_iterator rend(StringRef path)
Get reverse end iterator over path.
Definition: Path.cpp:313
file_type type() const
Definition: FileSystem.h:206
void system_temp_directory(bool erasedOnReboot, SmallVectorImpl< char > &result)
Get the typical temporary directory for the system, e.g., "/var/tmp" or "C:/TEMP".
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef relative_path(StringRef path, Style style=Style::native)
Get relative path.
Definition: Path.cpp:421
bool home_directory(SmallVectorImpl< char > &result)
Get the user&#39;s home directory.
std::error_code access(const Twine &Path, AccessMode Mode)
Can the file be accessed?
std::string Hash(const Unit &U)
Definition: FuzzerSHA1.cpp:216
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
Definition: MD5.cpp:234
StringRef stem(StringRef path, Style style=Style::native)
Get stem.
Definition: Path.cpp:577
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
static Expected< std::string > replace(StringRef S, StringRef From, StringRef To)
bool operator==(uint64_t V1, const APInt &V2)
Definition: APInt.h:1946
bool exists(file_status status)
Does file exist?
Definition: Path.cpp:956
bool has_root_name(const Twine &path, Style style=Style::native)
Has root name?
Definition: Path.cpp:617
iterator end() const
Definition: StringRef.h:108
FSEntity
Definition: Path.cpp:156
StringRef extension(StringRef path, Style style=Style::native)
Get extension.
Definition: Path.cpp:590
static std::error_code make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path, bool use_current_directory)
Definition: Path.cpp:805
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, unsigned Mode=0666)