Line data Source code
1 : //===-- Path.cpp - Implement OS Path Concept ------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file implements the operating system Path API.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "llvm/Support/Path.h"
15 : #include "llvm/ADT/ArrayRef.h"
16 : #include "llvm/Config/llvm-config.h"
17 : #include "llvm/Support/Endian.h"
18 : #include "llvm/Support/Errc.h"
19 : #include "llvm/Support/ErrorHandling.h"
20 : #include "llvm/Support/FileSystem.h"
21 : #include "llvm/Support/Process.h"
22 : #include "llvm/Support/Signals.h"
23 : #include <cctype>
24 : #include <cstring>
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 : #ifdef _WIN32
42 : return (style == Style::posix) ? Style::posix : Style::windows;
43 : #else
44 238482202 : return (style == Style::windows) ? Style::windows : Style::posix;
45 : #endif
46 : }
47 :
48 : inline const char *separators(Style style) {
49 : if (real_style(style) == Style::windows)
50 : return "\\/";
51 : return "/";
52 : }
53 :
54 : inline char preferred_separator(Style style) {
55 : if (real_style(style) == Style::windows)
56 : return '\\';
57 : return '/';
58 : }
59 :
60 35289054 : StringRef find_first_component(StringRef path, Style style) {
61 : // Look for this first component in the following order.
62 : // * empty (in this case we return an empty string)
63 : // * either C: or {//,\\}net.
64 : // * {/,\}
65 : // * {file,directory}name
66 :
67 35289054 : if (path.empty())
68 555655 : return path;
69 :
70 : if (real_style(style) == Style::windows) {
71 : // C:
72 7926 : if (path.size() >= 2 &&
73 8039 : std::isalpha(static_cast<unsigned char>(path[0])) && path[1] == ':')
74 131 : return path.substr(0, 2);
75 : }
76 :
77 : // //net
78 68300284 : if ((path.size() > 2) && is_separator(path[0], style) &&
79 48529917 : path[0] == path[1] && !is_separator(path[2], style)) {
80 : // Find the next directory separator.
81 817 : size_t end = path.find_first_of(separators(style), 2);
82 817 : return path.substr(0, end);
83 : }
84 :
85 : // {/,\}
86 69464124 : if (is_separator(path[0], style))
87 13814474 : return path.substr(0, 1);
88 :
89 : // * {file,directory}name
90 20925303 : size_t end = path.find_first_of(separators(style));
91 20923004 : return path.substr(0, end);
92 : }
93 :
94 : // Returns the first character of the filename in str. For paths ending in
95 : // '/', it returns the position of the '/'.
96 9829577 : size_t filename_pos(StringRef str, Style style) {
97 9829577 : if (str.size() > 0 && is_separator(str[str.size() - 1], style))
98 100575 : return str.size() - 1;
99 :
100 9729213 : size_t pos = str.find_last_of(separators(style), str.size() - 1);
101 :
102 : if (real_style(style) == Style::windows) {
103 209 : if (pos == StringRef::npos)
104 89 : pos = str.find_last_of(':', str.size() - 2);
105 : }
106 :
107 9729005 : if (pos == StringRef::npos || (pos == 1 && is_separator(str[0], style)))
108 758833 : return 0;
109 :
110 8970172 : return pos + 1;
111 : }
112 :
113 : // Returns the position of the root directory in str. If there is no root
114 : // directory in str, it returns StringRef::npos.
115 9875391 : size_t root_dir_start(StringRef str, Style style) {
116 : // case "c:/"
117 : if (real_style(style) == Style::windows) {
118 220 : if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style))
119 : return 2;
120 : }
121 :
122 : // case "//net"
123 9875681 : if (str.size() > 3 && is_separator(str[0], style) && str[0] == str[1] &&
124 300 : !is_separator(str[2], style)) {
125 268 : return str.find_first_of(separators(style), 2);
126 : }
127 :
128 : // case "/"
129 9875112 : if (str.size() > 0 && is_separator(str[0], style))
130 9106362 : return 0;
131 :
132 : return StringRef::npos;
133 : }
134 :
135 : // Returns the position past the end of the "parent path" of path. The parent
136 : // path will not end in '/', unless the parent is the root directory. If the
137 : // path has no parent, 0 is returned.
138 3301620 : size_t parent_path_end(StringRef path, Style style) {
139 3301620 : size_t end_pos = filename_pos(path, style);
140 :
141 : bool filename_was_sep =
142 3301619 : path.size() > 0 && is_separator(path[end_pos], style);
143 :
144 : // Skip separators until we reach root dir (or the start of the string).
145 3301619 : size_t root_dir_pos = root_dir_start(path, style);
146 6379278 : while (end_pos > 0 &&
147 9680836 : (root_dir_pos == StringRef::npos || end_pos > root_dir_pos) &&
148 12758432 : is_separator(path[end_pos - 1], style))
149 : --end_pos;
150 :
151 3301620 : if (end_pos == root_dir_pos && !filename_was_sep) {
152 : // We've reached the root dir and the input path was *not* ending in a
153 : // sequence of slashes. Include the root dir in the parent path.
154 13902 : return root_dir_pos + 1;
155 : }
156 :
157 : // Otherwise, just include before the last slash.
158 : return end_pos;
159 : }
160 : } // end unnamed namespace
161 :
162 : enum FSEntity {
163 : FS_Dir,
164 : FS_File,
165 : FS_Name
166 : };
167 :
168 : static std::error_code
169 25608 : createUniqueEntity(const Twine &Model, int &ResultFD,
170 : SmallVectorImpl<char> &ResultPath, bool MakeAbsolute,
171 : unsigned Mode, FSEntity Type,
172 : sys::fs::OpenFlags Flags = sys::fs::OF_None) {
173 : SmallString<128> ModelStorage;
174 25608 : Model.toVector(ModelStorage);
175 :
176 25608 : if (MakeAbsolute) {
177 : // Make model absolute by prepending a temp directory if it's not already.
178 6123 : if (!sys::path::is_absolute(Twine(ModelStorage))) {
179 : SmallString<128> TDir;
180 6123 : sys::path::system_temp_directory(true, TDir);
181 6123 : sys::path::append(TDir, Twine(ModelStorage));
182 6123 : ModelStorage.swap(TDir);
183 : }
184 : }
185 :
186 : // From here on, DO NOT modify model. It may be needed if the randomly chosen
187 : // path already exists.
188 25608 : ResultPath = ModelStorage;
189 : // Null terminate.
190 25608 : ResultPath.push_back(0);
191 : ResultPath.pop_back();
192 :
193 : // Limit the number of attempts we make, so that we don't infinite loop. E.g.
194 : // "permission denied" could be for a specific file (so we retry with a
195 : // different name) or for the whole directory (retry would always fail).
196 : // Checking which is racy, so we try a number of times, then give up.
197 : std::error_code EC;
198 25771 : for (int Retries = 128; Retries > 0; --Retries) {
199 : // Replace '%' with random chars.
200 2952375 : for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
201 5853210 : if (ModelStorage[i] == '%')
202 185868 : ResultPath[i] =
203 185868 : "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
204 : }
205 :
206 : // Try to open + create the file.
207 25770 : switch (Type) {
208 25716 : case FS_File: {
209 25716 : EC = sys::fs::openFileForReadWrite(Twine(ResultPath.begin()), ResultFD,
210 25716 : sys::fs::CD_CreateNew, Flags, Mode);
211 25716 : if (EC) {
212 : // errc::permission_denied happens on Windows when we try to open a file
213 : // that has been marked for deletion.
214 : if (EC == errc::file_exists || EC == errc::permission_denied)
215 163 : continue;
216 76 : return EC;
217 : }
218 :
219 25477 : return std::error_code();
220 : }
221 :
222 1 : case FS_Name: {
223 1 : EC = sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
224 : if (EC == errc::no_such_file_or_directory)
225 1 : return std::error_code();
226 0 : if (EC)
227 0 : return EC;
228 : continue;
229 : }
230 :
231 : case FS_Dir: {
232 53 : EC = sys::fs::create_directory(ResultPath.begin(), false);
233 53 : if (EC) {
234 : if (EC == errc::file_exists)
235 : continue;
236 0 : return EC;
237 : }
238 53 : return std::error_code();
239 : }
240 : }
241 0 : llvm_unreachable("Invalid Type");
242 : }
243 1 : return EC;
244 : }
245 :
246 : namespace llvm {
247 : namespace sys {
248 : namespace path {
249 :
250 35287950 : const_iterator begin(StringRef path, Style style) {
251 : const_iterator i;
252 35287950 : i.Path = path;
253 35287950 : i.Component = find_first_component(path, style);
254 35280098 : i.Position = 0;
255 35280098 : i.S = style;
256 35280098 : return i;
257 : }
258 :
259 35287145 : const_iterator end(StringRef path) {
260 : const_iterator i;
261 35287145 : i.Path = path;
262 35287145 : i.Position = path.size();
263 35287145 : return i;
264 : }
265 :
266 28387580 : const_iterator &const_iterator::operator++() {
267 : assert(Position < Path.size() && "Tried to increment past end!");
268 :
269 : // Increment Position to past the current component
270 28387580 : Position += Component.size();
271 :
272 : // Check for end.
273 28387580 : if (Position == Path.size()) {
274 8433975 : Component = StringRef();
275 8433975 : return *this;
276 : }
277 :
278 : // Both POSIX and Windows treat paths that begin with exactly two separators
279 : // specially.
280 31333212 : bool was_net = Component.size() > 2 && is_separator(Component[0], S) &&
281 19954406 : Component[1] == Component[0] && !is_separator(Component[2], S);
282 :
283 : // Handle separators.
284 39906828 : if (is_separator(Path[Position], S)) {
285 : // Root dir.
286 16663436 : if (was_net ||
287 : // c:/
288 16662635 : (real_style(S) == Style::windows && Component.endswith(":"))) {
289 866 : Component = Path.substr(Position, 1);
290 866 : return *this;
291 : }
292 :
293 : // Skip extra separators.
294 66650572 : while (Position != Path.size() && is_separator(Path[Position], S)) {
295 16662716 : ++Position;
296 : }
297 :
298 : // Treat trailing '/' as a '.', unless it is the root dir.
299 33325532 : if (Position == Path.size() && Component != "/") {
300 34 : --Position;
301 34 : Component = ".";
302 34 : return *this;
303 : }
304 : }
305 :
306 : // Find next component.
307 19952787 : size_t end_pos = Path.find_first_of(separators(S), Position);
308 19952748 : Component = Path.slice(Position, end_pos);
309 :
310 19951938 : return *this;
311 : }
312 :
313 62715339 : bool const_iterator::operator==(const const_iterator &RHS) const {
314 62715339 : return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
315 : }
316 :
317 287 : ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
318 287 : return Position - RHS.Position;
319 : }
320 :
321 3627034 : reverse_iterator rbegin(StringRef Path, Style style) {
322 : reverse_iterator I;
323 3627034 : I.Path = Path;
324 3627034 : I.Position = Path.size();
325 3627034 : I.S = style;
326 3627034 : return ++I;
327 : }
328 :
329 2025396 : reverse_iterator rend(StringRef Path) {
330 : reverse_iterator I;
331 2025396 : I.Path = Path;
332 2025396 : I.Component = Path.substr(0, 0);
333 2025396 : I.Position = 0;
334 2025396 : return I;
335 : }
336 :
337 6573776 : reverse_iterator &reverse_iterator::operator++() {
338 6573776 : size_t root_dir_pos = root_dir_start(Path, S);
339 :
340 : // Skip separators unless it's the root directory.
341 6573761 : size_t end_pos = Position;
342 15552229 : while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
343 17956926 : is_separator(Path[end_pos - 1], S))
344 : --end_pos;
345 :
346 : // Treat trailing '/' as a '.', unless it is the root dir.
347 9635071 : if (Position == Path.size() && !Path.empty() &&
348 12781520 : is_separator(Path.back(), S) &&
349 85068 : (root_dir_pos == StringRef::npos || end_pos - 1 > root_dir_pos)) {
350 74781 : --Position;
351 74781 : Component = ".";
352 74781 : return *this;
353 : }
354 :
355 : // Find next separator.
356 6498988 : size_t start_pos = filename_pos(Path.substr(0, end_pos), S);
357 6498975 : Component = Path.slice(start_pos, end_pos);
358 6498975 : Position = start_pos;
359 6498975 : return *this;
360 : }
361 :
362 2910112 : bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
363 2910112 : return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
364 208 : Position == RHS.Position;
365 : }
366 :
367 45 : ptrdiff_t reverse_iterator::operator-(const reverse_iterator &RHS) const {
368 45 : return Position - RHS.Position;
369 : }
370 :
371 8406601 : StringRef root_path(StringRef path, Style style) {
372 8406601 : const_iterator b = begin(path, style), pos = b, e = end(path);
373 8407221 : if (b != e) {
374 : bool has_net =
375 8161539 : b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
376 : bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
377 :
378 8161535 : if (has_net || has_drive) {
379 826 : if ((++pos != e) && is_separator((*pos)[0], style)) {
380 : // {C:/,//net/}, so get the first two components.
381 409 : return path.substr(0, b->size() + pos->size());
382 : } else {
383 : // just {C:,//net}, return the first component.
384 4 : return *b;
385 : }
386 : }
387 :
388 : // POSIX style root directory.
389 16322244 : if (is_separator((*b)[0], style)) {
390 7543612 : return *b;
391 : }
392 : }
393 :
394 862985 : return StringRef();
395 : }
396 :
397 13160902 : StringRef root_name(StringRef path, Style style) {
398 13160902 : const_iterator b = begin(path, style), e = end(path);
399 13160109 : if (b != e) {
400 : bool has_net =
401 13077533 : b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
402 : bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
403 :
404 13077379 : if (has_net || has_drive) {
405 : // just {C:,//net}, return the first component.
406 73 : return *b;
407 : }
408 : }
409 :
410 : // No path or no name.
411 13159882 : return StringRef();
412 : }
413 :
414 5937773 : StringRef root_directory(StringRef path, Style style) {
415 5937773 : const_iterator b = begin(path, style), pos = b, e = end(path);
416 5938232 : if (b != e) {
417 : bool has_net =
418 5748080 : b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0];
419 : bool has_drive = (real_style(style) == Style::windows) && b->endswith(":");
420 :
421 360 : if ((has_net || has_drive) &&
422 : // {C:,//net}, skip to the next component.
423 5748769 : (++pos != e) && is_separator((*pos)[0], style)) {
424 352 : return *pos;
425 : }
426 :
427 : // POSIX style root directory.
428 5747711 : if (!has_net && is_separator((*b)[0], style)) {
429 2978632 : return *b;
430 : }
431 : }
432 :
433 : // No path or no root.
434 2959133 : return StringRef();
435 : }
436 :
437 2872350 : StringRef relative_path(StringRef path, Style style) {
438 2872350 : StringRef root = root_path(path, style);
439 2872395 : return path.substr(root.size());
440 : }
441 :
442 15307030 : void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
443 : const Twine &b, const Twine &c, const Twine &d) {
444 : SmallString<32> a_storage;
445 : SmallString<32> b_storage;
446 : SmallString<32> c_storage;
447 : SmallString<32> d_storage;
448 :
449 : SmallVector<StringRef, 4> components;
450 15308418 : if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
451 613022 : if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
452 477510 : if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
453 265657 : if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
454 :
455 31969258 : for (auto &component : components) {
456 : bool path_has_sep =
457 16663469 : !path.empty() && is_separator(path[path.size() - 1], style);
458 : if (path_has_sep) {
459 : // Strip separators from beginning of component.
460 2402162 : size_t loc = component.find_first_not_of(separators(style));
461 2402261 : StringRef c = component.substr(loc);
462 :
463 : // Append it.
464 2402261 : path.append(c.begin(), c.end());
465 : continue;
466 : }
467 :
468 : bool component_has_sep =
469 14261016 : !component.empty() && is_separator(component[0], style);
470 13919583 : if (!component_has_sep &&
471 14260896 : !(path.empty() || has_root_name(component, style))) {
472 : // Add a separator.
473 12909754 : path.push_back(preferred_separator(style));
474 : }
475 :
476 28520300 : path.append(component.begin(), component.end());
477 : }
478 15305789 : }
479 :
480 5640568 : void append(SmallVectorImpl<char> &path, const Twine &a, const Twine &b,
481 : const Twine &c, const Twine &d) {
482 5640568 : append(path, Style::native, a, b, c, d);
483 5640548 : }
484 :
485 59 : void append(SmallVectorImpl<char> &path, const_iterator begin,
486 : const_iterator end, Style style) {
487 415 : for (; begin != end; ++begin)
488 356 : path::append(path, style, *begin);
489 59 : }
490 :
491 3263022 : StringRef parent_path(StringRef path, Style style) {
492 3263022 : size_t end_pos = parent_path_end(path, style);
493 3263021 : if (end_pos == StringRef::npos)
494 0 : return StringRef();
495 : else
496 3263021 : return path.substr(0, end_pos);
497 : }
498 :
499 38598 : void remove_filename(SmallVectorImpl<char> &path, Style style) {
500 77196 : size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()), style);
501 38598 : if (end_pos != StringRef::npos)
502 : path.set_size(end_pos);
503 38598 : }
504 :
505 29545 : void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
506 : Style style) {
507 29545 : StringRef p(path.begin(), path.size());
508 : SmallString<32> ext_storage;
509 29545 : StringRef ext = extension.toStringRef(ext_storage);
510 :
511 : // Erase existing extension.
512 : size_t pos = p.find_last_of('.');
513 29545 : if (pos != StringRef::npos && pos >= filename_pos(p, style))
514 : path.set_size(pos);
515 :
516 : // Append '.' if needed.
517 29545 : if (ext.size() > 0 && ext[0] != '.')
518 28442 : path.push_back('.');
519 :
520 : // Append extension.
521 29545 : path.append(ext.begin(), ext.end());
522 29545 : }
523 :
524 8 : void replace_path_prefix(SmallVectorImpl<char> &Path,
525 : const StringRef &OldPrefix, const StringRef &NewPrefix,
526 : Style style) {
527 8 : if (OldPrefix.empty() && NewPrefix.empty())
528 5 : return;
529 :
530 8 : StringRef OrigPath(Path.begin(), Path.size());
531 : if (!OrigPath.startswith(OldPrefix))
532 : return;
533 :
534 : // If prefixes have the same size we can simply copy the new one over.
535 7 : if (OldPrefix.size() == NewPrefix.size()) {
536 4 : std::copy(NewPrefix.begin(), NewPrefix.end(), Path.begin());
537 4 : return;
538 : }
539 :
540 3 : StringRef RelPath = OrigPath.substr(OldPrefix.size());
541 : SmallString<256> NewPath;
542 3 : path::append(NewPath, style, NewPrefix);
543 3 : path::append(NewPath, style, RelPath);
544 3 : Path.swap(NewPath);
545 : }
546 :
547 41954 : void native(const Twine &path, SmallVectorImpl<char> &result, Style style) {
548 : assert((!path.isSingleStringRef() ||
549 : path.getSingleStringRef().data() != result.data()) &&
550 : "path and result are not allowed to overlap!");
551 : // Clear result.
552 : result.clear();
553 41954 : path.toVector(result);
554 41954 : native(result, style);
555 41954 : }
556 :
557 50721 : void native(SmallVectorImpl<char> &Path, Style style) {
558 50721 : if (Path.empty())
559 : return;
560 : if (real_style(style) == Style::windows) {
561 : std::replace(Path.begin(), Path.end(), '/', '\\');
562 6 : if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
563 : SmallString<128> PathHome;
564 0 : home_directory(PathHome);
565 0 : PathHome.append(Path.begin() + 1, Path.end());
566 0 : Path = PathHome;
567 : }
568 : } else {
569 4715046 : for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
570 4664350 : if (*PI == '\\') {
571 42 : auto PN = PI + 1;
572 42 : if (PN < PE && *PN == '\\')
573 : ++PI; // increment once, the for loop will move over the escaped slash
574 : else
575 41 : *PI = '/';
576 : }
577 : }
578 : }
579 : }
580 :
581 262 : std::string convert_to_slash(StringRef path, Style style) {
582 : if (real_style(style) != Style::windows)
583 : return path;
584 :
585 : std::string s = path.str();
586 : std::replace(s.begin(), s.end(), '\\', '/');
587 : return s;
588 : }
589 :
590 1601530 : StringRef filename(StringRef path, Style style) { return *rbegin(path, style); }
591 :
592 119200 : StringRef stem(StringRef path, Style style) {
593 119200 : StringRef fname = filename(path, style);
594 : size_t pos = fname.find_last_of('.');
595 119200 : if (pos == StringRef::npos)
596 78410 : return fname;
597 : else
598 40790 : if ((fname.size() == 1 && fname == ".") ||
599 : (fname.size() == 2 && fname == ".."))
600 36 : return fname;
601 : else
602 40754 : return fname.substr(0, pos);
603 : }
604 :
605 69495 : StringRef extension(StringRef path, Style style) {
606 69495 : StringRef fname = filename(path, style);
607 : size_t pos = fname.find_last_of('.');
608 69495 : if (pos == StringRef::npos)
609 10666 : return StringRef();
610 : else
611 58829 : if ((fname.size() == 1 && fname == ".") ||
612 : (fname.size() == 2 && fname == ".."))
613 77 : return StringRef();
614 : else
615 58752 : return fname.substr(pos);
616 : }
617 :
618 252091096 : bool is_separator(char value, Style style) {
619 252091096 : if (value == '/')
620 : return true;
621 : if (real_style(style) == Style::windows)
622 26533 : return value == '\\';
623 : return false;
624 : }
625 :
626 13628 : StringRef get_separator(Style style) {
627 : if (real_style(style) == Style::windows)
628 0 : return "\\";
629 13628 : return "/";
630 : }
631 :
632 12916940 : bool has_root_name(const Twine &path, Style style) {
633 : SmallString<128> path_storage;
634 12916940 : StringRef p = path.toStringRef(path_storage);
635 :
636 12917645 : return !root_name(p, style).empty();
637 : }
638 :
639 5694326 : bool has_root_directory(const Twine &path, Style style) {
640 : SmallString<128> path_storage;
641 5694326 : StringRef p = path.toStringRef(path_storage);
642 :
643 5694483 : return !root_directory(p, style).empty();
644 : }
645 :
646 41 : bool has_root_path(const Twine &path, Style style) {
647 : SmallString<128> path_storage;
648 41 : StringRef p = path.toStringRef(path_storage);
649 :
650 41 : return !root_path(p, style).empty();
651 : }
652 :
653 0 : bool has_relative_path(const Twine &path, Style style) {
654 : SmallString<128> path_storage;
655 0 : StringRef p = path.toStringRef(path_storage);
656 :
657 0 : return !relative_path(p, style).empty();
658 : }
659 :
660 41 : bool has_filename(const Twine &path, Style style) {
661 : SmallString<128> path_storage;
662 41 : StringRef p = path.toStringRef(path_storage);
663 :
664 41 : return !filename(p, style).empty();
665 : }
666 :
667 242 : bool has_parent_path(const Twine &path, Style style) {
668 : SmallString<128> path_storage;
669 242 : StringRef p = path.toStringRef(path_storage);
670 :
671 242 : return !parent_path(p, style).empty();
672 : }
673 :
674 41 : bool has_stem(const Twine &path, Style style) {
675 : SmallString<128> path_storage;
676 41 : StringRef p = path.toStringRef(path_storage);
677 :
678 41 : return !stem(p, style).empty();
679 : }
680 :
681 471 : bool has_extension(const Twine &path, Style style) {
682 : SmallString<128> path_storage;
683 471 : StringRef p = path.toStringRef(path_storage);
684 :
685 471 : return !extension(p, style).empty();
686 : }
687 :
688 5427326 : bool is_absolute(const Twine &path, Style style) {
689 : SmallString<128> path_storage;
690 5427326 : StringRef p = path.toStringRef(path_storage);
691 :
692 5427510 : bool rootDir = has_root_directory(p, style);
693 : bool rootName =
694 6792 : (real_style(style) != Style::windows) || has_root_name(p, style);
695 :
696 5427411 : return rootDir && rootName;
697 : }
698 :
699 134724 : bool is_relative(const Twine &path, Style style) {
700 134724 : return !is_absolute(path, style);
701 : }
702 :
703 3633 : StringRef remove_leading_dotslash(StringRef Path, Style style) {
704 : // Remove leading "./" (or ".//" or "././" etc.)
705 3646 : while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
706 13 : Path = Path.substr(2);
707 19 : while (Path.size() > 0 && is_separator(Path[0], style))
708 6 : Path = Path.substr(1);
709 : }
710 3633 : return Path;
711 : }
712 :
713 2384930 : static SmallString<256> remove_dots(StringRef path, bool remove_dot_dot,
714 : Style style) {
715 : SmallVector<StringRef, 16> components;
716 :
717 : // Skip the root path, then look for traversal in the components.
718 2384930 : StringRef rel = path::relative_path(path, style);
719 10596087 : for (StringRef C :
720 25963218 : llvm::make_range(path::begin(rel, style), path::end(rel))) {
721 : if (C == ".")
722 : continue;
723 : // Leading ".." will remain in the path unless it's at the root.
724 10541612 : if (remove_dot_dot && C == "..") {
725 732057 : if (!components.empty() && components.back() != "..") {
726 : components.pop_back();
727 146470 : continue;
728 : }
729 585587 : if (path::is_absolute(path, style))
730 : continue;
731 : }
732 9809561 : components.push_back(C);
733 : }
734 :
735 2384995 : SmallString<256> buffer = path::root_path(path, style);
736 12049778 : for (StringRef C : components)
737 9664780 : path::append(buffer, style, C);
738 2384998 : return buffer;
739 : }
740 :
741 2384934 : bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot,
742 : Style style) {
743 4769868 : StringRef p(path.data(), path.size());
744 :
745 2384934 : SmallString<256> result = remove_dots(p, remove_dot_dot, style);
746 2385038 : if (result == path)
747 : return false;
748 :
749 687817 : path.swap(result);
750 687824 : return true;
751 : }
752 :
753 : } // end namespace path
754 :
755 : namespace fs {
756 :
757 10677 : std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
758 10677 : file_status Status;
759 10677 : std::error_code EC = status(Path, Status);
760 10677 : if (EC)
761 126 : return EC;
762 10551 : Result = Status.getUniqueID();
763 10551 : return std::error_code();
764 : }
765 :
766 13519 : std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
767 : SmallVectorImpl<char> &ResultPath,
768 : unsigned Mode) {
769 13519 : return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
770 : }
771 :
772 : static std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
773 : SmallVectorImpl<char> &ResultPath,
774 : unsigned Mode, OpenFlags Flags) {
775 : return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File,
776 5966 : Flags);
777 : }
778 :
779 165 : std::error_code createUniqueFile(const Twine &Model,
780 : SmallVectorImpl<char> &ResultPath,
781 : unsigned Mode) {
782 : int FD;
783 165 : auto EC = createUniqueFile(Model, FD, ResultPath, Mode);
784 165 : if (EC)
785 0 : return EC;
786 : // FD is only needed to avoid race conditions. Close it right away.
787 165 : close(FD);
788 165 : return EC;
789 : }
790 :
791 : static std::error_code
792 6070 : createTemporaryFile(const Twine &Model, int &ResultFD,
793 : llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
794 : SmallString<128> Storage;
795 6070 : StringRef P = Model.toNullTerminatedStringRef(Storage);
796 : assert(P.find_first_of(separators(Style::native)) == StringRef::npos &&
797 : "Model must be a simple filename.");
798 : // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
799 : return createUniqueEntity(P.begin(), ResultFD, ResultPath, true,
800 12140 : owner_read | owner_write, Type);
801 : }
802 :
803 : static std::error_code
804 6070 : createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
805 : llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
806 6070 : const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
807 6070 : return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
808 6070 : Type);
809 : }
810 :
811 6069 : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
812 : int &ResultFD,
813 : SmallVectorImpl<char> &ResultPath) {
814 6069 : return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
815 : }
816 :
817 5829 : std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
818 : SmallVectorImpl<char> &ResultPath) {
819 : int FD;
820 5829 : auto EC = createTemporaryFile(Prefix, Suffix, FD, ResultPath);
821 5829 : if (EC)
822 0 : return EC;
823 : // FD is only needed to avoid race conditions. Close it right away.
824 5829 : close(FD);
825 5829 : return EC;
826 : }
827 :
828 :
829 : // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
830 : // for consistency. We should try using mkdtemp.
831 53 : std::error_code createUniqueDirectory(const Twine &Prefix,
832 : SmallVectorImpl<char> &ResultPath) {
833 : int Dummy;
834 53 : return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, true, 0,
835 53 : FS_Dir);
836 : }
837 :
838 : std::error_code
839 0 : getPotentiallyUniqueFileName(const Twine &Model,
840 : SmallVectorImpl<char> &ResultPath) {
841 : int Dummy;
842 0 : return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
843 : }
844 :
845 : std::error_code
846 1 : getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
847 : SmallVectorImpl<char> &ResultPath) {
848 : int Dummy;
849 1 : return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
850 : }
851 :
852 266918 : static std::error_code make_absolute(const Twine ¤t_directory,
853 : SmallVectorImpl<char> &path,
854 : bool use_current_directory) {
855 533836 : StringRef p(path.data(), path.size());
856 :
857 266918 : bool rootDirectory = path::has_root_directory(p);
858 : bool rootName =
859 : (real_style(Style::native) != Style::windows) || path::has_root_name(p);
860 :
861 : // Already absolute.
862 266920 : if (rootName && rootDirectory)
863 23427 : return std::error_code();
864 :
865 : // All of the following conditions will need the current directory.
866 : SmallString<128> current_dir;
867 243493 : if (use_current_directory)
868 243312 : current_directory.toVector(current_dir);
869 181 : else if (std::error_code ec = current_path(current_dir))
870 0 : return ec;
871 :
872 : // Relative path. Prepend the current directory.
873 : if (!rootName && !rootDirectory) {
874 : // Append path to the current directory.
875 : path::append(current_dir, p);
876 : // Set path to the result.
877 : path.swap(current_dir);
878 : return std::error_code();
879 : }
880 :
881 : if (!rootName && rootDirectory) {
882 : StringRef cdrn = path::root_name(current_dir);
883 : SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
884 : path::append(curDirRootName, p);
885 : // Set path to the result.
886 : path.swap(curDirRootName);
887 : return std::error_code();
888 : }
889 :
890 : if (rootName && !rootDirectory) {
891 243494 : StringRef pRootName = path::root_name(p);
892 243484 : StringRef bRootDirectory = path::root_directory(current_dir);
893 243490 : StringRef bRelativePath = path::relative_path(current_dir);
894 243500 : StringRef pRelativePath = path::relative_path(p);
895 :
896 : SmallString<128> res;
897 243496 : path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
898 243476 : path.swap(res);
899 243502 : return std::error_code();
900 : }
901 :
902 : llvm_unreachable("All rootName and rootDirectory combinations should have "
903 : "occurred above!");
904 : }
905 :
906 243396 : std::error_code make_absolute(const Twine ¤t_directory,
907 : SmallVectorImpl<char> &path) {
908 243396 : return make_absolute(current_directory, path, true);
909 : }
910 :
911 23523 : std::error_code make_absolute(SmallVectorImpl<char> &path) {
912 23523 : return make_absolute(Twine(), path, false);
913 : }
914 :
915 2931 : std::error_code create_directories(const Twine &Path, bool IgnoreExisting,
916 : perms Perms) {
917 : SmallString<128> PathStorage;
918 2931 : StringRef P = Path.toStringRef(PathStorage);
919 :
920 : // Be optimistic and try to create the directory
921 5862 : std::error_code EC = create_directory(P, IgnoreExisting, Perms);
922 : // If we succeeded, or had any error other than the parent not existing, just
923 : // return it.
924 : if (EC != errc::no_such_file_or_directory)
925 1959 : return EC;
926 :
927 : // We failed because of a no_such_file_or_directory, try to create the
928 : // parent.
929 972 : StringRef Parent = path::parent_path(P);
930 972 : if (Parent.empty())
931 0 : return EC;
932 :
933 972 : if ((EC = create_directories(Parent, IgnoreExisting, Perms)))
934 465 : return EC;
935 :
936 507 : return create_directory(P, IgnoreExisting, Perms);
937 : }
938 :
939 307 : static std::error_code copy_file_internal(int ReadFD, int WriteFD) {
940 : const size_t BufSize = 4096;
941 307 : char *Buf = new char[BufSize];
942 : int BytesRead = 0, BytesWritten = 0;
943 : for (;;) {
944 632 : BytesRead = read(ReadFD, Buf, BufSize);
945 632 : if (BytesRead <= 0)
946 : break;
947 650 : while (BytesRead) {
948 325 : BytesWritten = write(WriteFD, Buf, BytesRead);
949 325 : if (BytesWritten < 0)
950 : break;
951 325 : BytesRead -= BytesWritten;
952 : }
953 325 : if (BytesWritten < 0)
954 : break;
955 : }
956 307 : delete[] Buf;
957 :
958 307 : if (BytesRead < 0 || BytesWritten < 0)
959 0 : return std::error_code(errno, std::generic_category());
960 307 : return std::error_code();
961 : }
962 :
963 310 : std::error_code copy_file(const Twine &From, const Twine &To) {
964 : int ReadFD, WriteFD;
965 310 : if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
966 4 : return EC;
967 306 : if (std::error_code EC =
968 : openFileForWrite(To, WriteFD, CD_CreateAlways, OF_None)) {
969 0 : close(ReadFD);
970 0 : return EC;
971 : }
972 :
973 306 : std::error_code EC = copy_file_internal(ReadFD, WriteFD);
974 :
975 306 : close(ReadFD);
976 306 : close(WriteFD);
977 :
978 306 : return EC;
979 : }
980 :
981 1 : std::error_code copy_file(const Twine &From, int ToFD) {
982 : int ReadFD;
983 1 : if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
984 0 : return EC;
985 :
986 1 : std::error_code EC = copy_file_internal(ReadFD, ToFD);
987 :
988 1 : close(ReadFD);
989 :
990 1 : return EC;
991 : }
992 :
993 1 : ErrorOr<MD5::MD5Result> md5_contents(int FD) {
994 1 : MD5 Hash;
995 :
996 : constexpr size_t BufSize = 4096;
997 1 : std::vector<uint8_t> Buf(BufSize);
998 : int BytesRead = 0;
999 : for (;;) {
1000 2 : BytesRead = read(FD, Buf.data(), BufSize);
1001 2 : if (BytesRead <= 0)
1002 : break;
1003 1 : Hash.update(makeArrayRef(Buf.data(), BytesRead));
1004 : }
1005 :
1006 1 : if (BytesRead < 0)
1007 0 : return std::error_code(errno, std::generic_category());
1008 : MD5::MD5Result Result;
1009 1 : Hash.final(Result);
1010 : return Result;
1011 : }
1012 :
1013 0 : ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
1014 : int FD;
1015 0 : if (auto EC = openFileForRead(Path, FD, OF_None))
1016 0 : return EC;
1017 :
1018 0 : auto Result = md5_contents(FD);
1019 0 : close(FD);
1020 : return Result;
1021 : }
1022 :
1023 10961 : bool exists(const basic_file_status &status) {
1024 10961 : return status_known(status) && status.type() != file_type::file_not_found;
1025 : }
1026 :
1027 10961 : bool status_known(const basic_file_status &s) {
1028 10961 : return s.type() != file_type::status_error;
1029 : }
1030 :
1031 0 : file_type get_file_type(const Twine &Path, bool Follow) {
1032 0 : file_status st;
1033 0 : if (status(Path, st, Follow))
1034 : return file_type::status_error;
1035 0 : return st.type();
1036 : }
1037 :
1038 3918 : bool is_directory(const basic_file_status &status) {
1039 3918 : return status.type() == file_type::directory_file;
1040 : }
1041 :
1042 4431 : std::error_code is_directory(const Twine &path, bool &result) {
1043 4431 : file_status st;
1044 4431 : if (std::error_code ec = status(path, st))
1045 548 : return ec;
1046 3883 : result = is_directory(st);
1047 3883 : return std::error_code();
1048 : }
1049 :
1050 7824 : bool is_regular_file(const basic_file_status &status) {
1051 7824 : return status.type() == file_type::regular_file;
1052 : }
1053 :
1054 8306 : std::error_code is_regular_file(const Twine &path, bool &result) {
1055 8306 : file_status st;
1056 8306 : if (std::error_code ec = status(path, st))
1057 3034 : return ec;
1058 5272 : result = is_regular_file(st);
1059 5272 : return std::error_code();
1060 : }
1061 :
1062 0 : bool is_symlink_file(const basic_file_status &status) {
1063 0 : return status.type() == file_type::symlink_file;
1064 : }
1065 :
1066 0 : std::error_code is_symlink_file(const Twine &path, bool &result) {
1067 0 : file_status st;
1068 0 : if (std::error_code ec = status(path, st, false))
1069 0 : return ec;
1070 0 : result = is_symlink_file(st);
1071 0 : return std::error_code();
1072 : }
1073 :
1074 0 : bool is_other(const basic_file_status &status) {
1075 0 : return exists(status) &&
1076 0 : !is_regular_file(status) &&
1077 0 : !is_directory(status);
1078 : }
1079 :
1080 0 : std::error_code is_other(const Twine &Path, bool &Result) {
1081 0 : file_status FileStatus;
1082 0 : if (std::error_code EC = status(Path, FileStatus))
1083 0 : return EC;
1084 0 : Result = is_other(FileStatus);
1085 0 : return std::error_code();
1086 : }
1087 :
1088 49664 : void directory_entry::replace_filename(const Twine &Filename, file_type Type,
1089 : basic_file_status Status) {
1090 99328 : SmallString<128> PathStr = path::parent_path(Path);
1091 49664 : path::append(PathStr, Filename);
1092 49664 : this->Path = PathStr.str();
1093 49664 : this->Type = Type;
1094 49664 : this->Status = Status;
1095 49664 : }
1096 :
1097 25 : ErrorOr<perms> getPermissions(const Twine &Path) {
1098 25 : file_status Status;
1099 25 : if (std::error_code EC = status(Path, Status))
1100 0 : return EC;
1101 :
1102 25 : return Status.permissions();
1103 : }
1104 :
1105 : } // end namespace fs
1106 : } // end namespace sys
1107 : } // end namespace llvm
1108 :
1109 : // Include the truly platform-specific parts.
1110 : #if defined(LLVM_ON_UNIX)
1111 : #include "Unix/Path.inc"
1112 : #endif
1113 : #if defined(_WIN32)
1114 : #include "Windows/Path.inc"
1115 : #endif
1116 :
1117 : namespace llvm {
1118 : namespace sys {
1119 : namespace fs {
1120 5955 : TempFile::TempFile(StringRef Name, int FD) : TmpName(Name), FD(FD) {}
1121 44226 : TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
1122 22113 : TempFile &TempFile::operator=(TempFile &&Other) {
1123 22113 : TmpName = std::move(Other.TmpName);
1124 22113 : FD = Other.FD;
1125 22113 : Other.Done = true;
1126 22113 : return *this;
1127 : }
1128 :
1129 28067 : TempFile::~TempFile() { assert(Done); }
1130 :
1131 5534 : Error TempFile::discard() {
1132 5534 : Done = true;
1133 : std::error_code RemoveEC;
1134 : // On windows closing will remove the file.
1135 : #ifndef _WIN32
1136 : // Always try to close and remove.
1137 5534 : if (!TmpName.empty()) {
1138 4856 : RemoveEC = fs::remove(TmpName);
1139 2428 : sys::DontRemoveFileOnSignal(TmpName);
1140 : }
1141 : #endif
1142 :
1143 5534 : if (!RemoveEC)
1144 5534 : TmpName = "";
1145 :
1146 5534 : if (FD != -1 && close(FD) == -1) {
1147 0 : std::error_code EC = std::error_code(errno, std::generic_category());
1148 0 : return errorCodeToError(EC);
1149 : }
1150 5534 : FD = -1;
1151 :
1152 5534 : return errorCodeToError(RemoveEC);
1153 : }
1154 :
1155 3526 : Error TempFile::keep(const Twine &Name) {
1156 : assert(!Done);
1157 3526 : Done = true;
1158 : // Always try to close and rename.
1159 : #ifdef _WIN32
1160 : // If we can't cancel the delete don't rename.
1161 : auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1162 : std::error_code RenameEC = setDeleteDisposition(H, false);
1163 : if (!RenameEC) {
1164 : RenameEC = rename_fd(FD, Name);
1165 : // If rename failed because it's cross-device, copy instead
1166 : if (RenameEC ==
1167 : std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) {
1168 : RenameEC = copy_file(TmpName, Name);
1169 : setDeleteDisposition(H, true);
1170 : }
1171 : }
1172 :
1173 : // If we can't rename, discard the temporary file.
1174 : if (RenameEC)
1175 : setDeleteDisposition(H, true);
1176 : #else
1177 7052 : std::error_code RenameEC = fs::rename(TmpName, Name);
1178 3526 : if (RenameEC) {
1179 : // If we can't rename, try to copy to work around cross-device link issues.
1180 0 : RenameEC = sys::fs::copy_file(TmpName, Name);
1181 : // If we can't rename or copy, discard the temporary file.
1182 0 : if (RenameEC)
1183 0 : remove(TmpName);
1184 : }
1185 3526 : sys::DontRemoveFileOnSignal(TmpName);
1186 : #endif
1187 :
1188 3526 : if (!RenameEC)
1189 : TmpName = "";
1190 :
1191 3526 : if (close(FD) == -1) {
1192 0 : std::error_code EC(errno, std::generic_category());
1193 0 : return errorCodeToError(EC);
1194 : }
1195 3526 : FD = -1;
1196 :
1197 3526 : return errorCodeToError(RenameEC);
1198 : }
1199 :
1200 0 : Error TempFile::keep() {
1201 : assert(!Done);
1202 0 : Done = true;
1203 :
1204 : #ifdef _WIN32
1205 : auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
1206 : if (std::error_code EC = setDeleteDisposition(H, false))
1207 : return errorCodeToError(EC);
1208 : #else
1209 0 : sys::DontRemoveFileOnSignal(TmpName);
1210 : #endif
1211 :
1212 0 : TmpName = "";
1213 :
1214 0 : if (close(FD) == -1) {
1215 0 : std::error_code EC(errno, std::generic_category());
1216 0 : return errorCodeToError(EC);
1217 : }
1218 0 : FD = -1;
1219 :
1220 : return Error::success();
1221 : }
1222 :
1223 5966 : Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode) {
1224 : int FD;
1225 : SmallString<128> ResultPath;
1226 5966 : if (std::error_code EC =
1227 5966 : createUniqueFile(Model, FD, ResultPath, Mode, OF_Delete))
1228 11 : return errorCodeToError(EC);
1229 :
1230 17865 : TempFile Ret(ResultPath, FD);
1231 : #ifndef _WIN32
1232 5955 : if (sys::RemoveFileOnSignal(ResultPath)) {
1233 : // Make sure we delete the file when RemoveFileOnSignal fails.
1234 0 : consumeError(Ret.discard());
1235 : std::error_code EC(errc::operation_not_permitted);
1236 0 : return errorCodeToError(EC);
1237 : }
1238 : #endif
1239 : return std::move(Ret);
1240 : }
1241 : }
1242 :
1243 : } // end namsspace sys
1244 : } // end namespace llvm
|