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 "llvm/Support/Signals.h"
22 #include <cctype>
23 #include <cstring>
24 
25 #if !defined(_MSC_VER) && !defined(__MINGW32__)
26 #include <unistd.h>
27 #else
28 #include <io.h>
29 #endif
30 
31 using namespace llvm;
32 using namespace llvm::support::endian;
33 
34 namespace {
35  using llvm::StringRef;
38 
39  inline Style real_style(Style style) {
40 #ifdef LLVM_ON_WIN32
41  return (style == Style::posix) ? Style::posix : Style::windows;
42 #else
43  return (style == Style::windows) ? Style::windows : Style::posix;
44 #endif
45  }
46 
47  inline const char *separators(Style style) {
48  if (real_style(style) == Style::windows)
49  return "\\/";
50  return "/";
51  }
52 
53  inline char preferred_separator(Style style) {
54  if (real_style(style) == Style::windows)
55  return '\\';
56  return '/';
57  }
58 
59  StringRef find_first_component(StringRef path, Style style) {
60  // Look for this first component in the following order.
61  // * empty (in this case we return an empty string)
62  // * either C: or {//,\\}net.
63  // * {/,\}
64  // * {file,directory}name
65 
66  if (path.empty())
67  return path;
68 
69  if (real_style(style) == Style::windows) {
70  // C:
71  if (path.size() >= 2 &&
72  std::isalpha(static_cast<unsigned char>(path[0])) && path[1] == ':')
73  return path.substr(0, 2);
74  }
75 
76  // //net
77  if ((path.size() > 2) && is_separator(path[0], style) &&
78  path[0] == path[1] && !is_separator(path[2], style)) {
79  // Find the next directory separator.
80  size_t end = path.find_first_of(separators(style), 2);
81  return path.substr(0, end);
82  }
83 
84  // {/,\}
85  if (is_separator(path[0], style))
86  return path.substr(0, 1);
87 
88  // * {file,directory}name
89  size_t end = path.find_first_of(separators(style));
90  return path.substr(0, end);
91  }
92 
93  size_t filename_pos(StringRef str, Style style) {
94  if (str.size() == 2 && is_separator(str[0], style) && str[0] == str[1])
95  return 0;
96 
97  if (str.size() > 0 && is_separator(str[str.size() - 1], style))
98  return str.size() - 1;
99 
100  size_t pos = str.find_last_of(separators(style), str.size() - 1);
101 
102  if (real_style(style) == Style::windows) {
103  if (pos == StringRef::npos)
104  pos = str.find_last_of(':', str.size() - 2);
105  }
106 
107  if (pos == StringRef::npos || (pos == 1 && is_separator(str[0], style)))
108  return 0;
109 
110  return pos + 1;
111  }
112 
113  size_t root_dir_start(StringRef str, Style style) {
114  // case "c:/"
115  if (real_style(style) == Style::windows) {
116  if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style))
117  return 2;
118  }
119 
120  // case "//"
121  if (str.size() == 2 && is_separator(str[0], style) && str[0] == str[1])
122  return StringRef::npos;
123 
124  // case "//net"
125  if (str.size() > 3 && is_separator(str[0], style) && str[0] == str[1] &&
126  !is_separator(str[2], style)) {
127  return str.find_first_of(separators(style), 2);
128  }
129 
130  // case "/"
131  if (str.size() > 0 && is_separator(str[0], style))
132  return 0;
133 
134  return StringRef::npos;
135  }
136 
137  size_t parent_path_end(StringRef path, Style style) {
138  size_t end_pos = filename_pos(path, style);
139 
140  bool filename_was_sep =
141  path.size() > 0 && is_separator(path[end_pos], style);
142 
143  // Skip separators except for root dir.
144  size_t root_dir_pos = root_dir_start(path.substr(0, end_pos), style);
145 
146  while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
147  is_separator(path[end_pos - 1], style))
148  --end_pos;
149 
150  if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
151  return StringRef::npos;
152 
153  return end_pos;
154  }
155 } // end unnamed namespace
156 
157 enum FSEntity {
161 };
162 
163 static std::error_code
164 createUniqueEntity(const Twine &Model, int &ResultFD,
165  SmallVectorImpl<char> &ResultPath, bool MakeAbsolute,
166  unsigned Mode, FSEntity Type,
168  SmallString<128> ModelStorage;
169  Model.toVector(ModelStorage);
170 
171  if (MakeAbsolute) {
172  // Make model absolute by prepending a temp directory if it's not already.
173  if (!sys::path::is_absolute(Twine(ModelStorage))) {
174  SmallString<128> TDir;
176  sys::path::append(TDir, Twine(ModelStorage));
177  ModelStorage.swap(TDir);
178  }
179  }
180 
181  // From here on, DO NOT modify model. It may be needed if the randomly chosen
182  // path already exists.
183  ResultPath = ModelStorage;
184  // Null terminate.
185  ResultPath.push_back(0);
186  ResultPath.pop_back();
187 
188 retry_random_path:
189  // Replace '%' with random chars.
190  for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
191  if (ModelStorage[i] == '%')
192  ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
193  }
194 
195  // Try to open + create the file.
196  switch (Type) {
197  case FS_File: {
198  if (std::error_code EC =
199  sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
200  Flags | sys::fs::F_Excl, Mode)) {
201  if (EC == errc::file_exists)
202  goto retry_random_path;
203  return EC;
204  }
205 
206  return std::error_code();
207  }
208 
209  case FS_Name: {
210  std::error_code EC =
213  return std::error_code();
214  if (EC)
215  return EC;
216  goto retry_random_path;
217  }
218 
219  case FS_Dir: {
220  if (std::error_code EC =
221  sys::fs::create_directory(ResultPath.begin(), false)) {
222  if (EC == errc::file_exists)
223  goto retry_random_path;
224  return EC;
225  }
226  return std::error_code();
227  }
228  }
229  llvm_unreachable("Invalid Type");
230 }
231 
232 namespace llvm {
233 namespace sys {
234 namespace path {
235 
237  const_iterator i;
238  i.Path = path;
239  i.Component = find_first_component(path, style);
240  i.Position = 0;
241  i.S = style;
242  return i;
243 }
244 
246  const_iterator i;
247  i.Path = path;
248  i.Position = path.size();
249  return i;
250 }
251 
252 const_iterator &const_iterator::operator++() {
253  assert(Position < Path.size() && "Tried to increment past end!");
254 
255  // Increment Position to past the current component
256  Position += Component.size();
257 
258  // Check for end.
259  if (Position == Path.size()) {
260  Component = StringRef();
261  return *this;
262  }
263 
264  // Both POSIX and Windows treat paths that begin with exactly two separators
265  // specially.
266  bool was_net = Component.size() > 2 && is_separator(Component[0], S) &&
267  Component[1] == Component[0] && !is_separator(Component[2], S);
268 
269  // Handle separators.
270  if (is_separator(Path[Position], S)) {
271  // Root dir.
272  if (was_net ||
273  // c:/
274  (real_style(S) == Style::windows && Component.endswith(":"))) {
275  Component = Path.substr(Position, 1);
276  return *this;
277  }
278 
279  // Skip extra separators.
280  while (Position != Path.size() && is_separator(Path[Position], S)) {
281  ++Position;
282  }
283 
284  // Treat trailing '/' as a '.'.
285  if (Position == Path.size()) {
286  --Position;
287  Component = ".";
288  return *this;
289  }
290  }
291 
292  // Find next component.
293  size_t end_pos = Path.find_first_of(separators(S), Position);
294  Component = Path.slice(Position, end_pos);
295 
296  return *this;
297 }
298 
300  return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
301 }
302 
304  return Position - RHS.Position;
305 }
306 
309  I.Path = Path;
310  I.Position = Path.size();
311  I.S = style;
312  return ++I;
313 }
314 
317  I.Path = Path;
318  I.Component = Path.substr(0, 0);
319  I.Position = 0;
320  return I;
321 }
322 
323 reverse_iterator &reverse_iterator::operator++() {
324  // If we're at the end and the previous char was a '/', return '.' unless
325  // we are the root path.
326  size_t root_dir_pos = root_dir_start(Path, S);
327  if (Position == Path.size() && Path.size() > root_dir_pos + 1 &&
328  is_separator(Path[Position - 1], S)) {
329  --Position;
330  Component = ".";
331  return *this;
332  }
333 
334  // Skip separators unless it's the root directory.
335  size_t end_pos = Position;
336 
337  while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
338  is_separator(Path[end_pos - 1], S))
339  --end_pos;
340 
341  // Find next separator.
342  size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
343  Component = Path.slice(start_pos, end_pos);
344  Position = start_pos;
345  return *this;
346 }
347 
349  return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
350  Position == RHS.Position;
351 }
352 
354  return Position - RHS.Position;
355 }
356 
358  const_iterator b = begin(path, style), pos = b, e = end(path);
359  if (b != e) {
360  bool has_net =
361  b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
362  bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
363 
364  if (has_net || has_drive) {
365  if ((++pos != e) && is_separator((*pos)[0], style)) {
366  // {C:/,//net/}, so get the first two components.
367  return path.substr(0, b->size() + pos->size());
368  } else {
369  // just {C:,//net}, return the first component.
370  return *b;
371  }
372  }
373 
374  // POSIX style root directory.
375  if (is_separator((*b)[0], style)) {
376  return *b;
377  }
378  }
379 
380  return StringRef();
381 }
382 
384  const_iterator b = begin(path, style), e = end(path);
385  if (b != e) {
386  bool has_net =
387  b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
388  bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
389 
390  if (has_net || has_drive) {
391  // just {C:,//net}, return the first component.
392  return *b;
393  }
394  }
395 
396  // No path or no name.
397  return StringRef();
398 }
399 
401  const_iterator b = begin(path, style), pos = b, e = end(path);
402  if (b != e) {
403  bool has_net =
404  b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
405  bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
406 
407  if ((has_net || has_drive) &&
408  // {C:,//net}, skip to the next component.
409  (++pos != e) && is_separator((*pos)[0], style)) {
410  return *pos;
411  }
412 
413  // POSIX style root directory.
414  if (!has_net && is_separator((*b)[0], style)) {
415  return *b;
416  }
417  }
418 
419  // No path or no root.
420  return StringRef();
421 }
422 
424  StringRef root = root_path(path, style);
425  return path.substr(root.size());
426 }
427 
428 void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
429  const Twine &b, const Twine &c, const Twine &d) {
430  SmallString<32> a_storage;
431  SmallString<32> b_storage;
432  SmallString<32> c_storage;
433  SmallString<32> d_storage;
434 
435  SmallVector<StringRef, 4> components;
436  if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
437  if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
438  if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
439  if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
440 
441  for (auto &component : components) {
442  bool path_has_sep =
443  !path.empty() && is_separator(path[path.size() - 1], style);
444  if (path_has_sep) {
445  // Strip separators from beginning of component.
446  size_t loc = component.find_first_not_of(separators(style));
447  StringRef c = component.substr(loc);
448 
449  // Append it.
450  path.append(c.begin(), c.end());
451  continue;
452  }
453 
454  bool component_has_sep =
455  !component.empty() && is_separator(component[0], style);
456  if (!component_has_sep &&
457  !(path.empty() || has_root_name(component, style))) {
458  // Add a separator.
459  path.push_back(preferred_separator(style));
460  }
461 
462  path.append(component.begin(), component.end());
463  }
464 }
465 
466 void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
467  const Twine &c, const Twine &d) {
468  append(path, Style::native, a, b, c, d);
469 }
470 
472  const_iterator end, Style style) {
473  for (; begin != end; ++begin)
474  path::append(path, style, *begin);
475 }
476 
478  size_t end_pos = parent_path_end(path, style);
479  if (end_pos == StringRef::npos)
480  return StringRef();
481  else
482  return path.substr(0, end_pos);
483 }
484 
486  size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
487  if (end_pos != StringRef::npos)
488  path.set_size(end_pos);
489 }
490 
492  Style style) {
493  StringRef p(path.begin(), path.size());
494  SmallString<32> ext_storage;
495  StringRef ext = extension.toStringRef(ext_storage);
496 
497  // Erase existing extension.
498  size_t pos = p.find_last_of('.');
499  if (pos != StringRef::npos && pos >= filename_pos(p, style))
500  path.set_size(pos);
501 
502  // Append '.' if needed.
503  if (ext.size() > 0 && ext[0] != '.')
504  path.push_back('.');
505 
506  // Append extension.
507  path.append(ext.begin(), ext.end());
508 }
509 
511  const StringRef &OldPrefix, const StringRef &NewPrefix,
512  Style style) {
513  if (OldPrefix.empty() && NewPrefix.empty())
514  return;
515 
516  StringRef OrigPath(Path.begin(), Path.size());
517  if (!OrigPath.startswith(OldPrefix))
518  return;
519 
520  // If prefixes have the same size we can simply copy the new one over.
521  if (OldPrefix.size() == NewPrefix.size()) {
522  std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
523  return;
524  }
525 
526  StringRef RelPath = OrigPath.substr(OldPrefix.size());
527  SmallString<256> NewPath;
528  path::append(NewPath, style, NewPrefix);
529  path::append(NewPath, style, RelPath);
530  Path.swap(NewPath);
531 }
532 
533 void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
534  assert((!path.isSingleStringRef() ||
535  path.getSingleStringRef().data() != result.data()) &&
536  "path and result are not allowed to overlap!");
537  // Clear result.
538  result.clear();
539  path.toVector(result);
540  native(result, style);
541 }
542 
543 void native(SmallVectorImpl<char> &Path, Style style) {
544  if (Path.empty())
545  return;
546  if (real_style(style) == Style::windows) {
547  std::replace(Path.begin(), Path.end(), '/', '\\');
548  if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
549  SmallString<128> PathHome;
550  home_directory(PathHome);
551  PathHome.append(Path.begin() + 1, Path.end());
552  Path = PathHome;
553  }
554  } else {
555  for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
556  if (*PI == '\\') {
557  auto PN = PI + 1;
558  if (PN < PE && *PN == '\\')
559  ++PI; // increment once, the for loop will move over the escaped slash
560  else
561  *PI = '/';
562  }
563  }
564  }
565 }
566 
567 std::string convert_to_slash(StringRef path, Style style) {
568  if (real_style(style) != Style::windows)
569  return path;
570 
571  std::string s = path.str();
572  std::replace(s.begin(), s.end(), '\\', '/');
573  return s;
574 }
575 
576 StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
577 
579  StringRef fname = filename(path, style);
580  size_t pos = fname.find_last_of('.');
581  if (pos == StringRef::npos)
582  return fname;
583  else
584  if ((fname.size() == 1 && fname == ".") ||
585  (fname.size() == 2 && fname == ".."))
586  return fname;
587  else
588  return fname.substr(0, pos);
589 }
590 
592  StringRef fname = filename(path, style);
593  size_t pos = fname.find_last_of('.');
594  if (pos == StringRef::npos)
595  return StringRef();
596  else
597  if ((fname.size() == 1 && fname == ".") ||
598  (fname.size() == 2 && fname == ".."))
599  return StringRef();
600  else
601  return fname.substr(pos);
602 }
603 
604 bool is_separator(char value, Style style) {
605  if (value == '/')
606  return true;
607  if (real_style(style) == Style::windows)
608  return value == '\\';
609  return false;
610 }
611 
613  if (real_style(style) == Style::windows)
614  return "\\";
615  return "/";
616 }
617 
618 bool has_root_name(const Twine &path, Style style) {
619  SmallString<128> path_storage;
620  StringRef p = path.toStringRef(path_storage);
621 
622  return !root_name(p, style).empty();
623 }
624 
625 bool has_root_directory(const Twine &path, Style style) {
626  SmallString<128> path_storage;
627  StringRef p = path.toStringRef(path_storage);
628 
629  return !root_directory(p, style).empty();
630 }
631 
632 bool has_root_path(const Twine &path, Style style) {
633  SmallString<128> path_storage;
634  StringRef p = path.toStringRef(path_storage);
635 
636  return !root_path(p, style).empty();
637 }
638 
639 bool has_relative_path(const Twine &path, Style style) {
640  SmallString<128> path_storage;
641  StringRef p = path.toStringRef(path_storage);
642 
643  return !relative_path(p, style).empty();
644 }
645 
646 bool has_filename(const Twine &path, Style style) {
647  SmallString<128> path_storage;
648  StringRef p = path.toStringRef(path_storage);
649 
650  return !filename(p, style).empty();
651 }
652 
653 bool has_parent_path(const Twine &path, Style style) {
654  SmallString<128> path_storage;
655  StringRef p = path.toStringRef(path_storage);
656 
657  return !parent_path(p, style).empty();
658 }
659 
660 bool has_stem(const Twine &path, Style style) {
661  SmallString<128> path_storage;
662  StringRef p = path.toStringRef(path_storage);
663 
664  return !stem(p, style).empty();
665 }
666 
667 bool has_extension(const Twine &path, Style style) {
668  SmallString<128> path_storage;
669  StringRef p = path.toStringRef(path_storage);
670 
671  return !extension(p, style).empty();
672 }
673 
674 bool is_absolute(const Twine &path, Style style) {
675  SmallString<128> path_storage;
676  StringRef p = path.toStringRef(path_storage);
677 
678  bool rootDir = has_root_directory(p, style);
679  bool rootName =
680  (real_style(style) != Style::windows) || has_root_name(p, style);
681 
682  return rootDir && rootName;
683 }
684 
685 bool is_relative(const Twine &path, Style style) {
686  return !is_absolute(path, style);
687 }
688 
690  // Remove leading "./" (or ".//" or "././" etc.)
691  while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
692  Path = Path.substr(2);
693  while (Path.size() > 0 && is_separator(Path[0], style))
694  Path = Path.substr(1);
695  }
696  return Path;
697 }
698 
699 static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
700  Style style) {
701  SmallVector<StringRef, 16> components;
702 
703  // Skip the root path, then look for traversal in the components.
704  StringRef rel = path::relative_path(path, style);
705  for (StringRef C :
706  llvm::make_range(path::begin(rel, style), path::end(rel))) {
707  if (C == ".")
708  continue;
709  // Leading ".." will remain in the path unless it's at the root.
710  if (remove_dot_dot && C == "..") {
711  if (!components.empty() && components.back() != "..") {
712  components.pop_back();
713  continue;
714  }
715  if (path::is_absolute(path, style))
716  continue;
717  }
718  components.push_back(C);
719  }
720 
721  SmallString<256> buffer = path::root_path(path, style);
722  for (StringRef C : components)
723  path::append(buffer, style, C);
724  return buffer;
725 }
726 
727 bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
728  Style style) {
729  StringRef p(path.data(), path.size());
730 
731  SmallString<256> result = remove_dots(p, remove_dot_dot, style);
732  if (result == path)
733  return false;
734 
735  path.swap(result);
736  return true;
737 }
738 
739 } // end namespace path
740 
741 namespace fs {
742 
743 std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
744  file_status Status;
745  std::error_code EC = status(Path, Status);
746  if (EC)
747  return EC;
748  Result = Status.getUniqueID();
749  return std::error_code();
750 }
751 
752 std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
753  SmallVectorImpl<char> &ResultPath,
754  unsigned Mode, sys::fs::OpenFlags Flags) {
755  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File,
756  Flags);
757 }
758 
759 std::error_code createUniqueFile(const Twine &Model,
760  SmallVectorImpl<char> &ResultPath) {
761  int Dummy;
762  return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
763 }
764 
765 static std::error_code
766 createTemporaryFile(const Twine &Model, int &ResultFD,
768  sys::fs::OpenFlags Flags) {
769  SmallString<128> Storage;
770  StringRef P = Model.toNullTerminatedStringRef(Storage);
772  "Model must be a simple filename.");
773  // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
774  return createUniqueEntity(P.begin(), ResultFD, ResultPath, true,
775  owner_read | owner_write, Type, Flags);
776 }
777 
778 static std::error_code
779 createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
782  const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
783  return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
784  Type, Flags);
785 }
786 
787 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
788  int &ResultFD,
789  SmallVectorImpl<char> &ResultPath,
790  sys::fs::OpenFlags Flags) {
791  return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File,
792  Flags);
793 }
794 
795 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
796  SmallVectorImpl<char> &ResultPath) {
797  int Dummy;
798  return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
799 }
800 
801 
802 // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
803 // for consistency. We should try using mkdtemp.
804 std::error_code createUniqueDirectory(const Twine &Prefix,
805  SmallVectorImpl<char> &ResultPath) {
806  int Dummy;
807  return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
808  true, 0, FS_Dir);
809 }
810 
811 static std::error_code make_absolute(const Twine &current_directory,
812  SmallVectorImpl<char> &path,
813  bool use_current_directory) {
814  StringRef p(path.data(), path.size());
815 
816  bool rootDirectory = path::has_root_directory(p);
817  bool rootName =
818  (real_style(Style::native) != Style::windows) || path::has_root_name(p);
819 
820  // Already absolute.
821  if (rootName && rootDirectory)
822  return std::error_code();
823 
824  // All of the following conditions will need the current directory.
825  SmallString<128> current_dir;
826  if (use_current_directory)
827  current_directory.toVector(current_dir);
828  else if (std::error_code ec = current_path(current_dir))
829  return ec;
830 
831  // Relative path. Prepend the current directory.
832  if (!rootName && !rootDirectory) {
833  // Append path to the current directory.
834  path::append(current_dir, p);
835  // Set path to the result.
836  path.swap(current_dir);
837  return std::error_code();
838  }
839 
840  if (!rootName && rootDirectory) {
841  StringRef cdrn = path::root_name(current_dir);
842  SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
843  path::append(curDirRootName, p);
844  // Set path to the result.
845  path.swap(curDirRootName);
846  return std::error_code();
847  }
848 
849  if (rootName && !rootDirectory) {
850  StringRef pRootName = path::root_name(p);
851  StringRef bRootDirectory = path::root_directory(current_dir);
852  StringRef bRelativePath = path::relative_path(current_dir);
853  StringRef pRelativePath = path::relative_path(p);
854 
855  SmallString<128> res;
856  path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
857  path.swap(res);
858  return std::error_code();
859  }
860 
861  llvm_unreachable("All rootName and rootDirectory combinations should have "
862  "occurred above!");
863 }
864 
865 std::error_code make_absolute(const Twine &current_directory,
866  SmallVectorImpl<char> &path) {
867  return make_absolute(current_directory, path, true);
868 }
869 
870 std::error_code make_absolute(SmallVectorImpl<char> &path) {
871  return make_absolute(Twine(), path, false);
872 }
873 
874 std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
875  perms Perms) {
876  SmallString<128> PathStorage;
877  StringRef P = Path.toStringRef(PathStorage);
878 
879  // Be optimistic and try to create the directory
880  std::error_code EC = create_directory(P, IgnoreExisting, Perms);
881  // If we succeeded, or had any error other than the parent not existing, just
882  // return it.
884  return EC;
885 
886  // We failed because of a no_such_file_or_directory, try to create the
887  // parent.
888  StringRef Parent = path::parent_path(P);
889  if (Parent.empty())
890  return EC;
891 
892  if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
893  return EC;
894 
895  return create_directory(P, IgnoreExisting, Perms);
896 }
897 
898 std::error_code copy_file(const Twine &From, const Twine &To) {
899  int ReadFD, WriteFD;
900  if (std::error_code EC = openFileForRead(From, ReadFD))
901  return EC;
902  if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
903  close(ReadFD);
904  return EC;
905  }
906 
907  const size_t BufSize = 4096;
908  char *Buf = new char[BufSize];
909  int BytesRead = 0, BytesWritten = 0;
910  for (;;) {
911  BytesRead = read(ReadFD, Buf, BufSize);
912  if (BytesRead <= 0)
913  break;
914  while (BytesRead) {
915  BytesWritten = write(WriteFD, Buf, BytesRead);
916  if (BytesWritten < 0)
917  break;
918  BytesRead -= BytesWritten;
919  }
920  if (BytesWritten < 0)
921  break;
922  }
923  close(ReadFD);
924  close(WriteFD);
925  delete[] Buf;
926 
927  if (BytesRead < 0 || BytesWritten < 0)
928  return std::error_code(errno, std::generic_category());
929  return std::error_code();
930 }
931 
933  MD5 Hash;
934 
935  constexpr size_t BufSize = 4096;
936  std::vector<uint8_t> Buf(BufSize);
937  int BytesRead = 0;
938  for (;;) {
939  BytesRead = read(FD, Buf.data(), BufSize);
940  if (BytesRead <= 0)
941  break;
942  Hash.update(makeArrayRef(Buf.data(), BytesRead));
943  }
944 
945  if (BytesRead < 0)
946  return std::error_code(errno, std::generic_category());
947  MD5::MD5Result Result;
948  Hash.final(Result);
949  return Result;
950 }
951 
953  int FD;
954  if (auto EC = openFileForRead(Path, FD))
955  return EC;
956 
957  auto Result = md5_contents(FD);
958  close(FD);
959  return Result;
960 }
961 
963  return status_known(status) && status.type() != file_type::file_not_found;
964 }
965 
967  return s.type() != file_type::status_error;
968 }
969 
970 file_type get_file_type(const Twine &Path, bool Follow) {
971  file_status st;
972  if (status(Path, st, Follow))
973  return file_type::status_error;
974  return st.type();
975 }
976 
978  return status.type() == file_type::directory_file;
979 }
980 
981 std::error_code is_directory(const Twine &path, bool &result) {
982  file_status st;
983  if (std::error_code ec = status(path, st))
984  return ec;
985  result = is_directory(st);
986  return std::error_code();
987 }
988 
990  return status.type() == file_type::regular_file;
991 }
992 
993 std::error_code is_regular_file(const Twine &path, bool &result) {
994  file_status st;
995  if (std::error_code ec = status(path, st))
996  return ec;
997  result = is_regular_file(st);
998  return std::error_code();
999 }
1000 
1002  return status.type() == file_type::symlink_file;
1003 }
1004 
1005 std::error_code is_symlink_file(const Twine &path, bool &result) {
1006  file_status st;
1007  if (std::error_code ec = status(path, st, false))
1008  return ec;
1009  result = is_symlink_file(st);
1010  return std::error_code();
1011 }
1012 
1014  return exists(status) &&
1015  !is_regular_file(status) &&
1016  !is_directory(status);
1017 }
1018 
1019 std::error_code is_other(const Twine &Path, bool &Result) {
1020  file_status FileStatus;
1021  if (std::error_code EC = status(Path, FileStatus))
1022  return EC;
1023  Result = is_other(FileStatus);
1024  return std::error_code();
1025 }
1026 
1027 void directory_entry::replace_filename(const Twine &filename,
1028  basic_file_status st) {
1029  SmallString<128> path = path::parent_path(Path);
1030  path::append(path, filename);
1031  Path = path.str();
1032  Status = st;
1033 }
1034 
1036  file_status Status;
1037  if (std::error_code EC = status(Path, Status))
1038  return EC;
1039 
1040  return Status.permissions();
1041 }
1042 
1043 } // end namespace fs
1044 } // end namespace sys
1045 } // end namespace llvm
1046 
1047 // Include the truly platform-specific parts.
1048 #if defined(LLVM_ON_UNIX)
1049 #include "Unix/Path.inc"
1050 #endif
1051 #if defined(LLVM_ON_WIN32)
1052 #include "Windows/Path.inc"
1053 #endif
1054 
1055 namespace llvm {
1056 namespace sys {
1057 namespace fs {
1058 TempFile::TempFile(StringRef Name, int FD) : TmpName(Name), FD(FD) {}
1059 TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
1060 TempFile &TempFile::operator=(TempFile &&Other) {
1061  TmpName = std::move(Other.TmpName);
1062  FD = Other.FD;
1063  Other.Done = true;
1064  return *this;
1065 }
1066 
1067 TempFile::~TempFile() { assert(Done); }
1068 
1069 Error TempFile::discard() {
1070  Done = true;
1071  std::error_code RemoveEC;
1072 // On windows closing will remove the file.
1073 #ifndef LLVM_ON_WIN32
1074  // Always try to close and remove.
1075  if (!TmpName.empty()) {
1076  RemoveEC = fs::remove(TmpName);
1077  sys::DontRemoveFileOnSignal(TmpName);
1078  }
1079 #endif
1080 
1081  if (!RemoveEC)
1082  TmpName = "";
1083 
1084  if (FD != -1 && close(FD) == -1) {
1085  std::error_code EC = std::error_code(errno, std::generic_category());
1086  return errorCodeToError(EC);
1087  }
1088  FD = -1;
1089 
1090  return errorCodeToError(RemoveEC);
1091 }
1092 
1093 Error TempFile::keep(const Twine &Name) {
1094  assert(!Done);
1095  Done = true;
1096  // Always try to close and rename.
1097 #ifdef LLVM_ON_WIN32
1098  // If we cant't cancel the delete don't rename.
1099  std::error_code RenameEC = cancelDeleteOnClose(FD);
1100  if (!RenameEC)
1101  RenameEC = rename_fd(FD, Name);
1102  // If we can't rename, discard the temporary file.
1103  if (RenameEC)
1104  removeFD(FD);
1105 #else
1106  std::error_code RenameEC = fs::rename(TmpName, Name);
1107  // If we can't rename, discard the temporary file.
1108  if (RenameEC)
1109  remove(TmpName);
1110  sys::DontRemoveFileOnSignal(TmpName);
1111 #endif
1112 
1113  if (!RenameEC)
1114  TmpName = "";
1115 
1116  if (close(FD) == -1) {
1117  std::error_code EC(errno, std::generic_category());
1118  return errorCodeToError(EC);
1119  }
1120  FD = -1;
1121 
1122  return errorCodeToError(RenameEC);
1123 }
1124 
1125 Error TempFile::keep() {
1126  assert(!Done);
1127  Done = true;
1128 
1129 #ifdef LLVM_ON_WIN32
1130  if (std::error_code EC = cancelDeleteOnClose(FD))
1131  return errorCodeToError(EC);
1132 #else
1133  sys::DontRemoveFileOnSignal(TmpName);
1134 #endif
1135 
1136  TmpName = "";
1137 
1138  if (close(FD) == -1) {
1139  std::error_code EC(errno, std::generic_category());
1140  return errorCodeToError(EC);
1141  }
1142  FD = -1;
1143 
1144  return Error::success();
1145 }
1146 
1147 Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) {
1148  int FD;
1149  SmallString<128> ResultPath;
1150  if (std::error_code EC = createUniqueFile(Model, FD, ResultPath, Mode,
1152  return errorCodeToError(EC);
1153 
1154  TempFile Ret(ResultPath, FD);
1155 #ifndef LLVM_ON_WIN32
1156  if (sys::RemoveFileOnSignal(ResultPath)) {
1157  // Make sure we delete the file when RemoveFileOnSignal fails.
1158  consumeError(Ret.discard());
1159  std::error_code EC(errc::operation_not_permitted);
1160  return errorCodeToError(EC);
1161  }
1162 #endif
1163  return std::move(Ret);
1164 }
1165 }
1166 
1167 namespace path {
1168 
1170  const Twine &Path2, const Twine &Path3) {
1171  if (getUserCacheDir(Result)) {
1172  append(Result, Path1, Path2, Path3);
1173  return true;
1174  }
1175  return false;
1176 }
1177 
1178 } // end namespace path
1179 } // end namsspace sys
1180 } // 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:604
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:874
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:245
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:485
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:236
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:510
SI Whole Quad Mode
bool status_known(const basic_file_status &s)
Is status available?
Definition: Path.cpp:966
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 openFileForRead(const Twine &Name, int &ResultFD, SmallVectorImpl< char > *RealPath=nullptr)
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
F_Excl - When opening a file, this flag makes raw_fd_ostream report an error if the file already exis...
Definition: FileSystem.h:674
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:398
StringRef toStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single StringRef if it can be represented as such.
Definition: Twine.h:453
bool has_extension(const Twine &path, Style style=Style::native)
Has extension?
Definition: Path.cpp:667
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.
bool is_directory(const basic_file_status &status)
Does status represent a directory?
Definition: Path.cpp:977
std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
Definition: Path.cpp:567
bool is_regular_file(const basic_file_status &status)
Does status represent a regular file?
Definition: Path.cpp:989
StringRef remove_leading_dotslash(StringRef path, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
Definition: Path.cpp:689
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:219
Definition: Path.cpp:158
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
ErrorOr< MD5::MD5Result > md5_contents(int FD)
Compute an MD5 hash of a file&#39;s contents.
Definition: Path.cpp:932
ErrorOr< perms > getPermissions(const Twine &Path)
Get file permissions.
Definition: Path.cpp:1035
bool has_stem(const Twine &path, Style style=Style::native)
Has stem?
Definition: Path.cpp:660
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:466
reverse_iterator rbegin(StringRef path, Style style=Style::native)
Get reverse begin iterator over path.
Definition: Path.cpp:307
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
Represents a temporary file.
Definition: FileSystem.h:729
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:674
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
StringRef root_path(StringRef path, Style style=Style::native)
Get root path.
Definition: Path.cpp:357
StringRef getSingleStringRef() const
This returns the twine as a single StringRef.
Definition: Twine.h:437
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:736
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:404
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:686
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
static std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, llvm::SmallVectorImpl< char > &ResultPath, FSEntity Type, sys::fs::OpenFlags Flags=sys::fs::F_None)
Definition: Path.cpp:779
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
Represents the result of a call to directory_iterator::status().
Definition: FileSystem.h:148
std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition: Path.cpp:898
#define P(N)
static SmallString< 256 > remove_dots(StringRef path, bool remove_dot_dot, Style style)
Definition: Path.cpp:699
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:653
UniqueID getUniqueID() const
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:78
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:116
bool has_filename(const Twine &path, Style style=Style::native)
Has filename?
Definition: Path.cpp:646
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:1169
std::error_code getUniqueID(const Twine Path, UniqueID &Result)
Definition: Path.cpp:743
file_type get_file_type(const Twine &Path, bool Follow=true)
Does status represent a directory?
Definition: Path.cpp:970
void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:477
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
Definition: Twine.cpp:32
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:962
StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
Definition: Path.cpp:612
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
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:400
void replace_extension(SmallVectorImpl< char > &path, const Twine &extension, Style style=Style::native)
Replace the file extension of path with extension.
Definition: Path.cpp:491
bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=nullptr)
This function registers signal handlers to ensure that if a signal gets delivered that the named file...
StringRef root_name(StringRef path, Style style=Style::native)
Get root name.
Definition: Path.cpp:383
std::error_code createUniqueDirectory(const Twine &Prefix, SmallVectorImpl< char > &ResultPath)
Definition: Path.cpp:804
static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute, unsigned Mode, FSEntity Type, sys::fs::OpenFlags Flags=sys::fs::F_None)
Definition: Path.cpp:164
bool is_other(const basic_file_status &status)
Does this status represent something that exists but is not a directory or regular file...
Definition: Path.cpp:1013
bool has_root_directory(const Twine &path, Style style=Style::native)
Has root directory?
Definition: Path.cpp:625
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:632
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:639
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:57
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:576
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:685
APInt operator-(APInt)
Definition: APInt.h:2023
Definition: MD5.h:41
static void rename(GlobalValue *GV)
Definition: AutoUpgrade.cpp:36
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:315
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:423
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
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?
Delete the file on close. Only makes a difference on windows.
Definition: FileSystem.h:689
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:578
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)
std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, unsigned Mode=all_read|all_write, sys::fs::OpenFlags Flags=sys::fs::F_RW)
Create a uniquely named file.
Definition: Path.cpp:752
bool operator==(uint64_t V1, const APInt &V2)
Definition: APInt.h:1946
bool has_root_name(const Twine &path, Style style=Style::native)
Has root name?
Definition: Path.cpp:618
bool is_symlink_file(const basic_file_status &status)
Does status represent a symlink file?
Definition: Path.cpp:1001
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:962
iterator end() const
Definition: StringRef.h:108
FSEntity
Definition: Path.cpp:157
StringRef extension(StringRef path, Style style=Style::native)
Get extension.
Definition: Path.cpp:591
static std::error_code make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path, bool use_current_directory)
Definition: Path.cpp:811
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, unsigned Mode=0666)