diff options
Diffstat (limited to 'src/libs/7zip/win/CPP/Windows/FileName.cpp')
-rw-r--r-- | src/libs/7zip/win/CPP/Windows/FileName.cpp | 687 |
1 files changed, 0 insertions, 687 deletions
diff --git a/src/libs/7zip/win/CPP/Windows/FileName.cpp b/src/libs/7zip/win/CPP/Windows/FileName.cpp deleted file mode 100644 index 0a6aee100..000000000 --- a/src/libs/7zip/win/CPP/Windows/FileName.cpp +++ /dev/null @@ -1,687 +0,0 @@ -// Windows/FileName.cpp - -#include "StdAfx.h" - -#include "FileName.h" - -#ifndef _UNICODE -extern bool g_IsNT; -#endif - -namespace NWindows { -namespace NFile { -namespace NName { - -#ifndef USE_UNICODE_FSTRING -void NormalizeDirPathPrefix(FString &dirPath) -{ - if (dirPath.IsEmpty()) - return; - if (dirPath.Back() != FCHAR_PATH_SEPARATOR) - dirPath += FCHAR_PATH_SEPARATOR; -} -#endif - -void NormalizeDirPathPrefix(UString &dirPath) -{ - if (dirPath.IsEmpty()) - return; - if (dirPath.Back() != WCHAR_PATH_SEPARATOR) - dirPath += WCHAR_PATH_SEPARATOR; -} - - -#ifdef _WIN32 - -const wchar_t *kSuperPathPrefix = L"\\\\?\\"; -static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\"; - -#define IS_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '.' && (s)[3] == '\\') -#define IS_SUPER_PREFIX(s) ((s)[0] == '\\' && (s)[1] == '\\' && (s)[2] == '?' && (s)[3] == '\\') -#define IS_SUPER_OR_DEVICE_PATH(s) ((s)[0] == '\\' && (s)[1] == '\\' && ((s)[2] == '?' || (s)[2] == '.') && (s)[3] == '\\') -#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') - -#define IS_UNC_WITH_SLASH(s) ( \ - ((s)[0] == 'U' || (s)[0] == 'u') && \ - ((s)[1] == 'N' || (s)[1] == 'n') && \ - ((s)[2] == 'C' || (s)[2] == 'c') && \ - (s)[3] == '\\') - -bool IsDevicePath(CFSTR s) throw() -{ - #ifdef UNDER_CE - - s = s; - return false; - /* - // actually we don't know the way to open device file in WinCE. - unsigned len = MyStringLen(s); - if (len < 5 || len > 5 || memcmp(s, FTEXT("DSK"), 3 * sizeof(FChar)) != 0) - return false; - if (s[4] != ':') - return false; - // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ)); - */ - - #else - - if (!IS_DEVICE_PATH(s)) - return false; - unsigned len = MyStringLen(s); - if (len == 6 && s[5] == ':') - return true; - if (len < 18 || len > 22 || memcmp(s + kDevicePathPrefixSize, FTEXT("PhysicalDrive"), 13 * sizeof(FChar)) != 0) - return false; - for (unsigned i = 17; i < len; i++) - if (s[i] < '0' || s[i] > '9') - return false; - return true; - - #endif -} - -bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } - -bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; } -bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); } -bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } -// bool IsSuperUncPath(const wchar_t *s) { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); } - -#ifndef USE_UNICODE_FSTRING -bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == '\\'; } -bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); } -bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); } -#endif // USE_UNICODE_FSTRING - -bool IsAbsolutePath(const wchar_t *s) throw() -{ - return s[0] == WCHAR_PATH_SEPARATOR || IsDrivePath(s); -} - -static const unsigned kDrivePrefixSize = 3; /* c:\ */ - -#ifndef USE_UNICODE_FSTRING - -static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s) throw() -{ - // Network path: we look "server\path\" as root prefix - int pos = FindCharPosInString(s, '\\'); - if (pos < 0) - return 0; - int pos2 = FindCharPosInString(s + pos + 1, '\\'); - if (pos2 < 0) - return 0; - return pos + pos2 + 2; -} - -static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s) throw() -{ - if (IsDrivePath(s)) - return kDrivePrefixSize; - if (s[0] != '\\' || s[1] != '\\') - return 0; - unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); - return (size == 0) ? 0 : 2 + size; -} - -static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s) throw() -{ - if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) - { - unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); - return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; - } - // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" - int pos = FindCharPosInString(s + kSuperPathPrefixSize, FCHAR_PATH_SEPARATOR); - if (pos < 0) - return 0; - return kSuperPathPrefixSize + pos + 1; -} - -unsigned GetRootPrefixSize(CFSTR s) throw() -{ - if (IS_DEVICE_PATH(s)) - return kDevicePathPrefixSize; - if (IsSuperPath(s)) - return GetRootPrefixSize_Of_SuperPath(s); - return GetRootPrefixSize_Of_SimplePath(s); -} - -#endif // USE_UNICODE_FSTRING - -static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw() -{ - // Network path: we look "server\path\" as root prefix - int pos = FindCharPosInString(s, L'\\'); - if (pos < 0) - return 0; - int pos2 = FindCharPosInString(s + pos + 1, L'\\'); - if (pos2 < 0) - return 0; - return pos + pos2 + 2; -} - -static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw() -{ - if (IsDrivePath(s)) - return kDrivePrefixSize; - if (s[0] != '\\' || s[1] != '\\') - return 0; - unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2); - return (size == 0) ? 0 : 2 + size; -} - -static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw() -{ - if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)) - { - unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize); - return (size == 0) ? 0 : kSuperUncPathPrefixSize + size; - } - // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\" - int pos = FindCharPosInString(s + kSuperPathPrefixSize, L'\\'); - if (pos < 0) - return 0; - return kSuperPathPrefixSize + pos + 1; -} - -unsigned GetRootPrefixSize(const wchar_t *s) throw() -{ - if (IS_DEVICE_PATH(s)) - return kDevicePathPrefixSize; - if (IsSuperPath(s)) - return GetRootPrefixSize_Of_SuperPath(s); - return GetRootPrefixSize_Of_SimplePath(s); -} - -#else // _WIN32 - -bool IsAbsolutePath(const wchar_t *s) throw() { return s[0] == WCHAR_PATH_SEPARATOR } - -#ifndef USE_UNICODE_FSTRING -unsigned GetRootPrefixSize(CFSTR s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; } -#endif -unsigned GetRootPrefixSize(const wchar_t *s) throw() { return s[0] == CHAR_PATH_SEPRATOR ? 1 : 0; } - -#endif // _WIN32 - - -#ifndef UNDER_CE - -static bool GetCurDir(UString &path) -{ - path.Empty(); - DWORD needLength; - #ifndef _UNICODE - if (!g_IsNT) - { - TCHAR s[MAX_PATH + 2]; - s[0] = 0; - needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); - path = fs2us(fas2fs(s)); - } - else - #endif - { - WCHAR s[MAX_PATH + 2]; - s[0] = 0; - needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); - path = s; - } - return (needLength > 0 && needLength <= MAX_PATH); -} - -static bool ResolveDotsFolders(UString &s) -{ - #ifdef _WIN32 - s.Replace(L'/', WCHAR_PATH_SEPARATOR); - #endif - for (int i = 0;;) - { - wchar_t c = s[i]; - if (c == 0) - return true; - if (c == '.' && (i == 0 || s[i - 1] == WCHAR_PATH_SEPARATOR)) - { - wchar_t c1 = s[i + 1]; - if (c1 == '.') - { - wchar_t c2 = s[i + 2]; - if (c2 == WCHAR_PATH_SEPARATOR || c2 == 0) - { - if (i == 0) - return false; - int k = i - 2; - for (; k >= 0; k--) - if (s[k] == WCHAR_PATH_SEPARATOR) - break; - unsigned num; - if (k >= 0) - { - num = i + 2 - k; - i = k; - } - else - { - num = (c2 == 0 ? (i + 2) : (i + 3)); - i = 0; - } - s.Delete(i, num); - continue; - } - } - else - { - if (c1 == WCHAR_PATH_SEPARATOR || c1 == 0) - { - unsigned num = 2; - if (i != 0) - i--; - else if (c1 == 0) - num = 1; - s.Delete(i, num); - continue; - } - } - } - i++; - } -} - -#endif // UNDER_CE - -#define LONG_PATH_DOTS_FOLDERS_PARSING - - -/* -Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\ -To solve that problem we check such path: - - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper - - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain -*/ -#ifdef LONG_PATH_DOTS_FOLDERS_PARSING -#ifndef UNDER_CE -static bool AreThereDotsFolders(CFSTR s) -{ - for (unsigned i = 0;; i++) - { - FChar c = s[i]; - if (c == 0) - return false; - if (c == '.' && (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR)) - { - FChar c1 = s[i + 1]; - if (c1 == 0 || c1 == CHAR_PATH_SEPARATOR || - (c1 == '.' && (s[i + 2] == 0 || s[i + 2] == CHAR_PATH_SEPARATOR))) - return true; - } - } -} -#endif -#endif // LONG_PATH_DOTS_FOLDERS_PARSING - -#ifdef WIN_LONG_PATH - -/* -Most of Windows versions have problems, if some file or dir name -contains '.' or ' ' at the end of name (Bad Path). -To solve that problem, we always use Super Path ("\\?\" prefix and full path) -in such cases. Note that "." and ".." are not bad names. - -There are 3 cases: - 1) If the path is already Super Path, we use that path - 2) If the path is not Super Path : - 2.1) Bad Path; we use only Super Path. - 2.2) Good Path; we use Main Path. If it fails, we use Super Path. - - NeedToUseOriginalPath returns: - kSuperPathType_UseOnlyMain : Super already - kSuperPathType_UseOnlySuper : not Super, Bad Path - kSuperPathType_UseMainAndSuper : not Super, Good Path -*/ - -int GetUseSuperPathType(CFSTR s) throw() -{ - if (IsSuperOrDevicePath(s)) - { - #ifdef LONG_PATH_DOTS_FOLDERS_PARSING - if ((s)[2] != '.') - if (AreThereDotsFolders(s + kSuperPathPrefixSize)) - return kSuperPathType_UseOnlySuper; - #endif - return kSuperPathType_UseOnlyMain; - } - - for (unsigned i = 0;; i++) - { - FChar c = s[i]; - if (c == 0) - return kSuperPathType_UseMainAndSuper; - if (c == '.' || c == ' ') - { - FChar c2 = s[i + 1]; - if (c2 == 0 || c2 == CHAR_PATH_SEPARATOR) - { - // if it's "." or "..", it's not bad name. - if (c == '.') - { - if (i == 0 || s[i - 1] == CHAR_PATH_SEPARATOR) - continue; - if (s[i - 1] == '.') - { - if (i - 1 == 0 || s[i - 2] == CHAR_PATH_SEPARATOR) - continue; - } - } - return kSuperPathType_UseOnlySuper; - } - } - } -} - - -/* - returns false in two cases: - - if GetCurDir was used, and GetCurDir returned error. - - if we can't resolve ".." name. - if path is ".", "..", res is empty. - if it's Super Path already, res is empty. - for \**** , and if GetCurDir is not drive (c:\), res is empty - for absolute paths, returns true, res is Super path. -*/ - - -static bool GetSuperPathBase(CFSTR s, UString &res) -{ - res.Empty(); - - FChar c = s[0]; - if (c == 0) - return true; - if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) - return true; - - if (IsSuperOrDevicePath(s)) - { - #ifdef LONG_PATH_DOTS_FOLDERS_PARSING - - if ((s)[2] == '.') - return true; - - // we will return true here, so we will try to use these problem paths. - - if (!AreThereDotsFolders(s + kSuperPathPrefixSize)) - return true; - - UString temp = fs2us(s); - unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp); - if (fixedSize == 0) - return true; - - UString rem = &temp[fixedSize]; - if (!ResolveDotsFolders(rem)) - return true; - - temp.DeleteFrom(fixedSize); - res += temp; - res += rem; - - #endif - - return true; - } - - if (c == CHAR_PATH_SEPARATOR) - { - if (s[1] == CHAR_PATH_SEPARATOR) - { - UString temp = fs2us(s + 2); - unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp); - if (fixedSize == 0) // maybe we must ignore that error to allow short network paths? - return false; - UString rem = &temp[fixedSize]; - if (!ResolveDotsFolders(rem)) - return false; - res += kSuperUncPrefix; - temp.DeleteFrom(fixedSize); - res += temp; - res += rem; - return true; - } - } - else - { - if (IsDrivePath(s)) - { - UString temp = fs2us(s); - UString rem = &temp[kDrivePrefixSize]; - if (!ResolveDotsFolders(rem)) - return true; - res += kSuperPathPrefix; - temp.DeleteFrom(kDrivePrefixSize); - res += temp; - res += rem; - return true; - } - } - - UString curDir; - if (!GetCurDir(curDir)) - return false; - if (curDir.Back() != WCHAR_PATH_SEPARATOR) - curDir += WCHAR_PATH_SEPARATOR; - - unsigned fixedSizeStart = 0; - unsigned fixedSize = 0; - const wchar_t *superMarker = NULL; - if (IsSuperPath(curDir)) - { - fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); - if (fixedSize == 0) - return false; - } - else - { - if (IsDrivePath(curDir)) - { - superMarker = kSuperPathPrefix; - fixedSize = kDrivePrefixSize; - } - else - { - if (curDir[0] != CHAR_PATH_SEPARATOR || curDir[1] != CHAR_PATH_SEPARATOR) - return false; - fixedSizeStart = 2; - fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); - if (fixedSize == 0) - return false; - superMarker = kSuperUncPrefix; - } - } - - UString temp; - if (c == CHAR_PATH_SEPARATOR) - { - temp = fs2us(s + 1); - } - else - { - temp += &curDir[fixedSizeStart + fixedSize]; - temp += fs2us(s); - } - if (!ResolveDotsFolders(temp)) - return false; - if (superMarker) - res += superMarker; - res += curDir.Mid(fixedSizeStart, fixedSize); - res += temp; - return true; -} - - -/* - In that case if GetSuperPathBase doesn't return new path, we don't need - to use same path that was used as main path - - GetSuperPathBase superPath.IsEmpty() onlyIfNew - false * * GetCurDir Error - true false * use Super path - true true true don't use any path, we already used mainPath - true true false use main path as Super Path, we don't try mainMath - That case is possible now if GetCurDir returns unknow - type of path (not drive and not network) - - We can change that code if we want to try mainPath, if GetSuperPathBase returns error, - and we didn't try mainPath still. - If we want to work that way, we don't need to use GetSuperPathBase return code. -*/ - -bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew) -{ - if (GetSuperPathBase(path, superPath)) - { - if (superPath.IsEmpty()) - { - // actually the only possible when onlyIfNew == true and superPath is empty - // is case when - - if (onlyIfNew) - return false; - superPath = fs2us(path); - } - return true; - } - return false; -} - -bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew) -{ - if (!GetSuperPathBase(s1, d1) || - !GetSuperPathBase(s2, d2)) - return false; - if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew) - return false; - if (d1.IsEmpty()) d1 = fs2us(s1); - if (d2.IsEmpty()) d2 = fs2us(s2); - return true; -} - - -/* -// returns true, if we need additional use with New Super path. -bool GetSuperPath(CFSTR path, UString &superPath) -{ - if (GetSuperPathBase(path, superPath)) - return !superPath.IsEmpty(); - return false; -} -*/ -#endif // WIN_LONG_PATH - -bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res) -{ - res = s; - - #ifdef UNDER_CE - - if (s[0] != CHAR_PATH_SEPARATOR) - { - if (!dirPrefix) - return false; - res = dirPrefix; - res += s; - } - - #else - - unsigned prefixSize = GetRootPrefixSize(s); - if (prefixSize != 0) - { - if (!AreThereDotsFolders(s + prefixSize)) - return true; - - UString rem = fs2us(s + prefixSize); - if (!ResolveDotsFolders(rem)) - return true; // maybe false; - res.DeleteFrom(prefixSize); - res += us2fs(rem); - return true; - } - - /* - FChar c = s[0]; - if (c == 0) - return true; - if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) - return true; - if (c == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) - return true; - if (IsDrivePath(s)) - return true; - */ - - UString curDir; - if (dirPrefix) - curDir = fs2us(dirPrefix); - else - { - if (!GetCurDir(curDir)) - return false; - } - if (!curDir.IsEmpty() && curDir.Back() != WCHAR_PATH_SEPARATOR) - curDir += WCHAR_PATH_SEPARATOR; - - unsigned fixedSize = 0; - - #ifdef _WIN32 - - if (IsSuperPath(curDir)) - { - fixedSize = GetRootPrefixSize_Of_SuperPath(curDir); - if (fixedSize == 0) - return false; - } - else - { - if (IsDrivePath(curDir)) - fixedSize = kDrivePrefixSize; - else - { - if (curDir[0] != WCHAR_PATH_SEPARATOR || curDir[1] != WCHAR_PATH_SEPARATOR) - return false; - fixedSize = GetRootPrefixSize_Of_NetworkPath(&curDir[2]); - if (fixedSize == 0) - return false; - fixedSize += 2; - } - } - - #endif // _WIN32 - - UString temp; - if (s[0] == CHAR_PATH_SEPARATOR) - { - temp = fs2us(s + 1); - } - else - { - temp += curDir.Ptr(fixedSize); - temp += fs2us(s); - } - if (!ResolveDotsFolders(temp)) - return false; - curDir.DeleteFrom(fixedSize); - res = us2fs(curDir); - res += us2fs(temp); - - #endif // UNDER_CE - - return true; -} - -bool GetFullPath(CFSTR path, FString &fullPath) -{ - return GetFullPath(NULL, path, fullPath); -} - -}}} |