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