Path.cpp revision 360784
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
499bool replace_path_prefix(SmallVectorImpl<char> &Path,
500                         const StringRef &OldPrefix, const StringRef &NewPrefix,
501                         Style style, bool strict) {
502  if (OldPrefix.empty() && NewPrefix.empty())
503    return false;
504
505  StringRef OrigPath(Path.begin(), Path.size());
506  StringRef OldPrefixDir;
507
508  if (!strict && OldPrefix.size() > OrigPath.size())
509    return false;
510
511  // Ensure OldPrefixDir does not have a trailing separator.
512  if (!OldPrefix.empty() && is_separator(OldPrefix.back()))
513    OldPrefixDir = parent_path(OldPrefix, style);
514  else
515    OldPrefixDir = OldPrefix;
516
517  if (!OrigPath.startswith(OldPrefixDir))
518    return false;
519
520  if (OrigPath.size() > OldPrefixDir.size())
521    if (!is_separator(OrigPath[OldPrefixDir.size()], style) && strict)
522      return false;
523
524  // If prefixes have the same size we can simply copy the new one over.
525  if (OldPrefixDir.size() == NewPrefix.size() && !strict) {
526    llvm::copy(NewPrefix, Path.begin());
527    return true;
528  }
529
530  StringRef RelPath = OrigPath.substr(OldPrefixDir.size());
531  SmallString<256> NewPath;
532  path::append(NewPath, style, NewPrefix);
533  if (!RelPath.empty()) {
534    if (!is_separator(RelPath[0], style) || !strict)
535      path::append(NewPath, style, RelPath);
536    else
537      path::append(NewPath, style, relative_path(RelPath, style));
538  }
539
540  Path.swap(NewPath);
541
542  return true;
543}
544
545void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
546  assert((!path.isSingleStringRef() ||
547          path.getSingleStringRef().data() != result.data()) &&
548         "path and result are not allowed to overlap!");
549  // Clear result.
550  result.clear();
551  path.toVector(result);
552  native(result, style);
553}
554
555void native(SmallVectorImpl<char> &Path, Style style) {
556  if (Path.empty())
557    return;
558  if (real_style(style) == Style::windows) {
559    std::replace(Path.begin(), Path.end(), '/', '\\');
560    if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
561      SmallString<128> PathHome;
562      home_directory(PathHome);
563      PathHome.append(Path.begin() + 1, Path.end());
564      Path = PathHome;
565    }
566  } else {
567    for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
568      if (*PI == '\\') {
569        auto PN = PI + 1;
570        if (PN < PE && *PN == '\\')
571          ++PI; // increment once, the for loop will move over the escaped slash
572        else
573          *PI = '/';
574      }
575    }
576  }
577}
578
579std::string convert_to_slash(StringRef path, Style style) {
580  if (real_style(style) != Style::windows)
581    return path;
582
583  std::string s = path.str();
584  std::replace(s.begin(), s.end(), '\\', '/');
585  return s;
586}
587
588StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
589
590StringRef stem(StringRef path, Style style) {
591  StringRef fname = filename(path, style);
592  size_t pos = fname.find_last_of('.');
593  if (pos == StringRef::npos)
594    return fname;
595  else
596    if ((fname.size() == 1 && fname == ".") ||
597        (fname.size() == 2 && fname == ".."))
598      return fname;
599    else
600      return fname.substr(0, pos);
601}
602
603StringRef extension(StringRef path, Style style) {
604  StringRef fname = filename(path, style);
605  size_t pos = fname.find_last_of('.');
606  if (pos == StringRef::npos)
607    return StringRef();
608  else
609    if ((fname.size() == 1 && fname == ".") ||
610        (fname.size() == 2 && fname == ".."))
611      return StringRef();
612    else
613      return fname.substr(pos);
614}
615
616bool is_separator(char value, Style style) {
617  if (value == '/')
618    return true;
619  if (real_style(style) == Style::windows)
620    return value == '\\';
621  return false;
622}
623
624StringRef get_separator(Style style) {
625  if (real_style(style) == Style::windows)
626    return "\\";
627  return "/";
628}
629
630bool has_root_name(const Twine &path, Style style) {
631  SmallString<128> path_storage;
632  StringRef p = path.toStringRef(path_storage);
633
634  return !root_name(p, style).empty();
635}
636
637bool has_root_directory(const Twine &path, Style style) {
638  SmallString<128> path_storage;
639  StringRef p = path.toStringRef(path_storage);
640
641  return !root_directory(p, style).empty();
642}
643
644bool has_root_path(const Twine &path, Style style) {
645  SmallString<128> path_storage;
646  StringRef p = path.toStringRef(path_storage);
647
648  return !root_path(p, style).empty();
649}
650
651bool has_relative_path(const Twine &path, Style style) {
652  SmallString<128> path_storage;
653  StringRef p = path.toStringRef(path_storage);
654
655  return !relative_path(p, style).empty();
656}
657
658bool has_filename(const Twine &path, Style style) {
659  SmallString<128> path_storage;
660  StringRef p = path.toStringRef(path_storage);
661
662  return !filename(p, style).empty();
663}
664
665bool has_parent_path(const Twine &path, Style style) {
666  SmallString<128> path_storage;
667  StringRef p = path.toStringRef(path_storage);
668
669  return !parent_path(p, style).empty();
670}
671
672bool has_stem(const Twine &path, Style style) {
673  SmallString<128> path_storage;
674  StringRef p = path.toStringRef(path_storage);
675
676  return !stem(p, style).empty();
677}
678
679bool has_extension(const Twine &path, Style style) {
680  SmallString<128> path_storage;
681  StringRef p = path.toStringRef(path_storage);
682
683  return !extension(p, style).empty();
684}
685
686bool is_absolute(const Twine &path, Style style) {
687  SmallString<128> path_storage;
688  StringRef p = path.toStringRef(path_storage);
689
690  bool rootDir = has_root_directory(p, style);
691  bool rootName =
692      (real_style(style) != Style::windows) || has_root_name(p, style);
693
694  return rootDir && rootName;
695}
696
697bool is_relative(const Twine &path, Style style) {
698  return !is_absolute(path, style);
699}
700
701StringRef remove_leading_dotslash(StringRef Path, Style style) {
702  // Remove leading "./" (or ".//" or "././" etc.)
703  while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
704    Path = Path.substr(2);
705    while (Path.size() > 0 && is_separator(Path[0], style))
706      Path = Path.substr(1);
707  }
708  return Path;
709}
710
711static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
712                                    Style style) {
713  SmallVector<StringRef, 16> components;
714
715  // Skip the root path, then look for traversal in the components.
716  StringRef rel = path::relative_path(path, style);
717  for (StringRef C :
718       llvm::make_range(path::begin(rel, style), path::end(rel))) {
719    if (C == ".")
720      continue;
721    // Leading ".." will remain in the path unless it's at the root.
722    if (remove_dot_dot && C == "..") {
723      if (!components.empty() && components.back() != "..") {
724        components.pop_back();
725        continue;
726      }
727      if (path::is_absolute(path, style))
728        continue;
729    }
730    components.push_back(C);
731  }
732
733  SmallString<256> buffer = path::root_path(path, style);
734  for (StringRef C : components)
735    path::append(buffer, style, C);
736  return buffer;
737}
738
739bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
740                 Style style) {
741  StringRef p(path.data(), path.size());
742
743  SmallString<256> result = remove_dots(p, remove_dot_dot, style);
744  if (result == path)
745    return false;
746
747  path.swap(result);
748  return true;
749}
750
751} // end namespace path
752
753namespace fs {
754
755std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
756  file_status Status;
757  std::error_code EC = status(Path, Status);
758  if (EC)
759    return EC;
760  Result = Status.getUniqueID();
761  return std::error_code();
762}
763
764void createUniquePath(const Twine &Model, SmallVectorImpl<char> &ResultPath,
765                      bool MakeAbsolute) {
766  SmallString<128> ModelStorage;
767  Model.toVector(ModelStorage);
768
769  if (MakeAbsolute) {
770    // Make model absolute by prepending a temp directory if it's not already.
771    if (!sys::path::is_absolute(Twine(ModelStorage))) {
772      SmallString<128> TDir;
773      sys::path::system_temp_directory(true, TDir);
774      sys::path::append(TDir, Twine(ModelStorage));
775      ModelStorage.swap(TDir);
776    }
777  }
778
779  ResultPath = ModelStorage;
780  ResultPath.push_back(0);
781  ResultPath.pop_back();
782
783  // Replace '%' with random chars.
784  for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
785    if (ModelStorage[i] == '%')
786      ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
787  }
788}
789
790std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
791                                 SmallVectorImpl<char> &ResultPath,
792                                 unsigned Mode) {
793  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
794}
795
796static std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
797                                        SmallVectorImpl<char> &ResultPath,
798                                        unsigned Mode, OpenFlags Flags) {
799  return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File,
800                            Flags);
801}
802
803std::error_code createUniqueFile(const Twine &Model,
804                                 SmallVectorImpl<char> &ResultPath,
805                                 unsigned Mode) {
806  int FD;
807  auto EC = createUniqueFile(Model, FD, ResultPath, Mode);
808  if (EC)
809    return EC;
810  // FD is only needed to avoid race conditions. Close it right away.
811  close(FD);
812  return EC;
813}
814
815static std::error_code
816createTemporaryFile(const Twine &Model, int &ResultFD,
817                    llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
818  SmallString<128> Storage;
819  StringRef P = Model.toNullTerminatedStringRef(Storage);
820  assert(P.find_first_of(separators(Style::native)) == StringRef::npos &&
821         "Model must be a simple filename.");
822  // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
823  return createUniqueEntity(P.begin(), ResultFD, ResultPath, true,
824                            owner_read | owner_write, Type);
825}
826
827static std::error_code
828createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
829                    llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
830  const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
831  return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
832                             Type);
833}
834
835std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
836                                    int &ResultFD,
837                                    SmallVectorImpl<char> &ResultPath) {
838  return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
839}
840
841std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
842                                    SmallVectorImpl<char> &ResultPath) {
843  int FD;
844  auto EC = createTemporaryFile(Prefix, Suffix, FD, ResultPath);
845  if (EC)
846    return EC;
847  // FD is only needed to avoid race conditions. Close it right away.
848  close(FD);
849  return EC;
850}
851
852
853// This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
854// for consistency. We should try using mkdtemp.
855std::error_code createUniqueDirectory(const Twine &Prefix,
856                                      SmallVectorImpl<char> &ResultPath) {
857  int Dummy;
858  return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, true, 0,
859                            FS_Dir);
860}
861
862std::error_code
863getPotentiallyUniqueFileName(const Twine &Model,
864                             SmallVectorImpl<char> &ResultPath) {
865  int Dummy;
866  return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
867}
868
869std::error_code
870getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
871                                 SmallVectorImpl<char> &ResultPath) {
872  int Dummy;
873  return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
874}
875
876void make_absolute(const Twine &current_directory,
877                   SmallVectorImpl<char> &path) {
878  StringRef p(path.data(), path.size());
879
880  bool rootDirectory = path::has_root_directory(p);
881  bool rootName = path::has_root_name(p);
882
883  // Already absolute.
884  if ((rootName || real_style(Style::native) != Style::windows) &&
885      rootDirectory)
886    return;
887
888  // All of the following conditions will need the current directory.
889  SmallString<128> current_dir;
890  current_directory.toVector(current_dir);
891
892  // Relative path. Prepend the current directory.
893  if (!rootName && !rootDirectory) {
894    // Append path to the current directory.
895    path::append(current_dir, p);
896    // Set path to the result.
897    path.swap(current_dir);
898    return;
899  }
900
901  if (!rootName && rootDirectory) {
902    StringRef cdrn = path::root_name(current_dir);
903    SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
904    path::append(curDirRootName, p);
905    // Set path to the result.
906    path.swap(curDirRootName);
907    return;
908  }
909
910  if (rootName && !rootDirectory) {
911    StringRef pRootName      = path::root_name(p);
912    StringRef bRootDirectory = path::root_directory(current_dir);
913    StringRef bRelativePath  = path::relative_path(current_dir);
914    StringRef pRelativePath  = path::relative_path(p);
915
916    SmallString<128> res;
917    path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
918    path.swap(res);
919    return;
920  }
921
922  llvm_unreachable("All rootName and rootDirectory combinations should have "
923                   "occurred above!");
924}
925
926std::error_code make_absolute(SmallVectorImpl<char> &path) {
927  if (path::is_absolute(path))
928    return {};
929
930  SmallString<128> current_dir;
931  if (std::error_code ec = current_path(current_dir))
932    return ec;
933
934  make_absolute(current_dir, path);
935  return {};
936}
937
938std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
939                                   perms Perms) {
940  SmallString<128> PathStorage;
941  StringRef P = Path.toStringRef(PathStorage);
942
943  // Be optimistic and try to create the directory
944  std::error_code EC = create_directory(P, IgnoreExisting, Perms);
945  // If we succeeded, or had any error other than the parent not existing, just
946  // return it.
947  if (EC != errc::no_such_file_or_directory)
948    return EC;
949
950  // We failed because of a no_such_file_or_directory, try to create the
951  // parent.
952  StringRef Parent = path::parent_path(P);
953  if (Parent.empty())
954    return EC;
955
956  if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
957      return EC;
958
959  return create_directory(P, IgnoreExisting, Perms);
960}
961
962static std::error_code copy_file_internal(int ReadFD, int WriteFD) {
963  const size_t BufSize = 4096;
964  char *Buf = new char[BufSize];
965  int BytesRead = 0, BytesWritten = 0;
966  for (;;) {
967    BytesRead = read(ReadFD, Buf, BufSize);
968    if (BytesRead <= 0)
969      break;
970    while (BytesRead) {
971      BytesWritten = write(WriteFD, Buf, BytesRead);
972      if (BytesWritten < 0)
973        break;
974      BytesRead -= BytesWritten;
975    }
976    if (BytesWritten < 0)
977      break;
978  }
979  delete[] Buf;
980
981  if (BytesRead < 0 || BytesWritten < 0)
982    return std::error_code(errno, std::generic_category());
983  return std::error_code();
984}
985
986#ifndef __APPLE__
987std::error_code copy_file(const Twine &From, const Twine &To) {
988  int ReadFD, WriteFD;
989  if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
990    return EC;
991  if (std::error_code EC =
992          openFileForWrite(To, WriteFD, CD_CreateAlways, OF_None)) {
993    close(ReadFD);
994    return EC;
995  }
996
997  std::error_code EC = copy_file_internal(ReadFD, WriteFD);
998
999  close(ReadFD);
1000  close(WriteFD);
1001
1002  return EC;
1003}
1004#endif
1005
1006std::error_code copy_file(const Twine &From, int ToFD) {
1007  int ReadFD;
1008  if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
1009    return EC;
1010
1011  std::error_code EC = copy_file_internal(ReadFD, ToFD);
1012
1013  close(ReadFD);
1014
1015  return EC;
1016}
1017
1018ErrorOr<MD5::MD5Result> md5_contents(int FD) {
1019  MD5 Hash;
1020
1021  constexpr size_t BufSize = 4096;
1022  std::vector<uint8_t> Buf(BufSize);
1023  int BytesRead = 0;
1024  for (;;) {
1025    BytesRead = read(FD, Buf.data(), BufSize);
1026    if (BytesRead <= 0)
1027      break;
1028    Hash.update(makeArrayRef(Buf.data(), BytesRead));
1029  }
1030
1031  if (BytesRead < 0)
1032    return std::error_code(errno, std::generic_category());
1033  MD5::MD5Result Result;
1034  Hash.final(Result);
1035  return Result;
1036}
1037
1038ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
1039  int FD;
1040  if (auto EC = openFileForRead(Path, FD, OF_None))
1041    return EC;
1042
1043  auto Result = md5_contents(FD);
1044  close(FD);
1045  return Result;
1046}
1047
1048bool exists(const basic_file_status &status) {
1049  return status_known(status) && status.type() != file_type::file_not_found;
1050}
1051
1052bool status_known(const basic_file_status &s) {
1053  return s.type() != file_type::status_error;
1054}
1055
1056file_type get_file_type(const Twine &Path, bool Follow) {
1057  file_status st;
1058  if (status(Path, st, Follow))
1059    return file_type::status_error;
1060  return st.type();
1061}
1062
1063bool is_directory(const basic_file_status &status) {
1064  return status.type() == file_type::directory_file;
1065}
1066
1067std::error_code is_directory(const Twine &path, bool &result) {
1068  file_status st;
1069  if (std::error_code ec = status(path, st))
1070    return ec;
1071  result = is_directory(st);
1072  return std::error_code();
1073}
1074
1075bool is_regular_file(const basic_file_status &status) {
1076  return status.type() == file_type::regular_file;
1077}
1078
1079std::error_code is_regular_file(const Twine &path, bool &result) {
1080  file_status st;
1081  if (std::error_code ec = status(path, st))
1082    return ec;
1083  result = is_regular_file(st);
1084  return std::error_code();
1085}
1086
1087bool is_symlink_file(const basic_file_status &status) {
1088  return status.type() == file_type::symlink_file;
1089}
1090
1091std::error_code is_symlink_file(const Twine &path, bool &result) {
1092  file_status st;
1093  if (std::error_code ec = status(path, st, false))
1094    return ec;
1095  result = is_symlink_file(st);
1096  return std::error_code();
1097}
1098
1099bool is_other(const basic_file_status &status) {
1100  return exists(status) &&
1101         !is_regular_file(status) &&
1102         !is_directory(status);
1103}
1104
1105std::error_code is_other(const Twine &Path, bool &Result) {
1106  file_status FileStatus;
1107  if (std::error_code EC = status(Path, FileStatus))
1108    return EC;
1109  Result = is_other(FileStatus);
1110  return std::error_code();
1111}
1112
1113void directory_entry::replace_filename(const Twine &Filename, file_type Type,
1114                                       basic_file_status Status) {
1115  SmallString<128> PathStr = path::parent_path(Path);
1116  path::append(PathStr, Filename);
1117  this->Path = PathStr.str();
1118  this->Type = Type;
1119  this->Status = Status;
1120}
1121
1122ErrorOr<perms> getPermissions(const Twine &Path) {
1123  file_status Status;
1124  if (std::error_code EC = status(Path, Status))
1125    return EC;
1126
1127  return Status.permissions();
1128}
1129
1130} // end namespace fs
1131} // end namespace sys
1132} // end namespace llvm
1133
1134// Include the truly platform-specific parts.
1135#if defined(LLVM_ON_UNIX)
1136#include "Unix/Path.inc"
1137#endif
1138#if defined(_WIN32)
1139#include "Windows/Path.inc"
1140#endif
1141
1142namespace llvm {
1143namespace sys {
1144namespace fs {
1145TempFile::TempFile(StringRef Name, int FD) : TmpName(Name), FD(FD) {}
1146TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
1147TempFile &TempFile::operator=(TempFile &&Other) {
1148  TmpName = std::move(Other.TmpName);
1149  FD = Other.FD;
1150  Other.Done = true;
1151  Other.FD = -1;
1152  return *this;
1153}
1154
1155TempFile::~TempFile() { assert(Done); }
1156
1157Error TempFile::discard() {
1158  Done = true;
1159  if (FD != -1 && close(FD) == -1) {
1160    std::error_code EC = std::error_code(errno, std::generic_category());
1161    return errorCodeToError(EC);
1162  }
1163  FD = -1;
1164
1165#ifdef _WIN32
1166  // On windows closing will remove the file.
1167  TmpName = "";
1168  return Error::success();
1169#else
1170  // Always try to close and remove.
1171  std::error_code RemoveEC;
1172  if (!TmpName.empty()) {
1173    RemoveEC = fs::remove(TmpName);
1174    sys::DontRemoveFileOnSignal(TmpName);
1175    if (!RemoveEC)
1176      TmpName = "";
1177  }
1178  return errorCodeToError(RemoveEC);
1179#endif
1180}
1181
1182Error TempFile::keep(const Twine &Name) {
1183  assert(!Done);
1184  Done = true;
1185  // Always try to close and rename.
1186#ifdef _WIN32
1187  // If we can't cancel the delete don't rename.
1188  auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1189  std::error_code RenameEC = setDeleteDisposition(H, false);
1190  if (!RenameEC) {
1191    RenameEC = rename_fd(FD, Name);
1192    // If rename failed because it's cross-device, copy instead
1193    if (RenameEC ==
1194      std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) {
1195      RenameEC = copy_file(TmpName, Name);
1196      setDeleteDisposition(H, true);
1197    }
1198  }
1199
1200  // If we can't rename, discard the temporary file.
1201  if (RenameEC)
1202    setDeleteDisposition(H, true);
1203#else
1204  std::error_code RenameEC = fs::rename(TmpName, Name);
1205  if (RenameEC) {
1206    // If we can't rename, try to copy to work around cross-device link issues.
1207    RenameEC = sys::fs::copy_file(TmpName, Name);
1208    // If we can't rename or copy, discard the temporary file.
1209    if (RenameEC)
1210      remove(TmpName);
1211  }
1212  sys::DontRemoveFileOnSignal(TmpName);
1213#endif
1214
1215  if (!RenameEC)
1216    TmpName = "";
1217
1218  if (close(FD) == -1) {
1219    std::error_code EC(errno, std::generic_category());
1220    return errorCodeToError(EC);
1221  }
1222  FD = -1;
1223
1224  return errorCodeToError(RenameEC);
1225}
1226
1227Error TempFile::keep() {
1228  assert(!Done);
1229  Done = true;
1230
1231#ifdef _WIN32
1232  auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1233  if (std::error_code EC = setDeleteDisposition(H, false))
1234    return errorCodeToError(EC);
1235#else
1236  sys::DontRemoveFileOnSignal(TmpName);
1237#endif
1238
1239  TmpName = "";
1240
1241  if (close(FD) == -1) {
1242    std::error_code EC(errno, std::generic_category());
1243    return errorCodeToError(EC);
1244  }
1245  FD = -1;
1246
1247  return Error::success();
1248}
1249
1250Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) {
1251  int FD;
1252  SmallString<128> ResultPath;
1253  if (std::error_code EC =
1254          createUniqueFile(Model, FD, ResultPath, Mode, OF_Delete))
1255    return errorCodeToError(EC);
1256
1257  TempFile Ret(ResultPath, FD);
1258#ifndef _WIN32
1259  if (sys::RemoveFileOnSignal(ResultPath)) {
1260    // Make sure we delete the file when RemoveFileOnSignal fails.
1261    consumeError(Ret.discard());
1262    std::error_code EC(errc::operation_not_permitted);
1263    return errorCodeToError(EC);
1264  }
1265#endif
1266  return std::move(Ret);
1267}
1268}
1269
1270} // end namsspace sys
1271} // end namespace llvm
1272