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