LLVM API Documentation
00001 //===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file declares the llvm::sys::fs namespace. It is designed after 00011 // TR2/boost filesystem (v3), but modified to remove exception handling and the 00012 // path class. 00013 // 00014 // All functions return an error_code and their actual work via the last out 00015 // argument. The out argument is defined if and only if errc::success is 00016 // returned. A function may return any error code in the generic or system 00017 // category. However, they shall be equivalent to any error conditions listed 00018 // in each functions respective documentation if the condition applies. [ note: 00019 // this does not guarantee that error_code will be in the set of explicitly 00020 // listed codes, but it does guarantee that if any of the explicitly listed 00021 // errors occur, the correct error_code will be used ]. All functions may 00022 // return errc::not_enough_memory if there is not enough memory to complete the 00023 // operation. 00024 // 00025 //===----------------------------------------------------------------------===// 00026 00027 #ifndef LLVM_SUPPORT_FILESYSTEM_H 00028 #define LLVM_SUPPORT_FILESYSTEM_H 00029 00030 #include "llvm/ADT/IntrusiveRefCntPtr.h" 00031 #include "llvm/ADT/OwningPtr.h" 00032 #include "llvm/ADT/SmallString.h" 00033 #include "llvm/ADT/Twine.h" 00034 #include "llvm/Support/DataTypes.h" 00035 #include "llvm/Support/ErrorHandling.h" 00036 #include "llvm/Support/system_error.h" 00037 #include <ctime> 00038 #include <iterator> 00039 #include <stack> 00040 #include <string> 00041 #include <vector> 00042 00043 #ifdef HAVE_SYS_STAT_H 00044 #include <sys/stat.h> 00045 #endif 00046 00047 namespace llvm { 00048 namespace sys { 00049 namespace fs { 00050 00051 /// file_type - An "enum class" enumeration for the file system's view of the 00052 /// type. 00053 struct file_type { 00054 enum _ { 00055 status_error, 00056 file_not_found, 00057 regular_file, 00058 directory_file, 00059 symlink_file, 00060 block_file, 00061 character_file, 00062 fifo_file, 00063 socket_file, 00064 type_unknown 00065 }; 00066 00067 file_type(_ v) : v_(v) {} 00068 explicit file_type(int v) : v_(_(v)) {} 00069 operator int() const {return v_;} 00070 00071 private: 00072 int v_; 00073 }; 00074 00075 /// copy_option - An "enum class" enumeration of copy semantics for copy 00076 /// operations. 00077 struct copy_option { 00078 enum _ { 00079 fail_if_exists, 00080 overwrite_if_exists 00081 }; 00082 00083 copy_option(_ v) : v_(v) {} 00084 explicit copy_option(int v) : v_(_(v)) {} 00085 operator int() const {return v_;} 00086 00087 private: 00088 int v_; 00089 }; 00090 00091 /// space_info - Self explanatory. 00092 struct space_info { 00093 uint64_t capacity; 00094 uint64_t free; 00095 uint64_t available; 00096 }; 00097 00098 00099 enum perms { 00100 no_perms = 0, 00101 owner_read = 0400, 00102 owner_write = 0200, 00103 owner_exe = 0100, 00104 owner_all = owner_read | owner_write | owner_exe, 00105 group_read = 040, 00106 group_write = 020, 00107 group_exe = 010, 00108 group_all = group_read | group_write | group_exe, 00109 others_read = 04, 00110 others_write = 02, 00111 others_exe = 01, 00112 others_all = others_read | others_write | others_exe, 00113 all_all = owner_all | group_all | others_all, 00114 set_uid_on_exe = 04000, 00115 set_gid_on_exe = 02000, 00116 sticky_bit = 01000, 00117 perms_mask = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit, 00118 perms_not_known = 0xFFFF, 00119 add_perms = 0x1000, 00120 remove_perms = 0x2000, 00121 symlink_perms = 0x4000 00122 }; 00123 00124 // Helper functions so that you can use & and | to manipulate perms bits: 00125 inline perms operator|(perms l , perms r) { 00126 return static_cast<perms>( 00127 static_cast<unsigned short>(l) | static_cast<unsigned short>(r)); 00128 } 00129 inline perms operator&(perms l , perms r) { 00130 return static_cast<perms>( 00131 static_cast<unsigned short>(l) & static_cast<unsigned short>(r)); 00132 } 00133 inline perms &operator|=(perms &l, perms r) { 00134 l = l | r; 00135 return l; 00136 } 00137 inline perms &operator&=(perms &l, perms r) { 00138 l = l & r; 00139 return l; 00140 } 00141 inline perms operator~(perms x) { 00142 return static_cast<perms>(~static_cast<unsigned short>(x)); 00143 } 00144 00145 00146 00147 /// file_status - Represents the result of a call to stat and friends. It has 00148 /// a platform specific member to store the result. 00149 class file_status 00150 { 00151 #if defined(LLVM_ON_UNIX) 00152 dev_t fs_st_dev; 00153 ino_t fs_st_ino; 00154 #elif defined (LLVM_ON_WIN32) 00155 uint32_t LastWriteTimeHigh; 00156 uint32_t LastWriteTimeLow; 00157 uint32_t VolumeSerialNumber; 00158 uint32_t FileSizeHigh; 00159 uint32_t FileSizeLow; 00160 uint32_t FileIndexHigh; 00161 uint32_t FileIndexLow; 00162 #endif 00163 friend bool equivalent(file_status A, file_status B); 00164 friend error_code status(const Twine &path, file_status &result); 00165 file_type Type; 00166 perms Perms; 00167 public: 00168 explicit file_status(file_type v=file_type::status_error, 00169 perms prms=perms_not_known) 00170 : Type(v), Perms(prms) {} 00171 00172 // getters 00173 file_type type() const { return Type; } 00174 perms permissions() const { return Perms; } 00175 00176 // setters 00177 void type(file_type v) { Type = v; } 00178 void permissions(perms p) { Perms = p; } 00179 }; 00180 00181 /// file_magic - An "enum class" enumeration of file types based on magic (the first 00182 /// N bytes of the file). 00183 struct file_magic { 00184 enum _ { 00185 unknown = 0, ///< Unrecognized file 00186 bitcode, ///< Bitcode file 00187 archive, ///< ar style archive file 00188 elf_relocatable, ///< ELF Relocatable object file 00189 elf_executable, ///< ELF Executable image 00190 elf_shared_object, ///< ELF dynamically linked shared lib 00191 elf_core, ///< ELF core image 00192 macho_object, ///< Mach-O Object file 00193 macho_executable, ///< Mach-O Executable 00194 macho_fixed_virtual_memory_shared_lib, ///< Mach-O Shared Lib, FVM 00195 macho_core, ///< Mach-O Core File 00196 macho_preload_executabl, ///< Mach-O Preloaded Executable 00197 macho_dynamically_linked_shared_lib, ///< Mach-O dynlinked shared lib 00198 macho_dynamic_linker, ///< The Mach-O dynamic linker 00199 macho_bundle, ///< Mach-O Bundle file 00200 macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub 00201 macho_dsym_companion, ///< Mach-O dSYM companion file 00202 coff_object, ///< COFF object file 00203 pecoff_executable ///< PECOFF executable file 00204 }; 00205 00206 bool is_object() const { 00207 return v_ == unknown ? false : true; 00208 } 00209 00210 file_magic() : v_(unknown) {} 00211 file_magic(_ v) : v_(v) {} 00212 explicit file_magic(int v) : v_(_(v)) {} 00213 operator int() const {return v_;} 00214 00215 private: 00216 int v_; 00217 }; 00218 00219 /// @} 00220 /// @name Physical Operators 00221 /// @{ 00222 00223 /// @brief Make \a path an absolute path. 00224 /// 00225 /// Makes \a path absolute using the current directory if it is not already. An 00226 /// empty \a path will result in the current directory. 00227 /// 00228 /// /absolute/path => /absolute/path 00229 /// relative/../path => <current-directory>/relative/../path 00230 /// 00231 /// @param path A path that is modified to be an absolute path. 00232 /// @returns errc::success if \a path has been made absolute, otherwise a 00233 /// platform specific error_code. 00234 error_code make_absolute(SmallVectorImpl<char> &path); 00235 00236 /// @brief Copy the file at \a from to the path \a to. 00237 /// 00238 /// @param from The path to copy the file from. 00239 /// @param to The path to copy the file to. 00240 /// @param copt Behavior if \a to already exists. 00241 /// @returns errc::success if the file has been successfully copied. 00242 /// errc::file_exists if \a to already exists and \a copt == 00243 /// copy_option::fail_if_exists. Otherwise a platform specific 00244 /// error_code. 00245 error_code copy_file(const Twine &from, const Twine &to, 00246 copy_option copt = copy_option::fail_if_exists); 00247 00248 /// @brief Create all the non-existent directories in path. 00249 /// 00250 /// @param path Directories to create. 00251 /// @param existed Set to true if \a path already existed, false otherwise. 00252 /// @returns errc::success if is_directory(path) and existed have been set, 00253 /// otherwise a platform specific error_code. 00254 error_code create_directories(const Twine &path, bool &existed); 00255 00256 /// @brief Create the directory in path. 00257 /// 00258 /// @param path Directory to create. 00259 /// @param existed Set to true if \a path already existed, false otherwise. 00260 /// @returns errc::success if is_directory(path) and existed have been set, 00261 /// otherwise a platform specific error_code. 00262 error_code create_directory(const Twine &path, bool &existed); 00263 00264 /// @brief Create a hard link from \a from to \a to. 00265 /// 00266 /// @param to The path to hard link to. 00267 /// @param from The path to hard link from. This is created. 00268 /// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) 00269 /// , otherwise a platform specific error_code. 00270 error_code create_hard_link(const Twine &to, const Twine &from); 00271 00272 /// @brief Create a symbolic link from \a from to \a to. 00273 /// 00274 /// @param to The path to symbolically link to. 00275 /// @param from The path to symbolically link from. This is created. 00276 /// @returns errc::success if exists(to) && exists(from) && is_symlink(from), 00277 /// otherwise a platform specific error_code. 00278 error_code create_symlink(const Twine &to, const Twine &from); 00279 00280 /// @brief Get the current path. 00281 /// 00282 /// @param result Holds the current path on return. 00283 /// @returns errc::success if the current path has been stored in result, 00284 /// otherwise a platform specific error_code. 00285 error_code current_path(SmallVectorImpl<char> &result); 00286 00287 /// @brief Remove path. Equivalent to POSIX remove(). 00288 /// 00289 /// @param path Input path. 00290 /// @param existed Set to true if \a path existed, false if it did not. 00291 /// undefined otherwise. 00292 /// @returns errc::success if path has been removed and existed has been 00293 /// successfully set, otherwise a platform specific error_code. 00294 error_code remove(const Twine &path, bool &existed); 00295 00296 /// @brief Recursively remove all files below \a path, then \a path. Files are 00297 /// removed as if by POSIX remove(). 00298 /// 00299 /// @param path Input path. 00300 /// @param num_removed Number of files removed. 00301 /// @returns errc::success if path has been removed and num_removed has been 00302 /// successfully set, otherwise a platform specific error_code. 00303 error_code remove_all(const Twine &path, uint32_t &num_removed); 00304 00305 /// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). 00306 /// 00307 /// @param from The path to rename from. 00308 /// @param to The path to rename to. This is created. 00309 error_code rename(const Twine &from, const Twine &to); 00310 00311 /// @brief Resize path to size. File is resized as if by POSIX truncate(). 00312 /// 00313 /// @param path Input path. 00314 /// @param size Size to resize to. 00315 /// @returns errc::success if \a path has been resized to \a size, otherwise a 00316 /// platform specific error_code. 00317 error_code resize_file(const Twine &path, uint64_t size); 00318 00319 /// @} 00320 /// @name Physical Observers 00321 /// @{ 00322 00323 /// @brief Does file exist? 00324 /// 00325 /// @param status A file_status previously returned from stat. 00326 /// @returns True if the file represented by status exists, false if it does 00327 /// not. 00328 bool exists(file_status status); 00329 00330 /// @brief Does file exist? 00331 /// 00332 /// @param path Input path. 00333 /// @param result Set to true if the file represented by status exists, false if 00334 /// it does not. Undefined otherwise. 00335 /// @returns errc::success if result has been successfully set, otherwise a 00336 /// platform specific error_code. 00337 error_code exists(const Twine &path, bool &result); 00338 00339 /// @brief Simpler version of exists for clients that don't need to 00340 /// differentiate between an error and false. 00341 inline bool exists(const Twine &path) { 00342 bool result; 00343 return !exists(path, result) && result; 00344 } 00345 00346 /// @brief Do file_status's represent the same thing? 00347 /// 00348 /// @param A Input file_status. 00349 /// @param B Input file_status. 00350 /// 00351 /// assert(status_known(A) || status_known(B)); 00352 /// 00353 /// @returns True if A and B both represent the same file system entity, false 00354 /// otherwise. 00355 bool equivalent(file_status A, file_status B); 00356 00357 /// @brief Do paths represent the same thing? 00358 /// 00359 /// assert(status_known(A) || status_known(B)); 00360 /// 00361 /// @param A Input path A. 00362 /// @param B Input path B. 00363 /// @param result Set to true if stat(A) and stat(B) have the same device and 00364 /// inode (or equivalent). 00365 /// @returns errc::success if result has been successfully set, otherwise a 00366 /// platform specific error_code. 00367 error_code equivalent(const Twine &A, const Twine &B, bool &result); 00368 00369 /// @brief Simpler version of equivalent for clients that don't need to 00370 /// differentiate between an error and false. 00371 inline bool equivalent(const Twine &A, const Twine &B) { 00372 bool result; 00373 return !equivalent(A, B, result) && result; 00374 } 00375 00376 /// @brief Get file size. 00377 /// 00378 /// @param path Input path. 00379 /// @param result Set to the size of the file in \a path. 00380 /// @returns errc::success if result has been successfully set, otherwise a 00381 /// platform specific error_code. 00382 error_code file_size(const Twine &path, uint64_t &result); 00383 00384 /// @brief Does status represent a directory? 00385 /// 00386 /// @param status A file_status previously returned from status. 00387 /// @returns status.type() == file_type::directory_file. 00388 bool is_directory(file_status status); 00389 00390 /// @brief Is path a directory? 00391 /// 00392 /// @param path Input path. 00393 /// @param result Set to true if \a path is a directory, false if it is not. 00394 /// Undefined otherwise. 00395 /// @returns errc::success if result has been successfully set, otherwise a 00396 /// platform specific error_code. 00397 error_code is_directory(const Twine &path, bool &result); 00398 00399 /// @brief Does status represent a regular file? 00400 /// 00401 /// @param status A file_status previously returned from status. 00402 /// @returns status_known(status) && status.type() == file_type::regular_file. 00403 bool is_regular_file(file_status status); 00404 00405 /// @brief Is path a regular file? 00406 /// 00407 /// @param path Input path. 00408 /// @param result Set to true if \a path is a regular file, false if it is not. 00409 /// Undefined otherwise. 00410 /// @returns errc::success if result has been successfully set, otherwise a 00411 /// platform specific error_code. 00412 error_code is_regular_file(const Twine &path, bool &result); 00413 00414 /// @brief Does this status represent something that exists but is not a 00415 /// directory, regular file, or symlink? 00416 /// 00417 /// @param status A file_status previously returned from status. 00418 /// @returns exists(s) && !is_regular_file(s) && !is_directory(s) && 00419 /// !is_symlink(s) 00420 bool is_other(file_status status); 00421 00422 /// @brief Is path something that exists but is not a directory, 00423 /// regular file, or symlink? 00424 /// 00425 /// @param path Input path. 00426 /// @param result Set to true if \a path exists, but is not a directory, regular 00427 /// file, or a symlink, false if it does not. Undefined otherwise. 00428 /// @returns errc::success if result has been successfully set, otherwise a 00429 /// platform specific error_code. 00430 error_code is_other(const Twine &path, bool &result); 00431 00432 /// @brief Does status represent a symlink? 00433 /// 00434 /// @param status A file_status previously returned from stat. 00435 /// @returns status.type() == symlink_file. 00436 bool is_symlink(file_status status); 00437 00438 /// @brief Is path a symlink? 00439 /// 00440 /// @param path Input path. 00441 /// @param result Set to true if \a path is a symlink, false if it is not. 00442 /// Undefined otherwise. 00443 /// @returns errc::success if result has been successfully set, otherwise a 00444 /// platform specific error_code. 00445 error_code is_symlink(const Twine &path, bool &result); 00446 00447 /// @brief Get file status as if by POSIX stat(). 00448 /// 00449 /// @param path Input path. 00450 /// @param result Set to the file status. 00451 /// @returns errc::success if result has been successfully set, otherwise a 00452 /// platform specific error_code. 00453 error_code status(const Twine &path, file_status &result); 00454 00455 /// @brief Modifies permission bits on a file 00456 /// 00457 /// @param path Input path. 00458 /// @returns errc::success if permissions have been changed, otherwise a 00459 /// platform specific error_code. 00460 error_code permissions(const Twine &path, perms prms); 00461 00462 /// @brief Is status available? 00463 /// 00464 /// @param s Input file status. 00465 /// @returns True if status() != status_error. 00466 bool status_known(file_status s); 00467 00468 /// @brief Is status available? 00469 /// 00470 /// @param path Input path. 00471 /// @param result Set to true if status() != status_error. 00472 /// @returns errc::success if result has been successfully set, otherwise a 00473 /// platform specific error_code. 00474 error_code status_known(const Twine &path, bool &result); 00475 00476 /// @brief Generate a unique path and open it as a file. 00477 /// 00478 /// Generates a unique path suitable for a temporary file and then opens it as a 00479 /// file. The name is based on \a model with '%' replaced by a random char in 00480 /// [0-9a-f]. If \a model is not an absolute path, a suitable temporary 00481 /// directory will be prepended. 00482 /// 00483 /// This is an atomic operation. Either the file is created and opened, or the 00484 /// file system is left untouched. 00485 /// 00486 /// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s 00487 /// 00488 /// @param model Name to base unique path off of. 00489 /// @param result_fd Set to the opened file's file descriptor. 00490 /// @param result_path Set to the opened file's absolute path. 00491 /// @param makeAbsolute If true and \a model is not an absolute path, a temp 00492 /// directory will be prepended. 00493 /// @returns errc::success if result_{fd,path} have been successfully set, 00494 /// otherwise a platform specific error_code. 00495 error_code unique_file(const Twine &model, int &result_fd, 00496 SmallVectorImpl<char> &result_path, 00497 bool makeAbsolute = true, unsigned mode = 0600); 00498 00499 /// @brief Canonicalize path. 00500 /// 00501 /// Sets result to the file system's idea of what path is. The result is always 00502 /// absolute and has the same capitalization as the file system. 00503 /// 00504 /// @param path Input path. 00505 /// @param result Set to the canonicalized version of \a path. 00506 /// @returns errc::success if result has been successfully set, otherwise a 00507 /// platform specific error_code. 00508 error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); 00509 00510 /// @brief Are \a path's first bytes \a magic? 00511 /// 00512 /// @param path Input path. 00513 /// @param magic Byte sequence to compare \a path's first len(magic) bytes to. 00514 /// @returns errc::success if result has been successfully set, otherwise a 00515 /// platform specific error_code. 00516 error_code has_magic(const Twine &path, const Twine &magic, bool &result); 00517 00518 /// @brief Get \a path's first \a len bytes. 00519 /// 00520 /// @param path Input path. 00521 /// @param len Number of magic bytes to get. 00522 /// @param result Set to the first \a len bytes in the file pointed to by 00523 /// \a path. Or the entire file if file_size(path) < len, in which 00524 /// case result.size() returns the size of the file. 00525 /// @returns errc::success if result has been successfully set, 00526 /// errc::value_too_large if len is larger then the file pointed to by 00527 /// \a path, otherwise a platform specific error_code. 00528 error_code get_magic(const Twine &path, uint32_t len, 00529 SmallVectorImpl<char> &result); 00530 00531 /// @brief Identify the type of a binary file based on how magical it is. 00532 file_magic identify_magic(StringRef magic); 00533 00534 /// @brief Get and identify \a path's type based on its content. 00535 /// 00536 /// @param path Input path. 00537 /// @param result Set to the type of file, or LLVMFileType::Unknown_FileType. 00538 /// @returns errc::success if result has been successfully set, otherwise a 00539 /// platform specific error_code. 00540 error_code identify_magic(const Twine &path, file_magic &result); 00541 00542 /// @brief Get library paths the system linker uses. 00543 /// 00544 /// @param result Set to the list of system library paths. 00545 /// @returns errc::success if result has been successfully set, otherwise a 00546 /// platform specific error_code. 00547 error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); 00548 00549 /// @brief Get bitcode library paths the system linker uses 00550 /// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. 00551 /// 00552 /// @param result Set to the list of bitcode library paths. 00553 /// @returns errc::success if result has been successfully set, otherwise a 00554 /// platform specific error_code. 00555 error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); 00556 00557 /// @brief Find a library. 00558 /// 00559 /// Find the path to a library using its short name. Use the system 00560 /// dependent library paths to locate the library. 00561 /// 00562 /// c => /usr/lib/libc.so 00563 /// 00564 /// @param short_name Library name one would give to the system linker. 00565 /// @param result Set to the absolute path \a short_name represents. 00566 /// @returns errc::success if result has been successfully set, otherwise a 00567 /// platform specific error_code. 00568 error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); 00569 00570 /// @brief Get absolute path of main executable. 00571 /// 00572 /// @param argv0 The program name as it was spelled on the command line. 00573 /// @param MainAddr Address of some symbol in the executable (not in a library). 00574 /// @param result Set to the absolute path of the current executable. 00575 /// @returns errc::success if result has been successfully set, otherwise a 00576 /// platform specific error_code. 00577 error_code GetMainExecutable(const char *argv0, void *MainAddr, 00578 SmallVectorImpl<char> &result); 00579 00580 /// This class represents a memory mapped file. It is based on 00581 /// boost::iostreams::mapped_file. 00582 class mapped_file_region { 00583 mapped_file_region() LLVM_DELETED_FUNCTION; 00584 mapped_file_region(mapped_file_region&) LLVM_DELETED_FUNCTION; 00585 mapped_file_region &operator =(mapped_file_region&) LLVM_DELETED_FUNCTION; 00586 00587 public: 00588 enum mapmode { 00589 readonly, ///< May only access map via const_data as read only. 00590 readwrite, ///< May access map via data and modify it. Written to path. 00591 priv ///< May modify via data, but changes are lost on destruction. 00592 }; 00593 00594 private: 00595 /// Platform specific mapping state. 00596 mapmode Mode; 00597 uint64_t Size; 00598 void *Mapping; 00599 #ifdef LLVM_ON_WIN32 00600 int FileDescriptor; 00601 void *FileHandle; 00602 void *FileMappingHandle; 00603 #endif 00604 00605 error_code init(int FD, bool CloseFD, uint64_t Offset); 00606 00607 public: 00608 typedef char char_type; 00609 00610 #if LLVM_HAS_RVALUE_REFERENCES 00611 mapped_file_region(mapped_file_region&&); 00612 mapped_file_region &operator =(mapped_file_region&&); 00613 #endif 00614 00615 /// Construct a mapped_file_region at \a path starting at \a offset of length 00616 /// \a length and with access \a mode. 00617 /// 00618 /// \param path Path to the file to map. If it does not exist it will be 00619 /// created. 00620 /// \param mode How to map the memory. 00621 /// \param length Number of bytes to map in starting at \a offset. If the file 00622 /// is shorter than this, it will be extended. If \a length is 00623 /// 0, the entire file will be mapped. 00624 /// \param offset Byte offset from the beginning of the file where the map 00625 /// should begin. Must be a multiple of 00626 /// mapped_file_region::alignment(). 00627 /// \param ec This is set to errc::success if the map was constructed 00628 /// sucessfully. Otherwise it is set to a platform dependent error. 00629 mapped_file_region(const Twine &path, 00630 mapmode mode, 00631 uint64_t length, 00632 uint64_t offset, 00633 error_code &ec); 00634 00635 /// \param fd An open file descriptor to map. mapped_file_region takes 00636 /// ownership if closefd is true. It must have been opended in the correct 00637 /// mode. 00638 mapped_file_region(int fd, 00639 bool closefd, 00640 mapmode mode, 00641 uint64_t length, 00642 uint64_t offset, 00643 error_code &ec); 00644 00645 ~mapped_file_region(); 00646 00647 mapmode flags() const; 00648 uint64_t size() const; 00649 char *data() const; 00650 00651 /// Get a const view of the data. Modifying this memory has undefined 00652 /// behaivor. 00653 const char *const_data() const; 00654 00655 /// \returns The minimum alignment offset must be. 00656 static int alignment(); 00657 }; 00658 00659 /// @brief Memory maps the contents of a file 00660 /// 00661 /// @param path Path to file to map. 00662 /// @param file_offset Byte offset in file where mapping should begin. 00663 /// @param size Byte length of range of the file to map. 00664 /// @param map_writable If true, the file will be mapped in r/w such 00665 /// that changes to the mapped buffer will be flushed back 00666 /// to the file. If false, the file will be mapped read-only 00667 /// and the buffer will be read-only. 00668 /// @param result Set to the start address of the mapped buffer. 00669 /// @returns errc::success if result has been successfully set, otherwise a 00670 /// platform specific error_code. 00671 error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, 00672 bool map_writable, void *&result); 00673 00674 00675 /// @brief Memory unmaps the contents of a file 00676 /// 00677 /// @param base Pointer to the start of the buffer. 00678 /// @param size Byte length of the range to unmmap. 00679 /// @returns errc::success if result has been successfully set, otherwise a 00680 /// platform specific error_code. 00681 error_code unmap_file_pages(void *base, size_t size); 00682 00683 00684 00685 /// @} 00686 /// @name Iterators 00687 /// @{ 00688 00689 /// directory_entry - A single entry in a directory. Caches the status either 00690 /// from the result of the iteration syscall, or the first time status is 00691 /// called. 00692 class directory_entry { 00693 std::string Path; 00694 mutable file_status Status; 00695 00696 public: 00697 explicit directory_entry(const Twine &path, file_status st = file_status()) 00698 : Path(path.str()) 00699 , Status(st) {} 00700 00701 directory_entry() {} 00702 00703 void assign(const Twine &path, file_status st = file_status()) { 00704 Path = path.str(); 00705 Status = st; 00706 } 00707 00708 void replace_filename(const Twine &filename, file_status st = file_status()); 00709 00710 const std::string &path() const { return Path; } 00711 error_code status(file_status &result) const; 00712 00713 bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } 00714 bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } 00715 bool operator< (const directory_entry& rhs) const; 00716 bool operator<=(const directory_entry& rhs) const; 00717 bool operator> (const directory_entry& rhs) const; 00718 bool operator>=(const directory_entry& rhs) const; 00719 }; 00720 00721 namespace detail { 00722 struct DirIterState; 00723 00724 error_code directory_iterator_construct(DirIterState&, StringRef); 00725 error_code directory_iterator_increment(DirIterState&); 00726 error_code directory_iterator_destruct(DirIterState&); 00727 00728 /// DirIterState - Keeps state for the directory_iterator. It is reference 00729 /// counted in order to preserve InputIterator semantics on copy. 00730 struct DirIterState : public RefCountedBase<DirIterState> { 00731 DirIterState() 00732 : IterationHandle(0) {} 00733 00734 ~DirIterState() { 00735 directory_iterator_destruct(*this); 00736 } 00737 00738 intptr_t IterationHandle; 00739 directory_entry CurrentEntry; 00740 }; 00741 } 00742 00743 /// directory_iterator - Iterates through the entries in path. There is no 00744 /// operator++ because we need an error_code. If it's really needed we can make 00745 /// it call report_fatal_error on error. 00746 class directory_iterator { 00747 IntrusiveRefCntPtr<detail::DirIterState> State; 00748 00749 public: 00750 explicit directory_iterator(const Twine &path, error_code &ec) { 00751 State = new detail::DirIterState; 00752 SmallString<128> path_storage; 00753 ec = detail::directory_iterator_construct(*State, 00754 path.toStringRef(path_storage)); 00755 } 00756 00757 explicit directory_iterator(const directory_entry &de, error_code &ec) { 00758 State = new detail::DirIterState; 00759 ec = detail::directory_iterator_construct(*State, de.path()); 00760 } 00761 00762 /// Construct end iterator. 00763 directory_iterator() : State(new detail::DirIterState) {} 00764 00765 // No operator++ because we need error_code. 00766 directory_iterator &increment(error_code &ec) { 00767 ec = directory_iterator_increment(*State); 00768 return *this; 00769 } 00770 00771 const directory_entry &operator*() const { return State->CurrentEntry; } 00772 const directory_entry *operator->() const { return &State->CurrentEntry; } 00773 00774 bool operator==(const directory_iterator &RHS) const { 00775 return State->CurrentEntry == RHS.State->CurrentEntry; 00776 } 00777 00778 bool operator!=(const directory_iterator &RHS) const { 00779 return !(*this == RHS); 00780 } 00781 // Other members as required by 00782 // C++ Std, 24.1.1 Input iterators [input.iterators] 00783 }; 00784 00785 namespace detail { 00786 /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is 00787 /// reference counted in order to preserve InputIterator semantics on copy. 00788 struct RecDirIterState : public RefCountedBase<RecDirIterState> { 00789 RecDirIterState() 00790 : Level(0) 00791 , HasNoPushRequest(false) {} 00792 00793 std::stack<directory_iterator, std::vector<directory_iterator> > Stack; 00794 uint16_t Level; 00795 bool HasNoPushRequest; 00796 }; 00797 } 00798 00799 /// recursive_directory_iterator - Same as directory_iterator except for it 00800 /// recurses down into child directories. 00801 class recursive_directory_iterator { 00802 IntrusiveRefCntPtr<detail::RecDirIterState> State; 00803 00804 public: 00805 recursive_directory_iterator() {} 00806 explicit recursive_directory_iterator(const Twine &path, error_code &ec) 00807 : State(new detail::RecDirIterState) { 00808 State->Stack.push(directory_iterator(path, ec)); 00809 if (State->Stack.top() == directory_iterator()) 00810 State.reset(); 00811 } 00812 // No operator++ because we need error_code. 00813 recursive_directory_iterator &increment(error_code &ec) { 00814 static const directory_iterator end_itr; 00815 00816 if (State->HasNoPushRequest) 00817 State->HasNoPushRequest = false; 00818 else { 00819 file_status st; 00820 if ((ec = State->Stack.top()->status(st))) return *this; 00821 if (is_directory(st)) { 00822 State->Stack.push(directory_iterator(*State->Stack.top(), ec)); 00823 if (ec) return *this; 00824 if (State->Stack.top() != end_itr) { 00825 ++State->Level; 00826 return *this; 00827 } 00828 State->Stack.pop(); 00829 } 00830 } 00831 00832 while (!State->Stack.empty() 00833 && State->Stack.top().increment(ec) == end_itr) { 00834 State->Stack.pop(); 00835 --State->Level; 00836 } 00837 00838 // Check if we are done. If so, create an end iterator. 00839 if (State->Stack.empty()) 00840 State.reset(); 00841 00842 return *this; 00843 } 00844 00845 const directory_entry &operator*() const { return *State->Stack.top(); } 00846 const directory_entry *operator->() const { return &*State->Stack.top(); } 00847 00848 // observers 00849 /// Gets the current level. Starting path is at level 0. 00850 int level() const { return State->Level; } 00851 00852 /// Returns true if no_push has been called for this directory_entry. 00853 bool no_push_request() const { return State->HasNoPushRequest; } 00854 00855 // modifiers 00856 /// Goes up one level if Level > 0. 00857 void pop() { 00858 assert(State && "Cannot pop and end itertor!"); 00859 assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); 00860 00861 static const directory_iterator end_itr; 00862 error_code ec; 00863 do { 00864 if (ec) 00865 report_fatal_error("Error incrementing directory iterator."); 00866 State->Stack.pop(); 00867 --State->Level; 00868 } while (!State->Stack.empty() 00869 && State->Stack.top().increment(ec) == end_itr); 00870 00871 // Check if we are done. If so, create an end iterator. 00872 if (State->Stack.empty()) 00873 State.reset(); 00874 } 00875 00876 /// Does not go down into the current directory_entry. 00877 void no_push() { State->HasNoPushRequest = true; } 00878 00879 bool operator==(const recursive_directory_iterator &RHS) const { 00880 return State == RHS.State; 00881 } 00882 00883 bool operator!=(const recursive_directory_iterator &RHS) const { 00884 return !(*this == RHS); 00885 } 00886 // Other members as required by 00887 // C++ Std, 24.1.1 Input iterators [input.iterators] 00888 }; 00889 00890 /// @} 00891 00892 } // end namespace fs 00893 } // end namespace sys 00894 } // end namespace llvm 00895 00896 #endif