1//===-- Path.cpp - Implement OS Path Concept ------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file implements the operating system Path API.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Support/Path.h"
14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/Config/llvm-config.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 "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
31using namespace llvm;
32using namespace llvm::support::endian;
33
34namespace {
35  using llvm::StringRef;
36  using llvm::sys::path::is_separator;
37  using llvm::sys::path::Style;
38
39  inline Style real_style(Style style) {
40#ifdef _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  // Returns the first character of the filename in str. For paths ending in
94  // '/', it returns the position of the '/'.
95  size_t filename_pos(StringRef str, Style style) {
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  // Returns the position of the root directory in str. If there is no root
113  // directory in str, it returns StringRef::npos.
114  size_t root_dir_start(StringRef str, Style style) {
115    // case "c:/"
116    if (real_style(style) == Style::windows) {
117      if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style))
118        return 2;
119    }
120
121    // case "//net"
122    if (str.size() > 3 && is_separator(str[0], style) && str[0] == str[1] &&
123        !is_separator(str[2], style)) {
124      return str.find_first_of(separators(style), 2);
125    }
126
127    // case "/"
128    if (str.size() > 0 && is_separator(str[0], style))
129      return 0;
130
131    return StringRef::npos;
132  }
133
134  // Returns the position past the end of the "parent path" of path. The parent
135  // path will not end in '/', unless the parent is the root directory. If the
136  // path has no parent, 0 is returned.
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 until we reach root dir (or the start of the string).
144    size_t root_dir_pos = root_dir_start(path, style);
145    while (end_pos > 0 &&
146           (root_dir_pos == StringRef::npos || end_pos > root_dir_pos) &&
147           is_separator(path[end_pos - 1], style))
148      --end_pos;
149
150    if (end_pos == root_dir_pos && !filename_was_sep) {
151      // We've reached the root dir and the input path was *not* ending in a
152      // sequence of slashes. Include the root dir in the parent path.
153      return root_dir_pos + 1;
154    }
155
156    // Otherwise, just include before the last slash.
157    return end_pos;
158  }
159} // end unnamed namespace
160
161enum FSEntity {
162  FS_Dir,
163  FS_File,
164  FS_Name
165};
166
167static std::error_code
168createUniqueEntity(const Twine &Model, int &ResultFD,
169                   SmallVectorImpl<char> &ResultPath, bool MakeAbsolute,
170                   unsigned Mode, FSEntity Type,
171                   sys::fs::OpenFlags Flags = sys::fs::OF_None) {
172
173  // Limit the number of attempts we make, so that we don't infinite loop. E.g.
174  // "permission denied" could be for a specific file (so we retry with a
175  // different name) or for the whole directory (retry would always fail).
176  // Checking which is racy, so we try a number of times, then give up.
177  std::error_code EC;
178  for (int Retries = 128; Retries > 0; --Retries) {
179    sys::fs::createUniquePath(Model, ResultPath, MakeAbsolute);
180    // Try to open + create the file.
181    switch (Type) {
182    case FS_File: {
183      EC = sys::fs::openFileForReadWrite(Twine(ResultPath.begin()), ResultFD,
184                                         sys::fs::CD_CreateNew, Flags, Mode);
185      if (EC) {
186        // errc::permission_denied happens on Windows when we try to open a file
187        // that has been marked for deletion.
188        if (EC == errc::file_exists || EC == errc::permission_denied)
189          continue;
190        return EC;
191      }
192
193      return std::error_code();
194    }
195
196    case FS_Name: {
197      EC = sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
198      if (EC == errc::no_such_file_or_directory)
199        return std::error_code();
200      if (EC)
201        return EC;
202      continue;
203    }
204
205    case FS_Dir: {
206      EC = sys::fs::create_directory(ResultPath.begin(), false);
207      if (EC) {
208        if (EC == errc::file_exists)
209          continue;
210        return EC;
211      }
212      return std::error_code();
213    }
214    }
215    llvm_unreachable("Invalid Type");
216  }
217  return EC;
218}
219
220namespace llvm {
221namespace sys  {
222namespace path {
223
224const_iterator begin(StringRef path, Style style) {
225  const_iterator i;
226  i.Path      = path;
227  i.Component = find_first_component(path, style);
228  i.Position  = 0;
229  i.S = style;
230  return i;
231}
232
233const_iterator end(StringRef path) {
234  const_iterator i;
235  i.Path      = path;
236  i.Position  = path.size();
237  return i;
238}
239
240const_iterator &const_iterator::operator++() {
241  assert(Position < Path.size() && "Tried to increment past end!");
242
243  // Increment Position to past the current component
244  Position += Component.size();
245
246  // Check for end.
247  if (Position == Path.size()) {
248    Component = StringRef();
249    return *this;
250  }
251
252  // Both POSIX and Windows treat paths that begin with exactly two separators
253  // specially.
254  bool was_net = Component.size() > 2 && is_separator(Component[0], S) &&
255                 Component[1] == Component[0] && !is_separator(Component[2], S);
256
257  // Handle separators.
258  if (is_separator(Path[Position], S)) {
259    // Root dir.
260    if (was_net ||
261        // c:/
262        (real_style(S) == Style::windows && Component.endswith(":"))) {
263      Component = Path.substr(Position, 1);
264      return *this;
265    }
266
267    // Skip extra separators.
268    while (Position != Path.size() && is_separator(Path[Position], S)) {
269      ++Position;
270    }
271
272    // Treat trailing '/' as a '.', unless it is the root dir.
273    if (Position == Path.size() && Component != "/") {
274      --Position;
275      Component = ".";
276      return *this;
277    }
278  }
279
280  // Find next component.
281  size_t end_pos = Path.find_first_of(separators(S), Position);
282  Component = Path.slice(Position, end_pos);
283
284  return *this;
285}
286
287bool const_iterator::operator==(const const_iterator &RHS) const {
288  return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
289}
290
291ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
292  return Position - RHS.Position;
293}
294
295reverse_iterator rbegin(StringRef Path, Style style) {
296  reverse_iterator I;
297  I.Path = Path;
298  I.Position = Path.size();
299  I.S = style;
300  ++I;
301  return I;
302}
303
304reverse_iterator rend(StringRef Path) {
305  reverse_iterator I;
306  I.Path = Path;
307  I.Component = Path.substr(0, 0);
308  I.Position = 0;
309  return I;
310}
311
312reverse_iterator &reverse_iterator::operator++() {
313  size_t root_dir_pos = root_dir_start(Path, S);
314
315  // Skip separators unless it's the root directory.
316  size_t end_pos = Position;
317  while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
318         is_separator(Path[end_pos - 1], S))
319    --end_pos;
320
321  // Treat trailing '/' as a '.', unless it is the root dir.
322  if (Position == Path.size() && !Path.empty() &&
323      is_separator(Path.back(), S) &&
324      (root_dir_pos == StringRef::npos || end_pos - 1 > root_dir_pos)) {
325    --Position;
326    Component = ".";
327    return *this;
328  }
329
330  // Find next separator.
331  size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
332  Component = Path.slice(start_pos, end_pos);
333  Position = start_pos;
334  return *this;
335}
336
337bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
338  return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
339         Position == RHS.Position;
340}
341
342ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
343  return Position - RHS.Position;
344}
345
346StringRef root_path(StringRef path, Style style) {
347  const_iterator b = begin(path, style), pos = b, e = end(path);
348  if (b != e) {
349    bool has_net =
350        b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
351    bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
352
353    if (has_net || has_drive) {
354      if ((++pos != e) && is_separator((*pos)[0], style)) {
355        // {C:/,//net/}, so get the first two components.
356        return path.substr(0, b->size() + pos->size());
357      } else {
358        // just {C:,//net}, return the first component.
359        return *b;
360      }
361    }
362
363    // POSIX style root directory.
364    if (is_separator((*b)[0], style)) {
365      return *b;
366    }
367  }
368
369  return StringRef();
370}
371
372StringRef root_name(StringRef path, Style style) {
373  const_iterator b = begin(path, style), e = end(path);
374  if (b != e) {
375    bool has_net =
376        b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
377    bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
378
379    if (has_net || has_drive) {
380      // just {C:,//net}, return the first component.
381      return *b;
382    }
383  }
384
385  // No path or no name.
386  return StringRef();
387}
388
389StringRef root_directory(StringRef path, Style style) {
390  const_iterator b = begin(path, style), pos = b, e = end(path);
391  if (b != e) {
392    bool has_net =
393        b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
394    bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
395
396    if ((has_net || has_drive) &&
397        // {C:,//net}, skip to the next component.
398        (++pos != e) && is_separator((*pos)[0], style)) {
399      return *pos;
400    }
401
402    // POSIX style root directory.
403    if (!has_net && is_separator((*b)[0], style)) {
404      return *b;
405    }
406  }
407
408  // No path or no root.
409  return StringRef();
410}
411
412StringRef relative_path(StringRef path, Style style) {
413  StringRef root = root_path(path, style);
414  return path.substr(root.size());
415}
416
417void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
418            const Twine &b, const Twine &c, const Twine &d) {
419  SmallString<32> a_storage;
420  SmallString<32> b_storage;
421  SmallString<32> c_storage;
422  SmallString<32> d_storage;
423
424  SmallVector<StringRef, 4> components;
425  if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
426  if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
427  if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
428  if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
429
430  for (auto &component : components) {
431    bool path_has_sep =
432        !path.empty() && is_separator(path[path.size() - 1], style);
433    if (path_has_sep) {
434      // Strip separators from beginning of component.
435      size_t loc = component.find_first_not_of(separators(style));
436      StringRef c = component.substr(loc);
437
438      // Append it.
439      path.append(c.begin(), c.end());
440      continue;
441    }
442
443    bool component_has_sep =
444        !component.empty() && is_separator(component[0], style);
445    if (!component_has_sep &&
446        !(path.empty() || has_root_name(component, style))) {
447      // Add a separator.
448      path.push_back(preferred_separator(style));
449    }
450
451    path.append(component.begin(), component.end());
452  }
453}
454
455void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
456            const Twine &c, const Twine &d) {
457  append(path, Style::native, a, b, c, d);
458}
459
460void append(SmallVectorImpl<char> &path, const_iterator begin,
461            const_iterator end, Style style) {
462  for (; begin != end; ++begin)
463    path::append(path, style, *begin);
464}
465
466StringRef parent_path(StringRef path, Style style) {
467  size_t end_pos = parent_path_end(path, style);
468  if (end_pos == StringRef::npos)
469    return StringRef();
470  else
471    return path.substr(0, end_pos);
472}
473
474void remove_filename(SmallVectorImpl<char> &path, Style style) {
475  size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
476  if (end_pos != StringRef::npos)
477    path.set_size(end_pos);
478}
479
480void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
481                       Style style) {
482  StringRef p(path.begin(), path.size());
483  SmallString<32> ext_storage;
484  StringRef ext = extension.toStringRef(ext_storage);
485
486  // Erase existing extension.
487  size_t pos = p.find_last_of('.');
488  if (pos != StringRef::npos && pos >= filename_pos(p, style))
489    path.set_size(pos);
490
491  // Append '.' if needed.
492  if (ext.size() > 0 && ext[0] != '.')
493    path.push_back('.');
494
495  // Append extension.
496  path.append(ext.begin(), ext.end());
497}
498
499static bool starts_with(StringRef Path, StringRef Prefix,
500                        Style style = Style::native) {
501  // Windows prefix matching : case and separator insensitive
502  if (real_style(style) == Style::windows) {
503    if (Path.size() < Prefix.size())
504      return false;
505    for (size_t I = 0, E = Prefix.size(); I != E; ++I) {
506      bool SepPath = is_separator(Path[I], style);
507      bool SepPrefix = is_separator(Prefix[I], style);
508      if (SepPath != SepPrefix)
509        return false;
510      if (!SepPath && toLower(Path[I]) != toLower(Prefix[I]))
511        return false;
512    }
513    return true;
514  }
515  return Path.startswith(Prefix);
516}
517
518bool replace_path_prefix(SmallVectorImpl<char> &Path, StringRef OldPrefix,
519                         StringRef NewPrefix, Style style) {
520  if (OldPrefix.empty() && NewPrefix.empty())
521    return false;
522
523  StringRef OrigPath(Path.begin(), Path.size());
524  if (!starts_with(OrigPath, OldPrefix, style))
525    return false;
526
527  // If prefixes have the same size we can simply copy the new one over.
528  if (OldPrefix.size() == NewPrefix.size()) {
529    llvm::copy(NewPrefix, Path.begin());
530    return true;
531  }
532
533  StringRef RelPath = OrigPath.substr(OldPrefix.size());
534  SmallString<256> NewPath;
535  (Twine(NewPrefix) + RelPath).toVector(NewPath);
536  Path.swap(NewPath);
537  return true;
538}
539
540void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
541  assert((!path.isSingleStringRef() ||
542          path.getSingleStringRef().data() != result.data()) &&
543         "path and result are not allowed to overlap!");
544  // Clear result.
545  result.clear();
546  path.toVector(result);
547  native(result, style);
548}
549
550void native(SmallVectorImpl<char> &Path, Style style) {
551  if (Path.empty())
552    return;
553  if (real_style(style) == Style::windows) {
554    std::replace(Path.begin(), Path.end(), '/', '\\');
555    if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
556      SmallString<128> PathHome;
557      home_directory(PathHome);
558      PathHome.append(Path.begin() + 1, Path.end());
559      Path = PathHome;
560    }
561  } else {
562    for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI)
563      if (*PI == '\\')
564        *PI = '/';
565  }
566}
567
568std::string convert_to_slash(StringRef path, Style style) {
569  if (real_style(style) != Style::windows)
570    return std::string(path);
571
572  std::string s = path.str();
573  std::replace(s.begin(), s.end(), '\\', '/');
574  return s;
575}
576
577StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
578
579StringRef stem(StringRef path, Style style) {
580  StringRef fname = filename(path, style);
581  size_t pos = fname.find_last_of('.');
582  if (pos == StringRef::npos)
583    return fname;
584  else
585    if ((fname.size() == 1 && fname == ".") ||
586        (fname.size() == 2 && fname == ".."))
587      return fname;
588    else
589      return fname.substr(0, pos);
590}
591
592StringRef extension(StringRef path, Style style) {
593  StringRef fname = filename(path, style);
594  size_t pos = fname.find_last_of('.');
595  if (pos == StringRef::npos)
596    return StringRef();
597  else
598    if ((fname.size() == 1 && fname == ".") ||
599        (fname.size() == 2 && fname == ".."))
600      return StringRef();
601    else
602      return fname.substr(pos);
603}
604
605bool is_separator(char value, Style style) {
606  if (value == '/')
607    return true;
608  if (real_style(style) == Style::windows)
609    return value == '\\';
610  return false;
611}
612
613StringRef get_separator(Style style) {
614  if (real_style(style) == Style::windows)
615    return "\\";
616  return "/";
617}
618
619bool has_root_name(const Twine &path, Style style) {
620  SmallString<128> path_storage;
621  StringRef p = path.toStringRef(path_storage);
622
623  return !root_name(p, style).empty();
624}
625
626bool has_root_directory(const Twine &path, Style style) {
627  SmallString<128> path_storage;
628  StringRef p = path.toStringRef(path_storage);
629
630  return !root_directory(p, style).empty();
631}
632
633bool has_root_path(const Twine &path, Style style) {
634  SmallString<128> path_storage;
635  StringRef p = path.toStringRef(path_storage);
636
637  return !root_path(p, style).empty();
638}
639
640bool has_relative_path(const Twine &path, Style style) {
641  SmallString<128> path_storage;
642  StringRef p = path.toStringRef(path_storage);
643
644  return !relative_path(p, style).empty();
645}
646
647bool has_filename(const Twine &path, Style style) {
648  SmallString<128> path_storage;
649  StringRef p = path.toStringRef(path_storage);
650
651  return !filename(p, style).empty();
652}
653
654bool has_parent_path(const Twine &path, Style style) {
655  SmallString<128> path_storage;
656  StringRef p = path.toStringRef(path_storage);
657
658  return !parent_path(p, style).empty();
659}
660
661bool has_stem(const Twine &path, Style style) {
662  SmallString<128> path_storage;
663  StringRef p = path.toStringRef(path_storage);
664
665  return !stem(p, style).empty();
666}
667
668bool has_extension(const Twine &path, Style style) {
669  SmallString<128> path_storage;
670  StringRef p = path.toStringRef(path_storage);
671
672  return !extension(p, style).empty();
673}
674
675bool is_absolute(const Twine &path, Style style) {
676  SmallString<128> path_storage;
677  StringRef p = path.toStringRef(path_storage);
678
679  bool rootDir = has_root_directory(p, style);
680  bool rootName =
681      (real_style(style) != Style::windows) || has_root_name(p, style);
682
683  return rootDir && rootName;
684}
685
686bool is_relative(const Twine &path, Style style) {
687  return !is_absolute(path, style);
688}
689
690StringRef remove_leading_dotslash(StringRef Path, Style style) {
691  // Remove leading "./" (or ".//" or "././" etc.)
692  while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
693    Path = Path.substr(2);
694    while (Path.size() > 0 && is_separator(Path[0], style))
695      Path = Path.substr(1);
696  }
697  return Path;
698}
699
700// Remove path traversal components ("." and "..") when possible, and
701// canonicalize slashes.
702bool remove_dots(SmallVectorImpl<char> &the_path, bool remove_dot_dot,
703                 Style style) {
704  style = real_style(style);
705  StringRef remaining(the_path.data(), the_path.size());
706  bool needs_change = false;
707  SmallVector<StringRef, 16> components;
708
709  // Consume the root path, if present.
710  StringRef root = path::root_path(remaining, style);
711  bool absolute = !root.empty();
712  if (absolute)
713    remaining = remaining.drop_front(root.size());
714
715  // Loop over path components manually. This makes it easier to detect
716  // non-preferred slashes and double separators that must be canonicalized.
717  while (!remaining.empty()) {
718    size_t next_slash = remaining.find_first_of(separators(style));
719    if (next_slash == StringRef::npos)
720      next_slash = remaining.size();
721    StringRef component = remaining.take_front(next_slash);
722    remaining = remaining.drop_front(next_slash);
723
724    // Eat the slash, and check if it is the preferred separator.
725    if (!remaining.empty()) {
726      needs_change |= remaining.front() != preferred_separator(style);
727      remaining = remaining.drop_front();
728      // The path needs to be rewritten if it has a trailing slash.
729      // FIXME: This is emergent behavior that could be removed.
730      needs_change |= remaining.empty();
731    }
732
733    // Check for path traversal components or double separators.
734    if (component.empty() || component == ".") {
735      needs_change = true;
736    } else if (remove_dot_dot && component == "..") {
737      needs_change = true;
738      // Do not allow ".." to remove the root component. If this is the
739      // beginning of a relative path, keep the ".." component.
740      if (!components.empty() && components.back() != "..") {
741        components.pop_back();
742      } else if (!absolute) {
743        components.push_back(component);
744      }
745    } else {
746      components.push_back(component);
747    }
748  }
749
750  // Avoid rewriting the path unless we have to.
751  if (!needs_change)
752    return false;
753
754  SmallString<256> buffer = root;
755  if (!components.empty()) {
756    buffer += components[0];
757    for (StringRef C : makeArrayRef(components).drop_front()) {
758      buffer += preferred_separator(style);
759      buffer += C;
760    }
761  }
762  the_path.swap(buffer);
763  return true;
764}
765
766} // end namespace path
767
768namespace fs {
769
770std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
771  file_status Status;
772  std::error_code EC = status(Path, Status);
773  if (EC)
774    return EC;
775  Result = Status.getUniqueID();
776  return std::error_code();
777}
778
779void createUniquePath(const Twine &Model, SmallVectorImpl<char> &ResultPath,
780                      bool MakeAbsolute) {
781  SmallString<128> ModelStorage;
782  Model.toVector(ModelStorage);
783
784  if (MakeAbsolute) {
785    // Make model absolute by prepending a temp directory if it's not already.
786    if (!sys::path::is_absolute(Twine(ModelStorage))) {
787      SmallString<128> TDir;
788      sys::path::system_temp_directory(true, TDir);
789      sys::path::append(TDir, Twine(ModelStorage));
790      ModelStorage.swap(TDir);
791    }
792  }
793
794  ResultPath = ModelStorage;
795  ResultPath.push_back(0);
796  ResultPath.pop_back();
797
798  // Replace '%' with random chars.
799  for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
800    if (ModelStorage[i] == '%')
801      ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
802  }
803}
804
805std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
806                                 SmallVectorImpl<char> &ResultPath,
807                                 unsigned Mode) {
808  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
809}
810
811static std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
812                                        SmallVectorImpl<char> &ResultPath,
813                                        unsigned Mode, OpenFlags Flags) {
814  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File,
815                            Flags);
816}
817
818std::error_code createUniqueFile(const Twine &Model,
819                                 SmallVectorImpl<char> &ResultPath,
820                                 unsigned Mode) {
821  int FD;
822  auto EC = createUniqueFile(Model, FD, ResultPath, Mode);
823  if (EC)
824    return EC;
825  // FD is only needed to avoid race conditions. Close it right away.
826  close(FD);
827  return EC;
828}
829
830static std::error_code
831createTemporaryFile(const Twine &Model, int &ResultFD,
832                    llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
833  SmallString<128> Storage;
834  StringRef P = Model.toNullTerminatedStringRef(Storage);
835  assert(P.find_first_of(separators(Style::native)) == StringRef::npos &&
836         "Model must be a simple filename.");
837  // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
838  return createUniqueEntity(P.begin(), ResultFD, ResultPath, true,
839                            owner_read | owner_write, Type);
840}
841
842static std::error_code
843createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
844                    llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
845  const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
846  return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
847                             Type);
848}
849
850std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
851                                    int &ResultFD,
852                                    SmallVectorImpl<char> &ResultPath) {
853  return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
854}
855
856std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
857                                    SmallVectorImpl<char> &ResultPath) {
858  int FD;
859  auto EC = createTemporaryFile(Prefix, Suffix, FD, ResultPath);
860  if (EC)
861    return EC;
862  // FD is only needed to avoid race conditions. Close it right away.
863  close(FD);
864  return EC;
865}
866
867
868// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
869// for consistency. We should try using mkdtemp.
870std::error_code createUniqueDirectory(const Twine &Prefix,
871                                      SmallVectorImpl<char> &ResultPath) {
872  int Dummy;
873  return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, true, 0,
874                            FS_Dir);
875}
876
877std::error_code
878getPotentiallyUniqueFileName(const Twine &Model,
879                             SmallVectorImpl<char> &ResultPath) {
880  int Dummy;
881  return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
882}
883
884std::error_code
885getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
886                                 SmallVectorImpl<char> &ResultPath) {
887  int Dummy;
888  return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
889}
890
891void make_absolute(const Twine &current_directory,
892                   SmallVectorImpl<char> &path) {
893  StringRef p(path.data(), path.size());
894
895  bool rootDirectory = path::has_root_directory(p);
896  bool rootName = path::has_root_name(p);
897
898  // Already absolute.
899  if ((rootName || real_style(Style::native) != Style::windows) &&
900      rootDirectory)
901    return;
902
903  // All of the following conditions will need the current directory.
904  SmallString<128> current_dir;
905  current_directory.toVector(current_dir);
906
907  // Relative path. Prepend the current directory.
908  if (!rootName && !rootDirectory) {
909    // Append path to the current directory.
910    path::append(current_dir, p);
911    // Set path to the result.
912    path.swap(current_dir);
913    return;
914  }
915
916  if (!rootName && rootDirectory) {
917    StringRef cdrn = path::root_name(current_dir);
918    SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
919    path::append(curDirRootName, p);
920    // Set path to the result.
921    path.swap(curDirRootName);
922    return;
923  }
924
925  if (rootName && !rootDirectory) {
926    StringRef pRootName      = path::root_name(p);
927    StringRef bRootDirectory = path::root_directory(current_dir);
928    StringRef bRelativePath  = path::relative_path(current_dir);
929    StringRef pRelativePath  = path::relative_path(p);
930
931    SmallString<128> res;
932    path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
933    path.swap(res);
934    return;
935  }
936
937  llvm_unreachable("All rootName and rootDirectory combinations should have "
938                   "occurred above!");
939}
940
941std::error_code make_absolute(SmallVectorImpl<char> &path) {
942  if (path::is_absolute(path))
943    return {};
944
945  SmallString<128> current_dir;
946  if (std::error_code ec = current_path(current_dir))
947    return ec;
948
949  make_absolute(current_dir, path);
950  return {};
951}
952
953std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
954                                   perms Perms) {
955  SmallString<128> PathStorage;
956  StringRef P = Path.toStringRef(PathStorage);
957
958  // Be optimistic and try to create the directory
959  std::error_code EC = create_directory(P, IgnoreExisting, Perms);
960  // If we succeeded, or had any error other than the parent not existing, just
961  // return it.
962  if (EC != errc::no_such_file_or_directory)
963    return EC;
964
965  // We failed because of a no_such_file_or_directory, try to create the
966  // parent.
967  StringRef Parent = path::parent_path(P);
968  if (Parent.empty())
969    return EC;
970
971  if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
972      return EC;
973
974  return create_directory(P, IgnoreExisting, Perms);
975}
976
977static std::error_code copy_file_internal(int ReadFD, int WriteFD) {
978  const size_t BufSize = 4096;
979  char *Buf = new char[BufSize];
980  int BytesRead = 0, BytesWritten = 0;
981  for (;;) {
982    BytesRead = read(ReadFD, Buf, BufSize);
983    if (BytesRead <= 0)
984      break;
985    while (BytesRead) {
986      BytesWritten = write(WriteFD, Buf, BytesRead);
987      if (BytesWritten < 0)
988        break;
989      BytesRead -= BytesWritten;
990    }
991    if (BytesWritten < 0)
992      break;
993  }
994  delete[] Buf;
995
996  if (BytesRead < 0 || BytesWritten < 0)
997    return std::error_code(errno, std::generic_category());
998  return std::error_code();
999}
1000
1001#ifndef __APPLE__
1002std::error_code copy_file(const Twine &From, const Twine &To) {
1003  int ReadFD, WriteFD;
1004  if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
1005    return EC;
1006  if (std::error_code EC =
1007          openFileForWrite(To, WriteFD, CD_CreateAlways, OF_None)) {
1008    close(ReadFD);
1009    return EC;
1010  }
1011
1012  std::error_code EC = copy_file_internal(ReadFD, WriteFD);
1013
1014  close(ReadFD);
1015  close(WriteFD);
1016
1017  return EC;
1018}
1019#endif
1020
1021std::error_code copy_file(const Twine &From, int ToFD) {
1022  int ReadFD;
1023  if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
1024    return EC;
1025
1026  std::error_code EC = copy_file_internal(ReadFD, ToFD);
1027
1028  close(ReadFD);
1029
1030  return EC;
1031}
1032
1033ErrorOr<MD5::MD5Result> md5_contents(int FD) {
1034  MD5 Hash;
1035
1036  constexpr size_t BufSize = 4096;
1037  std::vector<uint8_t> Buf(BufSize);
1038  int BytesRead = 0;
1039  for (;;) {
1040    BytesRead = read(FD, Buf.data(), BufSize);
1041    if (BytesRead <= 0)
1042      break;
1043    Hash.update(makeArrayRef(Buf.data(), BytesRead));
1044  }
1045
1046  if (BytesRead < 0)
1047    return std::error_code(errno, std::generic_category());
1048  MD5::MD5Result Result;
1049  Hash.final(Result);
1050  return Result;
1051}
1052
1053ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
1054  int FD;
1055  if (auto EC = openFileForRead(Path, FD, OF_None))
1056    return EC;
1057
1058  auto Result = md5_contents(FD);
1059  close(FD);
1060  return Result;
1061}
1062
1063bool exists(const basic_file_status &status) {
1064  return status_known(status) && status.type() != file_type::file_not_found;
1065}
1066
1067bool status_known(const basic_file_status &s) {
1068  return s.type() != file_type::status_error;
1069}
1070
1071file_type get_file_type(const Twine &Path, bool Follow) {
1072  file_status st;
1073  if (status(Path, st, Follow))
1074    return file_type::status_error;
1075  return st.type();
1076}
1077
1078bool is_directory(const basic_file_status &status) {
1079  return status.type() == file_type::directory_file;
1080}
1081
1082std::error_code is_directory(const Twine &path, bool &result) {
1083  file_status st;
1084  if (std::error_code ec = status(path, st))
1085    return ec;
1086  result = is_directory(st);
1087  return std::error_code();
1088}
1089
1090bool is_regular_file(const basic_file_status &status) {
1091  return status.type() == file_type::regular_file;
1092}
1093
1094std::error_code is_regular_file(const Twine &path, bool &result) {
1095  file_status st;
1096  if (std::error_code ec = status(path, st))
1097    return ec;
1098  result = is_regular_file(st);
1099  return std::error_code();
1100}
1101
1102bool is_symlink_file(const basic_file_status &status) {
1103  return status.type() == file_type::symlink_file;
1104}
1105
1106std::error_code is_symlink_file(const Twine &path, bool &result) {
1107  file_status st;
1108  if (std::error_code ec = status(path, st, false))
1109    return ec;
1110  result = is_symlink_file(st);
1111  return std::error_code();
1112}
1113
1114bool is_other(const basic_file_status &status) {
1115  return exists(status) &&
1116         !is_regular_file(status) &&
1117         !is_directory(status);
1118}
1119
1120std::error_code is_other(const Twine &Path, bool &Result) {
1121  file_status FileStatus;
1122  if (std::error_code EC = status(Path, FileStatus))
1123    return EC;
1124  Result = is_other(FileStatus);
1125  return std::error_code();
1126}
1127
1128void directory_entry::replace_filename(const Twine &Filename, file_type Type,
1129                                       basic_file_status Status) {
1130  SmallString<128> PathStr = path::parent_path(Path);
1131  path::append(PathStr, Filename);
1132  this->Path = std::string(PathStr.str());
1133  this->Type = Type;
1134  this->Status = Status;
1135}
1136
1137ErrorOr<perms> getPermissions(const Twine &Path) {
1138  file_status Status;
1139  if (std::error_code EC = status(Path, Status))
1140    return EC;
1141
1142  return Status.permissions();
1143}
1144
1145} // end namespace fs
1146} // end namespace sys
1147} // end namespace llvm
1148
1149// Include the truly platform-specific parts.
1150#if defined(LLVM_ON_UNIX)
1151#include "Unix/Path.inc"
1152#endif
1153#if defined(_WIN32)
1154#include "Windows/Path.inc"
1155#endif
1156
1157namespace llvm {
1158namespace sys {
1159namespace fs {
1160TempFile::TempFile(StringRef Name, int FD)
1161    : TmpName(std::string(Name)), FD(FD) {}
1162TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
1163TempFile &TempFile::operator=(TempFile &&Other) {
1164  TmpName = std::move(Other.TmpName);
1165  FD = Other.FD;
1166  Other.Done = true;
1167  Other.FD = -1;
1168  return *this;
1169}
1170
1171TempFile::~TempFile() { assert(Done); }
1172
1173Error TempFile::discard() {
1174  Done = true;
1175  if (FD != -1 && close(FD) == -1) {
1176    std::error_code EC = std::error_code(errno, std::generic_category());
1177    return errorCodeToError(EC);
1178  }
1179  FD = -1;
1180
1181#ifdef _WIN32
1182  // On windows closing will remove the file.
1183  TmpName = "";
1184  return Error::success();
1185#else
1186  // Always try to close and remove.
1187  std::error_code RemoveEC;
1188  if (!TmpName.empty()) {
1189    RemoveEC = fs::remove(TmpName);
1190    sys::DontRemoveFileOnSignal(TmpName);
1191    if (!RemoveEC)
1192      TmpName = "";
1193  }
1194  return errorCodeToError(RemoveEC);
1195#endif
1196}
1197
1198Error TempFile::keep(const Twine &Name) {
1199  assert(!Done);
1200  Done = true;
1201  // Always try to close and rename.
1202#ifdef _WIN32
1203  // If we can't cancel the delete don't rename.
1204  auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1205  std::error_code RenameEC = setDeleteDisposition(H, false);
1206  if (!RenameEC) {
1207    RenameEC = rename_fd(FD, Name);
1208    // If rename failed because it's cross-device, copy instead
1209    if (RenameEC ==
1210      std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) {
1211      RenameEC = copy_file(TmpName, Name);
1212      setDeleteDisposition(H, true);
1213    }
1214  }
1215
1216  // If we can't rename, discard the temporary file.
1217  if (RenameEC)
1218    setDeleteDisposition(H, true);
1219#else
1220  std::error_code RenameEC = fs::rename(TmpName, Name);
1221  if (RenameEC) {
1222    // If we can't rename, try to copy to work around cross-device link issues.
1223    RenameEC = sys::fs::copy_file(TmpName, Name);
1224    // If we can't rename or copy, discard the temporary file.
1225    if (RenameEC)
1226      remove(TmpName);
1227  }
1228  sys::DontRemoveFileOnSignal(TmpName);
1229#endif
1230
1231  if (!RenameEC)
1232    TmpName = "";
1233
1234  if (close(FD) == -1) {
1235    std::error_code EC(errno, std::generic_category());
1236    return errorCodeToError(EC);
1237  }
1238  FD = -1;
1239
1240  return errorCodeToError(RenameEC);
1241}
1242
1243Error TempFile::keep() {
1244  assert(!Done);
1245  Done = true;
1246
1247#ifdef _WIN32
1248  auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1249  if (std::error_code EC = setDeleteDisposition(H, false))
1250    return errorCodeToError(EC);
1251#else
1252  sys::DontRemoveFileOnSignal(TmpName);
1253#endif
1254
1255  TmpName = "";
1256
1257  if (close(FD) == -1) {
1258    std::error_code EC(errno, std::generic_category());
1259    return errorCodeToError(EC);
1260  }
1261  FD = -1;
1262
1263  return Error::success();
1264}
1265
1266Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) {
1267  int FD;
1268  SmallString<128> ResultPath;
1269  if (std::error_code EC =
1270          createUniqueFile(Model, FD, ResultPath, Mode, OF_Delete))
1271    return errorCodeToError(EC);
1272
1273  TempFile Ret(ResultPath, FD);
1274#ifndef _WIN32
1275  if (sys::RemoveFileOnSignal(ResultPath)) {
1276    // Make sure we delete the file when RemoveFileOnSignal fails.
1277    consumeError(Ret.discard());
1278    std::error_code EC(errc::operation_not_permitted);
1279    return errorCodeToError(EC);
1280  }
1281#endif
1282  return std::move(Ret);
1283}
1284}
1285
1286} // end namsspace sys
1287} // end namespace llvm
1288