Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

896 lines
31 KiB

  1. //===- llvm/Support/FileSystem.h - File System OS 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 declares the llvm::sys::fs namespace. It is designed after
  11. // TR2/boost filesystem (v3), but modified to remove exception handling and the
  12. // path class.
  13. //
  14. // All functions return an error_code and their actual work via the last out
  15. // argument. The out argument is defined if and only if errc::success is
  16. // returned. A function may return any error code in the generic or system
  17. // category. However, they shall be equivalent to any error conditions listed
  18. // in each functions respective documentation if the condition applies. [ note:
  19. // this does not guarantee that error_code will be in the set of explicitly
  20. // listed codes, but it does guarantee that if any of the explicitly listed
  21. // errors occur, the correct error_code will be used ]. All functions may
  22. // return errc::not_enough_memory if there is not enough memory to complete the
  23. // operation.
  24. //
  25. //===----------------------------------------------------------------------===//
  26. #ifndef LLVM_SUPPORT_FILESYSTEM_H
  27. #define LLVM_SUPPORT_FILESYSTEM_H
  28. #include "llvm/ADT/IntrusiveRefCntPtr.h"
  29. #include "llvm/ADT/OwningPtr.h"
  30. #include "llvm/ADT/SmallString.h"
  31. #include "llvm/ADT/Twine.h"
  32. #include "llvm/Support/DataTypes.h"
  33. #include "llvm/Support/ErrorHandling.h"
  34. #include "llvm/Support/system_error.h"
  35. #include <ctime>
  36. #include <iterator>
  37. #include <stack>
  38. #include <string>
  39. #include <vector>
  40. #ifdef HAVE_SYS_STAT_H
  41. #include <sys/stat.h>
  42. #endif
  43. namespace llvm {
  44. namespace sys {
  45. namespace fs {
  46. /// file_type - An "enum class" enumeration for the file system's view of the
  47. /// type.
  48. struct file_type {
  49. enum _ {
  50. status_error,
  51. file_not_found,
  52. regular_file,
  53. directory_file,
  54. symlink_file,
  55. block_file,
  56. character_file,
  57. fifo_file,
  58. socket_file,
  59. type_unknown
  60. };
  61. file_type(_ v) : v_(v) {}
  62. explicit file_type(int v) : v_(_(v)) {}
  63. operator int() const {return v_;}
  64. private:
  65. int v_;
  66. };
  67. /// copy_option - An "enum class" enumeration of copy semantics for copy
  68. /// operations.
  69. struct copy_option {
  70. enum _ {
  71. fail_if_exists,
  72. overwrite_if_exists
  73. };
  74. copy_option(_ v) : v_(v) {}
  75. explicit copy_option(int v) : v_(_(v)) {}
  76. operator int() const {return v_;}
  77. private:
  78. int v_;
  79. };
  80. /// space_info - Self explanatory.
  81. struct space_info {
  82. uint64_t capacity;
  83. uint64_t free;
  84. uint64_t available;
  85. };
  86. enum perms {
  87. no_perms = 0,
  88. owner_read = 0400,
  89. owner_write = 0200,
  90. owner_exe = 0100,
  91. owner_all = owner_read | owner_write | owner_exe,
  92. group_read = 040,
  93. group_write = 020,
  94. group_exe = 010,
  95. group_all = group_read | group_write | group_exe,
  96. others_read = 04,
  97. others_write = 02,
  98. others_exe = 01,
  99. others_all = others_read | others_write | others_exe,
  100. all_all = owner_all | group_all | others_all,
  101. set_uid_on_exe = 04000,
  102. set_gid_on_exe = 02000,
  103. sticky_bit = 01000,
  104. perms_mask = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit,
  105. perms_not_known = 0xFFFF,
  106. add_perms = 0x1000,
  107. remove_perms = 0x2000,
  108. symlink_perms = 0x4000
  109. };
  110. // Helper functions so that you can use & and | to manipulate perms bits:
  111. inline perms operator|(perms l , perms r) {
  112. return static_cast<perms>(
  113. static_cast<unsigned short>(l) | static_cast<unsigned short>(r));
  114. }
  115. inline perms operator&(perms l , perms r) {
  116. return static_cast<perms>(
  117. static_cast<unsigned short>(l) & static_cast<unsigned short>(r));
  118. }
  119. inline perms &operator|=(perms &l, perms r) {
  120. l = l | r;
  121. return l;
  122. }
  123. inline perms &operator&=(perms &l, perms r) {
  124. l = l & r;
  125. return l;
  126. }
  127. inline perms operator~(perms x) {
  128. return static_cast<perms>(~static_cast<unsigned short>(x));
  129. }
  130. /// file_status - Represents the result of a call to stat and friends. It has
  131. /// a platform specific member to store the result.
  132. class file_status
  133. {
  134. #if defined(LLVM_ON_UNIX)
  135. dev_t fs_st_dev;
  136. ino_t fs_st_ino;
  137. #elif defined (LLVM_ON_WIN32)
  138. uint32_t LastWriteTimeHigh;
  139. uint32_t LastWriteTimeLow;
  140. uint32_t VolumeSerialNumber;
  141. uint32_t FileSizeHigh;
  142. uint32_t FileSizeLow;
  143. uint32_t FileIndexHigh;
  144. uint32_t FileIndexLow;
  145. #endif
  146. friend bool equivalent(file_status A, file_status B);
  147. friend error_code status(const Twine &path, file_status &result);
  148. file_type Type;
  149. perms Perms;
  150. public:
  151. explicit file_status(file_type v=file_type::status_error,
  152. perms prms=perms_not_known)
  153. : Type(v), Perms(prms) {}
  154. // getters
  155. file_type type() const { return Type; }
  156. perms permissions() const { return Perms; }
  157. // setters
  158. void type(file_type v) { Type = v; }
  159. void permissions(perms p) { Perms = p; }
  160. };
  161. /// file_magic - An "enum class" enumeration of file types based on magic (the first
  162. /// N bytes of the file).
  163. struct file_magic {
  164. enum _ {
  165. unknown = 0, ///< Unrecognized file
  166. bitcode, ///< Bitcode file
  167. archive, ///< ar style archive file
  168. elf_relocatable, ///< ELF Relocatable object file
  169. elf_executable, ///< ELF Executable image
  170. elf_shared_object, ///< ELF dynamically linked shared lib
  171. elf_core, ///< ELF core image
  172. macho_object, ///< Mach-O Object file
  173. macho_executable, ///< Mach-O Executable
  174. macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM
  175. macho_core, ///< Mach-O Core File
  176. macho_preload_executabl, ///< Mach-O Preloaded Executable
  177. macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib
  178. macho_dynamic_linker, ///< The Mach-O dynamic linker
  179. macho_bundle, ///< Mach-O Bundle file
  180. macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub
  181. macho_dsym_companion, ///< Mach-O dSYM companion file
  182. coff_object, ///< COFF object file
  183. pecoff_executable ///< PECOFF executable file
  184. };
  185. bool is_object() const {
  186. return v_ == unknown ? false : true;
  187. }
  188. file_magic() : v_(unknown) {}
  189. file_magic(_ v) : v_(v) {}
  190. explicit file_magic(int v) : v_(_(v)) {}
  191. operator int() const {return v_;}
  192. private:
  193. int v_;
  194. };
  195. /// @}
  196. /// @name Physical Operators
  197. /// @{
  198. /// @brief Make \a path an absolute path.
  199. ///
  200. /// Makes \a path absolute using the current directory if it is not already. An
  201. /// empty \a path will result in the current directory.
  202. ///
  203. /// /absolute/path => /absolute/path
  204. /// relative/../path => <current-directory>/relative/../path
  205. ///
  206. /// @param path A path that is modified to be an absolute path.
  207. /// @returns errc::success if \a path has been made absolute, otherwise a
  208. /// platform specific error_code.
  209. error_code make_absolute(SmallVectorImpl<char> &path);
  210. /// @brief Copy the file at \a from to the path \a to.
  211. ///
  212. /// @param from The path to copy the file from.
  213. /// @param to The path to copy the file to.
  214. /// @param copt Behavior if \a to already exists.
  215. /// @returns errc::success if the file has been successfully copied.
  216. /// errc::file_exists if \a to already exists and \a copt ==
  217. /// copy_option::fail_if_exists. Otherwise a platform specific
  218. /// error_code.
  219. error_code copy_file(const Twine &from, const Twine &to,
  220. copy_option copt = copy_option::fail_if_exists);
  221. /// @brief Create all the non-existent directories in path.
  222. ///
  223. /// @param path Directories to create.
  224. /// @param existed Set to true if \a path already existed, false otherwise.
  225. /// @returns errc::success if is_directory(path) and existed have been set,
  226. /// otherwise a platform specific error_code.
  227. error_code create_directories(const Twine &path, bool &existed);
  228. /// @brief Create the directory in path.
  229. ///
  230. /// @param path Directory to create.
  231. /// @param existed Set to true if \a path already existed, false otherwise.
  232. /// @returns errc::success if is_directory(path) and existed have been set,
  233. /// otherwise a platform specific error_code.
  234. error_code create_directory(const Twine &path, bool &existed);
  235. /// @brief Create a hard link from \a from to \a to.
  236. ///
  237. /// @param to The path to hard link to.
  238. /// @param from The path to hard link from. This is created.
  239. /// @returns errc::success if exists(to) && exists(from) && equivalent(to, from)
  240. /// , otherwise a platform specific error_code.
  241. error_code create_hard_link(const Twine &to, const Twine &from);
  242. /// @brief Create a symbolic link from \a from to \a to.
  243. ///
  244. /// @param to The path to symbolically link to.
  245. /// @param from The path to symbolically link from. This is created.
  246. /// @returns errc::success if exists(to) && exists(from) && is_symlink(from),
  247. /// otherwise a platform specific error_code.
  248. error_code create_symlink(const Twine &to, const Twine &from);
  249. /// @brief Get the current path.
  250. ///
  251. /// @param result Holds the current path on return.
  252. /// @returns errc::success if the current path has been stored in result,
  253. /// otherwise a platform specific error_code.
  254. error_code current_path(SmallVectorImpl<char> &result);
  255. /// @brief Remove path. Equivalent to POSIX remove().
  256. ///
  257. /// @param path Input path.
  258. /// @param existed Set to true if \a path existed, false if it did not.
  259. /// undefined otherwise.
  260. /// @returns errc::success if path has been removed and existed has been
  261. /// successfully set, otherwise a platform specific error_code.
  262. error_code remove(const Twine &path, bool &existed);
  263. /// @brief Recursively remove all files below \a path, then \a path. Files are
  264. /// removed as if by POSIX remove().
  265. ///
  266. /// @param path Input path.
  267. /// @param num_removed Number of files removed.
  268. /// @returns errc::success if path has been removed and num_removed has been
  269. /// successfully set, otherwise a platform specific error_code.
  270. error_code remove_all(const Twine &path, uint32_t &num_removed);
  271. /// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename().
  272. ///
  273. /// @param from The path to rename from.
  274. /// @param to The path to rename to. This is created.
  275. error_code rename(const Twine &from, const Twine &to);
  276. /// @brief Resize path to size. File is resized as if by POSIX truncate().
  277. ///
  278. /// @param path Input path.
  279. /// @param size Size to resize to.
  280. /// @returns errc::success if \a path has been resized to \a size, otherwise a
  281. /// platform specific error_code.
  282. error_code resize_file(const Twine &path, uint64_t size);
  283. /// @}
  284. /// @name Physical Observers
  285. /// @{
  286. /// @brief Does file exist?
  287. ///
  288. /// @param status A file_status previously returned from stat.
  289. /// @returns True if the file represented by status exists, false if it does
  290. /// not.
  291. bool exists(file_status status);
  292. /// @brief Does file exist?
  293. ///
  294. /// @param path Input path.
  295. /// @param result Set to true if the file represented by status exists, false if
  296. /// it does not. Undefined otherwise.
  297. /// @returns errc::success if result has been successfully set, otherwise a
  298. /// platform specific error_code.
  299. error_code exists(const Twine &path, bool &result);
  300. /// @brief Simpler version of exists for clients that don't need to
  301. /// differentiate between an error and false.
  302. inline bool exists(const Twine &path) {
  303. bool result;
  304. return !exists(path, result) && result;
  305. }
  306. /// @brief Do file_status's represent the same thing?
  307. ///
  308. /// @param A Input file_status.
  309. /// @param B Input file_status.
  310. ///
  311. /// assert(status_known(A) || status_known(B));
  312. ///
  313. /// @returns True if A and B both represent the same file system entity, false
  314. /// otherwise.
  315. bool equivalent(file_status A, file_status B);
  316. /// @brief Do paths represent the same thing?
  317. ///
  318. /// assert(status_known(A) || status_known(B));
  319. ///
  320. /// @param A Input path A.
  321. /// @param B Input path B.
  322. /// @param result Set to true if stat(A) and stat(B) have the same device and
  323. /// inode (or equivalent).
  324. /// @returns errc::success if result has been successfully set, otherwise a
  325. /// platform specific error_code.
  326. error_code equivalent(const Twine &A, const Twine &B, bool &result);
  327. /// @brief Simpler version of equivalent for clients that don't need to
  328. /// differentiate between an error and false.
  329. inline bool equivalent(const Twine &A, const Twine &B) {
  330. bool result;
  331. return !equivalent(A, B, result) && result;
  332. }
  333. /// @brief Get file size.
  334. ///
  335. /// @param path Input path.
  336. /// @param result Set to the size of the file in \a path.
  337. /// @returns errc::success if result has been successfully set, otherwise a
  338. /// platform specific error_code.
  339. error_code file_size(const Twine &path, uint64_t &result);
  340. /// @brief Does status represent a directory?
  341. ///
  342. /// @param status A file_status previously returned from status.
  343. /// @returns status.type() == file_type::directory_file.
  344. bool is_directory(file_status status);
  345. /// @brief Is path a directory?
  346. ///
  347. /// @param path Input path.
  348. /// @param result Set to true if \a path is a directory, false if it is not.
  349. /// Undefined otherwise.
  350. /// @returns errc::success if result has been successfully set, otherwise a
  351. /// platform specific error_code.
  352. error_code is_directory(const Twine &path, bool &result);
  353. /// @brief Does status represent a regular file?
  354. ///
  355. /// @param status A file_status previously returned from status.
  356. /// @returns status_known(status) && status.type() == file_type::regular_file.
  357. bool is_regular_file(file_status status);
  358. /// @brief Is path a regular file?
  359. ///
  360. /// @param path Input path.
  361. /// @param result Set to true if \a path is a regular file, false if it is not.
  362. /// Undefined otherwise.
  363. /// @returns errc::success if result has been successfully set, otherwise a
  364. /// platform specific error_code.
  365. error_code is_regular_file(const Twine &path, bool &result);
  366. /// @brief Does this status represent something that exists but is not a
  367. /// directory, regular file, or symlink?
  368. ///
  369. /// @param status A file_status previously returned from status.
  370. /// @returns exists(s) && !is_regular_file(s) && !is_directory(s) &&
  371. /// !is_symlink(s)
  372. bool is_other(file_status status);
  373. /// @brief Is path something that exists but is not a directory,
  374. /// regular file, or symlink?
  375. ///
  376. /// @param path Input path.
  377. /// @param result Set to true if \a path exists, but is not a directory, regular
  378. /// file, or a symlink, false if it does not. Undefined otherwise.
  379. /// @returns errc::success if result has been successfully set, otherwise a
  380. /// platform specific error_code.
  381. error_code is_other(const Twine &path, bool &result);
  382. /// @brief Does status represent a symlink?
  383. ///
  384. /// @param status A file_status previously returned from stat.
  385. /// @returns status.type() == symlink_file.
  386. bool is_symlink(file_status status);
  387. /// @brief Is path a symlink?
  388. ///
  389. /// @param path Input path.
  390. /// @param result Set to true if \a path is a symlink, false if it is not.
  391. /// Undefined otherwise.
  392. /// @returns errc::success if result has been successfully set, otherwise a
  393. /// platform specific error_code.
  394. error_code is_symlink(const Twine &path, bool &result);
  395. /// @brief Get file status as if by POSIX stat().
  396. ///
  397. /// @param path Input path.
  398. /// @param result Set to the file status.
  399. /// @returns errc::success if result has been successfully set, otherwise a
  400. /// platform specific error_code.
  401. error_code status(const Twine &path, file_status &result);
  402. /// @brief Modifies permission bits on a file
  403. ///
  404. /// @param path Input path.
  405. /// @returns errc::success if permissions have been changed, otherwise a
  406. /// platform specific error_code.
  407. error_code permissions(const Twine &path, perms prms);
  408. /// @brief Is status available?
  409. ///
  410. /// @param s Input file status.
  411. /// @returns True if status() != status_error.
  412. bool status_known(file_status s);
  413. /// @brief Is status available?
  414. ///
  415. /// @param path Input path.
  416. /// @param result Set to true if status() != status_error.
  417. /// @returns errc::success if result has been successfully set, otherwise a
  418. /// platform specific error_code.
  419. error_code status_known(const Twine &path, bool &result);
  420. /// @brief Generate a unique path and open it as a file.
  421. ///
  422. /// Generates a unique path suitable for a temporary file and then opens it as a
  423. /// file. The name is based on \a model with '%' replaced by a random char in
  424. /// [0-9a-f]. If \a model is not an absolute path, a suitable temporary
  425. /// directory will be prepended.
  426. ///
  427. /// This is an atomic operation. Either the file is created and opened, or the
  428. /// file system is left untouched.
  429. ///
  430. /// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s
  431. ///
  432. /// @param model Name to base unique path off of.
  433. /// @param result_fd Set to the opened file's file descriptor.
  434. /// @param result_path Set to the opened file's absolute path.
  435. /// @param makeAbsolute If true and \a model is not an absolute path, a temp
  436. /// directory will be prepended.
  437. /// @returns errc::success if result_{fd,path} have been successfully set,
  438. /// otherwise a platform specific error_code.
  439. error_code unique_file(const Twine &model, int &result_fd,
  440. SmallVectorImpl<char> &result_path,
  441. bool makeAbsolute = true, unsigned mode = 0600);
  442. /// @brief Canonicalize path.
  443. ///
  444. /// Sets result to the file system's idea of what path is. The result is always
  445. /// absolute and has the same capitalization as the file system.
  446. ///
  447. /// @param path Input path.
  448. /// @param result Set to the canonicalized version of \a path.
  449. /// @returns errc::success if result has been successfully set, otherwise a
  450. /// platform specific error_code.
  451. error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result);
  452. /// @brief Are \a path's first bytes \a magic?
  453. ///
  454. /// @param path Input path.
  455. /// @param magic Byte sequence to compare \a path's first len(magic) bytes to.
  456. /// @returns errc::success if result has been successfully set, otherwise a
  457. /// platform specific error_code.
  458. error_code has_magic(const Twine &path, const Twine &magic, bool &result);
  459. /// @brief Get \a path's first \a len bytes.
  460. ///
  461. /// @param path Input path.
  462. /// @param len Number of magic bytes to get.
  463. /// @param result Set to the first \a len bytes in the file pointed to by
  464. /// \a path. Or the entire file if file_size(path) < len, in which
  465. /// case result.size() returns the size of the file.
  466. /// @returns errc::success if result has been successfully set,
  467. /// errc::value_too_large if len is larger then the file pointed to by
  468. /// \a path, otherwise a platform specific error_code.
  469. error_code get_magic(const Twine &path, uint32_t len,
  470. SmallVectorImpl<char> &result);
  471. /// @brief Identify the type of a binary file based on how magical it is.
  472. file_magic identify_magic(StringRef magic);
  473. /// @brief Get and identify \a path's type based on its content.
  474. ///
  475. /// @param path Input path.
  476. /// @param result Set to the type of file, or LLVMFileType::Unknown_FileType.
  477. /// @returns errc::success if result has been successfully set, otherwise a
  478. /// platform specific error_code.
  479. error_code identify_magic(const Twine &path, file_magic &result);
  480. /// @brief Get library paths the system linker uses.
  481. ///
  482. /// @param result Set to the list of system library paths.
  483. /// @returns errc::success if result has been successfully set, otherwise a
  484. /// platform specific error_code.
  485. error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result);
  486. /// @brief Get bitcode library paths the system linker uses
  487. /// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR.
  488. ///
  489. /// @param result Set to the list of bitcode library paths.
  490. /// @returns errc::success if result has been successfully set, otherwise a
  491. /// platform specific error_code.
  492. error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result);
  493. /// @brief Find a library.
  494. ///
  495. /// Find the path to a library using its short name. Use the system
  496. /// dependent library paths to locate the library.
  497. ///
  498. /// c => /usr/lib/libc.so
  499. ///
  500. /// @param short_name Library name one would give to the system linker.
  501. /// @param result Set to the absolute path \a short_name represents.
  502. /// @returns errc::success if result has been successfully set, otherwise a
  503. /// platform specific error_code.
  504. error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result);
  505. /// @brief Get absolute path of main executable.
  506. ///
  507. /// @param argv0 The program name as it was spelled on the command line.
  508. /// @param MainAddr Address of some symbol in the executable (not in a library).
  509. /// @param result Set to the absolute path of the current executable.
  510. /// @returns errc::success if result has been successfully set, otherwise a
  511. /// platform specific error_code.
  512. error_code GetMainExecutable(const char *argv0, void *MainAddr,
  513. SmallVectorImpl<char> &result);
  514. /// This class represents a memory mapped file. It is based on
  515. /// boost::iostreams::mapped_file.
  516. class mapped_file_region {
  517. mapped_file_region() LLVM_DELETED_FUNCTION;
  518. mapped_file_region(mapped_file_region&) LLVM_DELETED_FUNCTION;
  519. mapped_file_region &operator =(mapped_file_region&) LLVM_DELETED_FUNCTION;
  520. public:
  521. enum mapmode {
  522. readonly, ///< May only access map via const_data as read only.
  523. readwrite, ///< May access map via data and modify it. Written to path.
  524. priv ///< May modify via data, but changes are lost on destruction.
  525. };
  526. private:
  527. /// Platform specific mapping state.
  528. mapmode Mode;
  529. uint64_t Size;
  530. void *Mapping;
  531. #ifdef LLVM_ON_WIN32
  532. int FileDescriptor;
  533. void *FileHandle;
  534. void *FileMappingHandle;
  535. #endif
  536. error_code init(int FD, bool CloseFD, uint64_t Offset);
  537. public:
  538. typedef char char_type;
  539. #if LLVM_HAS_RVALUE_REFERENCES
  540. mapped_file_region(mapped_file_region&&);
  541. mapped_file_region &operator =(mapped_file_region&&);
  542. #endif
  543. /// Construct a mapped_file_region at \a path starting at \a offset of length
  544. /// \a length and with access \a mode.
  545. ///
  546. /// \param path Path to the file to map. If it does not exist it will be
  547. /// created.
  548. /// \param mode How to map the memory.
  549. /// \param length Number of bytes to map in starting at \a offset. If the file
  550. /// is shorter than this, it will be extended. If \a length is
  551. /// 0, the entire file will be mapped.
  552. /// \param offset Byte offset from the beginning of the file where the map
  553. /// should begin. Must be a multiple of
  554. /// mapped_file_region::alignment().
  555. /// \param ec This is set to errc::success if the map was constructed
  556. /// sucessfully. Otherwise it is set to a platform dependent error.
  557. mapped_file_region(const Twine &path,
  558. mapmode mode,
  559. uint64_t length,
  560. uint64_t offset,
  561. error_code &ec);
  562. /// \param fd An open file descriptor to map. mapped_file_region takes
  563. /// ownership if closefd is true. It must have been opended in the correct
  564. /// mode.
  565. mapped_file_region(int fd,
  566. bool closefd,
  567. mapmode mode,
  568. uint64_t length,
  569. uint64_t offset,
  570. error_code &ec);
  571. ~mapped_file_region();
  572. mapmode flags() const;
  573. uint64_t size() const;
  574. char *data() const;
  575. /// Get a const view of the data. Modifying this memory has undefined
  576. /// behaivor.
  577. const char *const_data() const;
  578. /// \returns The minimum alignment offset must be.
  579. static int alignment();
  580. };
  581. /// @brief Memory maps the contents of a file
  582. ///
  583. /// @param path Path to file to map.
  584. /// @param file_offset Byte offset in file where mapping should begin.
  585. /// @param size Byte length of range of the file to map.
  586. /// @param map_writable If true, the file will be mapped in r/w such
  587. /// that changes to the mapped buffer will be flushed back
  588. /// to the file. If false, the file will be mapped read-only
  589. /// and the buffer will be read-only.
  590. /// @param result Set to the start address of the mapped buffer.
  591. /// @returns errc::success if result has been successfully set, otherwise a
  592. /// platform specific error_code.
  593. error_code map_file_pages(const Twine &path, off_t file_offset, size_t size,
  594. bool map_writable, void *&result);
  595. /// @brief Memory unmaps the contents of a file
  596. ///
  597. /// @param base Pointer to the start of the buffer.
  598. /// @param size Byte length of the range to unmmap.
  599. /// @returns errc::success if result has been successfully set, otherwise a
  600. /// platform specific error_code.
  601. error_code unmap_file_pages(void *base, size_t size);
  602. /// @}
  603. /// @name Iterators
  604. /// @{
  605. /// directory_entry - A single entry in a directory. Caches the status either
  606. /// from the result of the iteration syscall, or the first time status is
  607. /// called.
  608. class directory_entry {
  609. std::string Path;
  610. mutable file_status Status;
  611. public:
  612. explicit directory_entry(const Twine &path, file_status st = file_status())
  613. : Path(path.str())
  614. , Status(st) {}
  615. directory_entry() {}
  616. void assign(const Twine &path, file_status st = file_status()) {
  617. Path = path.str();
  618. Status = st;
  619. }
  620. void replace_filename(const Twine &filename, file_status st = file_status());
  621. const std::string &path() const { return Path; }
  622. error_code status(file_status &result) const;
  623. bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; }
  624. bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); }
  625. bool operator< (const directory_entry& rhs) const;
  626. bool operator<=(const directory_entry& rhs) const;
  627. bool operator> (const directory_entry& rhs) const;
  628. bool operator>=(const directory_entry& rhs) const;
  629. };
  630. namespace detail {
  631. struct DirIterState;
  632. error_code directory_iterator_construct(DirIterState&, StringRef);
  633. error_code directory_iterator_increment(DirIterState&);
  634. error_code directory_iterator_destruct(DirIterState&);
  635. /// DirIterState - Keeps state for the directory_iterator. It is reference
  636. /// counted in order to preserve InputIterator semantics on copy.
  637. struct DirIterState : public RefCountedBase<DirIterState> {
  638. DirIterState()
  639. : IterationHandle(0) {}
  640. ~DirIterState() {
  641. directory_iterator_destruct(*this);
  642. }
  643. intptr_t IterationHandle;
  644. directory_entry CurrentEntry;
  645. };
  646. }
  647. /// directory_iterator - Iterates through the entries in path. There is no
  648. /// operator++ because we need an error_code. If it's really needed we can make
  649. /// it call report_fatal_error on error.
  650. class directory_iterator {
  651. IntrusiveRefCntPtr<detail::DirIterState> State;
  652. public:
  653. explicit directory_iterator(const Twine &path, error_code &ec) {
  654. State = new detail::DirIterState;
  655. SmallString<128> path_storage;
  656. ec = detail::directory_iterator_construct(*State,
  657. path.toStringRef(path_storage));
  658. }
  659. explicit directory_iterator(const directory_entry &de, error_code &ec) {
  660. State = new detail::DirIterState;
  661. ec = detail::directory_iterator_construct(*State, de.path());
  662. }
  663. /// Construct end iterator.
  664. directory_iterator() : State(new detail::DirIterState) {}
  665. // No operator++ because we need error_code.
  666. directory_iterator &increment(error_code &ec) {
  667. ec = directory_iterator_increment(*State);
  668. return *this;
  669. }
  670. const directory_entry &operator*() const { return State->CurrentEntry; }
  671. const directory_entry *operator->() const { return &State->CurrentEntry; }
  672. bool operator==(const directory_iterator &RHS) const {
  673. return State->CurrentEntry == RHS.State->CurrentEntry;
  674. }
  675. bool operator!=(const directory_iterator &RHS) const {
  676. return !(*this == RHS);
  677. }
  678. // Other members as required by
  679. // C++ Std, 24.1.1 Input iterators [input.iterators]
  680. };
  681. namespace detail {
  682. /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is
  683. /// reference counted in order to preserve InputIterator semantics on copy.
  684. struct RecDirIterState : public RefCountedBase<RecDirIterState> {
  685. RecDirIterState()
  686. : Level(0)
  687. , HasNoPushRequest(false) {}
  688. std::stack<directory_iterator, std::vector<directory_iterator> > Stack;
  689. uint16_t Level;
  690. bool HasNoPushRequest;
  691. };
  692. }
  693. /// recursive_directory_iterator - Same as directory_iterator except for it
  694. /// recurses down into child directories.
  695. class recursive_directory_iterator {
  696. IntrusiveRefCntPtr<detail::RecDirIterState> State;
  697. public:
  698. recursive_directory_iterator() {}
  699. explicit recursive_directory_iterator(const Twine &path, error_code &ec)
  700. : State(new detail::RecDirIterState) {
  701. State->Stack.push(directory_iterator(path, ec));
  702. if (State->Stack.top() == directory_iterator())
  703. State.reset();
  704. }
  705. // No operator++ because we need error_code.
  706. recursive_directory_iterator &increment(error_code &ec) {
  707. static const directory_iterator end_itr;
  708. if (State->HasNoPushRequest)
  709. State->HasNoPushRequest = false;
  710. else {
  711. file_status st;
  712. if ((ec = State->Stack.top()->status(st))) return *this;
  713. if (is_directory(st)) {
  714. State->Stack.push(directory_iterator(*State->Stack.top(), ec));
  715. if (ec) return *this;
  716. if (State->Stack.top() != end_itr) {
  717. ++State->Level;
  718. return *this;
  719. }
  720. State->Stack.pop();
  721. }
  722. }
  723. while (!State->Stack.empty()
  724. && State->Stack.top().increment(ec) == end_itr) {
  725. State->Stack.pop();
  726. --State->Level;
  727. }
  728. // Check if we are done. If so, create an end iterator.
  729. if (State->Stack.empty())
  730. State.reset();
  731. return *this;
  732. }
  733. const directory_entry &operator*() const { return *State->Stack.top(); }
  734. const directory_entry *operator->() const { return &*State->Stack.top(); }
  735. // observers
  736. /// Gets the current level. Starting path is at level 0.
  737. int level() const { return State->Level; }
  738. /// Returns true if no_push has been called for this directory_entry.
  739. bool no_push_request() const { return State->HasNoPushRequest; }
  740. // modifiers
  741. /// Goes up one level if Level > 0.
  742. void pop() {
  743. assert(State && "Cannot pop and end itertor!");
  744. assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
  745. static const directory_iterator end_itr;
  746. error_code ec;
  747. do {
  748. if (ec)
  749. report_fatal_error("Error incrementing directory iterator.");
  750. State->Stack.pop();
  751. --State->Level;
  752. } while (!State->Stack.empty()
  753. && State->Stack.top().increment(ec) == end_itr);
  754. // Check if we are done. If so, create an end iterator.
  755. if (State->Stack.empty())
  756. State.reset();
  757. }
  758. /// Does not go down into the current directory_entry.
  759. void no_push() { State->HasNoPushRequest = true; }
  760. bool operator==(const recursive_directory_iterator &RHS) const {
  761. return State == RHS.State;
  762. }
  763. bool operator!=(const recursive_directory_iterator &RHS) const {
  764. return !(*this == RHS);
  765. }
  766. // Other members as required by
  767. // C++ Std, 24.1.1 Input iterators [input.iterators]
  768. };
  769. /// @}
  770. } // end namespace fs
  771. } // end namespace sys
  772. } // end namespace llvm
  773. #endif