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