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