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/COFF.h"
15 #include "llvm/Support/Endian.h"
16 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/Process.h"
21 #include <cctype>
22 #include <cstdio>
23 #include <cstring>
24 #include <fcntl.h>
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
34 namespace {
35 using llvm::StringRef;
36 using llvm::sys::path::is_separator;
37
38 #ifdef LLVM_ON_WIN32
39 const char *separators = "\\/";
40 const char preferred_separator = '\\';
41 #else
42 const char separators = '/';
43 const char preferred_separator = '/';
44 #endif
45
find_first_component(StringRef path)46 StringRef find_first_component(StringRef path) {
47 // Look for this first component in the following order.
48 // * empty (in this case we return an empty string)
49 // * either C: or {//,\\}net.
50 // * {/,\}
51 // * {.,..}
52 // * {file,directory}name
53
54 if (path.empty())
55 return path;
56
57 #ifdef LLVM_ON_WIN32
58 // C:
59 if (path.size() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) &&
60 path[1] == ':')
61 return path.substr(0, 2);
62 #endif
63
64 // //net
65 if ((path.size() > 2) &&
66 is_separator(path[0]) &&
67 path[0] == path[1] &&
68 !is_separator(path[2])) {
69 // Find the next directory separator.
70 size_t end = path.find_first_of(separators, 2);
71 return path.substr(0, end);
72 }
73
74 // {/,\}
75 if (is_separator(path[0]))
76 return path.substr(0, 1);
77
78 if (path.startswith(".."))
79 return path.substr(0, 2);
80
81 if (path[0] == '.')
82 return path.substr(0, 1);
83
84 // * {file,directory}name
85 size_t end = path.find_first_of(separators);
86 return path.substr(0, end);
87 }
88
filename_pos(StringRef str)89 size_t filename_pos(StringRef str) {
90 if (str.size() == 2 &&
91 is_separator(str[0]) &&
92 str[0] == str[1])
93 return 0;
94
95 if (str.size() > 0 && is_separator(str[str.size() - 1]))
96 return str.size() - 1;
97
98 size_t pos = str.find_last_of(separators, str.size() - 1);
99
100 #ifdef LLVM_ON_WIN32
101 if (pos == StringRef::npos)
102 pos = str.find_last_of(':', str.size() - 2);
103 #endif
104
105 if (pos == StringRef::npos ||
106 (pos == 1 && is_separator(str[0])))
107 return 0;
108
109 return pos + 1;
110 }
111
root_dir_start(StringRef str)112 size_t root_dir_start(StringRef str) {
113 // case "c:/"
114 #ifdef LLVM_ON_WIN32
115 if (str.size() > 2 &&
116 str[1] == ':' &&
117 is_separator(str[2]))
118 return 2;
119 #endif
120
121 // case "//"
122 if (str.size() == 2 &&
123 is_separator(str[0]) &&
124 str[0] == str[1])
125 return StringRef::npos;
126
127 // case "//net"
128 if (str.size() > 3 &&
129 is_separator(str[0]) &&
130 str[0] == str[1] &&
131 !is_separator(str[2])) {
132 return str.find_first_of(separators, 2);
133 }
134
135 // case "/"
136 if (str.size() > 0 && is_separator(str[0]))
137 return 0;
138
139 return StringRef::npos;
140 }
141
parent_path_end(StringRef path)142 size_t parent_path_end(StringRef path) {
143 size_t end_pos = filename_pos(path);
144
145 bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]);
146
147 // Skip separators except for root dir.
148 size_t root_dir_pos = root_dir_start(path.substr(0, end_pos));
149
150 while(end_pos > 0 &&
151 (end_pos - 1) != root_dir_pos &&
152 is_separator(path[end_pos - 1]))
153 --end_pos;
154
155 if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
156 return StringRef::npos;
157
158 return end_pos;
159 }
160 } // end unnamed namespace
161
162 enum FSEntity {
163 FS_Dir,
164 FS_File,
165 FS_Name
166 };
167
createUniqueEntity(const Twine & Model,int & ResultFD,SmallVectorImpl<char> & ResultPath,bool MakeAbsolute,unsigned Mode,FSEntity Type)168 static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD,
169 SmallVectorImpl<char> &ResultPath,
170 bool MakeAbsolute, unsigned Mode,
171 FSEntity Type) {
172 SmallString<128> ModelStorage;
173 Model.toVector(ModelStorage);
174
175 if (MakeAbsolute) {
176 // Make model absolute by prepending a temp directory if it's not already.
177 if (!sys::path::is_absolute(Twine(ModelStorage))) {
178 SmallString<128> TDir;
179 sys::path::system_temp_directory(true, TDir);
180 sys::path::append(TDir, Twine(ModelStorage));
181 ModelStorage.swap(TDir);
182 }
183 }
184
185 // From here on, DO NOT modify model. It may be needed if the randomly chosen
186 // path already exists.
187 ResultPath = ModelStorage;
188 // Null terminate.
189 ResultPath.push_back(0);
190 ResultPath.pop_back();
191
192 retry_random_path:
193 // Replace '%' with random chars.
194 for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
195 if (ModelStorage[i] == '%')
196 ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
197 }
198
199 // Try to open + create the file.
200 switch (Type) {
201 case FS_File: {
202 if (std::error_code EC =
203 sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
204 sys::fs::F_RW | sys::fs::F_Excl, Mode)) {
205 if (EC == errc::file_exists)
206 goto retry_random_path;
207 return EC;
208 }
209
210 return std::error_code();
211 }
212
213 case FS_Name: {
214 std::error_code EC =
215 sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
216 if (EC == errc::no_such_file_or_directory)
217 return std::error_code();
218 if (EC)
219 return EC;
220 goto retry_random_path;
221 }
222
223 case FS_Dir: {
224 if (std::error_code EC =
225 sys::fs::create_directory(ResultPath.begin(), false)) {
226 if (EC == errc::file_exists)
227 goto retry_random_path;
228 return EC;
229 }
230 return std::error_code();
231 }
232 }
233 llvm_unreachable("Invalid Type");
234 }
235
236 namespace llvm {
237 namespace sys {
238 namespace path {
239
begin(StringRef path)240 const_iterator begin(StringRef path) {
241 const_iterator i;
242 i.Path = path;
243 i.Component = find_first_component(path);
244 i.Position = 0;
245 return i;
246 }
247
end(StringRef path)248 const_iterator end(StringRef path) {
249 const_iterator i;
250 i.Path = path;
251 i.Position = path.size();
252 return i;
253 }
254
operator ++()255 const_iterator &const_iterator::operator++() {
256 assert(Position < Path.size() && "Tried to increment past end!");
257
258 // Increment Position to past the current component
259 Position += Component.size();
260
261 // Check for end.
262 if (Position == Path.size()) {
263 Component = StringRef();
264 return *this;
265 }
266
267 // Both POSIX and Windows treat paths that begin with exactly two separators
268 // specially.
269 bool was_net = Component.size() > 2 &&
270 is_separator(Component[0]) &&
271 Component[1] == Component[0] &&
272 !is_separator(Component[2]);
273
274 // Handle separators.
275 if (is_separator(Path[Position])) {
276 // Root dir.
277 if (was_net
278 #ifdef LLVM_ON_WIN32
279 // c:/
280 || Component.endswith(":")
281 #endif
282 ) {
283 Component = Path.substr(Position, 1);
284 return *this;
285 }
286
287 // Skip extra separators.
288 while (Position != Path.size() &&
289 is_separator(Path[Position])) {
290 ++Position;
291 }
292
293 // Treat trailing '/' as a '.'.
294 if (Position == Path.size()) {
295 --Position;
296 Component = ".";
297 return *this;
298 }
299 }
300
301 // Find next component.
302 size_t end_pos = Path.find_first_of(separators, Position);
303 Component = Path.slice(Position, end_pos);
304
305 return *this;
306 }
307
operator ==(const const_iterator & RHS) const308 bool const_iterator::operator==(const const_iterator &RHS) const {
309 return Path.begin() == RHS.Path.begin() && Position == RHS.Position;
310 }
311
operator -(const const_iterator & RHS) const312 ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
313 return Position - RHS.Position;
314 }
315
rbegin(StringRef Path)316 reverse_iterator rbegin(StringRef Path) {
317 reverse_iterator I;
318 I.Path = Path;
319 I.Position = Path.size();
320 return ++I;
321 }
322
rend(StringRef Path)323 reverse_iterator rend(StringRef Path) {
324 reverse_iterator I;
325 I.Path = Path;
326 I.Component = Path.substr(0, 0);
327 I.Position = 0;
328 return I;
329 }
330
operator ++()331 reverse_iterator &reverse_iterator::operator++() {
332 // If we're at the end and the previous char was a '/', return '.' unless
333 // we are the root path.
334 size_t root_dir_pos = root_dir_start(Path);
335 if (Position == Path.size() &&
336 Path.size() > root_dir_pos + 1 &&
337 is_separator(Path[Position - 1])) {
338 --Position;
339 Component = ".";
340 return *this;
341 }
342
343 // Skip separators unless it's the root directory.
344 size_t end_pos = Position;
345
346 while(end_pos > 0 &&
347 (end_pos - 1) != root_dir_pos &&
348 is_separator(Path[end_pos - 1]))
349 --end_pos;
350
351 // Find next separator.
352 size_t start_pos = filename_pos(Path.substr(0, end_pos));
353 Component = Path.slice(start_pos, end_pos);
354 Position = start_pos;
355 return *this;
356 }
357
operator ==(const reverse_iterator & RHS) const358 bool reverse_iterator::operator==(const reverse_iterator &RHS) const {
359 return Path.begin() == RHS.Path.begin() && Component == RHS.Component &&
360 Position == RHS.Position;
361 }
362
root_path(StringRef path)363 StringRef root_path(StringRef path) {
364 const_iterator b = begin(path),
365 pos = b,
366 e = end(path);
367 if (b != e) {
368 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
369 bool has_drive =
370 #ifdef LLVM_ON_WIN32
371 b->endswith(":");
372 #else
373 false;
374 #endif
375
376 if (has_net || has_drive) {
377 if ((++pos != e) && is_separator((*pos)[0])) {
378 // {C:/,//net/}, so get the first two components.
379 return path.substr(0, b->size() + pos->size());
380 } else {
381 // just {C:,//net}, return the first component.
382 return *b;
383 }
384 }
385
386 // POSIX style root directory.
387 if (is_separator((*b)[0])) {
388 return *b;
389 }
390 }
391
392 return StringRef();
393 }
394
root_name(StringRef path)395 StringRef root_name(StringRef path) {
396 const_iterator b = begin(path),
397 e = end(path);
398 if (b != e) {
399 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
400 bool has_drive =
401 #ifdef LLVM_ON_WIN32
402 b->endswith(":");
403 #else
404 false;
405 #endif
406
407 if (has_net || has_drive) {
408 // just {C:,//net}, return the first component.
409 return *b;
410 }
411 }
412
413 // No path or no name.
414 return StringRef();
415 }
416
root_directory(StringRef path)417 StringRef root_directory(StringRef path) {
418 const_iterator b = begin(path),
419 pos = b,
420 e = end(path);
421 if (b != e) {
422 bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
423 bool has_drive =
424 #ifdef LLVM_ON_WIN32
425 b->endswith(":");
426 #else
427 false;
428 #endif
429
430 if ((has_net || has_drive) &&
431 // {C:,//net}, skip to the next component.
432 (++pos != e) && is_separator((*pos)[0])) {
433 return *pos;
434 }
435
436 // POSIX style root directory.
437 if (!has_net && is_separator((*b)[0])) {
438 return *b;
439 }
440 }
441
442 // No path or no root.
443 return StringRef();
444 }
445
relative_path(StringRef path)446 StringRef relative_path(StringRef path) {
447 StringRef root = root_path(path);
448 return path.substr(root.size());
449 }
450
append(SmallVectorImpl<char> & path,const Twine & a,const Twine & b,const Twine & c,const Twine & d)451 void append(SmallVectorImpl<char> &path, const Twine &a,
452 const Twine &b,
453 const Twine &c,
454 const Twine &d) {
455 SmallString<32> a_storage;
456 SmallString<32> b_storage;
457 SmallString<32> c_storage;
458 SmallString<32> d_storage;
459
460 SmallVector<StringRef, 4> components;
461 if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
462 if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
463 if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
464 if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
465
466 for (SmallVectorImpl<StringRef>::const_iterator i = components.begin(),
467 e = components.end();
468 i != e; ++i) {
469 bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]);
470 bool component_has_sep = !i->empty() && is_separator((*i)[0]);
471 bool is_root_name = has_root_name(*i);
472
473 if (path_has_sep) {
474 // Strip separators from beginning of component.
475 size_t loc = i->find_first_not_of(separators);
476 StringRef c = i->substr(loc);
477
478 // Append it.
479 path.append(c.begin(), c.end());
480 continue;
481 }
482
483 if (!component_has_sep && !(path.empty() || is_root_name)) {
484 // Add a separator.
485 path.push_back(preferred_separator);
486 }
487
488 path.append(i->begin(), i->end());
489 }
490 }
491
append(SmallVectorImpl<char> & path,const_iterator begin,const_iterator end)492 void append(SmallVectorImpl<char> &path,
493 const_iterator begin, const_iterator end) {
494 for (; begin != end; ++begin)
495 path::append(path, *begin);
496 }
497
parent_path(StringRef path)498 StringRef parent_path(StringRef path) {
499 size_t end_pos = parent_path_end(path);
500 if (end_pos == StringRef::npos)
501 return StringRef();
502 else
503 return path.substr(0, end_pos);
504 }
505
remove_filename(SmallVectorImpl<char> & path)506 void remove_filename(SmallVectorImpl<char> &path) {
507 size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()));
508 if (end_pos != StringRef::npos)
509 path.set_size(end_pos);
510 }
511
replace_extension(SmallVectorImpl<char> & path,const Twine & extension)512 void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) {
513 StringRef p(path.begin(), path.size());
514 SmallString<32> ext_storage;
515 StringRef ext = extension.toStringRef(ext_storage);
516
517 // Erase existing extension.
518 size_t pos = p.find_last_of('.');
519 if (pos != StringRef::npos && pos >= filename_pos(p))
520 path.set_size(pos);
521
522 // Append '.' if needed.
523 if (ext.size() > 0 && ext[0] != '.')
524 path.push_back('.');
525
526 // Append extension.
527 path.append(ext.begin(), ext.end());
528 }
529
native(const Twine & path,SmallVectorImpl<char> & result)530 void native(const Twine &path, SmallVectorImpl<char> &result) {
531 assert((!path.isSingleStringRef() ||
532 path.getSingleStringRef().data() != result.data()) &&
533 "path and result are not allowed to overlap!");
534 // Clear result.
535 result.clear();
536 path.toVector(result);
537 native(result);
538 }
539
native(SmallVectorImpl<char> & Path)540 void native(SmallVectorImpl<char> &Path) {
541 #ifdef LLVM_ON_WIN32
542 std::replace(Path.begin(), Path.end(), '/', '\\');
543 #else
544 for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) {
545 if (*PI == '\\') {
546 auto PN = PI + 1;
547 if (PN < PE && *PN == '\\')
548 ++PI; // increment once, the for loop will move over the escaped slash
549 else
550 *PI = '/';
551 }
552 }
553 #endif
554 }
555
filename(StringRef path)556 StringRef filename(StringRef path) {
557 return *rbegin(path);
558 }
559
stem(StringRef path)560 StringRef stem(StringRef path) {
561 StringRef fname = filename(path);
562 size_t pos = fname.find_last_of('.');
563 if (pos == StringRef::npos)
564 return fname;
565 else
566 if ((fname.size() == 1 && fname == ".") ||
567 (fname.size() == 2 && fname == ".."))
568 return fname;
569 else
570 return fname.substr(0, pos);
571 }
572
extension(StringRef path)573 StringRef extension(StringRef path) {
574 StringRef fname = filename(path);
575 size_t pos = fname.find_last_of('.');
576 if (pos == StringRef::npos)
577 return StringRef();
578 else
579 if ((fname.size() == 1 && fname == ".") ||
580 (fname.size() == 2 && fname == ".."))
581 return StringRef();
582 else
583 return fname.substr(pos);
584 }
585
is_separator(char value)586 bool is_separator(char value) {
587 switch(value) {
588 #ifdef LLVM_ON_WIN32
589 case '\\': // fall through
590 #endif
591 case '/': return true;
592 default: return false;
593 }
594 }
595
596 static const char preferred_separator_string[] = { preferred_separator, '\0' };
597
get_separator()598 StringRef get_separator() {
599 return preferred_separator_string;
600 }
601
has_root_name(const Twine & path)602 bool has_root_name(const Twine &path) {
603 SmallString<128> path_storage;
604 StringRef p = path.toStringRef(path_storage);
605
606 return !root_name(p).empty();
607 }
608
has_root_directory(const Twine & path)609 bool has_root_directory(const Twine &path) {
610 SmallString<128> path_storage;
611 StringRef p = path.toStringRef(path_storage);
612
613 return !root_directory(p).empty();
614 }
615
has_root_path(const Twine & path)616 bool has_root_path(const Twine &path) {
617 SmallString<128> path_storage;
618 StringRef p = path.toStringRef(path_storage);
619
620 return !root_path(p).empty();
621 }
622
has_relative_path(const Twine & path)623 bool has_relative_path(const Twine &path) {
624 SmallString<128> path_storage;
625 StringRef p = path.toStringRef(path_storage);
626
627 return !relative_path(p).empty();
628 }
629
has_filename(const Twine & path)630 bool has_filename(const Twine &path) {
631 SmallString<128> path_storage;
632 StringRef p = path.toStringRef(path_storage);
633
634 return !filename(p).empty();
635 }
636
has_parent_path(const Twine & path)637 bool has_parent_path(const Twine &path) {
638 SmallString<128> path_storage;
639 StringRef p = path.toStringRef(path_storage);
640
641 return !parent_path(p).empty();
642 }
643
has_stem(const Twine & path)644 bool has_stem(const Twine &path) {
645 SmallString<128> path_storage;
646 StringRef p = path.toStringRef(path_storage);
647
648 return !stem(p).empty();
649 }
650
has_extension(const Twine & path)651 bool has_extension(const Twine &path) {
652 SmallString<128> path_storage;
653 StringRef p = path.toStringRef(path_storage);
654
655 return !extension(p).empty();
656 }
657
is_absolute(const Twine & path)658 bool is_absolute(const Twine &path) {
659 SmallString<128> path_storage;
660 StringRef p = path.toStringRef(path_storage);
661
662 bool rootDir = has_root_directory(p),
663 #ifdef LLVM_ON_WIN32
664 rootName = has_root_name(p);
665 #else
666 rootName = true;
667 #endif
668
669 return rootDir && rootName;
670 }
671
is_relative(const Twine & path)672 bool is_relative(const Twine &path) {
673 return !is_absolute(path);
674 }
675
676 } // end namespace path
677
678 namespace fs {
679
getUniqueID(const Twine Path,UniqueID & Result)680 std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
681 file_status Status;
682 std::error_code EC = status(Path, Status);
683 if (EC)
684 return EC;
685 Result = Status.getUniqueID();
686 return std::error_code();
687 }
688
createUniqueFile(const Twine & Model,int & ResultFd,SmallVectorImpl<char> & ResultPath,unsigned Mode)689 std::error_code createUniqueFile(const Twine &Model, int &ResultFd,
690 SmallVectorImpl<char> &ResultPath,
691 unsigned Mode) {
692 return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File);
693 }
694
createUniqueFile(const Twine & Model,SmallVectorImpl<char> & ResultPath)695 std::error_code createUniqueFile(const Twine &Model,
696 SmallVectorImpl<char> &ResultPath) {
697 int Dummy;
698 return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name);
699 }
700
701 static std::error_code
createTemporaryFile(const Twine & Model,int & ResultFD,llvm::SmallVectorImpl<char> & ResultPath,FSEntity Type)702 createTemporaryFile(const Twine &Model, int &ResultFD,
703 llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
704 SmallString<128> Storage;
705 StringRef P = Model.toNullTerminatedStringRef(Storage);
706 assert(P.find_first_of(separators) == StringRef::npos &&
707 "Model must be a simple filename.");
708 // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage.
709 return createUniqueEntity(P.begin(), ResultFD, ResultPath,
710 true, owner_read | owner_write, Type);
711 }
712
713 static std::error_code
createTemporaryFile(const Twine & Prefix,StringRef Suffix,int & ResultFD,llvm::SmallVectorImpl<char> & ResultPath,FSEntity Type)714 createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD,
715 llvm::SmallVectorImpl<char> &ResultPath, FSEntity Type) {
716 const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%.";
717 return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath,
718 Type);
719 }
720
createTemporaryFile(const Twine & Prefix,StringRef Suffix,int & ResultFD,SmallVectorImpl<char> & ResultPath)721 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
722 int &ResultFD,
723 SmallVectorImpl<char> &ResultPath) {
724 return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File);
725 }
726
createTemporaryFile(const Twine & Prefix,StringRef Suffix,SmallVectorImpl<char> & ResultPath)727 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
728 SmallVectorImpl<char> &ResultPath) {
729 int Dummy;
730 return createTemporaryFile(Prefix, Suffix, Dummy, ResultPath, FS_Name);
731 }
732
733
734 // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly
735 // for consistency. We should try using mkdtemp.
createUniqueDirectory(const Twine & Prefix,SmallVectorImpl<char> & ResultPath)736 std::error_code createUniqueDirectory(const Twine &Prefix,
737 SmallVectorImpl<char> &ResultPath) {
738 int Dummy;
739 return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath,
740 true, 0, FS_Dir);
741 }
742
make_absolute(SmallVectorImpl<char> & path)743 std::error_code make_absolute(SmallVectorImpl<char> &path) {
744 StringRef p(path.data(), path.size());
745
746 bool rootDirectory = path::has_root_directory(p),
747 #ifdef LLVM_ON_WIN32
748 rootName = path::has_root_name(p);
749 #else
750 rootName = true;
751 #endif
752
753 // Already absolute.
754 if (rootName && rootDirectory)
755 return std::error_code();
756
757 // All of the following conditions will need the current directory.
758 SmallString<128> current_dir;
759 if (std::error_code ec = current_path(current_dir))
760 return ec;
761
762 // Relative path. Prepend the current directory.
763 if (!rootName && !rootDirectory) {
764 // Append path to the current directory.
765 path::append(current_dir, p);
766 // Set path to the result.
767 path.swap(current_dir);
768 return std::error_code();
769 }
770
771 if (!rootName && rootDirectory) {
772 StringRef cdrn = path::root_name(current_dir);
773 SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
774 path::append(curDirRootName, p);
775 // Set path to the result.
776 path.swap(curDirRootName);
777 return std::error_code();
778 }
779
780 if (rootName && !rootDirectory) {
781 StringRef pRootName = path::root_name(p);
782 StringRef bRootDirectory = path::root_directory(current_dir);
783 StringRef bRelativePath = path::relative_path(current_dir);
784 StringRef pRelativePath = path::relative_path(p);
785
786 SmallString<128> res;
787 path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
788 path.swap(res);
789 return std::error_code();
790 }
791
792 llvm_unreachable("All rootName and rootDirectory combinations should have "
793 "occurred above!");
794 }
795
create_directories(const Twine & Path,bool IgnoreExisting)796 std::error_code create_directories(const Twine &Path, bool IgnoreExisting) {
797 SmallString<128> PathStorage;
798 StringRef P = Path.toStringRef(PathStorage);
799
800 // Be optimistic and try to create the directory
801 std::error_code EC = create_directory(P, IgnoreExisting);
802 // If we succeeded, or had any error other than the parent not existing, just
803 // return it.
804 if (EC != errc::no_such_file_or_directory)
805 return EC;
806
807 // We failed because of a no_such_file_or_directory, try to create the
808 // parent.
809 StringRef Parent = path::parent_path(P);
810 if (Parent.empty())
811 return EC;
812
813 if ((EC = create_directories(Parent)))
814 return EC;
815
816 return create_directory(P, IgnoreExisting);
817 }
818
copy_file(const Twine & From,const Twine & To)819 std::error_code copy_file(const Twine &From, const Twine &To) {
820 int ReadFD, WriteFD;
821 if (std::error_code EC = openFileForRead(From, ReadFD))
822 return EC;
823 if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
824 close(ReadFD);
825 return EC;
826 }
827
828 const size_t BufSize = 4096;
829 char *Buf = new char[BufSize];
830 int BytesRead = 0, BytesWritten = 0;
831 for (;;) {
832 BytesRead = read(ReadFD, Buf, BufSize);
833 if (BytesRead <= 0)
834 break;
835 while (BytesRead) {
836 BytesWritten = write(WriteFD, Buf, BytesRead);
837 if (BytesWritten < 0)
838 break;
839 BytesRead -= BytesWritten;
840 }
841 if (BytesWritten < 0)
842 break;
843 }
844 close(ReadFD);
845 close(WriteFD);
846 delete[] Buf;
847
848 if (BytesRead < 0 || BytesWritten < 0)
849 return std::error_code(errno, std::generic_category());
850 return std::error_code();
851 }
852
exists(file_status status)853 bool exists(file_status status) {
854 return status_known(status) && status.type() != file_type::file_not_found;
855 }
856
status_known(file_status s)857 bool status_known(file_status s) {
858 return s.type() != file_type::status_error;
859 }
860
is_directory(file_status status)861 bool is_directory(file_status status) {
862 return status.type() == file_type::directory_file;
863 }
864
is_directory(const Twine & path,bool & result)865 std::error_code is_directory(const Twine &path, bool &result) {
866 file_status st;
867 if (std::error_code ec = status(path, st))
868 return ec;
869 result = is_directory(st);
870 return std::error_code();
871 }
872
is_regular_file(file_status status)873 bool is_regular_file(file_status status) {
874 return status.type() == file_type::regular_file;
875 }
876
is_regular_file(const Twine & path,bool & result)877 std::error_code is_regular_file(const Twine &path, bool &result) {
878 file_status st;
879 if (std::error_code ec = status(path, st))
880 return ec;
881 result = is_regular_file(st);
882 return std::error_code();
883 }
884
is_other(file_status status)885 bool is_other(file_status status) {
886 return exists(status) &&
887 !is_regular_file(status) &&
888 !is_directory(status);
889 }
890
is_other(const Twine & Path,bool & Result)891 std::error_code is_other(const Twine &Path, bool &Result) {
892 file_status FileStatus;
893 if (std::error_code EC = status(Path, FileStatus))
894 return EC;
895 Result = is_other(FileStatus);
896 return std::error_code();
897 }
898
replace_filename(const Twine & filename,file_status st)899 void directory_entry::replace_filename(const Twine &filename, file_status st) {
900 SmallString<128> path(Path.begin(), Path.end());
901 path::remove_filename(path);
902 path::append(path, filename);
903 Path = path.str();
904 Status = st;
905 }
906
907 /// @brief Identify the magic in magic.
identify_magic(StringRef Magic)908 file_magic identify_magic(StringRef Magic) {
909 if (Magic.size() < 4)
910 return file_magic::unknown;
911 switch ((unsigned char)Magic[0]) {
912 case 0x00: {
913 // COFF bigobj or short import library file
914 if (Magic[1] == (char)0x00 && Magic[2] == (char)0xff &&
915 Magic[3] == (char)0xff) {
916 size_t MinSize = offsetof(COFF::BigObjHeader, UUID) + sizeof(COFF::BigObjMagic);
917 if (Magic.size() < MinSize)
918 return file_magic::coff_import_library;
919
920 int BigObjVersion = *reinterpret_cast<const support::ulittle16_t*>(
921 Magic.data() + offsetof(COFF::BigObjHeader, Version));
922 if (BigObjVersion < COFF::BigObjHeader::MinBigObjectVersion)
923 return file_magic::coff_import_library;
924
925 const char *Start = Magic.data() + offsetof(COFF::BigObjHeader, UUID);
926 if (memcmp(Start, COFF::BigObjMagic, sizeof(COFF::BigObjMagic)) != 0)
927 return file_magic::coff_import_library;
928 return file_magic::coff_object;
929 }
930 // Windows resource file
931 const char Expected[] = { 0, 0, 0, 0, '\x20', 0, 0, 0, '\xff' };
932 if (Magic.size() >= sizeof(Expected) &&
933 memcmp(Magic.data(), Expected, sizeof(Expected)) == 0)
934 return file_magic::windows_resource;
935 // 0x0000 = COFF unknown machine type
936 if (Magic[1] == 0)
937 return file_magic::coff_object;
938 break;
939 }
940 case 0xDE: // 0x0B17C0DE = BC wraper
941 if (Magic[1] == (char)0xC0 && Magic[2] == (char)0x17 &&
942 Magic[3] == (char)0x0B)
943 return file_magic::bitcode;
944 break;
945 case 'B':
946 if (Magic[1] == 'C' && Magic[2] == (char)0xC0 && Magic[3] == (char)0xDE)
947 return file_magic::bitcode;
948 break;
949 case '!':
950 if (Magic.size() >= 8)
951 if (memcmp(Magic.data(),"!<arch>\n",8) == 0)
952 return file_magic::archive;
953 break;
954
955 case '\177':
956 if (Magic.size() >= 18 && Magic[1] == 'E' && Magic[2] == 'L' &&
957 Magic[3] == 'F') {
958 bool Data2MSB = Magic[5] == 2;
959 unsigned high = Data2MSB ? 16 : 17;
960 unsigned low = Data2MSB ? 17 : 16;
961 if (Magic[high] == 0)
962 switch (Magic[low]) {
963 default: break;
964 case 1: return file_magic::elf_relocatable;
965 case 2: return file_magic::elf_executable;
966 case 3: return file_magic::elf_shared_object;
967 case 4: return file_magic::elf_core;
968 }
969 else
970 // It's still some type of ELF file.
971 return file_magic::elf;
972 }
973 break;
974
975 case 0xCA:
976 if (Magic[1] == char(0xFE) && Magic[2] == char(0xBA) &&
977 Magic[3] == char(0xBE)) {
978 // This is complicated by an overlap with Java class files.
979 // See the Mach-O section in /usr/share/file/magic for details.
980 if (Magic.size() >= 8 && Magic[7] < 43)
981 return file_magic::macho_universal_binary;
982 }
983 break;
984
985 // The two magic numbers for mach-o are:
986 // 0xfeedface - 32-bit mach-o
987 // 0xfeedfacf - 64-bit mach-o
988 case 0xFE:
989 case 0xCE:
990 case 0xCF: {
991 uint16_t type = 0;
992 if (Magic[0] == char(0xFE) && Magic[1] == char(0xED) &&
993 Magic[2] == char(0xFA) &&
994 (Magic[3] == char(0xCE) || Magic[3] == char(0xCF))) {
995 /* Native endian */
996 if (Magic.size() >= 16) type = Magic[14] << 8 | Magic[15];
997 } else if ((Magic[0] == char(0xCE) || Magic[0] == char(0xCF)) &&
998 Magic[1] == char(0xFA) && Magic[2] == char(0xED) &&
999 Magic[3] == char(0xFE)) {
1000 /* Reverse endian */
1001 if (Magic.size() >= 14) type = Magic[13] << 8 | Magic[12];
1002 }
1003 switch (type) {
1004 default: break;
1005 case 1: return file_magic::macho_object;
1006 case 2: return file_magic::macho_executable;
1007 case 3: return file_magic::macho_fixed_virtual_memory_shared_lib;
1008 case 4: return file_magic::macho_core;
1009 case 5: return file_magic::macho_preload_executable;
1010 case 6: return file_magic::macho_dynamically_linked_shared_lib;
1011 case 7: return file_magic::macho_dynamic_linker;
1012 case 8: return file_magic::macho_bundle;
1013 case 9: return file_magic::macho_dynamically_linked_shared_lib_stub;
1014 case 10: return file_magic::macho_dsym_companion;
1015 }
1016 break;
1017 }
1018 case 0xF0: // PowerPC Windows
1019 case 0x83: // Alpha 32-bit
1020 case 0x84: // Alpha 64-bit
1021 case 0x66: // MPS R4000 Windows
1022 case 0x50: // mc68K
1023 case 0x4c: // 80386 Windows
1024 case 0xc4: // ARMNT Windows
1025 if (Magic[1] == 0x01)
1026 return file_magic::coff_object;
1027
1028 case 0x90: // PA-RISC Windows
1029 case 0x68: // mc68K Windows
1030 if (Magic[1] == 0x02)
1031 return file_magic::coff_object;
1032 break;
1033
1034 case 'M': // Possible MS-DOS stub on Windows PE file
1035 if (Magic[1] == 'Z') {
1036 uint32_t off =
1037 *reinterpret_cast<const support::ulittle32_t*>(Magic.data() + 0x3c);
1038 // PE/COFF file, either EXE or DLL.
1039 if (off < Magic.size() &&
1040 memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0)
1041 return file_magic::pecoff_executable;
1042 }
1043 break;
1044
1045 case 0x64: // x86-64 Windows.
1046 if (Magic[1] == char(0x86))
1047 return file_magic::coff_object;
1048 break;
1049
1050 default:
1051 break;
1052 }
1053 return file_magic::unknown;
1054 }
1055
identify_magic(const Twine & Path,file_magic & Result)1056 std::error_code identify_magic(const Twine &Path, file_magic &Result) {
1057 int FD;
1058 if (std::error_code EC = openFileForRead(Path, FD))
1059 return EC;
1060
1061 char Buffer[32];
1062 int Length = read(FD, Buffer, sizeof(Buffer));
1063 if (close(FD) != 0 || Length < 0)
1064 return std::error_code(errno, std::generic_category());
1065
1066 Result = identify_magic(StringRef(Buffer, Length));
1067 return std::error_code();
1068 }
1069
status(file_status & result) const1070 std::error_code directory_entry::status(file_status &result) const {
1071 return fs::status(Path, result);
1072 }
1073
1074 } // end namespace fs
1075 } // end namespace sys
1076 } // end namespace llvm
1077
1078 // Include the truly platform-specific parts.
1079 #if defined(LLVM_ON_UNIX)
1080 #include "Unix/Path.inc"
1081 #endif
1082 #if defined(LLVM_ON_WIN32)
1083 #include "Windows/Path.inc"
1084 #endif
1085