/3rd_party/llvm/lib/Support/Path.cpp

https://code.google.com/p/softart/ · C++ · 1039 lines · 791 code · 163 blank · 85 comment · 258 complexity · 03826c8c88e8c6a85a4d4e64ad033bb3 MD5 · raw file

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