diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-06-21 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-12-17 14:59:19 +0500 |
| commit | 5b39dc76f1bc82f941d5c800ab9f34407a06b53a (patch) | |
| tree | fe5e17420300b715021a76328444088d32047963 /CPP/Windows/FileName.cpp | |
| parent | 93be7d4abfd4233228f58ee1fbbcd76d91be66a4 (diff) | |
| download | 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.gz 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.tar.bz2 7zip-5b39dc76f1bc82f941d5c800ab9f34407a06b53a.zip | |
23.0123.01
Diffstat (limited to 'CPP/Windows/FileName.cpp')
| -rw-r--r-- | CPP/Windows/FileName.cpp | 171 |
1 files changed, 86 insertions, 85 deletions
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp index d61ff7e..c9c4f8b 100644 --- a/CPP/Windows/FileName.cpp +++ b/CPP/Windows/FileName.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | #include <limits.h> | 6 | #include <limits.h> |
| 7 | #include <unistd.h> | 7 | #include <unistd.h> |
| 8 | #include "../Common/StringConvert.h" | 8 | #include "../Common/StringConvert.h" |
| 9 | #include "FileDir.h" | ||
| 10 | #endif | 9 | #endif |
| 11 | 10 | ||
| 11 | #include "FileDir.h" | ||
| 12 | #include "FileName.h" | 12 | #include "FileName.h" |
| 13 | 13 | ||
| 14 | #ifndef _UNICODE | 14 | #ifndef _UNICODE |
| @@ -68,7 +68,7 @@ void NormalizeDirPathPrefix(UString &dirPath) | |||
| 68 | #ifdef _WIN32 | 68 | #ifdef _WIN32 |
| 69 | 69 | ||
| 70 | #ifndef USE_UNICODE_FSTRING | 70 | #ifndef USE_UNICODE_FSTRING |
| 71 | #ifdef WIN_LONG_PATH | 71 | #ifdef Z7_LONG_PATH |
| 72 | static void NormalizeDirSeparators(UString &s) | 72 | static void NormalizeDirSeparators(UString &s) |
| 73 | { | 73 | { |
| 74 | const unsigned len = s.Len(); | 74 | const unsigned len = s.Len(); |
| @@ -90,7 +90,7 @@ void NormalizeDirSeparators(FString &s) | |||
| 90 | #endif | 90 | #endif |
| 91 | 91 | ||
| 92 | 92 | ||
| 93 | #define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) | 93 | #define IS_LETTER_CHAR(c) ((((unsigned)(int)(c) | 0x20) - (unsigned)'a' <= (unsigned)('z' - 'a'))) |
| 94 | 94 | ||
| 95 | bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } | 95 | bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); } |
| 96 | 96 | ||
| @@ -120,7 +120,7 @@ bool IsAltPathPrefix(CFSTR s) throw() | |||
| 120 | #if defined(_WIN32) && !defined(UNDER_CE) | 120 | #if defined(_WIN32) && !defined(UNDER_CE) |
| 121 | 121 | ||
| 122 | const char * const kSuperPathPrefix = "\\\\?\\"; | 122 | const char * const kSuperPathPrefix = "\\\\?\\"; |
| 123 | #ifdef WIN_LONG_PATH | 123 | #ifdef Z7_LONG_PATH |
| 124 | static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; | 124 | static const char * const kSuperUncPrefix = "\\\\?\\UNC\\"; |
| 125 | #endif | 125 | #endif |
| 126 | 126 | ||
| @@ -191,7 +191,7 @@ unsigned GetNetworkServerPrefixSize(CFSTR s) throw() | |||
| 191 | if (c == '.' || c == '?') | 191 | if (c == '.' || c == '?') |
| 192 | return 0; | 192 | return 0; |
| 193 | } | 193 | } |
| 194 | int pos = FindSepar(s + prefixSize); | 194 | const int pos = FindSepar(s + prefixSize); |
| 195 | if (pos < 0) | 195 | if (pos < 0) |
| 196 | return 0; | 196 | return 0; |
| 197 | return prefixSize + (unsigned)(pos + 1); | 197 | return prefixSize + (unsigned)(pos + 1); |
| @@ -199,11 +199,11 @@ unsigned GetNetworkServerPrefixSize(CFSTR s) throw() | |||
| 199 | 199 | ||
| 200 | bool IsNetworkShareRootPath(CFSTR s) throw() | 200 | bool IsNetworkShareRootPath(CFSTR s) throw() |
| 201 | { | 201 | { |
| 202 | unsigned prefixSize = GetNetworkServerPrefixSize(s); | 202 | const unsigned prefixSize = GetNetworkServerPrefixSize(s); |
| 203 | if (prefixSize == 0) | 203 | if (prefixSize == 0) |
| 204 | return false; | 204 | return false; |
| 205 | s += prefixSize; | 205 | s += prefixSize; |
| 206 | int pos = FindSepar(s); | 206 | const int pos = FindSepar(s); |
| 207 | if (pos < 0) | 207 | if (pos < 0) |
| 208 | return true; | 208 | return true; |
| 209 | return s[(unsigned)pos + 1] == 0; | 209 | return s[(unsigned)pos + 1] == 0; |
| @@ -217,6 +217,37 @@ bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } | |||
| 217 | bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } | 217 | bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } |
| 218 | // bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } | 218 | // bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } |
| 219 | 219 | ||
| 220 | bool IsAltStreamPrefixWithColon(const UString &s) throw() | ||
| 221 | { | ||
| 222 | if (s.IsEmpty()) | ||
| 223 | return false; | ||
| 224 | if (s.Back() != ':') | ||
| 225 | return false; | ||
| 226 | unsigned pos = 0; | ||
| 227 | if (IsSuperPath(s)) | ||
| 228 | pos = kSuperPathPrefixSize; | ||
| 229 | if (s.Len() - pos == 2 && IsDrivePath2(s.Ptr(pos))) | ||
| 230 | return false; | ||
| 231 | return true; | ||
| 232 | } | ||
| 233 | |||
| 234 | bool If_IsSuperPath_RemoveSuperPrefix(UString &s) | ||
| 235 | { | ||
| 236 | if (!IsSuperPath(s)) | ||
| 237 | return false; | ||
| 238 | unsigned start = 0; | ||
| 239 | unsigned count = kSuperPathPrefixSize; | ||
| 240 | const wchar_t *s2 = s.Ptr(kSuperPathPrefixSize); | ||
| 241 | if (IS_UNC_WITH_SLASH(s2)) | ||
| 242 | { | ||
| 243 | start = 2; | ||
| 244 | count = kSuperUncPathPrefixSize - 2; | ||
| 245 | } | ||
| 246 | s.Delete(start, count); | ||
| 247 | return true; | ||
| 248 | } | ||
| 249 | |||
| 250 | |||
| 220 | #ifndef USE_UNICODE_FSTRING | 251 | #ifndef USE_UNICODE_FSTRING |
| 221 | bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } | 252 | bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; } |
| 222 | // bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } | 253 | // bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; } |
| @@ -288,7 +319,7 @@ static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) | |||
| 288 | return 0; | 319 | return 0; |
| 289 | if (s[1] == 0 || !IS_SEPAR(s[1])) | 320 | if (s[1] == 0 || !IS_SEPAR(s[1])) |
| 290 | return 1; | 321 | return 1; |
| 291 | unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); | 322 | const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); |
| 292 | return (size == 0) ? 0 : 2 + size; | 323 | return (size == 0) ? 0 : 2 + size; |
| 293 | } | 324 | } |
| 294 | 325 | ||
| @@ -296,11 +327,11 @@ static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) | |||
| 296 | { | 327 | { |
| 297 | if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) | 328 | if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) |
| 298 | { | 329 | { |
| 299 | unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); | 330 | const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); |
| 300 | return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; | 331 | return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; |
| 301 | } | 332 | } |
| 302 | // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" | 333 | // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" |
| 303 | int pos = FindSepar(s + kSuperPathPrefixSize); | 334 | const int pos = FindSepar(s + kSuperPathPrefixSize); |
| 304 | if (pos < 0) | 335 | if (pos < 0) |
| 305 | return 0; | 336 | return 0; |
| 306 | return kSuperPathPrefixSize + pos + 1; | 337 | return kSuperPathPrefixSize + pos + 1; |
| @@ -379,42 +410,26 @@ unsigned GetRootPrefixSize(const wchar_t *s) throw() { return IS_SEPAR(s[0]) ? 1 | |||
| 379 | 410 | ||
| 380 | #ifndef UNDER_CE | 411 | #ifndef UNDER_CE |
| 381 | 412 | ||
| 382 | static bool GetCurDir(UString &path) | ||
| 383 | { | ||
| 384 | path.Empty(); | ||
| 385 | 413 | ||
| 386 | #ifdef _WIN32 | 414 | #ifdef USE_UNICODE_FSTRING |
| 387 | 415 | ||
| 388 | DWORD needLength; | 416 | #define GetCurDir NDir::GetCurrentDir |
| 389 | #ifndef _UNICODE | ||
| 390 | if (!g_IsNT) | ||
| 391 | { | ||
| 392 | TCHAR s[MAX_PATH + 2]; | ||
| 393 | s[0] = 0; | ||
| 394 | needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); | ||
| 395 | path = fs2us(fas2fs(s)); | ||
| 396 | } | ||
| 397 | else | ||
| 398 | #endif | ||
| 399 | { | ||
| 400 | WCHAR s[MAX_PATH + 2]; | ||
| 401 | s[0] = 0; | ||
| 402 | needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); | ||
| 403 | path = s; | ||
| 404 | } | ||
| 405 | return (needLength > 0 && needLength <= MAX_PATH); | ||
| 406 | 417 | ||
| 407 | #else | 418 | #else |
| 408 | 419 | ||
| 420 | static bool GetCurDir(UString &path) | ||
| 421 | { | ||
| 422 | path.Empty(); | ||
| 409 | FString s; | 423 | FString s; |
| 410 | if (!NDir::GetCurrentDir(s)) | 424 | if (!NDir::GetCurrentDir(s)) |
| 411 | return false; | 425 | return false; |
| 412 | path = GetUnicodeString(s); | 426 | path = fs2us(s); |
| 413 | return true; | 427 | return true; |
| 414 | |||
| 415 | #endif | ||
| 416 | } | 428 | } |
| 417 | 429 | ||
| 430 | #endif | ||
| 431 | |||
| 432 | |||
| 418 | static bool ResolveDotsFolders(UString &s) | 433 | static bool ResolveDotsFolders(UString &s) |
| 419 | { | 434 | { |
| 420 | #ifdef _WIN32 | 435 | #ifdef _WIN32 |
| @@ -516,7 +531,7 @@ static bool AreThereDotsFolders(CFSTR s) | |||
| 516 | #endif | 531 | #endif |
| 517 | #endif // LONG_PATH_DOTS_FOLDERS_PARSING | 532 | #endif // LONG_PATH_DOTS_FOLDERS_PARSING |
| 518 | 533 | ||
| 519 | #ifdef WIN_LONG_PATH | 534 | #ifdef Z7_LONG_PATH |
| 520 | 535 | ||
| 521 | /* | 536 | /* |
| 522 | Most of Windows versions have problems, if some file or dir name | 537 | Most of Windows versions have problems, if some file or dir name |
| @@ -610,11 +625,11 @@ static bool GetSuperPathBase(CFSTR s, UString &res) | |||
| 610 | return true; | 625 | return true; |
| 611 | 626 | ||
| 612 | UString temp = fs2us(s); | 627 | UString temp = fs2us(s); |
| 613 | unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); | 628 | const unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); |
| 614 | if (fixedSize == 0) | 629 | if (fixedSize == 0) |
| 615 | return true; | 630 | return true; |
| 616 | 631 | ||
| 617 | UString rem = &temp[fixedSize]; | 632 | UString rem = temp.Ptr(fixedSize); |
| 618 | if (!ResolveDotsFolders(rem)) | 633 | if (!ResolveDotsFolders(rem)) |
| 619 | return true; | 634 | return true; |
| 620 | 635 | ||
| @@ -632,13 +647,13 @@ static bool GetSuperPathBase(CFSTR s, UString &res) | |||
| 632 | if (IS_SEPAR(s[1])) | 647 | if (IS_SEPAR(s[1])) |
| 633 | { | 648 | { |
| 634 | UString temp = fs2us(s + 2); | 649 | UString temp = fs2us(s + 2); |
| 635 | unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); | 650 | const unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); |
| 636 | // we ignore that error to allow short network paths server\share? | 651 | // we ignore that error to allow short network paths server\share? |
| 637 | /* | 652 | /* |
| 638 | if (fixedSize == 0) | 653 | if (fixedSize == 0) |
| 639 | return false; | 654 | return false; |
| 640 | */ | 655 | */ |
| 641 | UString rem = &temp[fixedSize]; | 656 | UString rem = temp.Ptr(fixedSize); |
| 642 | if (!ResolveDotsFolders(rem)) | 657 | if (!ResolveDotsFolders(rem)) |
| 643 | return false; | 658 | return false; |
| 644 | res += kSuperUncPrefix; | 659 | res += kSuperUncPrefix; |
| @@ -783,7 +798,7 @@ bool GetSuperPath(CFSTR path, UString &superPath) | |||
| 783 | return false; | 798 | return false; |
| 784 | } | 799 | } |
| 785 | */ | 800 | */ |
| 786 | #endif // WIN_LONG_PATH | 801 | #endif // Z7_LONG_PATH |
| 787 | 802 | ||
| 788 | bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) | 803 | bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) |
| 789 | { | 804 | { |
| @@ -801,8 +816,11 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) | |||
| 801 | 816 | ||
| 802 | #else | 817 | #else |
| 803 | 818 | ||
| 804 | unsigned prefixSize = GetRootPrefixSize(s); | 819 | const unsigned prefixSize = GetRootPrefixSize(s); |
| 805 | if (prefixSize != 0) | 820 | if (prefixSize != 0) |
| 821 | #ifdef _WIN32 | ||
| 822 | if (prefixSize != 1) | ||
| 823 | #endif | ||
| 806 | { | 824 | { |
| 807 | if (!AreThereDotsFolders(s + prefixSize)) | 825 | if (!AreThereDotsFolders(s + prefixSize)) |
| 808 | return true; | 826 | return true; |
| @@ -815,21 +833,9 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) | |||
| 815 | return true; | 833 | return true; |
| 816 | } | 834 | } |
| 817 | 835 | ||
| 818 | /* | ||
| 819 | FChar c = s[0]; | ||
| 820 | if (c == 0) | ||
| 821 | return true; | ||
| 822 | if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) | ||
| 823 | return true; | ||
| 824 | if (IS_SEPAR(c) && IS_SEPAR(s[1])) | ||
| 825 | return true; | ||
| 826 | if (IsDrivePath(s)) | ||
| 827 | return true; | ||
| 828 | */ | ||
| 829 | |||
| 830 | UString curDir; | 836 | UString curDir; |
| 831 | if (dirPrefix) | 837 | if (dirPrefix && prefixSize == 0) |
| 832 | curDir = fs2us(dirPrefix); | 838 | curDir = fs2us(dirPrefix); // we use (dirPrefix), only if (s) path is relative |
| 833 | else | 839 | else |
| 834 | { | 840 | { |
| 835 | if (!GetCurDir(curDir)) | 841 | if (!GetCurDir(curDir)) |
| @@ -837,46 +843,40 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) | |||
| 837 | } | 843 | } |
| 838 | NormalizeDirPathPrefix(curDir); | 844 | NormalizeDirPathPrefix(curDir); |
| 839 | 845 | ||
| 840 | unsigned fixedSize = 0; | 846 | unsigned fixedSize = GetRootPrefixSize(curDir); |
| 841 | 847 | ||
| 842 | #ifdef _WIN32 | 848 | UString temp; |
| 843 | 849 | #ifdef _WIN32 | |
| 844 | if (IsSuperPath(curDir)) | 850 | if (prefixSize != 0) |
| 845 | { | 851 | { |
| 846 | fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); | 852 | /* (s) is absolute path, but only (prefixSize == 1) is possible here. |
| 853 | So for full resolving we need root of current folder and | ||
| 854 | relative part of (s). */ | ||
| 855 | s += prefixSize; | ||
| 856 | // (s) is relative part now | ||
| 847 | if (fixedSize == 0) | 857 | if (fixedSize == 0) |
| 848 | return false; | ||
| 849 | } | ||
| 850 | else | ||
| 851 | { | ||
| 852 | if (IsDrivePath(curDir)) | ||
| 853 | fixedSize = kDrivePrefixSize; | ||
| 854 | else | ||
| 855 | { | 858 | { |
| 856 | if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1])) | 859 | // (curDir) is not absolute. |
| 857 | return false; | 860 | // That case is unexpected, but we support it too. |
| 858 | fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2)); | 861 | curDir.Empty(); |
| 859 | if (fixedSize == 0) | 862 | curDir.Add_PathSepar(); |
| 860 | return false; | 863 | fixedSize = 1; |
| 861 | fixedSize += 2; | 864 | // (curDir) now is just Separ character. |
| 865 | // So final (res) path later also will have Separ prefix. | ||
| 862 | } | 866 | } |
| 863 | } | 867 | } |
| 864 | |||
| 865 | #endif // _WIN32 | ||
| 866 | |||
| 867 | UString temp; | ||
| 868 | if (IS_SEPAR(s[0])) | ||
| 869 | { | ||
| 870 | temp = fs2us(s + 1); | ||
| 871 | } | ||
| 872 | else | 868 | else |
| 869 | #endif // _WIN32 | ||
| 873 | { | 870 | { |
| 874 | temp += curDir.Ptr(fixedSize); | 871 | // (s) is relative path |
| 875 | temp += fs2us(s); | 872 | temp = curDir.Ptr(fixedSize); |
| 873 | // (temp) is relative_part_of(curDir) | ||
| 876 | } | 874 | } |
| 875 | temp += fs2us(s); | ||
| 877 | if (!ResolveDotsFolders(temp)) | 876 | if (!ResolveDotsFolders(temp)) |
| 878 | return false; | 877 | return false; |
| 879 | curDir.DeleteFrom(fixedSize); | 878 | curDir.DeleteFrom(fixedSize); |
| 879 | // (curDir) now contains only absolute prefix part | ||
| 880 | res = us2fs(curDir); | 880 | res = us2fs(curDir); |
| 881 | res += us2fs(temp); | 881 | res += us2fs(temp); |
| 882 | 882 | ||
| @@ -885,6 +885,7 @@ bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) | |||
| 885 | return true; | 885 | return true; |
| 886 | } | 886 | } |
| 887 | 887 | ||
| 888 | |||
| 888 | bool GetFullPath(CFSTR path, FString &fullPath) | 889 | bool GetFullPath(CFSTR path, FString &fullPath) |
| 889 | { | 890 | { |
| 890 | return GetFullPath(NULL, path, fullPath); | 891 | return GetFullPath(NULL, path, fullPath); |
