WPILibC++  unspecified
FileSystem.h
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/IntrusiveRefCntPtr.h"
31 #include "llvm/SmallString.h"
32 #include "llvm/Twine.h"
33 
34 #include <sys/stat.h>
35 
36 #include <ctime>
37 #include <stack>
38 #include <system_error>
39 #include <tuple>
40 #include <vector>
41 
42 namespace llvm {
43 namespace sys {
44 namespace fs {
45 
47 enum class file_type {
48  status_error,
49  file_not_found,
50  regular_file,
51  directory_file,
52  symlink_file,
53  block_file,
54  character_file,
55  fifo_file,
56  socket_file,
57  type_unknown
58 };
59 
60 enum perms {
61  no_perms = 0,
62  owner_read = 0400,
63  owner_write = 0200,
64  owner_exe = 0100,
65  owner_all = owner_read | owner_write | owner_exe,
66  group_read = 040,
67  group_write = 020,
68  group_exe = 010,
69  group_all = group_read | group_write | group_exe,
70  others_read = 04,
71  others_write = 02,
72  others_exe = 01,
73  others_all = others_read | others_write | others_exe,
74  all_read = owner_read | group_read | others_read,
75  all_write = owner_write | group_write | others_write,
76  all_exe = owner_exe | group_exe | others_exe,
77  all_all = owner_all | group_all | others_all,
78  set_uid_on_exe = 04000,
79  set_gid_on_exe = 02000,
80  sticky_bit = 01000,
81  perms_not_known = 0xFFFF
82 };
83 
84 // Helper functions so that you can use & and | to manipulate perms bits:
85 inline perms operator|(perms l, perms r) {
86  return static_cast<perms>(static_cast<unsigned short>(l) |
87  static_cast<unsigned short>(r));
88 }
89 inline perms operator&(perms l, perms r) {
90  return static_cast<perms>(static_cast<unsigned short>(l) &
91  static_cast<unsigned short>(r));
92 }
93 inline perms &operator|=(perms &l, perms r) {
94  l = l | r;
95  return l;
96 }
97 inline perms &operator&=(perms &l, perms r) {
98  l = l & r;
99  return l;
100 }
101 inline perms operator~(perms x) {
102  return static_cast<perms>(
103  static_cast<unsigned short>(~static_cast<unsigned short>(x)));
104 }
105 
106 class UniqueID {
107  uint64_t Device;
108  uint64_t File;
109 
110 public:
111  UniqueID() = default;
112  UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
113  bool operator==(const UniqueID &Other) const {
114  return Device == Other.Device && File == Other.File;
115  }
116  bool operator!=(const UniqueID &Other) const { return !(*this == Other); }
117  bool operator<(const UniqueID &Other) const {
118  return std::tie(Device, File) < std::tie(Other.Device, Other.File);
119  }
120  uint64_t getDevice() const { return Device; }
121  uint64_t getFile() const { return File; }
122 };
123 
127 {
128  #ifdef _WIN32
129  uint32_t LastAccessedTimeHigh;
130  uint32_t LastAccessedTimeLow;
131  uint32_t LastWriteTimeHigh;
132  uint32_t LastWriteTimeLow;
133  uint32_t VolumeSerialNumber;
134  uint32_t FileSizeHigh;
135  uint32_t FileSizeLow;
136  uint32_t FileIndexHigh;
137  uint32_t FileIndexLow;
138  #else
139  dev_t fs_st_dev;
140  ino_t fs_st_ino;
141  time_t fs_st_atime;
142  time_t fs_st_mtime;
143  uid_t fs_st_uid;
144  gid_t fs_st_gid;
145  off_t fs_st_size;
146  #endif
147  friend bool equivalent(file_status A, file_status B);
148  file_type Type;
149  perms Perms;
150 
151 public:
152  #ifdef _WIN32
153  file_status()
154  : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0),
155  LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0),
156  FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0),
157  Type(file_type::status_error), Perms(perms_not_known) {}
158 
159  file_status(file_type Type)
160  : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0),
161  LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0),
162  FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0), Type(Type),
163  Perms(perms_not_known) {}
164 
165  file_status(file_type Type, uint32_t LastAccessTimeHigh,
166  uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
167  uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,
168  uint32_t FileSizeHigh, uint32_t FileSizeLow,
169  uint32_t FileIndexHigh, uint32_t FileIndexLow)
170  : LastAccessedTimeHigh(LastAccessTimeHigh), LastAccessedTimeLow(LastAccessTimeLow),
171  LastWriteTimeHigh(LastWriteTimeHigh),
172  LastWriteTimeLow(LastWriteTimeLow),
173  VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh),
174  FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh),
175  FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {}
176  #else
177  file_status()
178  : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0),
179  fs_st_uid(0), fs_st_gid(0), fs_st_size(0),
180  Type(file_type::status_error), Perms(perms_not_known) {}
181 
182  file_status(file_type Type)
183  : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0),
184  fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type),
185  Perms(perms_not_known) {}
186 
187  file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t ATime,
188  time_t MTime, uid_t UID, gid_t GID, off_t Size)
189  : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_atime(ATime), fs_st_mtime(MTime),
190  fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type),
191  Perms(Perms) {}
192  #endif
193 
194  // getters
195  file_type type() const { return Type; }
196  perms permissions() const { return Perms; }
197  UniqueID getUniqueID() const;
198 
199  #ifdef _WIN32
200  uint32_t getUser() const {
201  return 9999; // Not applicable to Windows, so...
202  }
203  uint32_t getGroup() const {
204  return 9999; // Not applicable to Windows, so...
205  }
206  uint64_t getSize() const {
207  return (uint64_t(FileSizeHigh) << 32) + FileSizeLow;
208  }
209  #else
210  uint32_t getUser() const { return fs_st_uid; }
211  uint32_t getGroup() const { return fs_st_gid; }
212  uint64_t getSize() const { return fs_st_size; }
213  #endif
214 
215  // setters
216  void type(file_type v) { Type = v; }
217  void permissions(perms p) { Perms = p; }
218 };
219 
223 
235 std::error_code make_absolute(const Twine &current_directory,
236  SmallVectorImpl<char> &path);
237 
249 std::error_code make_absolute(SmallVectorImpl<char> &path);
250 
256 std::error_code current_path(SmallVectorImpl<char> &result);
257 
261 
267 bool exists(file_status status);
268 
269 enum class AccessMode { Exist, Write, Execute };
270 
276 std::error_code access(const Twine &Path, AccessMode Mode);
277 
282 inline bool exists(const Twine &Path) {
283  return !access(Path, AccessMode::Exist);
284 }
285 
290 inline bool can_write(const Twine &Path) {
291  return !access(Path, AccessMode::Write);
292 }
293 
303 bool equivalent(file_status A, file_status B);
304 
315 std::error_code equivalent(const Twine &A, const Twine &B, bool &result);
316 
319 inline bool equivalent(const Twine &A, const Twine &B) {
320  bool result;
321  return !equivalent(A, B, result) && result;
322 }
323 
328 bool is_directory(file_status status);
329 
337 std::error_code is_directory(const Twine &path, bool &result);
338 
341 inline bool is_directory(const Twine &Path) {
342  bool Result;
343  return !is_directory(Path, Result) && Result;
344 }
345 
350 bool is_regular_file(file_status status);
351 
359 std::error_code is_regular_file(const Twine &path, bool &result);
360 
363 inline bool is_regular_file(const Twine &Path) {
364  bool Result;
365  if (is_regular_file(Path, Result))
366  return false;
367  return Result;
368 }
369 
375 bool is_other(file_status status);
376 
385 std::error_code is_other(const Twine &path, bool &result);
386 
393 std::error_code status(const Twine &path, file_status &result);
394 
396 std::error_code status(int FD, file_status &Result);
397 
402 bool status_known(file_status s);
403 
410 std::error_code status_known(const Twine &path, bool &result);
411 
412 enum OpenFlags : unsigned {
413  F_None = 0,
414 
417  F_Excl = 1,
418 
422  F_Append = 2,
423 
426  F_Text = 4,
427 
429  F_RW = 8
430 };
431 
432 inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
433  return OpenFlags(unsigned(A) | unsigned(B));
434 }
435 
436 inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
437  A = A | B;
438  return A;
439 }
440 
441 std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
442  OpenFlags Flags, unsigned Mode = 0666);
443 
444 std::error_code openFileForRead(const Twine &Name, int &ResultFD,
445  SmallVectorImpl<char> *RealPath = nullptr);
446 std::error_code getUniqueID(const Twine Path, UniqueID &Result);
447 
451 
456  std::string Path;
457  mutable file_status Status;
458 
459 public:
460  explicit directory_entry(const Twine &path, file_status st = file_status())
461  : Path(path.str())
462  , Status(st) {}
463 
464  directory_entry() {}
465 
466  void assign(const Twine &path, file_status st = file_status()) {
467  Path = path.str();
468  Status = st;
469  }
470 
471  void replace_filename(const Twine &filename, file_status st = file_status());
472 
473  const std::string &path() const { return Path; }
474  std::error_code status(file_status &result) const;
475 
476  bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; }
477  bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); }
478  bool operator< (const directory_entry& rhs) const;
479  bool operator<=(const directory_entry& rhs) const;
480  bool operator> (const directory_entry& rhs) const;
481  bool operator>=(const directory_entry& rhs) const;
482 };
483 
484 namespace detail {
485  struct DirIterState;
486 
487  std::error_code directory_iterator_construct(DirIterState &, StringRef);
488  std::error_code directory_iterator_increment(DirIterState &);
489  std::error_code directory_iterator_destruct(DirIterState &);
490 
493  struct DirIterState : public RefCountedBase<DirIterState> {
494  DirIterState()
495  : IterationHandle(0) {}
496 
497  ~DirIterState() {
498  directory_iterator_destruct(*this);
499  }
500 
501  intptr_t IterationHandle;
502  directory_entry CurrentEntry;
503  };
504 } // end namespace detail
505 
511 
512 public:
513  explicit directory_iterator(const Twine &path, std::error_code &ec) {
514  State = new detail::DirIterState;
515  SmallString<128> path_storage;
516  ec = detail::directory_iterator_construct(*State,
517  path.toStringRef(path_storage));
518  }
519 
520  explicit directory_iterator(const directory_entry &de, std::error_code &ec) {
521  State = new detail::DirIterState;
522  ec = detail::directory_iterator_construct(*State, de.path());
523  }
524 
526  directory_iterator() : State(nullptr) {}
527 
528  // No operator++ because we need error_code.
529  directory_iterator &increment(std::error_code &ec) {
530  ec = directory_iterator_increment(*State);
531  return *this;
532  }
533 
534  const directory_entry &operator*() const { return State->CurrentEntry; }
535  const directory_entry *operator->() const { return &State->CurrentEntry; }
536 
537  bool operator==(const directory_iterator &RHS) const {
538  if (State == RHS.State)
539  return true;
540  if (!RHS.State)
541  return State->CurrentEntry == directory_entry();
542  if (!State)
543  return RHS.State->CurrentEntry == directory_entry();
544  return State->CurrentEntry == RHS.State->CurrentEntry;
545  }
546 
547  bool operator!=(const directory_iterator &RHS) const {
548  return !(*this == RHS);
549  }
550  // Other members as required by
551  // C++ Std, 24.1.1 Input iterators [input.iterators]
552 };
553 
554 namespace detail {
557  struct RecDirIterState : public RefCountedBase<RecDirIterState> {
559  : Level(0)
560  , HasNoPushRequest(false) {}
561 
562  std::stack<directory_iterator, std::vector<directory_iterator> > Stack;
563  uint16_t Level;
564  bool HasNoPushRequest;
565  };
566 } // end namespace detail
567 
572 
573 public:
575  explicit recursive_directory_iterator(const Twine &path, std::error_code &ec)
576  : State(new detail::RecDirIterState) {
577  State->Stack.push(directory_iterator(path, ec));
578  if (State->Stack.top() == directory_iterator())
579  State.reset();
580  }
581  // No operator++ because we need error_code.
582  recursive_directory_iterator &increment(std::error_code &ec) {
583  const directory_iterator end_itr;
584 
585  if (State->HasNoPushRequest)
586  State->HasNoPushRequest = false;
587  else {
588  file_status st;
589  if ((ec = State->Stack.top()->status(st))) return *this;
590  if (is_directory(st)) {
591  State->Stack.push(directory_iterator(*State->Stack.top(), ec));
592  if (ec) return *this;
593  if (State->Stack.top() != end_itr) {
594  ++State->Level;
595  return *this;
596  }
597  State->Stack.pop();
598  }
599  }
600 
601  while (!State->Stack.empty()
602  && State->Stack.top().increment(ec) == end_itr) {
603  State->Stack.pop();
604  --State->Level;
605  }
606 
607  // Check if we are done. If so, create an end iterator.
608  if (State->Stack.empty())
609  State.reset();
610 
611  return *this;
612  }
613 
614  const directory_entry &operator*() const { return *State->Stack.top(); }
615  const directory_entry *operator->() const { return &*State->Stack.top(); }
616 
617  // observers
619  int level() const { return State->Level; }
620 
622  bool no_push_request() const { return State->HasNoPushRequest; }
623 
624  // modifiers
626  void pop() {
627  assert(State && "Cannot pop an end iterator!");
628  assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
629 
630  const directory_iterator end_itr;
631  std::error_code ec;
632  do {
633  if (ec) {
634  //report_fatal_error("Error incrementing directory iterator.");
635  while (!State->Stack.empty()) State->Stack.pop();
636  break;
637  }
638  State->Stack.pop();
639  --State->Level;
640  } while (!State->Stack.empty()
641  && State->Stack.top().increment(ec) == end_itr);
642 
643  // Check if we are done. If so, create an end iterator.
644  if (State->Stack.empty())
645  State.reset();
646  }
647 
649  void no_push() { State->HasNoPushRequest = true; }
650 
651  bool operator==(const recursive_directory_iterator &RHS) const {
652  return State == RHS.State;
653  }
654 
655  bool operator!=(const recursive_directory_iterator &RHS) const {
656  return !(*this == RHS);
657  }
658  // Other members as required by
659  // C++ Std, 24.1.1 Input iterators [input.iterators]
660 };
661 
663 
664 } // end namespace fs
665 } // end namespace sys
666 } // end namespace llvm
667 
668 #endif // LLVM_SUPPORT_FILESYSTEM_H
Definition: Path.inc:31
void pop()
Goes up one level if Level > 0.
Definition: FileSystem.h:626
recursive_directory_iterator - Same as directory_iterator except for it recurses down into child dire...
Definition: FileSystem.h:570
file_status - Represents the result of a call to stat and friends.
Definition: FileSystem.h:126
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:15
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
DirIterState - Keeps state for the directory_iterator.
Definition: FileSystem.h:493
bool no_push_request() const
Returns true if no_push has been called for this directory_entry.
Definition: FileSystem.h:622
RefCountedBase - A generic base class for objects that wish to have their lifetimes managed using ref...
Definition: IntrusiveRefCntPtr.h:44
Definition: FileSystem.h:106
void no_push()
Does not go down into the current directory_entry.
Definition: FileSystem.h:649
RecDirIterState - Keeps state for the recursive_directory_iterator.
Definition: FileSystem.h:557
StringRef toStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single StringRef if it can be represented as such.
Definition: Twine.h:456
directory_iterator()
Construct end iterator.
Definition: FileSystem.h:526
directory_iterator - Iterates through the entries in path.
Definition: FileSystem.h:509
int level() const
Gets the current level. Starting path is at level 0.
Definition: FileSystem.h:619
directory_entry - A single entry in a directory.
Definition: FileSystem.h:455
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:42