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