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