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 27 #ifndef LLVM_SUPPORT_FILESYSTEM_H 28 #define LLVM_SUPPORT_FILESYSTEM_H 29 30 #include "llvm/ADT/IntrusiveRefCntPtr.h" 31 #include "llvm/ADT/SmallString.h" 32 #include "llvm/ADT/Twine.h" 33 #include "llvm/Support/DataTypes.h" 34 #include "llvm/Support/ErrorHandling.h" 35 #include "llvm/Support/TimeValue.h" 36 #include <ctime> 37 #include <iterator> 38 #include <stack> 39 #include <string> 40 #include <system_error> 41 #include <tuple> 42 #include <vector> 43 44 #ifdef HAVE_SYS_STAT_H 45 #include <sys/stat.h> 46 #endif 47 48 namespace llvm { 49 namespace sys { 50 namespace fs { 51 52 /// An enumeration for the file system's view of the type. 53 enum class file_type { 54 status_error, 55 file_not_found, 56 regular_file, 57 directory_file, 58 symlink_file, 59 block_file, 60 character_file, 61 fifo_file, 62 socket_file, 63 type_unknown 64 }; 65 66 /// space_info - Self explanatory. 67 struct space_info { 68 uint64_t capacity; 69 uint64_t free; 70 uint64_t available; 71 }; 72 73 enum perms { 74 no_perms = 0, 75 owner_read = 0400, 76 owner_write = 0200, 77 owner_exe = 0100, 78 owner_all = owner_read | owner_write | owner_exe, 79 group_read = 040, 80 group_write = 020, 81 group_exe = 010, 82 group_all = group_read | group_write | group_exe, 83 others_read = 04, 84 others_write = 02, 85 others_exe = 01, 86 others_all = others_read | others_write | others_exe, 87 all_read = owner_read | group_read | others_read, 88 all_write = owner_write | group_write | others_write, 89 all_exe = owner_exe | group_exe | others_exe, 90 all_all = owner_all | group_all | others_all, 91 set_uid_on_exe = 04000, 92 set_gid_on_exe = 02000, 93 sticky_bit = 01000, 94 perms_not_known = 0xFFFF 95 }; 96 97 // Helper functions so that you can use & and | to manipulate perms bits: 98 inline perms operator|(perms l , perms r) { 99 return static_cast<perms>( 100 static_cast<unsigned short>(l) | static_cast<unsigned short>(r)); 101 } 102 inline perms operator&(perms l , perms r) { 103 return static_cast<perms>( 104 static_cast<unsigned short>(l) & static_cast<unsigned short>(r)); 105 } 106 inline perms &operator|=(perms &l, perms r) { 107 l = l | r; 108 return l; 109 } 110 inline perms &operator&=(perms &l, perms r) { 111 l = l & r; 112 return l; 113 } 114 inline perms operator~(perms x) { 115 return static_cast<perms>(~static_cast<unsigned short>(x)); 116 } 117 118 class UniqueID { 119 uint64_t Device; 120 uint64_t File; 121 122 public: 123 UniqueID() {} 124 UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} 125 bool operator==(const UniqueID &Other) const { 126 return Device == Other.Device && File == Other.File; 127 } 128 bool operator!=(const UniqueID &Other) const { return !(*this == Other); } 129 bool operator<(const UniqueID &Other) const { 130 return std::tie(Device, File) < std::tie(Other.Device, Other.File); 131 } 132 uint64_t getDevice() const { return Device; } 133 uint64_t getFile() const { return File; } 134 }; 135 136 /// file_status - Represents the result of a call to stat and friends. It has 137 /// a platform-specific member to store the result. 138 class file_status 139 { 140 #if defined(LLVM_ON_UNIX) 141 dev_t fs_st_dev; 142 ino_t fs_st_ino; 143 time_t fs_st_mtime; 144 uid_t fs_st_uid; 145 gid_t fs_st_gid; 146 off_t fs_st_size; 147 #elif defined (LLVM_ON_WIN32) 148 uint32_t LastWriteTimeHigh; 149 uint32_t LastWriteTimeLow; 150 uint32_t VolumeSerialNumber; 151 uint32_t FileSizeHigh; 152 uint32_t FileSizeLow; 153 uint32_t FileIndexHigh; 154 uint32_t FileIndexLow; 155 #endif 156 friend bool equivalent(file_status A, file_status B); 157 file_type Type; 158 perms Perms; 159 public: 160 #if defined(LLVM_ON_UNIX) 161 file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), 162 fs_st_uid(0), fs_st_gid(0), fs_st_size(0), 163 Type(file_type::status_error), Perms(perms_not_known) {} 164 165 file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), 166 fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type), 167 Perms(perms_not_known) {} 168 169 file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime, 170 uid_t UID, gid_t GID, off_t Size) 171 : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID), 172 fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {} 173 #elif defined(LLVM_ON_WIN32) 174 file_status() : LastWriteTimeHigh(0), LastWriteTimeLow(0), 175 VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), 176 FileIndexHigh(0), FileIndexLow(0), Type(file_type::status_error), 177 Perms(perms_not_known) {} 178 179 file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0), 180 VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), 181 FileIndexHigh(0), FileIndexLow(0), Type(Type), 182 Perms(perms_not_known) {} 183 184 file_status(file_type Type, uint32_t LastWriteTimeHigh, 185 uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, 186 uint32_t FileSizeHigh, uint32_t FileSizeLow, 187 uint32_t FileIndexHigh, uint32_t FileIndexLow) 188 : LastWriteTimeHigh(LastWriteTimeHigh), 189 LastWriteTimeLow(LastWriteTimeLow), 190 VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), 191 FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), 192 FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} 193 #endif 194 195 // getters 196 file_type type() const { return Type; } 197 perms permissions() const { return Perms; } 198 TimeValue getLastModificationTime() const; 199 UniqueID getUniqueID() const; 200 201 #if defined(LLVM_ON_UNIX) 202 uint32_t getUser() const { return fs_st_uid; } 203 uint32_t getGroup() const { return fs_st_gid; } 204 uint64_t getSize() const { return fs_st_size; } 205 #elif defined (LLVM_ON_WIN32) 206 uint32_t getUser() const { 207 return 9999; // Not applicable to Windows, so... 208 } 209 uint32_t getGroup() const { 210 return 9999; // Not applicable to Windows, so... 211 } 212 uint64_t getSize() const { 213 return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; 214 } 215 #endif 216 217 // setters 218 void type(file_type v) { Type = v; } 219 void permissions(perms p) { Perms = p; } 220 }; 221 222 /// file_magic - An "enum class" enumeration of file types based on magic (the first 223 /// N bytes of the file). 224 struct file_magic { 225 enum Impl { 226 unknown = 0, ///< Unrecognized file 227 bitcode, ///< Bitcode file 228 archive, ///< ar style archive file 229 elf_relocatable, ///< ELF Relocatable object file 230 elf_executable, ///< ELF Executable image 231 elf_shared_object, ///< ELF dynamically linked shared lib 232 elf_core, ///< ELF core image 233 macho_object, ///< Mach-O Object file 234 macho_executable, ///< Mach-O Executable 235 macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM 236 macho_core, ///< Mach-O Core File 237 macho_preload_executable, ///< Mach-O Preloaded Executable 238 macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib 239 macho_dynamic_linker, ///< The Mach-O dynamic linker 240 macho_bundle, ///< Mach-O Bundle file 241 macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub 242 macho_dsym_companion, ///< Mach-O dSYM companion file 243 macho_universal_binary, ///< Mach-O universal binary 244 coff_object, ///< COFF object file 245 coff_import_library, ///< COFF import library 246 pecoff_executable, ///< PECOFF executable file 247 windows_resource ///< Windows compiled resource file (.rc) 248 }; 249 250 bool is_object() const { 251 return V == unknown ? false : true; 252 } 253 254 file_magic() : V(unknown) {} 255 file_magic(Impl V) : V(V) {} 256 operator Impl() const { return V; } 257 258 private: 259 Impl V; 260 }; 261 262 /// @} 263 /// @name Physical Operators 264 /// @{ 265 266 /// @brief Make \a path an absolute path. 267 /// 268 /// Makes \a path absolute using the current directory if it is not already. An 269 /// empty \a path will result in the current directory. 270 /// 271 /// /absolute/path => /absolute/path 272 /// relative/../path => <current-directory>/relative/../path 273 /// 274 /// @param path A path that is modified to be an absolute path. 275 /// @returns errc::success if \a path has been made absolute, otherwise a 276 /// platform-specific error_code. 277 std::error_code make_absolute(SmallVectorImpl<char> &path); 278 279 /// @brief Normalize path separators in \a Path 280 /// 281 /// If the path contains any '\' separators, they are transformed into '/'. 282 /// This is particularly useful when cross-compiling Windows on Linux, but is 283 /// safe to invoke on Windows, which accepts both characters as a path 284 /// separator. 285 std::error_code normalize_separators(SmallVectorImpl<char> &Path); 286 287 /// @brief Create all the non-existent directories in path. 288 /// 289 /// @param path Directories to create. 290 /// @returns errc::success if is_directory(path), otherwise a platform 291 /// specific error_code. If IgnoreExisting is false, also returns 292 /// error if the directory already existed. 293 std::error_code create_directories(const Twine &path, 294 bool IgnoreExisting = true); 295 296 /// @brief Create the directory in path. 297 /// 298 /// @param path Directory to create. 299 /// @returns errc::success if is_directory(path), otherwise a platform 300 /// specific error_code. If IgnoreExisting is false, also returns 301 /// error if the directory already existed. 302 std::error_code create_directory(const Twine &path, bool IgnoreExisting = true); 303 304 /// @brief Create a link from \a from to \a to. 305 /// 306 /// The link may be a soft or a hard link, depending on the platform. The caller 307 /// may not assume which one. Currently on windows it creates a hard link since 308 /// soft links require extra privileges. On unix, it creates a soft link since 309 /// hard links don't work on SMB file systems. 310 /// 311 /// @param to The path to hard link to. 312 /// @param from The path to hard link from. This is created. 313 /// @returns errc::success if the link was created, otherwise a platform 314 /// specific error_code. 315 std::error_code create_link(const Twine &to, const Twine &from); 316 317 /// @brief Get the current path. 318 /// 319 /// @param result Holds the current path on return. 320 /// @returns errc::success if the current path has been stored in result, 321 /// otherwise a platform-specific error_code. 322 std::error_code current_path(SmallVectorImpl<char> &result); 323 324 /// @brief Remove path. Equivalent to POSIX remove(). 325 /// 326 /// @param path Input path. 327 /// @returns errc::success if path has been removed or didn't exist, otherwise a 328 /// platform-specific error code. If IgnoreNonExisting is false, also 329 /// returns error if the file didn't exist. 330 std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); 331 332 /// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). 333 /// 334 /// @param from The path to rename from. 335 /// @param to The path to rename to. This is created. 336 std::error_code rename(const Twine &from, const Twine &to); 337 338 /// @brief Copy the contents of \a From to \a To. 339 /// 340 /// @param From The path to copy from. 341 /// @param To The path to copy to. This is created. 342 std::error_code copy_file(const Twine &From, const Twine &To); 343 344 /// @brief Resize path to size. File is resized as if by POSIX truncate(). 345 /// 346 /// @param path Input path. 347 /// @param size Size to resize to. 348 /// @returns errc::success if \a path has been resized to \a size, otherwise a 349 /// platform-specific error_code. 350 std::error_code resize_file(const Twine &path, uint64_t size); 351 352 /// @} 353 /// @name Physical Observers 354 /// @{ 355 356 /// @brief Does file exist? 357 /// 358 /// @param status A file_status previously returned from stat. 359 /// @returns True if the file represented by status exists, false if it does 360 /// not. 361 bool exists(file_status status); 362 363 /// @brief Does file exist? 364 /// 365 /// @param path Input path. 366 /// @param result Set to true if the file represented by status exists, false if 367 /// it does not. Undefined otherwise. 368 /// @returns errc::success if result has been successfully set, otherwise a 369 /// platform-specific error_code. 370 std::error_code exists(const Twine &path, bool &result); 371 372 /// @brief Simpler version of exists for clients that don't need to 373 /// differentiate between an error and false. 374 inline bool exists(const Twine &path) { 375 bool result; 376 return !exists(path, result) && result; 377 } 378 379 /// @brief Can we execute this file? 380 /// 381 /// @param Path Input path. 382 /// @returns True if we can execute it, false otherwise. 383 bool can_execute(const Twine &Path); 384 385 /// @brief Can we write this file? 386 /// 387 /// @param Path Input path. 388 /// @returns True if we can write to it, false otherwise. 389 bool can_write(const Twine &Path); 390 391 /// @brief Do file_status's represent the same thing? 392 /// 393 /// @param A Input file_status. 394 /// @param B Input file_status. 395 /// 396 /// assert(status_known(A) || status_known(B)); 397 /// 398 /// @returns True if A and B both represent the same file system entity, false 399 /// otherwise. 400 bool equivalent(file_status A, file_status B); 401 402 /// @brief Do paths represent the same thing? 403 /// 404 /// assert(status_known(A) || status_known(B)); 405 /// 406 /// @param A Input path A. 407 /// @param B Input path B. 408 /// @param result Set to true if stat(A) and stat(B) have the same device and 409 /// inode (or equivalent). 410 /// @returns errc::success if result has been successfully set, otherwise a 411 /// platform-specific error_code. 412 std::error_code equivalent(const Twine &A, const Twine &B, bool &result); 413 414 /// @brief Simpler version of equivalent for clients that don't need to 415 /// differentiate between an error and false. 416 inline bool equivalent(const Twine &A, const Twine &B) { 417 bool result; 418 return !equivalent(A, B, result) && result; 419 } 420 421 /// @brief Does status represent a directory? 422 /// 423 /// @param status A file_status previously returned from status. 424 /// @returns status.type() == file_type::directory_file. 425 bool is_directory(file_status status); 426 427 /// @brief Is path a directory? 428 /// 429 /// @param path Input path. 430 /// @param result Set to true if \a path is a directory, false if it is not. 431 /// Undefined otherwise. 432 /// @returns errc::success if result has been successfully set, otherwise a 433 /// platform-specific error_code. 434 std::error_code is_directory(const Twine &path, bool &result); 435 436 /// @brief Simpler version of is_directory for clients that don't need to 437 /// differentiate between an error and false. 438 inline bool is_directory(const Twine &Path) { 439 bool Result; 440 return !is_directory(Path, Result) && Result; 441 } 442 443 /// @brief Does status represent a regular file? 444 /// 445 /// @param status A file_status previously returned from status. 446 /// @returns status_known(status) && status.type() == file_type::regular_file. 447 bool is_regular_file(file_status status); 448 449 /// @brief Is path a regular file? 450 /// 451 /// @param path Input path. 452 /// @param result Set to true if \a path is a regular file, false if it is not. 453 /// Undefined otherwise. 454 /// @returns errc::success if result has been successfully set, otherwise a 455 /// platform-specific error_code. 456 std::error_code is_regular_file(const Twine &path, bool &result); 457 458 /// @brief Simpler version of is_regular_file for clients that don't need to 459 /// differentiate between an error and false. 460 inline bool is_regular_file(const Twine &Path) { 461 bool Result; 462 if (is_regular_file(Path, Result)) 463 return false; 464 return Result; 465 } 466 467 /// @brief Does this status represent something that exists but is not a 468 /// directory, regular file, or symlink? 469 /// 470 /// @param status A file_status previously returned from status. 471 /// @returns exists(s) && !is_regular_file(s) && !is_directory(s) 472 bool is_other(file_status status); 473 474 /// @brief Is path something that exists but is not a directory, 475 /// regular file, or symlink? 476 /// 477 /// @param path Input path. 478 /// @param result Set to true if \a path exists, but is not a directory, regular 479 /// file, or a symlink, false if it does not. Undefined otherwise. 480 /// @returns errc::success if result has been successfully set, otherwise a 481 /// platform-specific error_code. 482 std::error_code is_other(const Twine &path, bool &result); 483 484 /// @brief Get file status as if by POSIX stat(). 485 /// 486 /// @param path Input path. 487 /// @param result Set to the file status. 488 /// @returns errc::success if result has been successfully set, otherwise a 489 /// platform-specific error_code. 490 std::error_code status(const Twine &path, file_status &result); 491 492 /// @brief A version for when a file descriptor is already available. 493 std::error_code status(int FD, file_status &Result); 494 495 /// @brief Get file size. 496 /// 497 /// @param Path Input path. 498 /// @param Result Set to the size of the file in \a Path. 499 /// @returns errc::success if result has been successfully set, otherwise a 500 /// platform-specific error_code. 501 inline std::error_code file_size(const Twine &Path, uint64_t &Result) { 502 file_status Status; 503 std::error_code EC = status(Path, Status); 504 if (EC) 505 return EC; 506 Result = Status.getSize(); 507 return std::error_code(); 508 } 509 510 /// @brief Set the file modification and access time. 511 /// 512 /// @returns errc::success if the file times were successfully set, otherwise a 513 /// platform-specific error_code or errc::function_not_supported on 514 /// platforms where the functionality isn't available. 515 std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); 516 517 /// @brief Is status available? 518 /// 519 /// @param s Input file status. 520 /// @returns True if status() != status_error. 521 bool status_known(file_status s); 522 523 /// @brief Is status available? 524 /// 525 /// @param path Input path. 526 /// @param result Set to true if status() != status_error. 527 /// @returns errc::success if result has been successfully set, otherwise a 528 /// platform-specific error_code. 529 std::error_code status_known(const Twine &path, bool &result); 530 531 /// @brief Create a uniquely named file. 532 /// 533 /// Generates a unique path suitable for a temporary file and then opens it as a 534 /// file. The name is based on \a model with '%' replaced by a random char in 535 /// [0-9a-f]. If \a model is not an absolute path, a suitable temporary 536 /// directory will be prepended. 537 /// 538 /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 539 /// 540 /// This is an atomic operation. Either the file is created and opened, or the 541 /// file system is left untouched. 542 /// 543 /// The intendend use is for files that are to be kept, possibly after 544 /// renaming them. For example, when running 'clang -c foo.o', the file can 545 /// be first created as foo-abc123.o and then renamed. 546 /// 547 /// @param Model Name to base unique path off of. 548 /// @param ResultFD Set to the opened file's file descriptor. 549 /// @param ResultPath Set to the opened file's absolute path. 550 /// @returns errc::success if Result{FD,Path} have been successfully set, 551 /// otherwise a platform-specific error_code. 552 std::error_code createUniqueFile(const Twine &Model, int &ResultFD, 553 SmallVectorImpl<char> &ResultPath, 554 unsigned Mode = all_read | all_write); 555 556 /// @brief Simpler version for clients that don't want an open file. 557 std::error_code createUniqueFile(const Twine &Model, 558 SmallVectorImpl<char> &ResultPath); 559 560 /// @brief Create a file in the system temporary directory. 561 /// 562 /// The filename is of the form prefix-random_chars.suffix. Since the directory 563 /// is not know to the caller, Prefix and Suffix cannot have path separators. 564 /// The files are created with mode 0600. 565 /// 566 /// This should be used for things like a temporary .s that is removed after 567 /// running the assembler. 568 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 569 int &ResultFD, 570 SmallVectorImpl<char> &ResultPath); 571 572 /// @brief Simpler version for clients that don't want an open file. 573 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 574 SmallVectorImpl<char> &ResultPath); 575 576 std::error_code createUniqueDirectory(const Twine &Prefix, 577 SmallVectorImpl<char> &ResultPath); 578 579 enum OpenFlags : unsigned { 580 F_None = 0, 581 582 /// F_Excl - When opening a file, this flag makes raw_fd_ostream 583 /// report an error if the file already exists. 584 F_Excl = 1, 585 586 /// F_Append - When opening a file, if it already exists append to the 587 /// existing file instead of returning an error. This may not be specified 588 /// with F_Excl. 589 F_Append = 2, 590 591 /// The file should be opened in text mode on platforms that make this 592 /// distinction. 593 F_Text = 4, 594 595 /// Open the file for read and write. 596 F_RW = 8 597 }; 598 599 inline OpenFlags operator|(OpenFlags A, OpenFlags B) { 600 return OpenFlags(unsigned(A) | unsigned(B)); 601 } 602 603 inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { 604 A = A | B; 605 return A; 606 } 607 608 std::error_code openFileForWrite(const Twine &Name, int &ResultFD, 609 OpenFlags Flags, unsigned Mode = 0666); 610 611 std::error_code openFileForRead(const Twine &Name, int &ResultFD); 612 613 /// @brief Identify the type of a binary file based on how magical it is. 614 file_magic identify_magic(StringRef magic); 615 616 /// @brief Get and identify \a path's type based on its content. 617 /// 618 /// @param path Input path. 619 /// @param result Set to the type of file, or file_magic::unknown. 620 /// @returns errc::success if result has been successfully set, otherwise a 621 /// platform-specific error_code. 622 std::error_code identify_magic(const Twine &path, file_magic &result); 623 624 std::error_code getUniqueID(const Twine Path, UniqueID &Result); 625 626 /// This class represents a memory mapped file. It is based on 627 /// boost::iostreams::mapped_file. 628 class mapped_file_region { 629 mapped_file_region() LLVM_DELETED_FUNCTION; 630 mapped_file_region(mapped_file_region&) LLVM_DELETED_FUNCTION; 631 mapped_file_region &operator =(mapped_file_region&) LLVM_DELETED_FUNCTION; 632 633 public: 634 enum mapmode { 635 readonly, ///< May only access map via const_data as read only. 636 readwrite, ///< May access map via data and modify it. Written to path. 637 priv ///< May modify via data, but changes are lost on destruction. 638 }; 639 640 private: 641 /// Platform-specific mapping state. 642 mapmode Mode; 643 uint64_t Size; 644 void *Mapping; 645 #ifdef LLVM_ON_WIN32 646 int FileDescriptor; 647 void *FileHandle; 648 void *FileMappingHandle; 649 #endif 650 651 std::error_code init(int FD, bool CloseFD, uint64_t Offset); 652 653 public: 654 typedef char char_type; 655 656 mapped_file_region(mapped_file_region&&); 657 mapped_file_region &operator =(mapped_file_region&&); 658 659 /// Construct a mapped_file_region at \a path starting at \a offset of length 660 /// \a length and with access \a mode. 661 /// 662 /// \param path Path to the file to map. If it does not exist it will be 663 /// created. 664 /// \param mode How to map the memory. 665 /// \param length Number of bytes to map in starting at \a offset. If the file 666 /// is shorter than this, it will be extended. If \a length is 667 /// 0, the entire file will be mapped. 668 /// \param offset Byte offset from the beginning of the file where the map 669 /// should begin. Must be a multiple of 670 /// mapped_file_region::alignment(). 671 /// \param ec This is set to errc::success if the map was constructed 672 /// successfully. Otherwise it is set to a platform dependent error. 673 mapped_file_region(const Twine &path, mapmode mode, uint64_t length, 674 uint64_t offset, std::error_code &ec); 675 676 /// \param fd An open file descriptor to map. mapped_file_region takes 677 /// ownership if closefd is true. It must have been opended in the correct 678 /// mode. 679 mapped_file_region(int fd, bool closefd, mapmode mode, uint64_t length, 680 uint64_t offset, std::error_code &ec); 681 682 ~mapped_file_region(); 683 684 mapmode flags() const; 685 uint64_t size() const; 686 char *data() const; 687 688 /// Get a const view of the data. Modifying this memory has undefined 689 /// behavior. 690 const char *const_data() const; 691 692 /// \returns The minimum alignment offset must be. 693 static int alignment(); 694 }; 695 696 /// Return the path to the main executable, given the value of argv[0] from 697 /// program startup and the address of main itself. In extremis, this function 698 /// may fail and return an empty path. 699 std::string getMainExecutable(const char *argv0, void *MainExecAddr); 700 701 /// @} 702 /// @name Iterators 703 /// @{ 704 705 /// directory_entry - A single entry in a directory. Caches the status either 706 /// from the result of the iteration syscall, or the first time status is 707 /// called. 708 class directory_entry { 709 std::string Path; 710 mutable file_status Status; 711 712 public: 713 explicit directory_entry(const Twine &path, file_status st = file_status()) 714 : Path(path.str()) 715 , Status(st) {} 716 717 directory_entry() {} 718 719 void assign(const Twine &path, file_status st = file_status()) { 720 Path = path.str(); 721 Status = st; 722 } 723 724 void replace_filename(const Twine &filename, file_status st = file_status()); 725 726 const std::string &path() const { return Path; } 727 std::error_code status(file_status &result) const; 728 729 bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } 730 bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } 731 bool operator< (const directory_entry& rhs) const; 732 bool operator<=(const directory_entry& rhs) const; 733 bool operator> (const directory_entry& rhs) const; 734 bool operator>=(const directory_entry& rhs) const; 735 }; 736 737 namespace detail { 738 struct DirIterState; 739 740 std::error_code directory_iterator_construct(DirIterState &, StringRef); 741 std::error_code directory_iterator_increment(DirIterState &); 742 std::error_code directory_iterator_destruct(DirIterState &); 743 744 /// DirIterState - Keeps state for the directory_iterator. It is reference 745 /// counted in order to preserve InputIterator semantics on copy. 746 struct DirIterState : public RefCountedBase<DirIterState> { 747 DirIterState() 748 : IterationHandle(0) {} 749 750 ~DirIterState() { 751 directory_iterator_destruct(*this); 752 } 753 754 intptr_t IterationHandle; 755 directory_entry CurrentEntry; 756 }; 757 } 758 759 /// directory_iterator - Iterates through the entries in path. There is no 760 /// operator++ because we need an error_code. If it's really needed we can make 761 /// it call report_fatal_error on error. 762 class directory_iterator { 763 IntrusiveRefCntPtr<detail::DirIterState> State; 764 765 public: 766 explicit directory_iterator(const Twine &path, std::error_code &ec) { 767 State = new detail::DirIterState; 768 SmallString<128> path_storage; 769 ec = detail::directory_iterator_construct(*State, 770 path.toStringRef(path_storage)); 771 } 772 773 explicit directory_iterator(const directory_entry &de, std::error_code &ec) { 774 State = new detail::DirIterState; 775 ec = detail::directory_iterator_construct(*State, de.path()); 776 } 777 778 /// Construct end iterator. 779 directory_iterator() : State(nullptr) {} 780 781 // No operator++ because we need error_code. 782 directory_iterator &increment(std::error_code &ec) { 783 ec = directory_iterator_increment(*State); 784 return *this; 785 } 786 787 const directory_entry &operator*() const { return State->CurrentEntry; } 788 const directory_entry *operator->() const { return &State->CurrentEntry; } 789 790 bool operator==(const directory_iterator &RHS) const { 791 if (State == RHS.State) 792 return true; 793 if (!RHS.State) 794 return State->CurrentEntry == directory_entry(); 795 if (!State) 796 return RHS.State->CurrentEntry == directory_entry(); 797 return State->CurrentEntry == RHS.State->CurrentEntry; 798 } 799 800 bool operator!=(const directory_iterator &RHS) const { 801 return !(*this == RHS); 802 } 803 // Other members as required by 804 // C++ Std, 24.1.1 Input iterators [input.iterators] 805 }; 806 807 namespace detail { 808 /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is 809 /// reference counted in order to preserve InputIterator semantics on copy. 810 struct RecDirIterState : public RefCountedBase<RecDirIterState> { 811 RecDirIterState() 812 : Level(0) 813 , HasNoPushRequest(false) {} 814 815 std::stack<directory_iterator, std::vector<directory_iterator> > Stack; 816 uint16_t Level; 817 bool HasNoPushRequest; 818 }; 819 } 820 821 /// recursive_directory_iterator - Same as directory_iterator except for it 822 /// recurses down into child directories. 823 class recursive_directory_iterator { 824 IntrusiveRefCntPtr<detail::RecDirIterState> State; 825 826 public: 827 recursive_directory_iterator() {} 828 explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) 829 : State(new detail::RecDirIterState) { 830 State->Stack.push(directory_iterator(path, ec)); 831 if (State->Stack.top() == directory_iterator()) 832 State.reset(); 833 } 834 // No operator++ because we need error_code. 835 recursive_directory_iterator &increment(std::error_code &ec) { 836 const directory_iterator end_itr; 837 838 if (State->HasNoPushRequest) 839 State->HasNoPushRequest = false; 840 else { 841 file_status st; 842 if ((ec = State->Stack.top()->status(st))) return *this; 843 if (is_directory(st)) { 844 State->Stack.push(directory_iterator(*State->Stack.top(), ec)); 845 if (ec) return *this; 846 if (State->Stack.top() != end_itr) { 847 ++State->Level; 848 return *this; 849 } 850 State->Stack.pop(); 851 } 852 } 853 854 while (!State->Stack.empty() 855 && State->Stack.top().increment(ec) == end_itr) { 856 State->Stack.pop(); 857 --State->Level; 858 } 859 860 // Check if we are done. If so, create an end iterator. 861 if (State->Stack.empty()) 862 State.reset(); 863 864 return *this; 865 } 866 867 const directory_entry &operator*() const { return *State->Stack.top(); } 868 const directory_entry *operator->() const { return &*State->Stack.top(); } 869 870 // observers 871 /// Gets the current level. Starting path is at level 0. 872 int level() const { return State->Level; } 873 874 /// Returns true if no_push has been called for this directory_entry. 875 bool no_push_request() const { return State->HasNoPushRequest; } 876 877 // modifiers 878 /// Goes up one level if Level > 0. 879 void pop() { 880 assert(State && "Cannot pop an end iterator!"); 881 assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 882 883 const directory_iterator end_itr; 884 std::error_code ec; 885 do { 886 if (ec) 887 report_fatal_error("Error incrementing directory iterator."); 888 State->Stack.pop(); 889 --State->Level; 890 } while (!State->Stack.empty() 891 && State->Stack.top().increment(ec) == end_itr); 892 893 // Check if we are done. If so, create an end iterator. 894 if (State->Stack.empty()) 895 State.reset(); 896 } 897 898 /// Does not go down into the current directory_entry. 899 void no_push() { State->HasNoPushRequest = true; } 900 901 bool operator==(const recursive_directory_iterator &RHS) const { 902 return State == RHS.State; 903 } 904 905 bool operator!=(const recursive_directory_iterator &RHS) const { 906 return !(*this == RHS); 907 } 908 // Other members as required by 909 // C++ Std, 24.1.1 Input iterators [input.iterators] 910 }; 911 912 /// @} 913 914 } // end namespace fs 915 } // end namespace sys 916 } // end namespace llvm 917 918 #endif 919