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