1 //===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares the llvm::sys::fs namespace. It is designed after 10 // TR2/boost filesystem (v3), but modified to remove exception handling and the 11 // path class. 12 // 13 // All functions return an error_code and their actual work via the last out 14 // argument. The out argument is defined if and only if errc::success is 15 // returned. A function may return any error code in the generic or system 16 // category. However, they shall be equivalent to any error conditions listed 17 // in each functions respective documentation if the condition applies. [ note: 18 // this does not guarantee that error_code will be in the set of explicitly 19 // listed codes, but it does guarantee that if any of the explicitly listed 20 // errors occur, the correct error_code will be used ]. All functions may 21 // return errc::not_enough_memory if there is not enough memory to complete the 22 // operation. 23 // 24 //===----------------------------------------------------------------------===// 25 26 #ifndef LLVM_SUPPORT_FILESYSTEM_H 27 #define LLVM_SUPPORT_FILESYSTEM_H 28 29 #include "llvm/ADT/SmallString.h" 30 #include "llvm/ADT/StringRef.h" 31 #include "llvm/ADT/Twine.h" 32 #include "llvm/Config/llvm-config.h" 33 #include "llvm/Support/Chrono.h" 34 #include "llvm/Support/Error.h" 35 #include "llvm/Support/ErrorHandling.h" 36 #include "llvm/Support/ErrorOr.h" 37 #include "llvm/Support/FileSystem/UniqueID.h" 38 #include "llvm/Support/MD5.h" 39 #include <cassert> 40 #include <cstdint> 41 #include <ctime> 42 #include <memory> 43 #include <string> 44 #include <system_error> 45 #include <vector> 46 47 namespace llvm { 48 namespace sys { 49 namespace fs { 50 51 #if defined(_WIN32) 52 // A Win32 HANDLE is a typedef of void* 53 using file_t = void *; 54 #else 55 using file_t = int; 56 #endif 57 58 extern const file_t kInvalidFile; 59 60 /// An enumeration for the file system's view of the type. 61 enum class file_type { 62 status_error, 63 file_not_found, 64 regular_file, 65 directory_file, 66 symlink_file, 67 block_file, 68 character_file, 69 fifo_file, 70 socket_file, 71 type_unknown 72 }; 73 74 /// space_info - Self explanatory. 75 struct space_info { 76 uint64_t capacity; 77 uint64_t free; 78 uint64_t available; 79 }; 80 81 enum perms { 82 no_perms = 0, 83 owner_read = 0400, 84 owner_write = 0200, 85 owner_exe = 0100, 86 owner_all = owner_read | owner_write | owner_exe, 87 group_read = 040, 88 group_write = 020, 89 group_exe = 010, 90 group_all = group_read | group_write | group_exe, 91 others_read = 04, 92 others_write = 02, 93 others_exe = 01, 94 others_all = others_read | others_write | others_exe, 95 all_read = owner_read | group_read | others_read, 96 all_write = owner_write | group_write | others_write, 97 all_exe = owner_exe | group_exe | others_exe, 98 all_all = owner_all | group_all | others_all, 99 set_uid_on_exe = 04000, 100 set_gid_on_exe = 02000, 101 sticky_bit = 01000, 102 all_perms = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit, 103 perms_not_known = 0xFFFF 104 }; 105 106 // Helper functions so that you can use & and | to manipulate perms bits: 107 inline perms operator|(perms l, perms r) { 108 return static_cast<perms>(static_cast<unsigned short>(l) | 109 static_cast<unsigned short>(r)); 110 } 111 inline perms operator&(perms l, perms r) { 112 return static_cast<perms>(static_cast<unsigned short>(l) & 113 static_cast<unsigned short>(r)); 114 } 115 inline perms &operator|=(perms &l, perms r) { 116 l = l | r; 117 return l; 118 } 119 inline perms &operator&=(perms &l, perms r) { 120 l = l & r; 121 return l; 122 } 123 inline perms operator~(perms x) { 124 // Avoid UB by explicitly truncating the (unsigned) ~ result. 125 return static_cast<perms>( 126 static_cast<unsigned short>(~static_cast<unsigned short>(x))); 127 } 128 129 /// Represents the result of a call to directory_iterator::status(). This is a 130 /// subset of the information returned by a regular sys::fs::status() call, and 131 /// represents the information provided by Windows FileFirstFile/FindNextFile. 132 class basic_file_status { 133 protected: 134 #if defined(LLVM_ON_UNIX) 135 time_t fs_st_atime = 0; 136 time_t fs_st_mtime = 0; 137 uint32_t fs_st_atime_nsec = 0; 138 uint32_t fs_st_mtime_nsec = 0; 139 uid_t fs_st_uid = 0; 140 gid_t fs_st_gid = 0; 141 off_t fs_st_size = 0; 142 #elif defined (_WIN32) 143 uint32_t LastAccessedTimeHigh = 0; 144 uint32_t LastAccessedTimeLow = 0; 145 uint32_t LastWriteTimeHigh = 0; 146 uint32_t LastWriteTimeLow = 0; 147 uint32_t FileSizeHigh = 0; 148 uint32_t FileSizeLow = 0; 149 #endif 150 file_type Type = file_type::status_error; 151 perms Perms = perms_not_known; 152 153 public: 154 basic_file_status() = default; 155 156 explicit basic_file_status(file_type Type) : Type(Type) {} 157 158 #if defined(LLVM_ON_UNIX) 159 basic_file_status(file_type Type, perms Perms, time_t ATime, 160 uint32_t ATimeNSec, time_t MTime, uint32_t MTimeNSec, 161 uid_t UID, gid_t GID, off_t Size) 162 : fs_st_atime(ATime), fs_st_mtime(MTime), 163 fs_st_atime_nsec(ATimeNSec), fs_st_mtime_nsec(MTimeNSec), 164 fs_st_uid(UID), fs_st_gid(GID), 165 fs_st_size(Size), Type(Type), Perms(Perms) {} 166 #elif defined(_WIN32) 167 basic_file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh, 168 uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh, 169 uint32_t LastWriteTimeLow, uint32_t FileSizeHigh, 170 uint32_t FileSizeLow) 171 : LastAccessedTimeHigh(LastAccessTimeHigh), 172 LastAccessedTimeLow(LastAccessTimeLow), 173 LastWriteTimeHigh(LastWriteTimeHigh), 174 LastWriteTimeLow(LastWriteTimeLow), FileSizeHigh(FileSizeHigh), 175 FileSizeLow(FileSizeLow), Type(Type), Perms(Perms) {} 176 #endif 177 178 // getters 179 file_type type() const { return Type; } 180 perms permissions() const { return Perms; } 181 182 /// The file access time as reported from the underlying file system. 183 /// 184 /// Also see comments on \c getLastModificationTime() related to the precision 185 /// of the returned value. 186 TimePoint<> getLastAccessedTime() const; 187 188 /// The file modification time as reported from the underlying file system. 189 /// 190 /// The returned value allows for nanosecond precision but the actual 191 /// resolution is an implementation detail of the underlying file system. 192 /// There is no guarantee for what kind of resolution you can expect, the 193 /// resolution can differ across platforms and even across mountpoints on the 194 /// same machine. 195 TimePoint<> getLastModificationTime() 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 (_WIN32) 202 uint32_t getUser() const { 203 return 9999; // Not applicable to Windows, so... 204 } 205 206 uint32_t getGroup() const { 207 return 9999; // Not applicable to Windows, so... 208 } 209 210 uint64_t getSize() const { 211 return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; 212 } 213 #endif 214 215 // setters 216 void type(file_type v) { Type = v; } 217 void permissions(perms p) { Perms = p; } 218 }; 219 220 /// Represents the result of a call to sys::fs::status(). 221 class file_status : public basic_file_status { 222 friend bool equivalent(file_status A, file_status B); 223 224 #if defined(LLVM_ON_UNIX) 225 dev_t fs_st_dev = 0; 226 nlink_t fs_st_nlinks = 0; 227 ino_t fs_st_ino = 0; 228 #elif defined (_WIN32) 229 uint32_t NumLinks = 0; 230 uint32_t VolumeSerialNumber = 0; 231 uint64_t PathHash = 0; 232 #endif 233 234 public: 235 file_status() = default; 236 237 explicit file_status(file_type Type) : basic_file_status(Type) {} 238 239 #if defined(LLVM_ON_UNIX) 240 file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino, 241 time_t ATime, uint32_t ATimeNSec, 242 time_t MTime, uint32_t MTimeNSec, 243 uid_t UID, gid_t GID, off_t Size) 244 : basic_file_status(Type, Perms, ATime, ATimeNSec, MTime, MTimeNSec, 245 UID, GID, Size), 246 fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {} 247 #elif defined(_WIN32) 248 file_status(file_type Type, perms Perms, uint32_t LinkCount, 249 uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow, 250 uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow, 251 uint32_t VolumeSerialNumber, uint32_t FileSizeHigh, 252 uint32_t FileSizeLow, uint64_t PathHash) 253 : basic_file_status(Type, Perms, LastAccessTimeHigh, LastAccessTimeLow, 254 LastWriteTimeHigh, LastWriteTimeLow, FileSizeHigh, 255 FileSizeLow), 256 NumLinks(LinkCount), VolumeSerialNumber(VolumeSerialNumber), 257 PathHash(PathHash) {} 258 #endif 259 260 UniqueID getUniqueID() const; 261 uint32_t getLinkCount() const; 262 }; 263 264 /// @} 265 /// @name Physical Operators 266 /// @{ 267 268 /// Make \a path an absolute path. 269 /// 270 /// Makes \a path absolute using the \a current_directory if it is not already. 271 /// An empty \a path will result in the \a current_directory. 272 /// 273 /// /absolute/path => /absolute/path 274 /// relative/../path => <current-directory>/relative/../path 275 /// 276 /// @param path A path that is modified to be an absolute path. 277 void make_absolute(const Twine ¤t_directory, SmallVectorImpl<char> &path); 278 279 /// Make \a path an absolute path. 280 /// 281 /// Makes \a path absolute using the current directory if it is not already. An 282 /// empty \a path will result in the current directory. 283 /// 284 /// /absolute/path => /absolute/path 285 /// relative/../path => <current-directory>/relative/../path 286 /// 287 /// @param path A path that is modified to be an absolute path. 288 /// @returns errc::success if \a path has been made absolute, otherwise a 289 /// platform-specific error_code. 290 std::error_code make_absolute(SmallVectorImpl<char> &path); 291 292 /// Create all the non-existent directories in path. 293 /// 294 /// @param path Directories to create. 295 /// @returns errc::success if is_directory(path), otherwise a platform 296 /// specific error_code. If IgnoreExisting is false, also returns 297 /// error if the directory already existed. 298 std::error_code create_directories(const Twine &path, 299 bool IgnoreExisting = true, 300 perms Perms = owner_all | group_all); 301 302 /// Create the directory in path. 303 /// 304 /// @param path Directory to create. 305 /// @returns errc::success if is_directory(path), otherwise a platform 306 /// specific error_code. If IgnoreExisting is false, also returns 307 /// error if the directory already existed. 308 std::error_code create_directory(const Twine &path, bool IgnoreExisting = true, 309 perms Perms = owner_all | group_all); 310 311 /// Create a link from \a from to \a to. 312 /// 313 /// The link may be a soft or a hard link, depending on the platform. The caller 314 /// may not assume which one. Currently on windows it creates a hard link since 315 /// soft links require extra privileges. On unix, it creates a soft link since 316 /// hard links don't work on SMB file systems. 317 /// 318 /// @param to The path to hard link to. 319 /// @param from The path to hard link from. This is created. 320 /// @returns errc::success if the link was created, otherwise a platform 321 /// specific error_code. 322 std::error_code create_link(const Twine &to, const Twine &from); 323 324 /// Create a hard link from \a from to \a to, or return an error. 325 /// 326 /// @param to The path to hard link to. 327 /// @param from The path to hard link from. This is created. 328 /// @returns errc::success if the link was created, otherwise a platform 329 /// specific error_code. 330 std::error_code create_hard_link(const Twine &to, const Twine &from); 331 332 /// Collapse all . and .. patterns, resolve all symlinks, and optionally 333 /// expand ~ expressions to the user's home directory. 334 /// 335 /// @param path The path to resolve. 336 /// @param output The location to store the resolved path. 337 /// @param expand_tilde If true, resolves ~ expressions to the user's home 338 /// directory. 339 std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output, 340 bool expand_tilde = false); 341 342 /// Expands ~ expressions to the user's home directory. On Unix ~user 343 /// directories are resolved as well. 344 /// 345 /// @param path The path to resolve. 346 void expand_tilde(const Twine &path, SmallVectorImpl<char> &output); 347 348 /// Get the current path. 349 /// 350 /// @param result Holds the current path on return. 351 /// @returns errc::success if the current path has been stored in result, 352 /// otherwise a platform-specific error_code. 353 std::error_code current_path(SmallVectorImpl<char> &result); 354 355 /// Set the current path. 356 /// 357 /// @param path The path to set. 358 /// @returns errc::success if the current path was successfully set, 359 /// otherwise a platform-specific error_code. 360 std::error_code set_current_path(const Twine &path); 361 362 /// Remove path. Equivalent to POSIX remove(). 363 /// 364 /// @param path Input path. 365 /// @returns errc::success if path has been removed or didn't exist, otherwise a 366 /// platform-specific error code. If IgnoreNonExisting is false, also 367 /// returns error if the file didn't exist. 368 std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); 369 370 /// Recursively delete a directory. 371 /// 372 /// @param path Input path. 373 /// @returns errc::success if path has been removed or didn't exist, otherwise a 374 /// platform-specific error code. 375 std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true); 376 377 /// Rename \a from to \a to. 378 /// 379 /// Files are renamed as if by POSIX rename(), except that on Windows there may 380 /// be a short interval of time during which the destination file does not 381 /// exist. 382 /// 383 /// @param from The path to rename from. 384 /// @param to The path to rename to. This is created. 385 std::error_code rename(const Twine &from, const Twine &to); 386 387 /// Copy the contents of \a From to \a To. 388 /// 389 /// @param From The path to copy from. 390 /// @param To The path to copy to. This is created. 391 std::error_code copy_file(const Twine &From, const Twine &To); 392 393 /// Copy the contents of \a From to \a To. 394 /// 395 /// @param From The path to copy from. 396 /// @param ToFD The open file descriptor of the destination file. 397 std::error_code copy_file(const Twine &From, int ToFD); 398 399 /// Resize path to size. File is resized as if by POSIX truncate(). 400 /// 401 /// @param FD Input file descriptor. 402 /// @param Size Size to resize to. 403 /// @returns errc::success if \a path has been resized to \a size, otherwise a 404 /// platform-specific error_code. 405 std::error_code resize_file(int FD, uint64_t Size); 406 407 /// Resize \p FD to \p Size before mapping \a mapped_file_region::readwrite. On 408 /// non-Windows, this calls \a resize_file(). On Windows, this is a no-op, 409 /// since the subsequent mapping (via \c CreateFileMapping) automatically 410 /// extends the file. 411 inline std::error_code resize_file_before_mapping_readwrite(int FD, 412 uint64_t Size) { 413 #ifdef _WIN32 414 (void)FD; 415 (void)Size; 416 return std::error_code(); 417 #else 418 return resize_file(FD, Size); 419 #endif 420 } 421 422 /// Compute an MD5 hash of a file's contents. 423 /// 424 /// @param FD Input file descriptor. 425 /// @returns An MD5Result with the hash computed, if successful, otherwise a 426 /// std::error_code. 427 ErrorOr<MD5::MD5Result> md5_contents(int FD); 428 429 /// Version of compute_md5 that doesn't require an open file descriptor. 430 ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path); 431 432 /// @} 433 /// @name Physical Observers 434 /// @{ 435 436 /// Does file exist? 437 /// 438 /// @param status A basic_file_status previously returned from stat. 439 /// @returns True if the file represented by status exists, false if it does 440 /// not. 441 bool exists(const basic_file_status &status); 442 443 enum class AccessMode { Exist, Write, Execute }; 444 445 /// Can the file be accessed? 446 /// 447 /// @param Path Input path. 448 /// @returns errc::success if the path can be accessed, otherwise a 449 /// platform-specific error_code. 450 std::error_code access(const Twine &Path, AccessMode Mode); 451 452 /// Does file exist? 453 /// 454 /// @param Path Input path. 455 /// @returns True if it exists, false otherwise. 456 inline bool exists(const Twine &Path) { 457 return !access(Path, AccessMode::Exist); 458 } 459 460 /// Can we execute this file? 461 /// 462 /// @param Path Input path. 463 /// @returns True if we can execute it, false otherwise. 464 bool can_execute(const Twine &Path); 465 466 /// Can we write this file? 467 /// 468 /// @param Path Input path. 469 /// @returns True if we can write to it, false otherwise. 470 inline bool can_write(const Twine &Path) { 471 return !access(Path, AccessMode::Write); 472 } 473 474 /// Do file_status's represent the same thing? 475 /// 476 /// @param A Input file_status. 477 /// @param B Input file_status. 478 /// 479 /// assert(status_known(A) || status_known(B)); 480 /// 481 /// @returns True if A and B both represent the same file system entity, false 482 /// otherwise. 483 bool equivalent(file_status A, file_status B); 484 485 /// Do paths represent the same thing? 486 /// 487 /// assert(status_known(A) || status_known(B)); 488 /// 489 /// @param A Input path A. 490 /// @param B Input path B. 491 /// @param result Set to true if stat(A) and stat(B) have the same device and 492 /// inode (or equivalent). 493 /// @returns errc::success if result has been successfully set, otherwise a 494 /// platform-specific error_code. 495 std::error_code equivalent(const Twine &A, const Twine &B, bool &result); 496 497 /// Simpler version of equivalent for clients that don't need to 498 /// differentiate between an error and false. 499 inline bool equivalent(const Twine &A, const Twine &B) { 500 bool result; 501 return !equivalent(A, B, result) && result; 502 } 503 504 /// Is the file mounted on a local filesystem? 505 /// 506 /// @param path Input path. 507 /// @param result Set to true if \a path is on fixed media such as a hard disk, 508 /// false if it is not. 509 /// @returns errc::success if result has been successfully set, otherwise a 510 /// platform specific error_code. 511 std::error_code is_local(const Twine &path, bool &result); 512 513 /// Version of is_local accepting an open file descriptor. 514 std::error_code is_local(int FD, bool &result); 515 516 /// Simpler version of is_local for clients that don't need to 517 /// differentiate between an error and false. 518 inline bool is_local(const Twine &Path) { 519 bool Result; 520 return !is_local(Path, Result) && Result; 521 } 522 523 /// Simpler version of is_local accepting an open file descriptor for 524 /// clients that don't need to differentiate between an error and false. 525 inline bool is_local(int FD) { 526 bool Result; 527 return !is_local(FD, Result) && Result; 528 } 529 530 /// Does status represent a directory? 531 /// 532 /// @param Path The path to get the type of. 533 /// @param Follow For symbolic links, indicates whether to return the file type 534 /// of the link itself, or of the target. 535 /// @returns A value from the file_type enumeration indicating the type of file. 536 file_type get_file_type(const Twine &Path, bool Follow = true); 537 538 /// Does status represent a directory? 539 /// 540 /// @param status A basic_file_status previously returned from status. 541 /// @returns status.type() == file_type::directory_file. 542 bool is_directory(const basic_file_status &status); 543 544 /// Is path a directory? 545 /// 546 /// @param path Input path. 547 /// @param result Set to true if \a path is a directory (after following 548 /// symlinks, false if it is not. Undefined otherwise. 549 /// @returns errc::success if result has been successfully set, otherwise a 550 /// platform-specific error_code. 551 std::error_code is_directory(const Twine &path, bool &result); 552 553 /// Simpler version of is_directory for clients that don't need to 554 /// differentiate between an error and false. 555 inline bool is_directory(const Twine &Path) { 556 bool Result; 557 return !is_directory(Path, Result) && Result; 558 } 559 560 /// Does status represent a regular file? 561 /// 562 /// @param status A basic_file_status previously returned from status. 563 /// @returns status_known(status) && status.type() == file_type::regular_file. 564 bool is_regular_file(const basic_file_status &status); 565 566 /// Is path a regular file? 567 /// 568 /// @param path Input path. 569 /// @param result Set to true if \a path is a regular file (after following 570 /// symlinks), false if it is not. Undefined otherwise. 571 /// @returns errc::success if result has been successfully set, otherwise a 572 /// platform-specific error_code. 573 std::error_code is_regular_file(const Twine &path, bool &result); 574 575 /// Simpler version of is_regular_file for clients that don't need to 576 /// differentiate between an error and false. 577 inline bool is_regular_file(const Twine &Path) { 578 bool Result; 579 if (is_regular_file(Path, Result)) 580 return false; 581 return Result; 582 } 583 584 /// Does status represent a symlink file? 585 /// 586 /// @param status A basic_file_status previously returned from status. 587 /// @returns status_known(status) && status.type() == file_type::symlink_file. 588 bool is_symlink_file(const basic_file_status &status); 589 590 /// Is path a symlink file? 591 /// 592 /// @param path Input path. 593 /// @param result Set to true if \a path is a symlink file, false if it is not. 594 /// Undefined otherwise. 595 /// @returns errc::success if result has been successfully set, otherwise a 596 /// platform-specific error_code. 597 std::error_code is_symlink_file(const Twine &path, bool &result); 598 599 /// Simpler version of is_symlink_file for clients that don't need to 600 /// differentiate between an error and false. 601 inline bool is_symlink_file(const Twine &Path) { 602 bool Result; 603 if (is_symlink_file(Path, Result)) 604 return false; 605 return Result; 606 } 607 608 /// Does this status represent something that exists but is not a 609 /// directory or regular file? 610 /// 611 /// @param status A basic_file_status previously returned from status. 612 /// @returns exists(s) && !is_regular_file(s) && !is_directory(s) 613 bool is_other(const basic_file_status &status); 614 615 /// Is path something that exists but is not a directory, 616 /// regular file, or symlink? 617 /// 618 /// @param path Input path. 619 /// @param result Set to true if \a path exists, but is not a directory, regular 620 /// file, or a symlink, false if it does not. Undefined otherwise. 621 /// @returns errc::success if result has been successfully set, otherwise a 622 /// platform-specific error_code. 623 std::error_code is_other(const Twine &path, bool &result); 624 625 /// Get file status as if by POSIX stat(). 626 /// 627 /// @param path Input path. 628 /// @param result Set to the file status. 629 /// @param follow When true, follows symlinks. Otherwise, the symlink itself is 630 /// statted. 631 /// @returns errc::success if result has been successfully set, otherwise a 632 /// platform-specific error_code. 633 std::error_code status(const Twine &path, file_status &result, 634 bool follow = true); 635 636 /// A version for when a file descriptor is already available. 637 std::error_code status(int FD, file_status &Result); 638 639 #ifdef _WIN32 640 /// A version for when a file descriptor is already available. 641 std::error_code status(file_t FD, file_status &Result); 642 #endif 643 644 /// Get file creation mode mask of the process. 645 /// 646 /// @returns Mask reported by umask(2) 647 /// @note There is no umask on Windows. This function returns 0 always 648 /// on Windows. This function does not return an error_code because 649 /// umask(2) never fails. It is not thread safe. 650 unsigned getUmask(); 651 652 /// Set file permissions. 653 /// 654 /// @param Path File to set permissions on. 655 /// @param Permissions New file permissions. 656 /// @returns errc::success if the permissions were successfully set, otherwise 657 /// a platform-specific error_code. 658 /// @note On Windows, all permissions except *_write are ignored. Using any of 659 /// owner_write, group_write, or all_write will make the file writable. 660 /// Otherwise, the file will be marked as read-only. 661 std::error_code setPermissions(const Twine &Path, perms Permissions); 662 663 /// Vesion of setPermissions accepting a file descriptor. 664 /// TODO Delete the path based overload once we implement the FD based overload 665 /// on Windows. 666 std::error_code setPermissions(int FD, perms Permissions); 667 668 /// Get file permissions. 669 /// 670 /// @param Path File to get permissions from. 671 /// @returns the permissions if they were successfully retrieved, otherwise a 672 /// platform-specific error_code. 673 /// @note On Windows, if the file does not have the FILE_ATTRIBUTE_READONLY 674 /// attribute, all_all will be returned. Otherwise, all_read | all_exe 675 /// will be returned. 676 ErrorOr<perms> getPermissions(const Twine &Path); 677 678 /// Get file size. 679 /// 680 /// @param Path Input path. 681 /// @param Result Set to the size of the file in \a Path. 682 /// @returns errc::success if result has been successfully set, otherwise a 683 /// platform-specific error_code. 684 inline std::error_code file_size(const Twine &Path, uint64_t &Result) { 685 file_status Status; 686 std::error_code EC = status(Path, Status); 687 if (EC) 688 return EC; 689 Result = Status.getSize(); 690 return std::error_code(); 691 } 692 693 /// Set the file modification and access time. 694 /// 695 /// @returns errc::success if the file times were successfully set, otherwise a 696 /// platform-specific error_code or errc::function_not_supported on 697 /// platforms where the functionality isn't available. 698 std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, 699 TimePoint<> ModificationTime); 700 701 /// Simpler version that sets both file modification and access time to the same 702 /// time. 703 inline std::error_code setLastAccessAndModificationTime(int FD, 704 TimePoint<> Time) { 705 return setLastAccessAndModificationTime(FD, Time, Time); 706 } 707 708 /// Is status available? 709 /// 710 /// @param s Input file status. 711 /// @returns True if status() != status_error. 712 bool status_known(const basic_file_status &s); 713 714 /// Is status available? 715 /// 716 /// @param path Input path. 717 /// @param result Set to true if status() != status_error. 718 /// @returns errc::success if result has been successfully set, otherwise a 719 /// platform-specific error_code. 720 std::error_code status_known(const Twine &path, bool &result); 721 722 enum CreationDisposition : unsigned { 723 /// CD_CreateAlways - When opening a file: 724 /// * If it already exists, truncate it. 725 /// * If it does not already exist, create a new file. 726 CD_CreateAlways = 0, 727 728 /// CD_CreateNew - When opening a file: 729 /// * If it already exists, fail. 730 /// * If it does not already exist, create a new file. 731 CD_CreateNew = 1, 732 733 /// CD_OpenExisting - When opening a file: 734 /// * If it already exists, open the file with the offset set to 0. 735 /// * If it does not already exist, fail. 736 CD_OpenExisting = 2, 737 738 /// CD_OpenAlways - When opening a file: 739 /// * If it already exists, open the file with the offset set to 0. 740 /// * If it does not already exist, create a new file. 741 CD_OpenAlways = 3, 742 }; 743 744 enum FileAccess : unsigned { 745 FA_Read = 1, 746 FA_Write = 2, 747 }; 748 749 enum OpenFlags : unsigned { 750 OF_None = 0, 751 752 /// The file should be opened in text mode on platforms like z/OS that make 753 /// this distinction. 754 OF_Text = 1, 755 756 /// The file should use a carriage linefeed '\r\n'. This flag should only be 757 /// used with OF_Text. Only makes a difference on Windows. 758 OF_CRLF = 2, 759 760 /// The file should be opened in text mode and use a carriage linefeed '\r\n'. 761 /// This flag has the same functionality as OF_Text on z/OS but adds a 762 /// carriage linefeed on Windows. 763 OF_TextWithCRLF = OF_Text | OF_CRLF, 764 765 /// The file should be opened in append mode. 766 OF_Append = 4, 767 768 /// The returned handle can be used for deleting the file. Only makes a 769 /// difference on windows. 770 OF_Delete = 8, 771 772 /// When a child process is launched, this file should remain open in the 773 /// child process. 774 OF_ChildInherit = 16, 775 776 /// Force files Atime to be updated on access. Only makes a difference on 777 /// Windows. 778 OF_UpdateAtime = 32, 779 }; 780 781 /// Create a potentially unique file name but does not create it. 782 /// 783 /// Generates a unique path suitable for a temporary file but does not 784 /// open or create the file. The name is based on \a Model with '%' 785 /// replaced by a random char in [0-9a-f]. If \a MakeAbsolute is true 786 /// then the system's temp directory is prepended first. If \a MakeAbsolute 787 /// is false the current directory will be used instead. 788 /// 789 /// This function does not check if the file exists. If you want to be sure 790 /// that the file does not yet exist, you should use enough '%' characters 791 /// in your model to ensure this. Each '%' gives 4-bits of entropy so you can 792 /// use 32 of them to get 128 bits of entropy. 793 /// 794 /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 795 /// 796 /// @param Model Name to base unique path off of. 797 /// @param ResultPath Set to the file's path. 798 /// @param MakeAbsolute Whether to use the system temp directory. 799 void createUniquePath(const Twine &Model, SmallVectorImpl<char> &ResultPath, 800 bool MakeAbsolute); 801 802 /// Create a uniquely named file. 803 /// 804 /// Generates a unique path suitable for a temporary file and then opens it as a 805 /// file. The name is based on \a Model with '%' replaced by a random char in 806 /// [0-9a-f]. If \a Model is not an absolute path, the temporary file will be 807 /// created in the current directory. 808 /// 809 /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s 810 /// 811 /// This is an atomic operation. Either the file is created and opened, or the 812 /// file system is left untouched. 813 /// 814 /// The intended use is for files that are to be kept, possibly after 815 /// renaming them. For example, when running 'clang -c foo.o', the file can 816 /// be first created as foo-abc123.o and then renamed. 817 /// 818 /// @param Model Name to base unique path off of. 819 /// @param ResultFD Set to the opened file's file descriptor. 820 /// @param ResultPath Set to the opened file's absolute path. 821 /// @param Flags Set to the opened file's flags. 822 /// @param Mode Set to the opened file's permissions. 823 /// @returns errc::success if Result{FD,Path} have been successfully set, 824 /// otherwise a platform-specific error_code. 825 std::error_code createUniqueFile(const Twine &Model, int &ResultFD, 826 SmallVectorImpl<char> &ResultPath, 827 OpenFlags Flags = OF_None, 828 unsigned Mode = all_read | all_write); 829 830 /// Simpler version for clients that don't want an open file. An empty 831 /// file will still be created. 832 std::error_code createUniqueFile(const Twine &Model, 833 SmallVectorImpl<char> &ResultPath, 834 unsigned Mode = all_read | all_write); 835 836 /// Represents a temporary file. 837 /// 838 /// The temporary file must be eventually discarded or given a final name and 839 /// kept. 840 /// 841 /// The destructor doesn't implicitly discard because there is no way to 842 /// properly handle errors in a destructor. 843 class TempFile { 844 bool Done = false; 845 TempFile(StringRef Name, int FD); 846 847 public: 848 /// This creates a temporary file with createUniqueFile and schedules it for 849 /// deletion with sys::RemoveFileOnSignal. 850 static Expected<TempFile> create(const Twine &Model, 851 unsigned Mode = all_read | all_write, 852 OpenFlags ExtraFlags = OF_None); 853 TempFile(TempFile &&Other); 854 TempFile &operator=(TempFile &&Other); 855 856 // Name of the temporary file. 857 std::string TmpName; 858 859 // The open file descriptor. 860 int FD = -1; 861 862 #ifdef _WIN32 863 // Whether we need to manually remove the file on close. 864 bool RemoveOnClose = false; 865 #endif 866 867 // Keep this with the given name. 868 Error keep(const Twine &Name); 869 870 // Keep this with the temporary name. 871 Error keep(); 872 873 // Delete the file. 874 Error discard(); 875 876 // This checks that keep or delete was called. 877 ~TempFile(); 878 }; 879 880 /// Create a file in the system temporary directory. 881 /// 882 /// The filename is of the form prefix-random_chars.suffix. Since the directory 883 /// is not know to the caller, Prefix and Suffix cannot have path separators. 884 /// The files are created with mode 0600. 885 /// 886 /// This should be used for things like a temporary .s that is removed after 887 /// running the assembler. 888 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 889 int &ResultFD, 890 SmallVectorImpl<char> &ResultPath, 891 OpenFlags Flags = OF_None); 892 893 /// Simpler version for clients that don't want an open file. An empty 894 /// file will still be created. 895 std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, 896 SmallVectorImpl<char> &ResultPath, 897 OpenFlags Flags = OF_None); 898 899 std::error_code createUniqueDirectory(const Twine &Prefix, 900 SmallVectorImpl<char> &ResultPath); 901 902 /// Get a unique name, not currently exisiting in the filesystem. Subject 903 /// to race conditions, prefer to use createUniqueFile instead. 904 /// 905 /// Similar to createUniqueFile, but instead of creating a file only 906 /// checks if it exists. This function is subject to race conditions, if you 907 /// want to use the returned name to actually create a file, use 908 /// createUniqueFile instead. 909 std::error_code getPotentiallyUniqueFileName(const Twine &Model, 910 SmallVectorImpl<char> &ResultPath); 911 912 /// Get a unique temporary file name, not currently exisiting in the 913 /// filesystem. Subject to race conditions, prefer to use createTemporaryFile 914 /// instead. 915 /// 916 /// Similar to createTemporaryFile, but instead of creating a file only 917 /// checks if it exists. This function is subject to race conditions, if you 918 /// want to use the returned name to actually create a file, use 919 /// createTemporaryFile instead. 920 std::error_code 921 getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix, 922 SmallVectorImpl<char> &ResultPath); 923 924 inline OpenFlags operator|(OpenFlags A, OpenFlags B) { 925 return OpenFlags(unsigned(A) | unsigned(B)); 926 } 927 928 inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { 929 A = A | B; 930 return A; 931 } 932 933 inline FileAccess operator|(FileAccess A, FileAccess B) { 934 return FileAccess(unsigned(A) | unsigned(B)); 935 } 936 937 inline FileAccess &operator|=(FileAccess &A, FileAccess B) { 938 A = A | B; 939 return A; 940 } 941 942 /// @brief Opens a file with the specified creation disposition, access mode, 943 /// and flags and returns a file descriptor. 944 /// 945 /// The caller is responsible for closing the file descriptor once they are 946 /// finished with it. 947 /// 948 /// @param Name The path of the file to open, relative or absolute. 949 /// @param ResultFD If the file could be opened successfully, its descriptor 950 /// is stored in this location. Otherwise, this is set to -1. 951 /// @param Disp Value specifying the existing-file behavior. 952 /// @param Access Value specifying whether to open the file in read, write, or 953 /// read-write mode. 954 /// @param Flags Additional flags. 955 /// @param Mode The access permissions of the file, represented in octal. 956 /// @returns errc::success if \a Name has been opened, otherwise a 957 /// platform-specific error_code. 958 std::error_code openFile(const Twine &Name, int &ResultFD, 959 CreationDisposition Disp, FileAccess Access, 960 OpenFlags Flags, unsigned Mode = 0666); 961 962 /// @brief Opens a file with the specified creation disposition, access mode, 963 /// and flags and returns a platform-specific file object. 964 /// 965 /// The caller is responsible for closing the file object once they are 966 /// finished with it. 967 /// 968 /// @param Name The path of the file to open, relative or absolute. 969 /// @param Disp Value specifying the existing-file behavior. 970 /// @param Access Value specifying whether to open the file in read, write, or 971 /// read-write mode. 972 /// @param Flags Additional flags. 973 /// @param Mode The access permissions of the file, represented in octal. 974 /// @returns errc::success if \a Name has been opened, otherwise a 975 /// platform-specific error_code. 976 Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp, 977 FileAccess Access, OpenFlags Flags, 978 unsigned Mode = 0666); 979 980 /// Converts from a Posix file descriptor number to a native file handle. 981 /// On Windows, this retreives the underlying handle. On non-Windows, this is a 982 /// no-op. 983 file_t convertFDToNativeFile(int FD); 984 985 #ifndef _WIN32 986 inline file_t convertFDToNativeFile(int FD) { return FD; } 987 #endif 988 989 /// Return an open handle to standard in. On Unix, this is typically FD 0. 990 /// Returns kInvalidFile when the stream is closed. 991 file_t getStdinHandle(); 992 993 /// Return an open handle to standard out. On Unix, this is typically FD 1. 994 /// Returns kInvalidFile when the stream is closed. 995 file_t getStdoutHandle(); 996 997 /// Return an open handle to standard error. On Unix, this is typically FD 2. 998 /// Returns kInvalidFile when the stream is closed. 999 file_t getStderrHandle(); 1000 1001 /// Reads \p Buf.size() bytes from \p FileHandle into \p Buf. Returns the number 1002 /// of bytes actually read. On Unix, this is equivalent to `return ::read(FD, 1003 /// Buf.data(), Buf.size())`, with error reporting. Returns 0 when reaching EOF. 1004 /// 1005 /// @param FileHandle File to read from. 1006 /// @param Buf Buffer to read into. 1007 /// @returns The number of bytes read, or error. 1008 Expected<size_t> readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf); 1009 1010 /// Default chunk size for \a readNativeFileToEOF(). 1011 enum : size_t { DefaultReadChunkSize = 4 * 4096 }; 1012 1013 /// Reads from \p FileHandle until EOF, appending to \p Buffer in chunks of 1014 /// size \p ChunkSize. 1015 /// 1016 /// This calls \a readNativeFile() in a loop. On Error, previous chunks that 1017 /// were read successfully are left in \p Buffer and returned. 1018 /// 1019 /// Note: For reading the final chunk at EOF, \p Buffer's capacity needs extra 1020 /// storage of \p ChunkSize. 1021 /// 1022 /// \param FileHandle File to read from. 1023 /// \param Buffer Where to put the file content. 1024 /// \param ChunkSize Size of chunks. 1025 /// \returns The error if EOF was not found. 1026 Error readNativeFileToEOF(file_t FileHandle, SmallVectorImpl<char> &Buffer, 1027 ssize_t ChunkSize = DefaultReadChunkSize); 1028 1029 /// Reads \p Buf.size() bytes from \p FileHandle at offset \p Offset into \p 1030 /// Buf. If 'pread' is available, this will use that, otherwise it will use 1031 /// 'lseek'. Returns the number of bytes actually read. Returns 0 when reaching 1032 /// EOF. 1033 /// 1034 /// @param FileHandle File to read from. 1035 /// @param Buf Buffer to read into. 1036 /// @param Offset Offset into the file at which the read should occur. 1037 /// @returns The number of bytes read, or error. 1038 Expected<size_t> readNativeFileSlice(file_t FileHandle, 1039 MutableArrayRef<char> Buf, 1040 uint64_t Offset); 1041 1042 /// @brief Opens the file with the given name in a write-only or read-write 1043 /// mode, returning its open file descriptor. If the file does not exist, it 1044 /// is created. 1045 /// 1046 /// The caller is responsible for closing the file descriptor once they are 1047 /// finished with it. 1048 /// 1049 /// @param Name The path of the file to open, relative or absolute. 1050 /// @param ResultFD If the file could be opened successfully, its descriptor 1051 /// is stored in this location. Otherwise, this is set to -1. 1052 /// @param Flags Additional flags used to determine whether the file should be 1053 /// opened in, for example, read-write or in write-only mode. 1054 /// @param Mode The access permissions of the file, represented in octal. 1055 /// @returns errc::success if \a Name has been opened, otherwise a 1056 /// platform-specific error_code. 1057 inline std::error_code 1058 openFileForWrite(const Twine &Name, int &ResultFD, 1059 CreationDisposition Disp = CD_CreateAlways, 1060 OpenFlags Flags = OF_None, unsigned Mode = 0666) { 1061 return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode); 1062 } 1063 1064 /// @brief Opens the file with the given name in a write-only or read-write 1065 /// mode, returning its open file descriptor. If the file does not exist, it 1066 /// is created. 1067 /// 1068 /// The caller is responsible for closing the freeing the file once they are 1069 /// finished with it. 1070 /// 1071 /// @param Name The path of the file to open, relative or absolute. 1072 /// @param Flags Additional flags used to determine whether the file should be 1073 /// opened in, for example, read-write or in write-only mode. 1074 /// @param Mode The access permissions of the file, represented in octal. 1075 /// @returns a platform-specific file descriptor if \a Name has been opened, 1076 /// otherwise an error object. 1077 inline Expected<file_t> openNativeFileForWrite(const Twine &Name, 1078 CreationDisposition Disp, 1079 OpenFlags Flags, 1080 unsigned Mode = 0666) { 1081 return openNativeFile(Name, Disp, FA_Write, Flags, Mode); 1082 } 1083 1084 /// @brief Opens the file with the given name in a write-only or read-write 1085 /// mode, returning its open file descriptor. If the file does not exist, it 1086 /// is created. 1087 /// 1088 /// The caller is responsible for closing the file descriptor once they are 1089 /// finished with it. 1090 /// 1091 /// @param Name The path of the file to open, relative or absolute. 1092 /// @param ResultFD If the file could be opened successfully, its descriptor 1093 /// is stored in this location. Otherwise, this is set to -1. 1094 /// @param Flags Additional flags used to determine whether the file should be 1095 /// opened in, for example, read-write or in write-only mode. 1096 /// @param Mode The access permissions of the file, represented in octal. 1097 /// @returns errc::success if \a Name has been opened, otherwise a 1098 /// platform-specific error_code. 1099 inline std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD, 1100 CreationDisposition Disp, 1101 OpenFlags Flags, 1102 unsigned Mode = 0666) { 1103 return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode); 1104 } 1105 1106 /// @brief Opens the file with the given name in a write-only or read-write 1107 /// mode, returning its open file descriptor. If the file does not exist, it 1108 /// is created. 1109 /// 1110 /// The caller is responsible for closing the freeing the file once they are 1111 /// finished with it. 1112 /// 1113 /// @param Name The path of the file to open, relative or absolute. 1114 /// @param Flags Additional flags used to determine whether the file should be 1115 /// opened in, for example, read-write or in write-only mode. 1116 /// @param Mode The access permissions of the file, represented in octal. 1117 /// @returns a platform-specific file descriptor if \a Name has been opened, 1118 /// otherwise an error object. 1119 inline Expected<file_t> openNativeFileForReadWrite(const Twine &Name, 1120 CreationDisposition Disp, 1121 OpenFlags Flags, 1122 unsigned Mode = 0666) { 1123 return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode); 1124 } 1125 1126 /// @brief Opens the file with the given name in a read-only mode, returning 1127 /// its open file descriptor. 1128 /// 1129 /// The caller is responsible for closing the file descriptor once they are 1130 /// finished with it. 1131 /// 1132 /// @param Name The path of the file to open, relative or absolute. 1133 /// @param ResultFD If the file could be opened successfully, its descriptor 1134 /// is stored in this location. Otherwise, this is set to -1. 1135 /// @param RealPath If nonnull, extra work is done to determine the real path 1136 /// of the opened file, and that path is stored in this 1137 /// location. 1138 /// @returns errc::success if \a Name has been opened, otherwise a 1139 /// platform-specific error_code. 1140 std::error_code openFileForRead(const Twine &Name, int &ResultFD, 1141 OpenFlags Flags = OF_None, 1142 SmallVectorImpl<char> *RealPath = nullptr); 1143 1144 /// @brief Opens the file with the given name in a read-only mode, returning 1145 /// its open file descriptor. 1146 /// 1147 /// The caller is responsible for closing the freeing the file once they are 1148 /// finished with it. 1149 /// 1150 /// @param Name The path of the file to open, relative or absolute. 1151 /// @param RealPath If nonnull, extra work is done to determine the real path 1152 /// of the opened file, and that path is stored in this 1153 /// location. 1154 /// @returns a platform-specific file descriptor if \a Name has been opened, 1155 /// otherwise an error object. 1156 Expected<file_t> 1157 openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None, 1158 SmallVectorImpl<char> *RealPath = nullptr); 1159 1160 /// Try to locks the file during the specified time. 1161 /// 1162 /// This function implements advisory locking on entire file. If it returns 1163 /// <em>errc::success</em>, the file is locked by the calling process. Until the 1164 /// process unlocks the file by calling \a unlockFile, all attempts to lock the 1165 /// same file will fail/block. The process that locked the file may assume that 1166 /// none of other processes read or write this file, provided that all processes 1167 /// lock the file prior to accessing its content. 1168 /// 1169 /// @param FD The descriptor representing the file to lock. 1170 /// @param Timeout Time in milliseconds that the process should wait before 1171 /// reporting lock failure. Zero value means try to get lock only 1172 /// once. 1173 /// @returns errc::success if lock is successfully obtained, 1174 /// errc::no_lock_available if the file cannot be locked, or platform-specific 1175 /// error_code otherwise. 1176 /// 1177 /// @note Care should be taken when using this function in a multithreaded 1178 /// context, as it may not prevent other threads in the same process from 1179 /// obtaining a lock on the same file, even if they are using a different file 1180 /// descriptor. 1181 std::error_code 1182 tryLockFile(int FD, 1183 std::chrono::milliseconds Timeout = std::chrono::milliseconds(0)); 1184 1185 /// Lock the file. 1186 /// 1187 /// This function acts as @ref tryLockFile but it waits infinitely. 1188 std::error_code lockFile(int FD); 1189 1190 /// Unlock the file. 1191 /// 1192 /// @param FD The descriptor representing the file to unlock. 1193 /// @returns errc::success if lock is successfully released or platform-specific 1194 /// error_code otherwise. 1195 std::error_code unlockFile(int FD); 1196 1197 /// @brief Close the file object. This should be used instead of ::close for 1198 /// portability. On error, the caller should assume the file is closed, as is 1199 /// the case for Process::SafelyCloseFileDescriptor 1200 /// 1201 /// @param F On input, this is the file to close. On output, the file is 1202 /// set to kInvalidFile. 1203 /// 1204 /// @returns An error code if closing the file failed. Typically, an error here 1205 /// means that the filesystem may have failed to perform some buffered writes. 1206 std::error_code closeFile(file_t &F); 1207 1208 #ifdef LLVM_ON_UNIX 1209 /// @brief Change ownership of a file. 1210 /// 1211 /// @param Owner The owner of the file to change to. 1212 /// @param Group The group of the file to change to. 1213 /// @returns errc::success if successfully updated file ownership, otherwise an 1214 /// error code is returned. 1215 std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group); 1216 #endif 1217 1218 /// RAII class that facilitates file locking. 1219 class FileLocker { 1220 int FD; ///< Locked file handle. 1221 FileLocker(int FD) : FD(FD) {} 1222 friend class llvm::raw_fd_ostream; 1223 1224 public: 1225 FileLocker(const FileLocker &L) = delete; 1226 FileLocker(FileLocker &&L) : FD(L.FD) { L.FD = -1; } 1227 ~FileLocker() { 1228 if (FD != -1) 1229 unlockFile(FD); 1230 } 1231 FileLocker &operator=(FileLocker &&L) { 1232 FD = L.FD; 1233 L.FD = -1; 1234 return *this; 1235 } 1236 FileLocker &operator=(const FileLocker &L) = delete; 1237 std::error_code unlock() { 1238 if (FD != -1) { 1239 std::error_code Result = unlockFile(FD); 1240 FD = -1; 1241 return Result; 1242 } 1243 return std::error_code(); 1244 } 1245 }; 1246 1247 std::error_code getUniqueID(const Twine Path, UniqueID &Result); 1248 1249 /// Get disk space usage information. 1250 /// 1251 /// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug. 1252 /// Note: Windows reports results according to the quota allocated to the user. 1253 /// 1254 /// @param Path Input path. 1255 /// @returns a space_info structure filled with the capacity, free, and 1256 /// available space on the device \a Path is on. A platform specific error_code 1257 /// is returned on error. 1258 ErrorOr<space_info> disk_space(const Twine &Path); 1259 1260 /// This class represents a memory mapped file. It is based on 1261 /// boost::iostreams::mapped_file. 1262 class mapped_file_region { 1263 public: 1264 enum mapmode { 1265 readonly, ///< May only access map via const_data as read only. 1266 readwrite, ///< May access map via data and modify it. Written to path. 1267 priv ///< May modify via data, but changes are lost on destruction. 1268 }; 1269 1270 private: 1271 /// Platform-specific mapping state. 1272 size_t Size = 0; 1273 void *Mapping = nullptr; 1274 #ifdef _WIN32 1275 sys::fs::file_t FileHandle = nullptr; 1276 #endif 1277 mapmode Mode = readonly; 1278 1279 void copyFrom(const mapped_file_region &Copied) { 1280 Size = Copied.Size; 1281 Mapping = Copied.Mapping; 1282 #ifdef _WIN32 1283 FileHandle = Copied.FileHandle; 1284 #endif 1285 Mode = Copied.Mode; 1286 } 1287 1288 void moveFromImpl(mapped_file_region &Moved) { 1289 copyFrom(Moved); 1290 Moved.copyFrom(mapped_file_region()); 1291 } 1292 1293 void unmapImpl(); 1294 void dontNeedImpl(); 1295 1296 std::error_code init(sys::fs::file_t FD, uint64_t Offset, mapmode Mode); 1297 1298 public: 1299 mapped_file_region() = default; 1300 mapped_file_region(mapped_file_region &&Moved) { moveFromImpl(Moved); } 1301 mapped_file_region &operator=(mapped_file_region &&Moved) { 1302 unmap(); 1303 moveFromImpl(Moved); 1304 return *this; 1305 } 1306 1307 mapped_file_region(const mapped_file_region &) = delete; 1308 mapped_file_region &operator=(const mapped_file_region &) = delete; 1309 1310 /// \param fd An open file descriptor to map. Does not take ownership of fd. 1311 mapped_file_region(sys::fs::file_t fd, mapmode mode, size_t length, uint64_t offset, 1312 std::error_code &ec); 1313 1314 ~mapped_file_region() { unmapImpl(); } 1315 1316 /// Check if this is a valid mapping. 1317 explicit operator bool() const { return Mapping; } 1318 1319 /// Unmap. 1320 void unmap() { 1321 unmapImpl(); 1322 copyFrom(mapped_file_region()); 1323 } 1324 void dontNeed() { dontNeedImpl(); } 1325 1326 size_t size() const; 1327 char *data() const; 1328 1329 /// Get a const view of the data. Modifying this memory has undefined 1330 /// behavior. 1331 const char *const_data() const; 1332 1333 /// \returns The minimum alignment offset must be. 1334 static int alignment(); 1335 }; 1336 1337 /// Return the path to the main executable, given the value of argv[0] from 1338 /// program startup and the address of main itself. In extremis, this function 1339 /// may fail and return an empty path. 1340 std::string getMainExecutable(const char *argv0, void *MainExecAddr); 1341 1342 /// @} 1343 /// @name Iterators 1344 /// @{ 1345 1346 /// directory_entry - A single entry in a directory. 1347 class directory_entry { 1348 // FIXME: different platforms make different information available "for free" 1349 // when traversing a directory. The design of this class wraps most of the 1350 // information in basic_file_status, so on platforms where we can't populate 1351 // that whole structure, callers end up paying for a stat(). 1352 // std::filesystem::directory_entry may be a better model. 1353 std::string Path; 1354 file_type Type = file_type::type_unknown; // Most platforms can provide this. 1355 bool FollowSymlinks = true; // Affects the behavior of status(). 1356 basic_file_status Status; // If available. 1357 1358 public: 1359 explicit directory_entry(const Twine &Path, bool FollowSymlinks = true, 1360 file_type Type = file_type::type_unknown, 1361 basic_file_status Status = basic_file_status()) 1362 : Path(Path.str()), Type(Type), FollowSymlinks(FollowSymlinks), 1363 Status(Status) {} 1364 1365 directory_entry() = default; 1366 1367 void replace_filename(const Twine &Filename, file_type Type, 1368 basic_file_status Status = basic_file_status()); 1369 1370 const std::string &path() const { return Path; } 1371 // Get basic information about entry file (a subset of fs::status()). 1372 // On most platforms this is a stat() call. 1373 // On windows the information was already retrieved from the directory. 1374 ErrorOr<basic_file_status> status() const; 1375 // Get the type of this file. 1376 // On most platforms (Linux/Mac/Windows/BSD), this was already retrieved. 1377 // On some platforms (e.g. Solaris) this is a stat() call. 1378 file_type type() const { 1379 if (Type != file_type::type_unknown) 1380 return Type; 1381 auto S = status(); 1382 return S ? S->type() : file_type::type_unknown; 1383 } 1384 1385 bool operator==(const directory_entry& RHS) const { return Path == RHS.Path; } 1386 bool operator!=(const directory_entry& RHS) const { return !(*this == RHS); } 1387 bool operator< (const directory_entry& RHS) const; 1388 bool operator<=(const directory_entry& RHS) const; 1389 bool operator> (const directory_entry& RHS) const; 1390 bool operator>=(const directory_entry& RHS) const; 1391 }; 1392 1393 namespace detail { 1394 1395 struct DirIterState; 1396 1397 std::error_code directory_iterator_construct(DirIterState &, StringRef, bool); 1398 std::error_code directory_iterator_increment(DirIterState &); 1399 std::error_code directory_iterator_destruct(DirIterState &); 1400 1401 /// Keeps state for the directory_iterator. 1402 struct DirIterState { 1403 ~DirIterState() { 1404 directory_iterator_destruct(*this); 1405 } 1406 1407 intptr_t IterationHandle = 0; 1408 directory_entry CurrentEntry; 1409 }; 1410 1411 } // end namespace detail 1412 1413 /// directory_iterator - Iterates through the entries in path. There is no 1414 /// operator++ because we need an error_code. If it's really needed we can make 1415 /// it call report_fatal_error on error. 1416 class directory_iterator { 1417 std::shared_ptr<detail::DirIterState> State; 1418 bool FollowSymlinks = true; 1419 1420 public: 1421 explicit directory_iterator(const Twine &path, std::error_code &ec, 1422 bool follow_symlinks = true) 1423 : FollowSymlinks(follow_symlinks) { 1424 State = std::make_shared<detail::DirIterState>(); 1425 SmallString<128> path_storage; 1426 ec = detail::directory_iterator_construct( 1427 *State, path.toStringRef(path_storage), FollowSymlinks); 1428 } 1429 1430 explicit directory_iterator(const directory_entry &de, std::error_code &ec, 1431 bool follow_symlinks = true) 1432 : FollowSymlinks(follow_symlinks) { 1433 State = std::make_shared<detail::DirIterState>(); 1434 ec = detail::directory_iterator_construct( 1435 *State, de.path(), FollowSymlinks); 1436 } 1437 1438 /// Construct end iterator. 1439 directory_iterator() = default; 1440 1441 // No operator++ because we need error_code. 1442 directory_iterator &increment(std::error_code &ec) { 1443 ec = directory_iterator_increment(*State); 1444 return *this; 1445 } 1446 1447 const directory_entry &operator*() const { return State->CurrentEntry; } 1448 const directory_entry *operator->() const { return &State->CurrentEntry; } 1449 1450 bool operator==(const directory_iterator &RHS) const { 1451 if (State == RHS.State) 1452 return true; 1453 if (!RHS.State) 1454 return State->CurrentEntry == directory_entry(); 1455 if (!State) 1456 return RHS.State->CurrentEntry == directory_entry(); 1457 return State->CurrentEntry == RHS.State->CurrentEntry; 1458 } 1459 1460 bool operator!=(const directory_iterator &RHS) const { 1461 return !(*this == RHS); 1462 } 1463 }; 1464 1465 namespace detail { 1466 1467 /// Keeps state for the recursive_directory_iterator. 1468 struct RecDirIterState { 1469 std::vector<directory_iterator> Stack; 1470 uint16_t Level = 0; 1471 bool HasNoPushRequest = false; 1472 }; 1473 1474 } // end namespace detail 1475 1476 /// recursive_directory_iterator - Same as directory_iterator except for it 1477 /// recurses down into child directories. 1478 class recursive_directory_iterator { 1479 std::shared_ptr<detail::RecDirIterState> State; 1480 bool Follow; 1481 1482 public: 1483 recursive_directory_iterator() = default; 1484 explicit recursive_directory_iterator(const Twine &path, std::error_code &ec, 1485 bool follow_symlinks = true) 1486 : State(std::make_shared<detail::RecDirIterState>()), 1487 Follow(follow_symlinks) { 1488 State->Stack.push_back(directory_iterator(path, ec, Follow)); 1489 if (State->Stack.back() == directory_iterator()) 1490 State.reset(); 1491 } 1492 1493 // No operator++ because we need error_code. 1494 recursive_directory_iterator &increment(std::error_code &ec) { 1495 const directory_iterator end_itr = {}; 1496 1497 if (State->HasNoPushRequest) 1498 State->HasNoPushRequest = false; 1499 else { 1500 file_type type = State->Stack.back()->type(); 1501 if (type == file_type::symlink_file && Follow) { 1502 // Resolve the symlink: is it a directory to recurse into? 1503 ErrorOr<basic_file_status> status = State->Stack.back()->status(); 1504 if (status) 1505 type = status->type(); 1506 // Otherwise broken symlink, and we'll continue. 1507 } 1508 if (type == file_type::directory_file) { 1509 State->Stack.push_back( 1510 directory_iterator(*State->Stack.back(), ec, Follow)); 1511 if (State->Stack.back() != end_itr) { 1512 ++State->Level; 1513 return *this; 1514 } 1515 State->Stack.pop_back(); 1516 } 1517 } 1518 1519 while (!State->Stack.empty() 1520 && State->Stack.back().increment(ec) == end_itr) { 1521 State->Stack.pop_back(); 1522 --State->Level; 1523 } 1524 1525 // Check if we are done. If so, create an end iterator. 1526 if (State->Stack.empty()) 1527 State.reset(); 1528 1529 return *this; 1530 } 1531 1532 const directory_entry &operator*() const { return *State->Stack.back(); } 1533 const directory_entry *operator->() const { return &*State->Stack.back(); } 1534 1535 // observers 1536 /// Gets the current level. Starting path is at level 0. 1537 int level() const { return State->Level; } 1538 1539 /// Returns true if no_push has been called for this directory_entry. 1540 bool no_push_request() const { return State->HasNoPushRequest; } 1541 1542 // modifiers 1543 /// Goes up one level if Level > 0. 1544 void pop() { 1545 assert(State && "Cannot pop an end iterator!"); 1546 assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 1547 1548 const directory_iterator end_itr = {}; 1549 std::error_code ec; 1550 do { 1551 if (ec) 1552 report_fatal_error("Error incrementing directory iterator."); 1553 State->Stack.pop_back(); 1554 --State->Level; 1555 } while (!State->Stack.empty() 1556 && State->Stack.back().increment(ec) == end_itr); 1557 1558 // Check if we are done. If so, create an end iterator. 1559 if (State->Stack.empty()) 1560 State.reset(); 1561 } 1562 1563 /// Does not go down into the current directory_entry. 1564 void no_push() { State->HasNoPushRequest = true; } 1565 1566 bool operator==(const recursive_directory_iterator &RHS) const { 1567 return State == RHS.State; 1568 } 1569 1570 bool operator!=(const recursive_directory_iterator &RHS) const { 1571 return !(*this == RHS); 1572 } 1573 }; 1574 1575 /// @} 1576 1577 } // end namespace fs 1578 } // end namespace sys 1579 } // end namespace llvm 1580 1581 #endif // LLVM_SUPPORT_FILESYSTEM_H 1582