23 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
24 #if defined(__APPLE__)
26 #elif defined(linux) || defined(__linux) || defined(__linux__)
27 #include <sys/sendfile.h>
29 #include <sys/statvfs.h>
37 #elif defined(_WIN32) || defined(_WIN64)
49 std::pair<Path, size_t> root(
const std::string& path)
51 bool root_found =
false;
52 size_t root_length = 0;
55 if (((path.size() == 1) && ((path[0] ==
'\\') || (path[0] ==
'/'))) || ((path.size() > 1) && ((path[0] ==
'\\') || (path[0] ==
'/')) && ((path[1] !=
'\\') && (path[1] !=
'/'))))
59 return std::make_pair(Path(
"/"), root_length);
63 if ((path.size() > 2) && ((path[0] ==
'\\') || (path[0] ==
'/')) && ((path[1] ==
'\\') || (path[1] ==
'/')) && ((path[2] ==
'\\') || (path[2] ==
'/')))
68 while (root_length < path.size())
70 if ((path[root_length] !=
'\\') && (path[root_length] !=
'/'))
75 return std::make_pair(Path(
"/"), root_length);
79 if ((path.size() > 2) && ((path[0] ==
'\\') || (path[0] ==
'/')) && ((path[1] ==
'\\') || (path[1] ==
'/')) && ((path[2] !=
'\\') && (path[2] !=
'/') && (path[2] !=
'?')))
84 while (root_length < path.size())
86 if ((path[root_length] ==
'\\') || (path[root_length] ==
'/'))
94 return std::make_pair(Path(path.substr(0, root_length)), root_length);
98 if ((path.size() > 3) && ((path[0] ==
'\\') && (path[1] ==
'\\') && (path[2] ==
'?') && (path[3] ==
'\\')))
105 while (root_length < path.size())
107 if (path[root_length] ==
':')
113 while (root_length < path.size())
115 if ((path[root_length] !=
'\\') && (path[root_length] !=
'/'))
126 return (root_found && (root_length > 0)) ? std::make_pair(Path(path.substr(0, root_length)), root_length) : std::make_pair<Path, size_t>(Path(), 0);
134 return Internals::root(
_path).first;
139 size_t root_length = Internals::root(
_path).second;
140 size_t relative_length =
_path.size() - root_length;
141 return Path(
_path.substr(root_length, relative_length));
146 bool parent_found =
false;
147 size_t parent_length =
_path.size();
150 bool filepart =
false;
151 while (parent_length > 0)
154 if ((
_path[parent_length] ==
'\\') || (
_path[parent_length] ==
'/'))
159 if ((parent_length == 1) && ((
_path[parent_length - 1] ==
'\\') || (
_path[parent_length - 1] ==
'/')))
161 parent_found =
false;
165 if ((parent_length > 0) && (
_path[parent_length - 1] ==
'?'))
167 parent_found = filepart;
172 if ((parent_length > 0) && (
_path[parent_length - 1] ==
':'))
174 parent_found = filepart;
180 while (parent_length > 0)
183 if ((
_path[parent_length] !=
'\\') && (
_path[parent_length] !=
'/'))
191 if ((parent_length == 0) && (
_path.size() > 1))
196 else if (
_path[parent_length] ==
':')
198 parent_found =
false;
206 return (parent_found && (parent_length > 0)) ?
Path(
_path.substr(0, parent_length)) :
Path();
211 bool filename_found =
false;
212 size_t filename_begin =
_path.size();
213 size_t filename_end =
_path.size();
216 while (filename_begin > 0)
219 if ((
_path[filename_begin] ==
'\\') || (
_path[filename_begin] ==
'/') || (
_path[filename_begin] ==
':'))
221 filename_found = ((
_path[filename_begin] ==
'\\') || (
_path[filename_begin] ==
'/'));
227 size_t filename_length = (filename_end - filename_begin);
229 return (filename_length > 0) ?
Path(
_path.substr(filename_begin, filename_length)) : (filename_found ?
Path(
".") :
Path());
234 bool ext_found =
false;
235 size_t ext_begin =
_path.size();
236 size_t ext_end =
_path.size();
239 while (ext_begin > 0)
242 if (
_path[ext_begin] ==
'.')
245 if ((ext_begin > 0) && (
_path[ext_begin - 1] ==
'.'))
249 if ((
_path[ext_begin] ==
'\\') || (
_path[ext_begin] ==
'/') || (
_path[ext_begin] ==
':'))
257 size_t ext_length = ext_end - ext_begin;
259 bool stem_found =
false;
260 size_t stem_begin = ext_begin;
261 size_t stem_end = (ext_found && (ext_length > 1)) ? ext_begin :
_path.size();
264 while (stem_begin > 0)
267 if ((
_path[stem_begin] ==
'\\') || (
_path[stem_begin] ==
'/') || (
_path[stem_begin] ==
':'))
269 stem_found = ((
_path[stem_begin] ==
'\\') || (
_path[stem_begin] ==
'/'));
275 size_t stem_length = (stem_end - stem_begin);
277 return (stem_length > 0) ?
Path(
_path.substr(stem_begin, stem_length)) : (stem_found ?
Path(
".") :
Path());
282 bool ext_found =
false;
283 size_t ext_begin =
_path.size();
284 size_t ext_end =
_path.size();
287 while (ext_begin > 0)
290 if (
_path[ext_begin] ==
'.')
293 if ((ext_begin > 0) && (
_path[ext_begin - 1] ==
'.'))
297 if ((
_path[ext_begin] ==
'\\') || (
_path[ext_begin] ==
'/') || (
_path[ext_begin] ==
':'))
305 size_t ext_length = ext_end - ext_begin;
307 return (ext_found && (ext_length > 1)) ?
Path(
_path.substr(ext_begin, ext_length)) :
Path();
312 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
313 char buffer[PATH_MAX];
315 char* result = realpath(
string().c_str(), buffer);
316 if (result ==
nullptr)
319 return Path(std::string(result));
320 #elif defined(_WIN32) || defined(_WIN64)
321 std::vector<wchar_t> buffer(MAX_PATH);
323 DWORD size = GetFullPathNameW(
wstring().c_str(), (DWORD)buffer.size(), buffer.data(),
nullptr);
324 if (size > buffer.size())
327 size = GetFullPathNameW(
wstring().c_str(), (DWORD)buffer.size(), buffer.data(),
nullptr);
333 std::wstring fullpath(buffer.data(), size);
335 size = GetLongPathNameW(fullpath.c_str(), buffer.data(), (DWORD)buffer.size());
336 if (size > buffer.size())
339 size = GetLongPathNameW(fullpath.c_str(), buffer.data(), (DWORD)buffer.size());
345 return Path(std::wstring(buffer.data(), size));
359 size_t index = result.
_path.size();
360 size_t length = result.
_path.size();
367 bool filepart =
false;
368 while (length <
_path.size())
370 if ((
_path[length] ==
'\\') || (
_path[length] ==
'/'))
373 std::string
temp(
_path.data() + index, length - index);
379 else if (!filepart && (
_path[length] ==
'.') && (((length + 1) ==
_path.size()) || ((
_path[length + 1] ==
'\\') || (
_path[length + 1] ==
'/'))))
385 else if (!filepart && (
_path[length] ==
'.') && (((length + 1) <
_path.size()) && (
_path[length + 1] ==
'.')) && (((length + 2) ==
_path.size()) || ((
_path[length + 2] ==
'\\') || (
_path[length + 2] ==
'/'))))
405 std::string
temp(
_path.data() + index, length - index);
416 for (
auto& ch : result.
_path)
417 if ((ch !=
'\\') && (ch !=
'/') &&
deprecated(ch))
425 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
428 int lresult = lstat(
string().c_str(), &lstatus);
429 if ((lresult == 0) && S_ISLNK(lstatus.st_mode))
433 int result = stat(
string().c_str(), &status);
436 if ((errno == ENOENT) || (errno == ENOTDIR))
442 if (S_ISLNK(status.st_mode))
444 else if (S_ISDIR(status.st_mode))
446 else if (S_ISREG(status.st_mode))
448 else if (S_ISBLK(status.st_mode))
450 else if (S_ISCHR(status.st_mode))
452 else if (S_ISFIFO(status.st_mode))
454 else if (S_ISSOCK(status.st_mode))
458 #elif defined(_WIN32) || defined(_WIN64)
463 if (
attributes & FILE_ATTRIBUTE_REPARSE_POINT)
465 else if (
attributes & FILE_ATTRIBUTE_DIRECTORY)
475 #if defined(_WIN32) || defined(_WIN64)
485 if (
attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
502 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
504 int result = stat(
string().c_str(), &status);
507 if ((errno == ENOENT) || (errno == ENOTDIR))
513 if (status.st_mode & S_IRUSR)
515 if (status.st_mode & S_IWUSR)
517 if (status.st_mode & S_IXUSR)
519 if (status.st_mode & S_IRGRP)
521 if (status.st_mode & S_IWGRP)
523 if (status.st_mode & S_IXGRP)
525 if (status.st_mode & S_IROTH)
527 if (status.st_mode & S_IWOTH)
529 if (status.st_mode & S_IXOTH)
531 if (status.st_mode & S_ISUID)
533 if (status.st_mode & S_ISGID)
535 if (status.st_mode & S_ISVTX)
543 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
545 int result = stat(
string().c_str(), &status);
548 #if defined(__APPLE__)
549 return UtcTimestamp(
Timestamp((status.st_mtimespec.tv_sec * 1000000000) + status.st_mtimespec.tv_nsec));
553 #elif defined(_WIN32) || defined(_WIN64)
554 HANDLE hFile = CreateFileW(
wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
555 if (hFile == INVALID_HANDLE_VALUE)
559 auto file =
resource(hFile, [](HANDLE hObject) { CloseHandle(hObject); });
562 if (!GetFileTime(file.get(), &
created,
nullptr,
nullptr))
566 if (!CloseHandle(hFile))
570 ULARGE_INTEGER result;
571 result.LowPart =
created.dwLowDateTime;
572 result.HighPart =
created.dwHighDateTime;
579 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
581 int result = stat(
string().c_str(), &status);
585 #if defined(__APPLE__)
586 return UtcTimestamp(
Timestamp((status.st_mtimespec.tv_sec * 1000000000) + status.st_mtimespec.tv_nsec));
590 #elif defined(_WIN32) || defined(_WIN64)
591 HANDLE hFile = CreateFileW(
wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
592 if (hFile == INVALID_HANDLE_VALUE)
596 auto file =
resource(hFile, [](HANDLE hObject) { CloseHandle(hObject); });
599 if (!GetFileTime(file.get(),
nullptr,
nullptr, &write))
603 if (!CloseHandle(hFile))
607 ULARGE_INTEGER result;
608 result.LowPart = write.dwLowDateTime;
609 result.HighPart = write.dwHighDateTime;
616 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
618 int result = stat(
string().c_str(), &status);
622 return (
size_t)status.st_nlink;
623 #elif defined(_WIN32) || defined(_WIN64)
624 HANDLE hFile = CreateFileW(
wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
625 if (hFile == INVALID_HANDLE_VALUE)
629 auto file =
resource(hFile, [](HANDLE hObject) { CloseHandle(hObject); });
631 BY_HANDLE_FILE_INFORMATION bhfi;
632 if (!GetFileInformationByHandle(file.get(), &bhfi))
636 if (!CloseHandle(hFile))
640 return (
size_t)bhfi.nNumberOfLinks;
646 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
647 struct statvfs stvfs;
648 int result = statvfs(
string().c_str(), &stvfs);
655 stvfs.f_blocks * stvfs.f_frsize,
656 stvfs.f_bfree * stvfs.f_frsize,
657 stvfs.f_bavail * stvfs.f_frsize
659 #elif defined(_WIN32) || defined(_WIN64)
660 ULARGE_INTEGER uiFreeBytesAvailable;
661 ULARGE_INTEGER uiTotalNumberOfBytes;
662 ULARGE_INTEGER uiTotalNumberOfFreeBytes;
663 if (!GetDiskFreeSpaceExW(
wstring().c_str(), &uiFreeBytesAvailable, &uiTotalNumberOfBytes, &uiTotalNumberOfFreeBytes))
669 (((uint64_t)uiTotalNumberOfBytes.HighPart) << 32) + uiTotalNumberOfBytes.LowPart,
670 (((uint64_t)uiTotalNumberOfFreeBytes.HighPart) << 32) + uiTotalNumberOfFreeBytes.LowPart,
671 (((uint64_t)uiFreeBytesAvailable.HighPart) << 32) + uiFreeBytesAvailable.LowPart
678 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
680 int result = stat(
string().c_str(), &st1);
685 result = stat(path.
string().c_str(), &st2);
690 return ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino) && (st1.st_size == st2.st_size) && (st1.st_mtime == st2.st_mtime));
691 #elif defined(_WIN32) || defined(_WIN64)
693 HANDLE hFile1 = CreateFileW(
wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
694 if (hFile1 == INVALID_HANDLE_VALUE)
698 auto file1 =
resource(hFile1, [](HANDLE hObject) { CloseHandle(hObject); });
700 BY_HANDLE_FILE_INFORMATION info1;
701 if (!GetFileInformationByHandle(file1.get(), &info1))
705 if (!CloseHandle(hFile1))
710 HANDLE hFile2 = CreateFileW(path.
wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
711 if (hFile2 == INVALID_HANDLE_VALUE)
715 auto file2 =
resource(hFile2, [](HANDLE hObject) { CloseHandle(hObject); });
717 BY_HANDLE_FILE_INFORMATION info2;
718 if (!GetFileInformationByHandle(file2.get(), &info2))
722 if (!CloseHandle(hFile2))
727 return ((info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber) &&
728 (info1.nFileIndexHigh == info2.nFileIndexHigh) &&
729 (info1.nFileIndexLow == info2.nFileIndexLow) &&
730 (info1.nFileSizeHigh == info2.nFileSizeHigh) &&
731 (info1.nFileSizeLow == info2.nFileSizeLow) &&
732 (info1.ftLastWriteTime.dwLowDateTime == info2.ftLastWriteTime.dwLowDateTime) &&
733 (info1.ftLastWriteTime.dwHighDateTime == info2.ftLastWriteTime.dwHighDateTime));
744 if ((last ==
'\\') || (last ==
'/'))
758 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
759 std::replace(
_path.begin(),
_path.end(),
'\\',
'/');
760 #elif defined(_WIN32) || defined(_WIN64)
761 std::replace(
_path.begin(),
_path.end(),
'/',
'\\');
772 size_t index =
_path.size();
778 if ((
_path[index] ==
'\\') || (
_path[index] ==
'/') || (
_path[index] ==
':'))
804 size_t dot =
_path.size();
805 size_t index =
_path.size();
811 if (
_path[index] ==
'.')
813 if ((index > 0) && (
_path[index - 1] ==
'.'))
819 if ((
_path[index] ==
'\\') || (
_path[index] ==
'/') || (
_path[index] ==
':'))
833 size_t index =
_path.size();
838 if (((
_path[index] !=
'\\') && (
_path[index] !=
'/')) || ((index > 0) && (
_path[index - 1] ==
':')))
851 char deprecated[] =
"\\/?%*:|\"<>";
852 return (std::find(deprecated, deprecated +
countof(deprecated), character) != (deprecated +
countof(deprecated)));
857 wchar_t deprecated[] = L
"\\/?%*:|\"<>";
858 return (std::find(deprecated, deprecated +
countof(deprecated), character) != (deprecated +
countof(deprecated)));
863 return "\\/?%*:|\"<>";
868 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) || defined(__APPLE__)
870 #elif defined(_WIN32) || defined(_WIN64)
877 return Internals::initial;
882 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
883 std::vector<char> buffer(PATH_MAX);
886 while (((result = getcwd(buffer.data(), buffer.size())) ==
nullptr) && (errno == ERANGE))
887 buffer.resize(buffer.size() * 2);
889 if (result ==
nullptr)
892 return Path(std::string(buffer.data()));
893 #elif defined(_WIN32) || defined(_WIN64)
894 std::vector<wchar_t> buffer(MAX_PATH);
896 DWORD size = GetCurrentDirectoryW((DWORD)buffer.size(), buffer.data());
897 if (size > buffer.size())
900 size = GetCurrentDirectoryW((DWORD)buffer.size(), buffer.data());
906 return Path(std::wstring(buffer.data(), size));
912 #if defined(__APPLE__)
913 char buffer[PROC_PIDPATHINFO_MAXSIZE];
915 int size = proc_pidpath(getpid(), buffer,
countof(buffer));
919 return Path(std::string(buffer, size));
920 #elif defined(unix) || defined(__unix) || defined(__unix__)
921 std::vector<char> buffer(PATH_MAX);
924 while ((size = readlink(
"/proc/self/exe", buffer.data(), buffer.size())) == (ssize_t)buffer.size())
925 buffer.resize(buffer.size() * 2);
930 return Path(std::string(buffer.data(), size));
931 #elif defined(_WIN32) || defined(_WIN64)
932 std::vector<wchar_t> buffer(MAX_PATH);
935 while ((size = GetModuleFileNameW(
nullptr, buffer.data(), (DWORD)buffer.size())) == buffer.size())
936 buffer.resize(buffer.size() * 2);
941 return Path(std::wstring(buffer.data(), size));
947 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
948 std::vector<char> buffer(PATH_MAX);
949 uid_t uid = getuid();
955 while (((result = getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &ppwd)) != 0) && (result == ERANGE))
956 buffer.resize(buffer.size() * 2);
958 if ((result != 0) || (ppwd ==
nullptr))
961 return Path(std::string(pwd.pw_dir));
962 #elif defined(_WIN32) || defined(_WIN64)
963 std::vector<wchar_t> buffer(MAX_PATH);
966 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken))
969 DWORD size = (DWORD)buffer.size();
970 if (!GetUserProfileDirectoryW(hToken, buffer.data(), &size))
973 if (!GetUserProfileDirectoryW(hToken, buffer.data(), &size))
980 if (!CloseHandle(hToken))
983 return Path(std::wstring(buffer.data(), size));
989 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
991 if (((
temp = getenv(
"TMPDIR")) !=
nullptr) || ((
temp = getenv(
"TMP")) !=
nullptr) || ((
temp = getenv(
"TEMP")) !=
nullptr) || ((
temp = getenv(
"TEMPDIR")) !=
nullptr))
994 return Path(std::string(
"/tmp"));
995 #elif defined(_WIN32) || defined(_WIN64)
996 std::vector<wchar_t> buffer(MAX_PATH);
998 DWORD size = GetTempPathW((DWORD)buffer.size(), buffer.data());
999 if (size > buffer.size())
1001 buffer.resize(size);
1002 size = GetTempPathW((DWORD)buffer.size(), buffer.data());
1008 return Path(std::wstring(buffer.data(), size));
1021 if (exists && !overwrite)
1038 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1040 int source = open(src.
string().c_str(), O_RDONLY, 0);
1046 int result = fstat(source, &status);
1054 int destination = open(dst.
string().c_str(), O_CREAT | O_WRONLY | O_TRUNC, status.st_mode);
1055 if (destination < 0)
1061 #if defined(linux) || defined(__linux) || defined(__linux__)
1065 size_t tot = status.st_size;
1069 if ((sent = sendfile(destination, source, &offset, tot - cur)) <= 0)
1071 if ((errno == EINTR) || (errno == EAGAIN))
1085 char buffer[BUFSIZ];
1090 size = read(source, buffer,
countof(buffer));
1097 size = write(destination, buffer, size);
1110 #elif defined(_WIN32) || defined(_WIN64)
1111 if (!CopyFileW(src.
wstring().c_str(), dst.
wstring().c_str(), FALSE))
1120 std::regex matcher(pattern);
1124 if (exists && !overwrite)
1130 if (pattern.empty() || std::regex_match(src.
filename().
string(), matcher))
1131 return Copy(src, dst, overwrite);
1142 for (
auto it = directory.
begin(); it != directory.
end(); ++it)
1144 if (pattern.empty() || std::regex_match(it->filename().string(), matcher))
1147 if (it->IsSymlink() || !it->IsDirectory())
1160 if (exists && !overwrite)
1165 return Copy(src, dst, overwrite);
1168 std::stack<std::tuple<Path, Path>> dirs;
1169 dirs.push(std::make_tuple(src, dst));
1172 while (!dirs.empty())
1175 std::tuple<Path, Path>
current = dirs.top();
1184 for (
auto it = srcdir.
begin(); it != srcdir.
end(); ++it)
1187 if (it->IsSymlink() || !it->IsDirectory())
1190 dirs.push(std::make_tuple(srcdir / it->
filename(), dstdir / it->
filename()));
1198 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1199 int result = rename(src.
string().c_str(), dst.
string().c_str());
1202 #elif defined(_WIN32) || defined(_WIN64)
1203 if (!MoveFileExW(src.
wstring().c_str(), dst.
wstring().c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH))
1211 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1214 int result = rmdir(path.
string().c_str());
1220 int result = unlink(path.
string().c_str());
1224 #elif defined(_WIN32) || defined(_WIN64)
1225 std::wstring wpath = path.
wstring();
1226 DWORD
attributes = GetFileAttributesW(wpath.c_str());
1232 if (!RemoveDirectoryW(wpath.c_str()))
1239 if (!SetFileAttributesW(wpath.c_str(),
attributes))
1241 if (!DeleteFileW(wpath.c_str()))
1250 std::regex matcher(pattern);
1252 bool is_directory =
false;
1253 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1255 is_directory =
true;
1256 #elif defined(_WIN32) || defined(_WIN64)
1257 std::wstring wpath = path.
wstring();
1258 DWORD
attributes = GetFileAttributesW(wpath.c_str());
1263 is_directory =
true;
1269 for (
auto it = directory.
begin(); it != directory.
end(); ++it)
1270 if (pattern.empty() || std::regex_match(it->filename().string(), matcher))
1276 if (pattern.empty() || std::regex_match(path.
filename().
string(), matcher))
1284 bool is_directory =
false;
1285 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1287 is_directory =
true;
1288 #elif defined(_WIN32) || defined(_WIN64)
1289 std::wstring wpath = path.
wstring();
1290 DWORD
attributes = GetFileAttributesW(wpath.c_str());
1295 is_directory =
true;
1301 for (
auto it = directory.
rbegin(); it != directory.
rend(); ++it)
1311 #if defined(_WIN32) || defined(_WIN64)
1312 std::wstring wpath = path.
wstring();
1313 DWORD result = GetFileAttributesW(wpath.c_str());
1314 if (result == INVALID_FILE_ATTRIBUTES)
1318 result |= FILE_ATTRIBUTE_NORMAL;
1320 result &= ~FILE_ATTRIBUTE_NORMAL;
1322 result |= FILE_ATTRIBUTE_ARCHIVE;
1324 result &= ~FILE_ATTRIBUTE_ARCHIVE;
1326 result |= FILE_ATTRIBUTE_HIDDEN;
1328 result &= ~FILE_ATTRIBUTE_HIDDEN;
1330 result |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
1332 result &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
1334 result |= FILE_ATTRIBUTE_OFFLINE;
1336 result &= ~FILE_ATTRIBUTE_OFFLINE;
1338 result |= FILE_ATTRIBUTE_READONLY;
1340 result &= ~FILE_ATTRIBUTE_READONLY;
1342 result |= FILE_ATTRIBUTE_SYSTEM;
1344 result &= ~FILE_ATTRIBUTE_SYSTEM;
1346 result |= FILE_ATTRIBUTE_TEMPORARY;
1348 result &= ~FILE_ATTRIBUTE_TEMPORARY;
1350 if (!SetFileAttributesW(wpath.c_str(), result))
1357 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1384 int result = chmod(path.
string().c_str(), mode);
1392 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1394 int result = stat(path.
string().c_str(), &status);
1398 struct timespec times[2];
1399 #if defined(__APPLE__)
1400 times[0] = status.st_atimespec;
1402 times[0] = status.st_atim;
1404 times[1].tv_sec = timestamp.
seconds();
1405 times[1].tv_nsec = timestamp.
nanoseconds() % 1000000000;
1407 result = utimensat(AT_FDCWD, path.
string().c_str(), times, 0);
1410 #elif defined(_WIN32) || defined(_WIN64)
1411 HANDLE hFile = CreateFileW(path.
wstring().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
1412 if (hFile == INVALID_HANDLE_VALUE)
1416 auto file =
resource(hFile, [](HANDLE hObject) { CloseHandle(hObject); });
1418 ULARGE_INTEGER result;
1419 result.QuadPart = (timestamp.
total() / 100) + 116444736000000000ull;
1422 created.dwLowDateTime = result.LowPart;
1423 created.dwHighDateTime = result.HighPart;
1424 if (!SetFileTime(file.get(), &
created,
nullptr,
nullptr))
1428 if (!CloseHandle(hFile))
1436 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1438 int result = stat(path.
string().c_str(), &status);
1442 struct timespec times[2];
1443 #if defined(__APPLE__)
1444 times[0] = status.st_atimespec;
1446 times[0] = status.st_atim;
1448 times[1].tv_sec = timestamp.
seconds();
1449 times[1].tv_nsec = timestamp.
nanoseconds() % 1000000000;
1451 result = utimensat(AT_FDCWD, path.
string().c_str(), times, 0);
1454 #elif defined(_WIN32) || defined(_WIN64)
1455 HANDLE hFile = CreateFileW(path.
wstring().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
1456 if (hFile == INVALID_HANDLE_VALUE)
1460 auto file =
resource(hFile, [](HANDLE hObject) { CloseHandle(hObject); });
1462 ULARGE_INTEGER result;
1463 result.QuadPart = (timestamp.
total() / 100) + 116444736000000000ull;
1466 write.dwLowDateTime = result.LowPart;
1467 write.dwHighDateTime = result.HighPart;
1468 if (!SetFileTime(file.get(),
nullptr,
nullptr, &write))
1472 if (!CloseHandle(hFile))
1480 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
1481 int result = chdir(path.
string().c_str());
1484 #elif defined(_WIN32) || defined(_WIN64)
1486 if (!SetCurrentDirectoryW(
temp.
wstring().c_str()))
DirectoryIterator begin() const
Get the directory begin iterator.
DirectoryIterator end() const
Get the directory end iterator.
DirectoryIterator rbegin() const
Get the directory recursive begin iterator.
static Directory Create(const Path &path, const Flags< FileAttributes > &attributes=Directory::DEFAULT_ATTRIBUTES, const Flags< FilePermissions > &permissions=Directory::DEFAULT_PERMISSIONS)
Create directory from the given path.
DirectoryIterator rend() const
Get the directory recursive end iterator.
static void WriteEmpty(const Path &path)
Write an empty file.
FileSystemException & Attach(const Path &path)
Attach the given path to the exception.
Path root() const
Decompose root path from the current path.
Path absolute() const
Transform the current path to the real path on a filesystem.
Path & ReplaceExtension(const Path &extension)
Replace the current path extension with a given one.
bool IsSymlink() const
Is the path points to symbolic link?
static Path unique()
Get the unique filename in UUID format "00000000-0000-0000-0000-000000000000".
UtcTimestamp created() const
Get the path created UTC timestamp.
static Path RemoveAll(const Path &path)
Recursively remove the given path (file, empty directory, symlink, etc) from the filesystem.
std::wstring wstring() const
Get the path value as a wide string.
size_t hardlinks() const
Get the path count of hardlinks.
Path validate(char placeholder='_') const
Transform the current path and replace all deprecated characters with a given placeholder (default is...
static Path CopyIf(const Path &src, const Path &dst, const std::string &pattern="", bool overwrite=false)
Copy all matched files from the the given source path to destination path (files, directories,...
Flags< FileAttributes > attributes() const
Get the path file attributes.
Path()
Initialize path with an empty value.
bool IsDirectory() const
Is the path points to directory?
Path & RemoveTrailingSeparators()
Remove all trailing separators form the current path.
static Path Copy(const Path &src, const Path &dst, bool overwrite=false)
Copy the given source path to destination path (file, empty directory, symlink, etc)
Path relative() const
Decompose relative path from the current path.
static Path Remove(const Path &path)
Remove the given path (file, empty directory, symlink, etc) from the filesystem.
static Path initial()
Get the initial path of the process.
bool IsExists() const
Is the path exists?
static Path home()
Get the home path of the process.
static void SetCreated(const Path &path, const UtcTimestamp ×tamp)
Set created UTC timestamp for the given path.
Path & ReplaceFilename(const Path &filename)
Replace the current path filename with a given one.
Path stem() const
Decompose stem from the current path.
static void SetAttributes(const Path &path, const Flags< FileAttributes > &attributes)
Set file attributes for the given path.
static void SetModified(const Path &path, const UtcTimestamp ×tamp)
Set modified UTC timestamp for the given path.
SpaceInfo space() const
Get the path space information.
Path & MakePreferred()
Convert all path separators to system ones ('\' for Windows or '/' for Unix)
static char separator() noexcept
Get the system path separator character ('\' for Windows or '/' for Unix)
Path parent() const
Decompose parent path from the current path.
static void Touch(const Path &path)
Touch the given path and set its modified UTC timestamp to the current value.
static Path CopyAll(const Path &src, const Path &dst, bool overwrite=false)
Recursively copy the given source path to destination path (files, directories, symlinks,...
Path canonical() const
Transform the current path and replace all '.' and '..' properly.
Path extension() const
Decompose extension from the current path.
static void SetCurrent(const Path &path)
Set the given path of the process as a current one.
bool empty() const noexcept
Is the path empty?
Path & Append(const Path &path)
Append the given path to the current one.
Path filename() const
Decompose filename from the current path.
Flags< FilePermissions > permissions() const
Get the path file permissions.
FileType type() const
Get the path file type.
const std::string & string() const noexcept
Get the path value as UTF-8 string.
static std::string deprecated()
Get filesystem deprecated characters ('\', '/', '?', '', '*', ':', '|', '"', '<', '>')
static Path temp()
Get the temporary path of the process.
static void SetPermissions(const Path &path, const Flags< FilePermissions > &permissions)
Set file permissions for the given path.
static Path RemoveIf(const Path &path, const std::string &pattern="")
Recursively remove the given path matched to the given pattern (file, empty directory,...
UtcTimestamp modified() const
Get the path modified UTC timestamp.
bool IsEquivalent(const Path &path) const
Is the current path is equivalent to the given one (points to the same node on a filesystem)?
static Path Rename(const Path &src, const Path &dst)
Rename the given source path to destination path (file, empty directory, symlink, etc)
static Path current()
Get the current path of the process.
std::string _path
Path string.
static Path executable()
Get the executable path of the process.
static Symlink CopySymlink(const Path &src, const Path &dst)
Copy the current symlink to another destination path.
uint64_t seconds() const noexcept
Get total seconds of the current timestamp.
uint64_t total() const noexcept
Get total value of the current timestamp (total nanoseconds)
uint64_t nanoseconds() const noexcept
Get total nanoseconds of the current timestamp.
static UUID Random()
Generate random UUID4 (randomly or pseudo-randomly generated version)
Static array countof definition.
Filesystem directory definition.
#define throwex
Throw extended exception macro.
C++ Common project definitions.
@ CHARACTER
Character device.
@ NONE
None (file not found)
auto resource(T handle, TCleaner cleaner)
Resource smart cleaner pattern.
constexpr size_t countof(const T(&)[N]) noexcept
Count of elements in static array.
@ IXOTH
Execute or search permission bit for other users.
@ IWUSR
Write permission bit for the owner of the file.
@ IWGRP
Write permission bit for the group owner of the file.
@ IXUSR
Execute (for ordinary files) or search (for directories) permission bit for the owner of the file.
@ ISVTX
This is the sticky bit.
@ IRGRP
Read permission bit for the group owner of the file.
@ IRUSR
Read permission bit for the owner of the file.
@ IXGRP
Execute or search permission bit for the group owner of the file.
@ IWOTH
Write permission bit for other users.
@ IROTH
Read permission bit for other users.
@ ISUID
This is the set-user-ID on execute bit.
@ ISGID
This is the set-group-ID on execute bit.
Filesystem path definition.
Resource smart cleaner pattern definition.
Filesystem space information.
Filesystem symlink definition.
Universally unique identifier (UUID) definition.