diff options
Diffstat (limited to '')
-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); |