27 #ifndef WPIUTIL_WPI_FILESYSTEM_H
28 #define WPIUTIL_WPI_FILESYSTEM_H
30 #include "wpi/Chrono.h"
31 #include "wpi/SmallString.h"
32 #include "wpi/StringRef.h"
33 #include "wpi/Twine.h"
34 #include "wpi/Error.h"
35 #include "wpi/ErrorHandling.h"
43 #include <system_error>
55 using file_t =
void *;
60 extern const file_t kInvalidFile;
63 enum class file_type {
88 owner_all = owner_read | owner_write | owner_exe,
92 group_all = group_read | group_write | group_exe,
96 others_all = others_read | others_write | others_exe,
97 all_read = owner_read | group_read | others_read,
98 all_write = owner_write | group_write | others_write,
99 all_exe = owner_exe | group_exe | others_exe,
100 all_all = owner_all | group_all | others_all,
101 set_uid_on_exe = 04000,
102 set_gid_on_exe = 02000,
104 all_perms = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit,
105 perms_not_known = 0xFFFF
109 inline perms operator|(perms l, perms r) {
110 return static_cast<perms>(static_cast<unsigned short>(l) |
111 static_cast<unsigned short>(r));
113 inline perms operator&(perms l, perms r) {
114 return static_cast<perms>(static_cast<unsigned short>(l) &
115 static_cast<unsigned short>(r));
117 inline perms &operator|=(perms &l, perms r) {
121 inline perms &operator&=(perms &l, perms r) {
125 inline perms operator~(perms x) {
127 return static_cast<perms>(
128 static_cast<unsigned short>(~static_cast<unsigned short>(x)));
137 UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
139 bool operator==(
const UniqueID &Other)
const {
140 return Device == Other.Device && File == Other.File;
142 bool operator!=(
const UniqueID &Other)
const {
return !(*
this == Other); }
143 bool operator<(
const UniqueID &Other)
const {
144 return std::tie(Device, File) < std::tie(Other.Device, Other.File);
147 uint64_t getDevice()
const {
return Device; }
148 uint64_t getFile()
const {
return File; }
157 time_t fs_st_atime = 0;
158 time_t fs_st_mtime = 0;
159 uint32_t fs_st_atime_nsec = 0;
160 uint32_t fs_st_mtime_nsec = 0;
163 off_t fs_st_size = 0;
165 uint32_t LastAccessedTimeHigh = 0;
166 uint32_t LastAccessedTimeLow = 0;
167 uint32_t LastWriteTimeHigh = 0;
168 uint32_t LastWriteTimeLow = 0;
169 uint32_t FileSizeHigh = 0;
170 uint32_t FileSizeLow = 0;
172 file_type Type = file_type::status_error;
173 perms Perms = perms_not_known;
182 uint32_t ATimeNSec, time_t MTime, uint32_t MTimeNSec,
183 uid_t UID, gid_t GID, off_t Size)
184 : fs_st_atime(ATime), fs_st_mtime(MTime),
185 fs_st_atime_nsec(ATimeNSec), fs_st_mtime_nsec(MTimeNSec),
186 fs_st_uid(UID), fs_st_gid(GID),
187 fs_st_size(Size), Type(Type), Perms(Perms) {}
190 uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
191 uint32_t LastWriteTimeLow, uint32_t FileSizeHigh,
192 uint32_t FileSizeLow)
193 : LastAccessedTimeHigh(LastAccessTimeHigh),
194 LastAccessedTimeLow(LastAccessTimeLow),
195 LastWriteTimeHigh(LastWriteTimeHigh),
196 LastWriteTimeLow(LastWriteTimeLow), FileSizeHigh(FileSizeHigh),
197 FileSizeLow(FileSizeLow), Type(Type), Perms(Perms) {}
201 file_type type()
const {
return Type; }
202 perms permissions()
const {
return Perms; }
220 uint32_t getUser()
const {
return fs_st_uid; }
221 uint32_t getGroup()
const {
return fs_st_gid; }
222 uint64_t getSize()
const {
return fs_st_size; }
224 uint32_t getUser()
const {
228 uint32_t getGroup()
const {
232 uint64_t getSize()
const {
233 return (uint64_t(FileSizeHigh) << 32) + FileSizeLow;
238 void type(file_type v) { Type = v; }
239 void permissions(perms p) { Perms = p; }
248 nlink_t fs_st_nlinks = 0;
251 uint32_t NumLinks = 0;
252 uint32_t VolumeSerialNumber = 0;
253 uint32_t FileIndexHigh = 0;
254 uint32_t FileIndexLow = 0;
263 file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino,
264 time_t ATime, uint32_t ATimeNSec,
265 time_t MTime, uint32_t MTimeNSec,
266 uid_t UID, gid_t GID, off_t Size)
269 fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {}
271 file_status(file_type Type, perms Perms, uint32_t LinkCount,
272 uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow,
273 uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow,
274 uint32_t VolumeSerialNumber, uint32_t FileSizeHigh,
275 uint32_t FileSizeLow, uint32_t FileIndexHigh,
276 uint32_t FileIndexLow)
278 LastWriteTimeHigh, LastWriteTimeLow, FileSizeHigh,
280 NumLinks(LinkCount), VolumeSerialNumber(VolumeSerialNumber),
281 FileIndexHigh(FileIndexHigh), FileIndexLow(FileIndexLow) {}
285 uint32_t getLinkCount()
const;
334 enum class AccessMode { Exist, Write, Execute };
341 std::error_code access(
const Twine &Path, AccessMode Mode);
347 inline bool exists(
const Twine &Path) {
348 return !access(Path, AccessMode::Exist);
355 inline bool can_write(
const Twine &Path) {
356 return !access(Path, AccessMode::Write);
368 bool equivalent(file_status A, file_status B);
380 std::error_code equivalent(
const Twine &A,
const Twine &B,
bool &result);
384 inline bool equivalent(
const Twine &A,
const Twine &B) {
386 return !equivalent(A, B, result) && result;
395 file_type get_file_type(
const Twine &Path,
bool Follow =
true);
401 bool is_directory(
const basic_file_status &status);
410 std::error_code is_directory(
const Twine &path,
bool &result);
414 inline bool is_directory(
const Twine &Path) {
416 return !is_directory(Path, Result) && Result;
423 bool is_regular_file(
const basic_file_status &status);
432 std::error_code is_regular_file(
const Twine &path,
bool &result);
436 inline bool is_regular_file(
const Twine &Path) {
438 if (is_regular_file(Path, Result))
447 bool is_symlink_file(
const basic_file_status &status);
456 std::error_code is_symlink_file(
const Twine &path,
bool &result);
460 inline bool is_symlink_file(
const Twine &Path) {
462 if (is_symlink_file(Path, Result))
472 bool is_other(
const basic_file_status &status);
482 std::error_code is_other(
const Twine &path,
bool &result);
492 std::error_code status(
const Twine &path, file_status &result,
496 std::error_code status(
int FD, file_status &Result);
502 bool status_known(
const basic_file_status &s);
510 std::error_code status_known(
const Twine &path,
bool &result);
512 enum CreationDisposition :
unsigned {
534 enum FileAccess :
unsigned {
539 enum OpenFlags :
unsigned {
563 inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
564 return OpenFlags(
unsigned(A) |
unsigned(B));
567 inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
572 inline FileAccess operator|(FileAccess A, FileAccess B) {
573 return FileAccess(
unsigned(A) |
unsigned(B));
576 inline FileAccess &operator|=(FileAccess &A, FileAccess B) {
597 std::error_code openFile(
const Twine &Name,
int &ResultFD,
598 CreationDisposition Disp, FileAccess Access,
599 OpenFlags Flags,
unsigned Mode = 0666);
615 Expected<file_t> openNativeFile(
const Twine &Name, CreationDisposition Disp,
616 FileAccess Access, OpenFlags Flags,
617 unsigned Mode = 0666);
634 inline std::error_code
635 openFileForWrite(
const Twine &Name,
int &ResultFD,
636 CreationDisposition Disp = CD_CreateAlways,
637 OpenFlags Flags = OF_None,
unsigned Mode = 0666) {
638 return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode);
654 inline Expected<file_t> openNativeFileForWrite(
const Twine &Name,
655 CreationDisposition Disp,
657 unsigned Mode = 0666) {
658 return openNativeFile(Name, Disp, FA_Write, Flags, Mode);
676 inline std::error_code openFileForReadWrite(
const Twine &Name,
int &ResultFD,
677 CreationDisposition Disp,
679 unsigned Mode = 0666) {
680 return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode);
696 inline Expected<file_t> openNativeFileForReadWrite(
const Twine &Name,
697 CreationDisposition Disp,
699 unsigned Mode = 0666) {
700 return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode);
717 std::error_code openFileForRead(
const Twine &Name,
int &ResultFD,
718 OpenFlags Flags = OF_None,
719 SmallVectorImpl<char> *RealPath =
nullptr);
734 openNativeFileForRead(
const Twine &Name, OpenFlags Flags = OF_None,
735 SmallVectorImpl<char> *RealPath =
nullptr);
742 void closeFile(file_t &F);
744 std::error_code getUniqueID(
const Twine Path, UniqueID &Result);
765 std::error_code init(
int FD, uint64_t Offset,
mapmode Mode);
776 std::error_code &ec);
806 file_type Type = file_type::type_unknown,
808 : Path(Path.
str()), Type(Type), FollowSymlinks(FollowSymlinks),
813 void replace_filename(
const Twine &Filename, file_type Type,
816 const std::string &path()
const {
return Path; }
818 file_type type()
const {
819 if (Type != file_type::type_unknown)
822 return S ? S->type() : file_type::type_unknown;
825 bool operator==(
const directory_entry& RHS)
const {
return Path == RHS.Path; }
826 bool operator!=(
const directory_entry& RHS)
const {
return !(*
this == RHS); }
837 std::error_code directory_iterator_construct(DirIterState &,
StringRef,
bool);
838 std::error_code directory_iterator_increment(DirIterState &);
839 std::error_code directory_iterator_destruct(DirIterState &);
844 directory_iterator_destruct(*
this);
847 intptr_t IterationHandle = 0;
857 std::shared_ptr<detail::DirIterState> State;
858 bool FollowSymlinks =
true;
862 bool follow_symlinks =
true)
863 : FollowSymlinks(follow_symlinks) {
864 State = std::make_shared<detail::DirIterState>();
866 ec = detail::directory_iterator_construct(
867 *State, path.
toStringRef(path_storage), FollowSymlinks);
871 bool follow_symlinks =
true)
872 : FollowSymlinks(follow_symlinks) {
873 State = std::make_shared<detail::DirIterState>();
874 ec = detail::directory_iterator_construct(
875 *State, de.path(), FollowSymlinks);
883 ec = directory_iterator_increment(*State);
887 const directory_entry &operator*()
const {
return State->CurrentEntry; }
888 const directory_entry *operator->()
const {
return &State->CurrentEntry; }
891 if (State == RHS.State)
897 return State->CurrentEntry == RHS.State->CurrentEntry;
901 return !(*
this == RHS);
909 std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
911 bool HasNoPushRequest =
false;
919 std::shared_ptr<detail::RecDirIterState> State;
925 bool follow_symlinks =
true)
926 : State(std::make_shared<detail::RecDirIterState>()),
927 Follow(follow_symlinks) {
937 if (State->HasNoPushRequest)
938 State->HasNoPushRequest =
false;
940 file_type type = State->Stack.top()->type();
941 if (type == file_type::symlink_file && Follow) {
945 type = status->type();
948 if (type == file_type::directory_file) {
950 if (State->Stack.top() != end_itr) {
958 while (!State->Stack.empty()
959 && State->Stack.top().increment(ec) == end_itr) {
965 if (State->Stack.empty())
971 const directory_entry &operator*()
const {
return *State->Stack.top(); }
972 const directory_entry *operator->()
const {
return &*State->Stack.top(); }
976 int level()
const {
return State->Level; }
984 assert(State &&
"Cannot pop an end iterator!");
985 assert(State->Level > 0 &&
"Cannot pop an iterator with level < 1");
992 while (!State->Stack.empty()) State->Stack.pop();
997 }
while (!State->Stack.empty()
998 && State->Stack.top().increment(ec) == end_itr);
1001 if (State->Stack.empty())
1006 void no_push() { State->HasNoPushRequest =
true; }
1009 return State == RHS.State;
1012 bool operator!=(
const recursive_directory_iterator &RHS)
const {
1013 return !(*
this == RHS);
1023 #endif // LLVM_SUPPORT_FILESYSTEM_H