FileSystem.h revision 218885
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_FILE_SYSTEM_H 28#define LLVM_SUPPORT_FILE_SYSTEM_H 29 30#include "llvm/ADT/SmallString.h" 31#include "llvm/ADT/Twine.h" 32#include "llvm/Support/DataTypes.h" 33#include "llvm/Support/PathV1.h" 34#include "llvm/Support/system_error.h" 35#include <ctime> 36#include <iterator> 37#include <string> 38 39namespace llvm { 40namespace sys { 41namespace fs { 42 43/// file_type - An "enum class" enumeration for the file system's view of the 44/// type. 45struct file_type { 46 enum _ { 47 status_error, 48 file_not_found, 49 regular_file, 50 directory_file, 51 symlink_file, 52 block_file, 53 character_file, 54 fifo_file, 55 socket_file, 56 type_unknown 57 }; 58 59 file_type(_ v) : v_(v) {} 60 explicit file_type(int v) : v_(_(v)) {} 61 operator int() const {return v_;} 62 63private: 64 int v_; 65}; 66 67/// copy_option - An "enum class" enumeration of copy semantics for copy 68/// operations. 69struct copy_option { 70 enum _ { 71 fail_if_exists, 72 overwrite_if_exists 73 }; 74 75 copy_option(_ v) : v_(v) {} 76 explicit copy_option(int v) : v_(_(v)) {} 77 operator int() const {return v_;} 78 79private: 80 int v_; 81}; 82 83/// space_info - Self explanatory. 84struct space_info { 85 uint64_t capacity; 86 uint64_t free; 87 uint64_t available; 88}; 89 90/// file_status - Represents the result of a call to stat and friends. It has 91/// a platform specific member to store the result. 92class file_status 93{ 94 // implementation defined status field. 95 file_type Type; 96public: 97 explicit file_status(file_type v=file_type::status_error) 98 : Type(v) {} 99 100 file_type type() const { return Type; } 101 void type(file_type v) { Type = v; } 102}; 103 104/// @} 105/// @name Physical Operators 106/// @{ 107 108/// @brief Make \a path an absolute path. 109/// 110/// Makes \a path absolute using the current directory if it is not already. An 111/// empty \a path will result in the current directory. 112/// 113/// /absolute/path => /absolute/path 114/// relative/../path => <current-directory>/relative/../path 115/// 116/// @param path A path that is modified to be an absolute path. 117/// @returns errc::success if \a path has been made absolute, otherwise a 118/// platform specific error_code. 119error_code make_absolute(SmallVectorImpl<char> &path); 120 121/// @brief Copy the file at \a from to the path \a to. 122/// 123/// @param from The path to copy the file from. 124/// @param to The path to copy the file to. 125/// @param copt Behavior if \a to already exists. 126/// @returns errc::success if the file has been successfully copied. 127/// errc::file_exists if \a to already exists and \a copt == 128/// copy_option::fail_if_exists. Otherwise a platform specific 129/// error_code. 130error_code copy_file(const Twine &from, const Twine &to, 131 copy_option copt = copy_option::fail_if_exists); 132 133/// @brief Create all the non-existent directories in path. 134/// 135/// @param path Directories to create. 136/// @param existed Set to true if \a path already existed, false otherwise. 137/// @returns errc::success if is_directory(path) and existed have been set, 138/// otherwise a platform specific error_code. 139error_code create_directories(const Twine &path, bool &existed); 140 141/// @brief Create the directory in path. 142/// 143/// @param path Directory to create. 144/// @param existed Set to true if \a path already existed, false otherwise. 145/// @returns errc::success if is_directory(path) and existed have been set, 146/// otherwise a platform specific error_code. 147error_code create_directory(const Twine &path, bool &existed); 148 149/// @brief Create a hard link from \a from to \a to. 150/// 151/// @param to The path to hard link to. 152/// @param from The path to hard link from. This is created. 153/// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) 154/// , otherwise a platform specific error_code. 155error_code create_hard_link(const Twine &to, const Twine &from); 156 157/// @brief Create a symbolic link from \a from to \a to. 158/// 159/// @param to The path to symbolically link to. 160/// @param from The path to symbolically link from. This is created. 161/// @returns errc::success if exists(to) && exists(from) && is_symlink(from), 162/// otherwise a platform specific error_code. 163error_code create_symlink(const Twine &to, const Twine &from); 164 165/// @brief Get the current path. 166/// 167/// @param result Holds the current path on return. 168/// @results errc::success if the current path has been stored in result, 169/// otherwise a platform specific error_code. 170error_code current_path(SmallVectorImpl<char> &result); 171 172/// @brief Remove path. Equivalent to POSIX remove(). 173/// 174/// @param path Input path. 175/// @param existed Set to true if \a path existed, false if it did not. 176/// undefined otherwise. 177/// @results errc::success if path has been removed and existed has been 178/// successfully set, otherwise a platform specific error_code. 179error_code remove(const Twine &path, bool &existed); 180 181/// @brief Recursively remove all files below \a path, then \a path. Files are 182/// removed as if by POSIX remove(). 183/// 184/// @param path Input path. 185/// @param num_removed Number of files removed. 186/// @results errc::success if path has been removed and num_removed has been 187/// successfully set, otherwise a platform specific error_code. 188error_code remove_all(const Twine &path, uint32_t &num_removed); 189 190/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). 191/// 192/// @param from The path to rename from. 193/// @param to The path to rename to. This is created. 194error_code rename(const Twine &from, const Twine &to); 195 196/// @brief Resize path to size. File is resized as if by POSIX truncate(). 197/// 198/// @param path Input path. 199/// @param size Size to resize to. 200/// @returns errc::success if \a path has been resized to \a size, otherwise a 201/// platform specific error_code. 202error_code resize_file(const Twine &path, uint64_t size); 203 204/// @brief Make file readable. 205/// 206/// @param path Input path. 207/// @param value If true, make readable, else, make unreadable. 208/// @results errc::success if readability has been successfully set, otherwise a 209/// platform specific error_code. 210error_code set_read(const Twine &path, bool value); 211 212/// @brief Make file writeable. 213/// 214/// @param path Input path. 215/// @param value If true, make writeable, else, make unwriteable. 216/// @results errc::success if writeability has been successfully set, otherwise 217/// a platform specific error_code. 218error_code set_write(const Twine &path, bool value); 219 220/// @brief Make file executable. 221/// 222/// @param path Input path. 223/// @param value If true, make executable, else, make unexecutable. 224/// @results errc::success if executability has been successfully set, otherwise 225/// a platform specific error_code. 226error_code set_execute(const Twine &path, bool value); 227 228/// @} 229/// @name Physical Observers 230/// @{ 231 232/// @brief Does file exist? 233/// 234/// @param status A file_status previously returned from stat. 235/// @results True if the file represented by status exists, false if it does 236/// not. 237bool exists(file_status status); 238 239/// @brief Does file exist? 240/// 241/// @param path Input path. 242/// @param result Set to true if the file represented by status exists, false if 243/// it does not. Undefined otherwise. 244/// @results errc::success if result has been successfully set, otherwise a 245/// platform specific error_code. 246error_code exists(const Twine &path, bool &result); 247 248/// @brief Do file_status's represent the same thing? 249/// 250/// @param A Input file_status. 251/// @param B Input file_status. 252/// 253/// assert(status_known(A) || status_known(B)); 254/// 255/// @results True if A and B both represent the same file system entity, false 256/// otherwise. 257bool equivalent(file_status A, file_status B); 258 259/// @brief Do paths represent the same thing? 260/// 261/// @param A Input path A. 262/// @param B Input path B. 263/// @param result Set to true if stat(A) and stat(B) have the same device and 264/// inode (or equivalent). 265/// @results errc::success if result has been successfully set, otherwise a 266/// platform specific error_code. 267error_code equivalent(const Twine &A, const Twine &B, bool &result); 268 269/// @brief Get file size. 270/// 271/// @param path Input path. 272/// @param result Set to the size of the file in \a path. 273/// @returns errc::success if result has been successfully set, otherwise a 274/// platform specific error_code. 275error_code file_size(const Twine &path, uint64_t &result); 276 277/// @brief Does status represent a directory? 278/// 279/// @param status A file_status previously returned from status. 280/// @results status.type() == file_type::directory_file. 281bool is_directory(file_status status); 282 283/// @brief Is path a directory? 284/// 285/// @param path Input path. 286/// @param result Set to true if \a path is a directory, false if it is not. 287/// Undefined otherwise. 288/// @results errc::success if result has been successfully set, otherwise a 289/// platform specific error_code. 290error_code is_directory(const Twine &path, bool &result); 291 292/// @brief Is path an empty file? 293/// 294/// @param path Input path. 295/// @param result Set to true if \a path is a an empty file, false if it is not. 296/// Undefined otherwise. 297/// @results errc::success if result has been successfully set, otherwise a 298/// platform specific error_code. 299error_code is_empty(const Twine &path, bool &result); 300 301/// @brief Does status represent a regular file? 302/// 303/// @param status A file_status previously returned from status. 304/// @results status_known(status) && status.type() == file_type::regular_file. 305bool is_regular_file(file_status status); 306 307/// @brief Is path a regular file? 308/// 309/// @param path Input path. 310/// @param result Set to true if \a path is a regular file, false if it is not. 311/// Undefined otherwise. 312/// @results errc::success if result has been successfully set, otherwise a 313/// platform specific error_code. 314error_code is_regular_file(const Twine &path, bool &result); 315 316/// @brief Does this status represent something that exists but is not a 317/// directory, regular file, or symlink? 318/// 319/// @param status A file_status previously returned from status. 320/// @results exists(s) && !is_regular_file(s) && !is_directory(s) && 321/// !is_symlink(s) 322bool is_other(file_status status); 323 324/// @brief Is path something that exists but is not a directory, 325/// regular file, or symlink? 326/// 327/// @param path Input path. 328/// @param result Set to true if \a path exists, but is not a directory, regular 329/// file, or a symlink, false if it does not. Undefined otherwise. 330/// @results errc::success if result has been successfully set, otherwise a 331/// platform specific error_code. 332error_code is_other(const Twine &path, bool &result); 333 334/// @brief Does status represent a symlink? 335/// 336/// @param status A file_status previously returned from stat. 337/// @param result status.type() == symlink_file. 338bool is_symlink(file_status status); 339 340/// @brief Is path a symlink? 341/// 342/// @param path Input path. 343/// @param result Set to true if \a path is a symlink, false if it is not. 344/// Undefined otherwise. 345/// @results errc::success if result has been successfully set, otherwise a 346/// platform specific error_code. 347error_code is_symlink(const Twine &path, bool &result); 348 349/// @brief Get last write time without changing it. 350/// 351/// @param path Input path. 352/// @param result Set to the last write time (UNIX time) of \a path if it 353/// exists. 354/// @results errc::success if result has been successfully set, otherwise a 355/// platform specific error_code. 356error_code last_write_time(const Twine &path, std::time_t &result); 357 358/// @brief Set last write time. 359/// 360/// @param path Input path. 361/// @param value Time to set (UNIX time) \a path's last write time to. 362/// @results errc::success if result has been successfully set, otherwise a 363/// platform specific error_code. 364error_code set_last_write_time(const Twine &path, std::time_t value); 365 366/// @brief Read a symlink's value. 367/// 368/// @param path Input path. 369/// @param result Set to the value of the symbolic link \a path. 370/// @results errc::success if result has been successfully set, otherwise a 371/// platform specific error_code. 372error_code read_symlink(const Twine &path, SmallVectorImpl<char> &result); 373 374/// @brief Get disk space usage information. 375/// 376/// @param path Input path. 377/// @param result Set to the capacity, free, and available space on the device 378/// \a path is on. 379/// @results errc::success if result has been successfully set, otherwise a 380/// platform specific error_code. 381error_code disk_space(const Twine &path, space_info &result); 382 383/// @brief Get file status as if by POSIX stat(). 384/// 385/// @param path Input path. 386/// @param result Set to the file status. 387/// @results errc::success if result has been successfully set, otherwise a 388/// platform specific error_code. 389error_code status(const Twine &path, file_status &result); 390 391/// @brief Is status available? 392/// 393/// @param path Input path. 394/// @results True if status() != status_error. 395bool status_known(file_status s); 396 397/// @brief Is status available? 398/// 399/// @param path Input path. 400/// @param result Set to true if status() != status_error. 401/// @results errc::success if result has been successfully set, otherwise a 402/// platform specific error_code. 403error_code status_known(const Twine &path, bool &result); 404 405/// @brief Get file status as if by POSIX lstat(). 406/// 407/// Does not resolve symlinks. 408/// 409/// @param path Input path. 410/// @param result Set to the file status. 411/// @results errc::success if result has been successfully set, otherwise a 412/// platform specific error_code. 413error_code symlink_status(const Twine &path, file_status &result); 414 415/// @brief Generate a unique path and open it as a file. 416/// 417/// Generates a unique path suitable for a temporary file and then opens it as a 418/// file. The name is based on \a model with '%' replaced by a random char in 419/// [0-9a-f]. If \a model is not an absolute path, a suitable temporary 420/// directory will be prepended. 421/// 422/// This is an atomic operation. Either the file is created and opened, or the 423/// file system is left untouched. 424/// 425/// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s 426/// 427/// @param model Name to base unique path off of. 428/// @param result_fs Set to the opened file's file descriptor. 429/// @param result_path Set to the opened file's absolute path. 430/// @results errc::success if result_{fd,path} have been successfully set, 431/// otherwise a platform specific error_code. 432error_code unique_file(const Twine &model, int &result_fd, 433 SmallVectorImpl<char> &result_path); 434 435/// @brief Canonicalize path. 436/// 437/// Sets result to the file system's idea of what path is. The result is always 438/// absolute and has the same capitalization as the file system. 439/// 440/// @param path Input path. 441/// @param result Set to the canonicalized version of \a path. 442/// @results errc::success if result has been successfully set, otherwise a 443/// platform specific error_code. 444error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); 445 446/// @brief Are \a path's first bytes \a magic? 447/// 448/// @param path Input path. 449/// @param magic Byte sequence to compare \a path's first len(magic) bytes to. 450/// @results errc::success if result has been successfully set, otherwise a 451/// platform specific error_code. 452error_code has_magic(const Twine &path, const Twine &magic, bool &result); 453 454/// @brief Get \a path's first \a len bytes. 455/// 456/// @param path Input path. 457/// @param len Number of magic bytes to get. 458/// @param result Set to the first \a len bytes in the file pointed to by 459/// \a path. Or the entire file if file_size(path) < len, in which 460/// case result.size() returns the size of the file. 461/// @results errc::success if result has been successfully set, 462/// errc::value_too_large if len is larger then the file pointed to by 463/// \a path, otherwise a platform specific error_code. 464error_code get_magic(const Twine &path, uint32_t len, 465 SmallVectorImpl<char> &result); 466 467/// @brief Get and identify \a path's type based on its content. 468/// 469/// @param path Input path. 470/// @param result Set to the type of file, or LLVMFileType::Unknown_FileType. 471/// @results errc::success if result has been successfully set, otherwise a 472/// platform specific error_code. 473error_code identify_magic(const Twine &path, LLVMFileType &result); 474 475/// @brief Is file bitcode? 476/// 477/// @param path Input path. 478/// @param result Set to true if \a path is a bitcode file, false if it is not, 479/// undefined otherwise. 480/// @results errc::success if result has been successfully set, otherwise a 481/// platform specific error_code. 482error_code is_bitcode(const Twine &path, bool &result); 483 484/// @brief Is file a dynamic library? 485/// 486/// @param path Input path. 487/// @param result Set to true if \a path is a dynamic library, false if it is 488/// not, undefined otherwise. 489/// @results errc::success if result has been successfully set, otherwise a 490/// platform specific error_code. 491error_code is_dynamic_library(const Twine &path, bool &result); 492 493/// @brief Is an object file? 494/// 495/// @param path Input path. 496/// @param result Set to true if \a path is an object file, false if it is not, 497/// undefined otherwise. 498/// @results errc::success if result has been successfully set, otherwise a 499/// platform specific error_code. 500error_code is_object_file(const Twine &path, bool &result); 501 502/// @brief Can file be read? 503/// 504/// @param path Input path. 505/// @param result Set to true if \a path is readable, false it it is not, 506/// undefined otherwise. 507/// @results errc::success if result has been successfully set, otherwise a 508/// platform specific error_code. 509error_code can_read(const Twine &path, bool &result); 510 511/// @brief Can file be written? 512/// 513/// @param path Input path. 514/// @param result Set to true if \a path is writeable, false it it is not, 515/// undefined otherwise. 516/// @results errc::success if result has been successfully set, otherwise a 517/// platform specific error_code. 518error_code can_write(const Twine &path, bool &result); 519 520/// @brief Can file be executed? 521/// 522/// @param path Input path. 523/// @param result Set to true if \a path is executable, false it it is not, 524/// undefined otherwise. 525/// @results errc::success if result has been successfully set, otherwise a 526/// platform specific error_code. 527error_code can_execute(const Twine &path, bool &result); 528 529/// @brief Get library paths the system linker uses. 530/// 531/// @param result Set to the list of system library paths. 532/// @results errc::success if result has been successfully set, otherwise a 533/// platform specific error_code. 534error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); 535 536/// @brief Get bitcode library paths the system linker uses 537/// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. 538/// 539/// @param result Set to the list of bitcode library paths. 540/// @results errc::success if result has been successfully set, otherwise a 541/// platform specific error_code. 542error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); 543 544/// @brief Find a library. 545/// 546/// Find the path to a library using its short name. Use the system 547/// dependent library paths to locate the library. 548/// 549/// c => /usr/lib/libc.so 550/// 551/// @param short_name Library name one would give to the system linker. 552/// @param result Set to the absolute path \a short_name represents. 553/// @results errc::success if result has been successfully set, otherwise a 554/// platform specific error_code. 555error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); 556 557/// @brief Get absolute path of main executable. 558/// 559/// @param argv0 The program name as it was spelled on the command line. 560/// @param MainAddr Address of some symbol in the executable (not in a library). 561/// @param result Set to the absolute path of the current executable. 562/// @results errc::success if result has been successfully set, otherwise a 563/// platform specific error_code. 564error_code GetMainExecutable(const char *argv0, void *MainAddr, 565 SmallVectorImpl<char> &result); 566 567/// @} 568/// @name Iterators 569/// @{ 570 571/// directory_entry - A single entry in a directory. Caches the status either 572/// from the result of the iteration syscall, or the first time status or 573/// symlink_status is called. 574class directory_entry { 575 std::string Path; 576 mutable file_status Status; 577 mutable file_status SymlinkStatus; 578 579public: 580 explicit directory_entry(const Twine &path, file_status st = file_status(), 581 file_status symlink_st = file_status()) 582 : Path(path.str()) 583 , Status(st) 584 , SymlinkStatus(symlink_st) {} 585 586 directory_entry() {} 587 588 void assign(const Twine &path, file_status st = file_status(), 589 file_status symlink_st = file_status()) { 590 Path = path.str(); 591 Status = st; 592 SymlinkStatus = symlink_st; 593 } 594 595 void replace_filename(const Twine &filename, file_status st = file_status(), 596 file_status symlink_st = file_status()); 597 598 StringRef path() const { return Path; } 599 error_code status(file_status &result) const; 600 error_code symlink_status(file_status &result) const; 601 602 bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } 603 bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } 604 bool operator< (const directory_entry& rhs) const; 605 bool operator<=(const directory_entry& rhs) const; 606 bool operator> (const directory_entry& rhs) const; 607 bool operator>=(const directory_entry& rhs) const; 608}; 609 610/// directory_iterator - Iterates through the entries in path. There is no 611/// operator++ because we need an error_code. If it's really needed we can make 612/// it call report_fatal_error on error. 613class directory_iterator { 614 intptr_t IterationHandle; 615 directory_entry CurrentEntry; 616 617 // Platform implementations implement these functions to handle iteration. 618 friend error_code directory_iterator_construct(directory_iterator &it, 619 StringRef path); 620 friend error_code directory_iterator_increment(directory_iterator &it); 621 friend error_code directory_iterator_destruct(directory_iterator &it); 622 623public: 624 explicit directory_iterator(const Twine &path, error_code &ec) 625 : IterationHandle(0) { 626 SmallString<128> path_storage; 627 ec = directory_iterator_construct(*this, path.toStringRef(path_storage)); 628 } 629 630 /// Construct end iterator. 631 directory_iterator() : IterationHandle(0) {} 632 633 ~directory_iterator() { 634 directory_iterator_destruct(*this); 635 } 636 637 // No operator++ because we need error_code. 638 directory_iterator &increment(error_code &ec) { 639 ec = directory_iterator_increment(*this); 640 return *this; 641 } 642 643 const directory_entry &operator*() const { return CurrentEntry; } 644 const directory_entry *operator->() const { return &CurrentEntry; } 645 646 bool operator!=(const directory_iterator &RHS) const { 647 return CurrentEntry != RHS.CurrentEntry; 648 } 649 // Other members as required by 650 // C++ Std, 24.1.1 Input iterators [input.iterators] 651}; 652 653/// recursive_directory_iterator - Same as directory_iterator except for it 654/// recurses down into child directories. 655class recursive_directory_iterator { 656 uint16_t Level; 657 bool HasNoPushRequest; 658 // implementation directory iterator status 659 660public: 661 explicit recursive_directory_iterator(const Twine &path, error_code &ec); 662 // No operator++ because we need error_code. 663 directory_iterator &increment(error_code &ec); 664 665 const directory_entry &operator*() const; 666 const directory_entry *operator->() const; 667 668 // observers 669 /// Gets the current level. path is at level 0. 670 int level() const; 671 /// Returns true if no_push has been called for this directory_entry. 672 bool no_push_request() const; 673 674 // modifiers 675 /// Goes up one level if Level > 0. 676 void pop(); 677 /// Does not go down into the current directory_entry. 678 void no_push(); 679 680 // Other members as required by 681 // C++ Std, 24.1.1 Input iterators [input.iterators] 682}; 683 684/// @} 685 686} // end namespace fs 687} // end namespace sys 688} // end namespace llvm 689 690#endif 691