7cc434bde744ca1e301b743428ca98c92afcf7f2
[oota-llvm.git] / lib / Support / PathV2.cpp
1 //===-- PathV2.cpp - Implement OS Path Concept ------------------*- C++ -*-===//
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 PathV2 API.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/PathV2.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/Endian.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include <cctype>
19 #include <cstdio>
20 #include <cstring>
21
22 namespace {
23   using llvm::StringRef;
24   using llvm::sys::path::is_separator;
25
26 #ifdef LLVM_ON_WIN32
27   const StringRef separators = "\\/";
28   const char      prefered_separator = '\\';
29 #else
30   const StringRef separators = "/";
31   const char      prefered_separator = '/';
32 #endif
33
34   const llvm::error_code success;
35
36   StringRef find_first_component(StringRef path) {
37     // Look for this first component in the following order.
38     // * empty (in this case we return an empty string)
39     // * either C: or {//,\\}net.
40     // * {/,\}
41     // * {.,..}
42     // * {file,directory}name
43
44     if (path.empty())
45       return path;
46
47 #ifdef LLVM_ON_WIN32
48     // C:
49     if (path.size() >= 2 && std::isalpha(path[0]) && path[1] == ':')
50       return path.substr(0, 2);
51 #endif
52
53     // //net
54     if ((path.size() > 2) &&
55         is_separator(path[0]) &&
56         path[0] == path[1] &&
57         !is_separator(path[2])) {
58       // Find the next directory separator.
59       size_t end = path.find_first_of(separators, 2);
60       return path.substr(0, end);
61     }
62
63     // {/,\}
64     if (is_separator(path[0]))
65       return path.substr(0, 1);
66
67     if (path.startswith(".."))
68       return path.substr(0, 2);
69
70     if (path[0] == '.')
71       return path.substr(0, 1);
72
73     // * {file,directory}name
74     size_t end = path.find_first_of(separators, 2);
75     return path.substr(0, end);
76   }
77
78   size_t filename_pos(StringRef str) {
79     if (str.size() == 2 &&
80         is_separator(str[0]) &&
81         str[0] == str[1])
82       return 0;
83
84     if (str.size() > 0 && is_separator(str[str.size() - 1]))
85       return str.size() - 1;
86
87     size_t pos = str.find_last_of(separators, str.size() - 1);
88
89 #ifdef LLVM_ON_WIN32
90     if (pos == StringRef::npos)
91       pos = str.find_last_of(':', str.size() - 2);
92 #endif
93
94     if (pos == StringRef::npos ||
95         (pos == 1 && is_separator(str[0])))
96       return 0;
97
98     return pos + 1;
99   }
100
101   size_t root_dir_start(StringRef str) {
102     // case "c:/"
103 #ifdef LLVM_ON_WIN32
104     if (str.size() > 2 &&
105         str[1] == ':' &&
106         is_separator(str[2]))
107       return 2;
108 #endif
109
110     // case "//"
111     if (str.size() == 2 &&
112         is_separator(str[0]) &&
113         str[0] == str[1])
114       return StringRef::npos;
115
116     // case "//net"
117     if (str.size() > 3 &&
118         is_separator(str[0]) &&
119         str[0] == str[1] &&
120         !is_separator(str[2])) {
121       return str.find_first_of(separators, 2);
122     }
123
124     // case "/"
125     if (str.size() > 0 && is_separator(str[0]))
126       return 0;
127
128     return StringRef::npos;
129   }
130
131   size_t parent_path_end(StringRef path) {
132     size_t end_pos = filename_pos(path);
133
134     bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]);
135
136     // Skip separators except for root dir.
137     size_t root_dir_pos = root_dir_start(path.substr(0, end_pos));
138
139     while(end_pos > 0 &&
140           (end_pos - 1) != root_dir_pos &&
141           is_separator(path[end_pos - 1]))
142       --end_pos;
143
144     if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
145       return StringRef::npos;
146
147     return end_pos;
148   }
149 } // end unnamed namespace
150
151 namespace llvm {
152 namespace sys  {
153 namespace path {
154
155 const_iterator begin(StringRef path) {
156   const_iterator i;
157   i.Path      = path;
158   i.Component = find_first_component(path);
159   i.Position  = 0;
160   return i;
161 }
162
163 const_iterator end(StringRef path) {
164   const_iterator i;
165   i.Path      = path;
166   i.Position  = path.size();
167   return i;
168 }
169
170 const_iterator &const_iterator::operator++() {
171   assert(Position < Path.size() && "Tried to increment past end!");
172
173   // Increment Position to past the current component
174   Position += Component.size();
175
176   // Check for end.
177   if (Position == Path.size()) {
178     Component = StringRef();
179     return *this;
180   }
181
182   // Both POSIX and Windows treat paths that begin with exactly two separators
183   // specially.
184   bool was_net = Component.size() > 2 &&
185     is_separator(Component[0]) &&
186     Component[1] == Component[0] &&
187     !is_separator(Component[2]);
188
189   // Handle separators.
190   if (is_separator(Path[Position])) {
191     // Root dir.
192     if (was_net
193 #ifdef LLVM_ON_WIN32
194         // c:/
195         || Component.endswith(":")
196 #endif
197         ) {
198       Component = Path.substr(Position, 1);
199       return *this;
200     }
201
202     // Skip extra separators.
203     while (Position != Path.size() &&
204            is_separator(Path[Position])) {
205       ++Position;
206     }
207
208     // Treat trailing '/' as a '.'.
209     if (Position == Path.size()) {
210       --Position;
211       Component = ".";
212       return *this;
213     }
214   }
215
216   // Find next component.
217   size_t end_pos = Path.find_first_of(separators, Position);
218   Component = Path.slice(Position, end_pos);
219
220   return *this;
221 }
222
223 const_iterator &const_iterator::operator--() {
224   // If we're at the end and the previous char was a '/', return '.'.
225   if (Position == Path.size() &&
226       Path.size() > 1 &&
227       is_separator(Path[Position - 1])
228 #ifdef LLVM_ON_WIN32
229       && Path[Position - 2] != ':'
230 #endif
231       ) {
232     --Position;
233     Component = ".";
234     return *this;
235   }
236
237   // Skip separators unless it's the root directory.
238   size_t root_dir_pos = root_dir_start(Path);
239   size_t end_pos = Position;
240
241   while(end_pos > 0 &&
242         (end_pos - 1) != root_dir_pos &&
243         is_separator(Path[end_pos - 1]))
244     --end_pos;
245
246   // Find next separator.
247   size_t start_pos = filename_pos(Path.substr(0, end_pos));
248   Component = Path.slice(start_pos, end_pos);
249   Position = start_pos;
250   return *this;
251 }
252
253 bool const_iterator::operator==(const const_iterator &RHS) const {
254   return Path.begin() == RHS.Path.begin() &&
255          Position == RHS.Position;
256 }
257
258 bool const_iterator::operator!=(const const_iterator &RHS) const {
259   return !(*this == RHS);
260 }
261
262 ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
263   return Position - RHS.Position;
264 }
265
266 const StringRef root_path(StringRef path) {
267   const_iterator b = begin(path),
268                  pos = b,
269                  e = end(path);
270   if (b != e) {
271     bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
272     bool has_drive =
273 #ifdef LLVM_ON_WIN32
274       b->endswith(":");
275 #else
276       false;
277 #endif
278
279     if (has_net || has_drive) {
280       if ((++pos != e) && is_separator((*pos)[0])) {
281         // {C:/,//net/}, so get the first two components.
282         return path.substr(0, b->size() + pos->size());
283       } else {
284         // just {C:,//net}, return the first component.
285         return *b;
286       }
287     }
288
289     // POSIX style root directory.
290     if (is_separator((*b)[0])) {
291       return *b;
292     }
293   }
294
295   return StringRef();
296 }
297
298 const StringRef root_name(StringRef path) {
299   const_iterator b = begin(path),
300                  e = end(path);
301   if (b != e) {
302     bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
303     bool has_drive =
304 #ifdef LLVM_ON_WIN32
305       b->endswith(":");
306 #else
307       false;
308 #endif
309
310     if (has_net || has_drive) {
311       // just {C:,//net}, return the first component.
312       return *b;
313     }
314   }
315
316   // No path or no name.
317   return StringRef();
318 }
319
320 const StringRef root_directory(StringRef path) {
321   const_iterator b = begin(path),
322                  pos = b,
323                  e = end(path);
324   if (b != e) {
325     bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
326     bool has_drive =
327 #ifdef LLVM_ON_WIN32
328       b->endswith(":");
329 #else
330       false;
331 #endif
332
333     if ((has_net || has_drive) &&
334         // {C:,//net}, skip to the next component.
335         (++pos != e) && is_separator((*pos)[0])) {
336       return *pos;
337     }
338
339     // POSIX style root directory.
340     if (!has_net && is_separator((*b)[0])) {
341       return *b;
342     }
343   }
344
345   // No path or no root.
346   return StringRef();
347 }
348
349 const StringRef relative_path(StringRef path) {
350   StringRef root = root_path(path);
351   return root.substr(root.size());
352 }
353
354 void append(SmallVectorImpl<char> &path, const Twine &a,
355                                          const Twine &b,
356                                          const Twine &c,
357                                          const Twine &d) {
358   SmallString<32> a_storage;
359   SmallString<32> b_storage;
360   SmallString<32> c_storage;
361   SmallString<32> d_storage;
362
363   SmallVector<StringRef, 4> components;
364   if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
365   if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
366   if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
367   if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
368
369   for (SmallVectorImpl<StringRef>::const_iterator i = components.begin(),
370                                                   e = components.end();
371                                                   i != e; ++i) {
372     bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]);
373     bool component_has_sep = !i->empty() && is_separator((*i)[0]);
374     bool is_root_name = has_root_name(*i);
375
376     if (path_has_sep) {
377       // Strip separators from beginning of component.
378       size_t loc = i->find_first_not_of(separators);
379       StringRef c = i->substr(loc);
380
381       // Append it.
382       path.append(c.begin(), c.end());
383       continue;
384     }
385
386     if (!component_has_sep && !(path.empty() || is_root_name)) {
387       // Add a separator.
388       path.push_back(prefered_separator);
389     }
390
391     path.append(i->begin(), i->end());
392   }
393 }
394
395 void append(SmallVectorImpl<char> &path,
396             const_iterator begin, const_iterator end) {
397   for (; begin != end; ++begin)
398     path::append(path, *begin);
399 }
400
401 const StringRef parent_path(StringRef path) {
402   size_t end_pos = parent_path_end(path);
403   if (end_pos == StringRef::npos)
404     return StringRef();
405   else
406     return path.substr(0, end_pos);
407 }
408
409 void remove_filename(SmallVectorImpl<char> &path) {
410   size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()));
411   if (end_pos != StringRef::npos)
412     path.set_size(end_pos);
413 }
414
415 void replace_extension(SmallVectorImpl<char> &path, const Twine &extension) {
416   StringRef p(path.begin(), path.size());
417   SmallString<32> ext_storage;
418   StringRef ext = extension.toStringRef(ext_storage);
419
420   // Erase existing extension.
421   size_t pos = p.find_last_of('.');
422   if (pos != StringRef::npos && pos >= filename_pos(p))
423     path.set_size(pos);
424
425   // Append '.' if needed.
426   if (ext.size() > 0 && ext[0] != '.')
427     path.push_back('.');
428
429   // Append extension.
430   path.append(ext.begin(), ext.end());
431 }
432
433 void native(const Twine &path, SmallVectorImpl<char> &result) {
434   // Clear result.
435   result.clear();
436 #ifdef LLVM_ON_WIN32
437   SmallString<128> path_storage;
438   StringRef p = path.toStringRef(path_storage);
439   result.reserve(p.size());
440   for (StringRef::const_iterator i = p.begin(),
441                                  e = p.end();
442                                  i != e;
443                                  ++i) {
444     if (*i == '/')
445       result.push_back('\\');
446     else
447       result.push_back(*i);
448   }
449 #else
450   path.toVector(result);
451 #endif
452 }
453
454 const StringRef filename(StringRef path) {
455   return *(--end(path));
456 }
457
458 const StringRef stem(StringRef path) {
459   StringRef fname = filename(path);
460   size_t pos = fname.find_last_of('.');
461   if (pos == StringRef::npos)
462     return fname;
463   else
464     if ((fname.size() == 1 && fname == ".") ||
465         (fname.size() == 2 && fname == ".."))
466       return fname;
467     else
468       return fname.substr(0, pos);
469 }
470
471 const StringRef extension(StringRef path) {
472   StringRef fname = filename(path);
473   size_t pos = fname.find_last_of('.');
474   if (pos == StringRef::npos)
475     return StringRef();
476   else
477     if ((fname.size() == 1 && fname == ".") ||
478         (fname.size() == 2 && fname == ".."))
479       return StringRef();
480     else
481       return fname.substr(pos);
482 }
483
484 bool is_separator(char value) {
485   switch(value) {
486 #ifdef LLVM_ON_WIN32
487     case '\\': // fall through
488 #endif
489     case '/': return true;
490     default: return false;
491   }
492 }
493
494 void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) {
495   result.clear();
496
497   // Check whether the temporary directory is specified by an environment
498   // variable.
499   const char *EnvironmentVariable;
500 #ifdef LLVM_ON_WIN32
501   EnvironmentVariable = "TEMP";
502 #else
503   EnvironmentVariable = "TMPDIR";
504 #endif
505   if (char *RequestedDir = getenv(EnvironmentVariable)) {
506     result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
507     return;
508   }
509
510   // Fall back to a system default.
511   const char *DefaultResult;
512 #ifdef LLVM_ON_WIN32
513   (void)erasedOnReboot;
514   DefaultResult = "C:\\TEMP";
515 #else
516   if (erasedOnReboot)
517     DefaultResult = "/tmp";
518   else
519     DefaultResult = "/var/tmp";
520 #endif
521   result.append(DefaultResult, DefaultResult + strlen(DefaultResult));
522 }
523
524 bool has_root_name(const Twine &path) {
525   SmallString<128> path_storage;
526   StringRef p = path.toStringRef(path_storage);
527
528   return !root_name(p).empty();
529 }
530
531 bool has_root_directory(const Twine &path) {
532   SmallString<128> path_storage;
533   StringRef p = path.toStringRef(path_storage);
534
535   return !root_directory(p).empty();
536 }
537
538 bool has_root_path(const Twine &path) {
539   SmallString<128> path_storage;
540   StringRef p = path.toStringRef(path_storage);
541
542   return !root_path(p).empty();
543 }
544
545 bool has_relative_path(const Twine &path) {
546   SmallString<128> path_storage;
547   StringRef p = path.toStringRef(path_storage);
548
549   return !relative_path(p).empty();
550 }
551
552 bool has_filename(const Twine &path) {
553   SmallString<128> path_storage;
554   StringRef p = path.toStringRef(path_storage);
555
556   return !filename(p).empty();
557 }
558
559 bool has_parent_path(const Twine &path) {
560   SmallString<128> path_storage;
561   StringRef p = path.toStringRef(path_storage);
562
563   return !parent_path(p).empty();
564 }
565
566 bool has_stem(const Twine &path) {
567   SmallString<128> path_storage;
568   StringRef p = path.toStringRef(path_storage);
569
570   return !stem(p).empty();
571 }
572
573 bool has_extension(const Twine &path) {
574   SmallString<128> path_storage;
575   StringRef p = path.toStringRef(path_storage);
576
577   return !extension(p).empty();
578 }
579
580 bool is_absolute(const Twine &path) {
581   SmallString<128> path_storage;
582   StringRef p = path.toStringRef(path_storage);
583
584   bool rootDir = has_root_directory(p),
585 #ifdef LLVM_ON_WIN32
586        rootName = has_root_name(p);
587 #else
588        rootName = true;
589 #endif
590
591   return rootDir && rootName;
592 }
593
594 bool is_relative(const Twine &path) {
595   return !is_absolute(path);
596 }
597
598 } // end namespace path
599
600 namespace fs {
601
602 error_code make_absolute(SmallVectorImpl<char> &path) {
603   StringRef p(path.data(), path.size());
604
605   bool rootName      = path::has_root_name(p),
606        rootDirectory = path::has_root_directory(p);
607
608   // Already absolute.
609   if (rootName && rootDirectory)
610     return success;
611
612   // All of the following conditions will need the current directory.
613   SmallString<128> current_dir;
614   if (error_code ec = current_path(current_dir)) return ec;
615
616   // Relative path. Prepend the current directory.
617   if (!rootName && !rootDirectory) {
618     // Append path to the current directory.
619     path::append(current_dir, p);
620     // Set path to the result.
621     path.swap(current_dir);
622     return success;
623   }
624
625   if (!rootName && rootDirectory) {
626     StringRef cdrn = path::root_name(current_dir);
627     SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
628     path::append(curDirRootName, p);
629     // Set path to the result.
630     path.swap(curDirRootName);
631     return success;
632   }
633
634   if (rootName && !rootDirectory) {
635     StringRef pRootName      = path::root_name(p);
636     StringRef bRootDirectory = path::root_directory(current_dir);
637     StringRef bRelativePath  = path::relative_path(current_dir);
638     StringRef pRelativePath  = path::relative_path(p);
639
640     SmallString<128> res;
641     path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
642     path.swap(res);
643     return success;
644   }
645
646   llvm_unreachable("All rootName and rootDirectory combinations should have "
647                    "occurred above!");
648 }
649
650 error_code create_directories(const Twine &path, bool &existed) {
651   SmallString<128> path_storage;
652   StringRef p = path.toStringRef(path_storage);
653
654   StringRef parent = path::parent_path(p);
655   bool parent_exists;
656
657   if (error_code ec = fs::exists(parent, parent_exists)) return ec;
658
659   if (!parent_exists)
660     if (error_code ec = create_directories(parent, existed)) return ec;
661
662   return create_directory(p, existed);
663 }
664
665 bool exists(file_status status) {
666   return status_known(status) && status.type() != file_type::file_not_found;
667 }
668
669 bool status_known(file_status s) {
670   return s.type() != file_type::status_error;
671 }
672
673 bool is_directory(file_status status) {
674   return status.type() == file_type::directory_file;
675 }
676
677 error_code is_directory(const Twine &path, bool &result) {
678   file_status st;
679   if (error_code ec = status(path, st))
680     return ec;
681   result = is_directory(st);
682   return success;
683 }
684
685 bool is_regular_file(file_status status) {
686   return status.type() == file_type::regular_file;
687 }
688
689 error_code is_regular_file(const Twine &path, bool &result) {
690   file_status st;
691   if (error_code ec = status(path, st))
692     return ec;
693   result = is_regular_file(st);
694   return success;
695 }
696
697 bool is_symlink(file_status status) {
698   return status.type() == file_type::symlink_file;
699 }
700
701 error_code is_symlink(const Twine &path, bool &result) {
702   file_status st;
703   if (error_code ec = status(path, st))
704     return ec;
705   result = is_symlink(st);
706   return success;
707 }
708
709 bool is_other(file_status status) {
710   return exists(status) &&
711          !is_regular_file(status) &&
712          !is_directory(status) &&
713          !is_symlink(status);
714 }
715
716 void directory_entry::replace_filename(const Twine &filename, file_status st) {
717   SmallString<128> path(Path.begin(), Path.end());
718   path::remove_filename(path);
719   path::append(path, filename);
720   Path = path.str();
721   Status = st;
722 }
723
724 error_code has_magic(const Twine &path, const Twine &magic, bool &result) {
725   SmallString<32>  MagicStorage;
726   StringRef Magic = magic.toStringRef(MagicStorage);
727   SmallString<32> Buffer;
728
729   if (error_code ec = get_magic(path, Magic.size(), Buffer)) {
730     if (ec == errc::value_too_large) {
731       // Magic.size() > file_size(Path).
732       result = false;
733       return success;
734     }
735     return ec;
736   }
737
738   result = Magic == Buffer;
739   return success;
740 }
741
742 /// @brief Identify the magic in magic.
743 file_magic identify_magic(StringRef magic) {
744   switch ((unsigned char)magic[0]) {
745     case 0xDE:  // 0x0B17C0DE = BC wraper
746       if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 &&
747           magic[3] == (char)0x0B)
748         return file_magic::bitcode;
749       break;
750     case 'B':
751       if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE)
752         return file_magic::bitcode;
753       break;
754     case '!':
755       if (magic.size() >= 8)
756         if (memcmp(magic.data(),"!<arch>\n",8) == 0)
757           return file_magic::archive;
758       break;
759
760     case '\177':
761       if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') {
762         if (magic.size() >= 18 && magic[17] == 0)
763           switch (magic[16]) {
764             default: break;
765             case 1: return file_magic::elf_relocatable;
766             case 2: return file_magic::elf_executable;
767             case 3: return file_magic::elf_shared_object;
768             case 4: return file_magic::elf_core;
769           }
770       }
771       break;
772
773     case 0xCA:
774       if (magic[1] == char(0xFE) && magic[2] == char(0xBA) &&
775           magic[3] == char(0xBE)) {
776         // This is complicated by an overlap with Java class files.
777         // See the Mach-O section in /usr/share/file/magic for details.
778         if (magic.size() >= 8 && magic[7] < 43)
779           // FIXME: Universal Binary of any type.
780           return file_magic::macho_dynamically_linked_shared_lib;
781       }
782       break;
783
784       // The two magic numbers for mach-o are:
785       // 0xfeedface - 32-bit mach-o
786       // 0xfeedfacf - 64-bit mach-o
787     case 0xFE:
788     case 0xCE:
789     case 0xCF: {
790       uint16_t type = 0;
791       if (magic[0] == char(0xFE) && magic[1] == char(0xED) &&
792           magic[2] == char(0xFA) &&
793           (magic[3] == char(0xCE) || magic[3] == char(0xCF))) {
794         /* Native endian */
795         if (magic.size() >= 16) type = magic[14] << 8 | magic[15];
796       } else if ((magic[0] == char(0xCE) || magic[0] == char(0xCF)) &&
797                  magic[1] == char(0xFA) && magic[2] == char(0xED) &&
798                  magic[3] == char(0xFE)) {
799         /* Reverse endian */
800         if (magic.size() >= 14) type = magic[13] << 8 | magic[12];
801       }
802       switch (type) {
803         default: break;
804         case 1: return file_magic::macho_object;
805         case 2: return file_magic::macho_executable;
806         case 3: return file_magic::macho_fixed_virtual_memory_shared_lib;
807         case 4: return file_magic::macho_core;
808         case 5: return file_magic::macho_preload_executabl;
809         case 6: return file_magic::macho_dynamically_linked_shared_lib;
810         case 7: return file_magic::macho_dynamic_linker;
811         case 8: return file_magic::macho_bundle;
812         case 9: return file_magic::macho_dynamic_linker;
813         case 10: return file_magic::macho_dsym_companion;
814       }
815       break;
816     }
817     case 0xF0: // PowerPC Windows
818     case 0x83: // Alpha 32-bit
819     case 0x84: // Alpha 64-bit
820     case 0x66: // MPS R4000 Windows
821     case 0x50: // mc68K
822     case 0x4c: // 80386 Windows
823       if (magic[1] == 0x01)
824         return file_magic::coff_object;
825
826     case 0x90: // PA-RISC Windows
827     case 0x68: // mc68K Windows
828       if (magic[1] == 0x02)
829         return file_magic::coff_object;
830       break;
831
832     case 0x4d: // Possible MS-DOS stub on Windows PE file
833       if (magic[1] == 0x5a) {
834         uint32_t off =
835           *reinterpret_cast<const support::ulittle32_t*>(magic.data() + 0x3c);
836         // PE/COFF file, either EXE or DLL.
837         if (off < magic.size() && memcmp(magic.data() + off, "PE\0\0",4) == 0)
838           return file_magic::pecoff_executable;
839       }
840       break;
841
842     case 0x64: // x86-64 Windows.
843       if (magic[1] == char(0x86))
844         return file_magic::coff_object;
845       break;
846
847     default:
848       break;
849   }
850   return file_magic::unknown;
851 }
852
853 error_code identify_magic(const Twine &path, file_magic &result) {
854   SmallString<32> Magic;
855   error_code ec = get_magic(path, Magic.capacity(), Magic);
856   if (ec && ec != errc::value_too_large)
857     return ec;
858
859   result = identify_magic(Magic);
860   return success;
861 }
862
863 namespace {
864 error_code remove_all_r(StringRef path, file_type ft, uint32_t &count) {
865   if (ft == file_type::directory_file) {
866     // This code would be a lot better with exceptions ;/.
867     error_code ec;
868     directory_iterator i(path, ec);
869     if (ec) return ec;
870     for (directory_iterator e; i != e; i.increment(ec)) {
871       if (ec) return ec;
872       file_status st;
873       if (error_code ec = i->status(st)) return ec;
874       if (error_code ec = remove_all_r(i->path(), st.type(), count)) return ec;
875     }
876     bool obviously_this_exists;
877     if (error_code ec = remove(path, obviously_this_exists)) return ec;
878     assert(obviously_this_exists);
879     ++count; // Include the directory itself in the items removed.
880   } else {
881     bool obviously_this_exists;
882     if (error_code ec = remove(path, obviously_this_exists)) return ec;
883     assert(obviously_this_exists);
884     ++count;
885   }
886
887   return success;
888 }
889 } // end unnamed namespace
890
891 error_code remove_all(const Twine &path, uint32_t &num_removed) {
892   SmallString<128> path_storage;
893   StringRef p = path.toStringRef(path_storage);
894
895   file_status fs;
896   if (error_code ec = status(path, fs))
897     return ec;
898   num_removed = 0;
899   return remove_all_r(p, fs.type(), num_removed);
900 }
901
902 error_code directory_entry::status(file_status &result) const {
903   return fs::status(Path, result);
904 }
905
906 } // end namespace fs
907 } // end namespace sys
908 } // end namespace llvm
909
910 // Include the truly platform-specific parts.
911 #if defined(LLVM_ON_UNIX)
912 #include "Unix/PathV2.inc"
913 #endif
914 #if defined(LLVM_ON_WIN32)
915 #include "Windows/PathV2.inc"
916 #endif