diff options
author | 2023-12-06 07:58:49 +1100 | |
---|---|---|
committer | 2023-12-06 07:58:49 +1100 | |
commit | 79bef1e23049fdac25f1fefd132e0b6c7d2cc3a1 (patch) | |
tree | 643e9313fe86f583c4022c338677cbc12b761df7 /3rdparty/lzma/CPP/Windows/FileDir.cpp | |
parent | 512ccf0c7c9b4f08e41038b2ed2de220e140385b (diff) |
3rdparty/lzma: Updated to version 23.01.
Diffstat (limited to '3rdparty/lzma/CPP/Windows/FileDir.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/Windows/FileDir.cpp | 235 |
1 files changed, 165 insertions, 70 deletions
diff --git a/3rdparty/lzma/CPP/Windows/FileDir.cpp b/3rdparty/lzma/CPP/Windows/FileDir.cpp index cce2638587e..5b1f340b5c7 100644 --- a/3rdparty/lzma/CPP/Windows/FileDir.cpp +++ b/3rdparty/lzma/CPP/Windows/FileDir.cpp @@ -65,46 +65,55 @@ namespace NDir { bool GetWindowsDir(FString &path) { - UINT needLength; + const unsigned kBufSize = MAX_PATH + 16; + UINT len; #ifndef _UNICODE if (!g_IsNT) { - TCHAR s[MAX_PATH + 2]; + TCHAR s[kBufSize + 1]; s[0] = 0; - needLength = ::GetWindowsDirectory(s, MAX_PATH + 1); + len = ::GetWindowsDirectory(s, kBufSize); path = fas2fs(s); } else #endif { - WCHAR s[MAX_PATH + 2]; + WCHAR s[kBufSize + 1]; s[0] = 0; - needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1); + len = ::GetWindowsDirectoryW(s, kBufSize); path = us2fs(s); } - return (needLength > 0 && needLength <= MAX_PATH); + return (len != 0 && len < kBufSize); } + +/* +new DOCs for GetSystemDirectory: + returned path does not end with a backslash unless the + system directory is the root directory. +*/ + bool GetSystemDir(FString &path) { - UINT needLength; + const unsigned kBufSize = MAX_PATH + 16; + UINT len; #ifndef _UNICODE if (!g_IsNT) { - TCHAR s[MAX_PATH + 2]; + TCHAR s[kBufSize + 1]; s[0] = 0; - needLength = ::GetSystemDirectory(s, MAX_PATH + 1); + len = ::GetSystemDirectory(s, kBufSize); path = fas2fs(s); } else #endif { - WCHAR s[MAX_PATH + 2]; + WCHAR s[kBufSize + 1]; s[0] = 0; - needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1); + len = ::GetSystemDirectoryW(s, kBufSize); path = us2fs(s); } - return (needLength > 0 && needLength <= MAX_PATH); + return (len != 0 && len < kBufSize); } #endif // UNDER_CE @@ -123,7 +132,7 @@ bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CF IF_USE_MAIN_PATH hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - #ifdef WIN_LONG_PATH + #ifdef Z7_LONG_PATH if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH) { UString superPath; @@ -158,7 +167,7 @@ bool SetFileAttrib(CFSTR path, DWORD attrib) IF_USE_MAIN_PATH if (::SetFileAttributesW(fs2us(path), attrib)) return true; - #ifdef WIN_LONG_PATH + #ifdef Z7_LONG_PATH if (USE_SUPER_PATH) { UString superPath; @@ -195,7 +204,7 @@ bool RemoveDir(CFSTR path) IF_USE_MAIN_PATH if (::RemoveDirectoryW(fs2us(path))) return true; - #ifdef WIN_LONG_PATH + #ifdef Z7_LONG_PATH if (USE_SUPER_PATH) { UString superPath; @@ -224,7 +233,7 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) if (::MoveFileW(fs2us(oldFile), fs2us(newFile))) return true; } - #ifdef WIN_LONG_PATH + #ifdef Z7_LONG_PATH if (USE_SUPER_PATH_2) { UString d1, d2; @@ -261,8 +270,11 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) else #endif { - Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW) - (void *)::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW"); + const + Func_CreateHardLinkW + my_CreateHardLinkW = Z7_GET_PROC_ADDRESS( + Func_CreateHardLinkW, ::GetModuleHandleW(L"kernel32.dll"), + "CreateHardLinkW"); if (!my_CreateHardLinkW) return false; IF_USE_MAIN_PATH_2(newFileName, existFileName) @@ -270,7 +282,7 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL)) return true; } - #ifdef WIN_LONG_PATH + #ifdef Z7_LONG_PATH if (USE_SUPER_PATH_2) { UString d1, d2; @@ -320,7 +332,7 @@ bool CreateDir(CFSTR path) IF_USE_MAIN_PATH if (::CreateDirectoryW(fs2us(path), NULL)) return true; - #ifdef WIN_LONG_PATH + #ifdef Z7_LONG_PATH if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) { UString superPath; @@ -355,7 +367,7 @@ static bool CreateDir2(CFSTR path) IF_USE_MAIN_PATH if (::CreateDirectoryW(fs2us(path), NULL)) return true; - #ifdef WIN_LONG_PATH + #ifdef Z7_LONG_PATH if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH) { UString superPath; @@ -390,7 +402,7 @@ bool CreateComplexDir(CFSTR _path) #ifdef _WIN32 { - DWORD attrib = NFind::GetFileAttrib(_path); + const DWORD attrib = NFind::GetFileAttrib(_path); if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) return true; } @@ -496,7 +508,7 @@ bool DeleteFileAlways(CFSTR path) IF_USE_MAIN_PATH if (::DeleteFileW(fs2us(path))) return true; - #ifdef WIN_LONG_PATH + #ifdef Z7_LONG_PATH if (USE_SUPER_PATH) { UString superPath; @@ -586,9 +598,12 @@ bool MyGetFullPathName(CFSTR path, FString &resFullPath) #ifdef _WIN32 +/* Win10: SetCurrentDirectory() doesn't support long paths and + doesn't support super prefix "\\?\", if long path behavior is not + enabled in registry (LongPathsEnabled) and in manifest (longPathAware). */ + bool SetCurrentDir(CFSTR path) { - // SetCurrentDirectory doesn't support \\?\ prefix #ifndef _UNICODE if (!g_IsNT) { @@ -602,28 +617,74 @@ bool SetCurrentDir(CFSTR path) } +/* +we use system function GetCurrentDirectory() +new GetCurrentDirectory() DOCs: + - If the function fails, the return value is zero. + - If the function succeeds, the return value specifies + the number of characters that are written to the buffer, + not including the terminating null character. + - If the buffer is not large enough, the return value specifies + the required size of the buffer, in characters, + including the null-terminating character. + +GetCurrentDir() calls GetCurrentDirectory(). +GetCurrentDirectory() in win10 in tests: + the returned (path) does not end with a backslash, if + current directory is not root directory of drive. + But that behavior is not guarantied in specification docs. +*/ + bool GetCurrentDir(FString &path) { + const unsigned kBufSize = MAX_PATH + 16; path.Empty(); - DWORD needLength; #ifndef _UNICODE if (!g_IsNT) { - TCHAR s[MAX_PATH + 2]; + TCHAR s[kBufSize + 1]; s[0] = 0; - needLength = ::GetCurrentDirectory(MAX_PATH + 1, s); + const DWORD len = ::GetCurrentDirectory(kBufSize, s); + if (len == 0 || len >= kBufSize) + return false; + s[kBufSize] = 0; // optional guard path = fas2fs(s); + return true; } else #endif { - WCHAR s[MAX_PATH + 2]; - s[0] = 0; - needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s); - path = us2fs(s); + DWORD len; + { + WCHAR s[kBufSize + 1]; + s[0] = 0; + len = ::GetCurrentDirectoryW(kBufSize, s); + if (len == 0) + return false; + if (len < kBufSize) + { + s[kBufSize] = 0; // optional guard + path = us2fs(s); + return true; + } + } + UString temp; + const DWORD len2 = ::GetCurrentDirectoryW(len, temp.GetBuf(len)); + if (len2 == 0) + return false; + temp.ReleaseBuf_CalcLen(len); + if (temp.Len() != len2 || len - 1 != len2) + { + /* it's unexpected case, if current dir of process + was changed between two function calls, + or some unexpected function implementation */ + // SetLastError((DWORD)E_FAIL); // we can set some error code + return false; + } + path = us2fs(temp); + return true; } - return (needLength > 0 && needLength <= MAX_PATH); } #endif // _WIN32 @@ -648,41 +709,59 @@ bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) return GetFullPathAndSplit(path, resDirPrefix, resFileName); } + + bool MyGetTempPath(FString &path) { #ifdef _WIN32 - path.Empty(); - DWORD needLength; + + /* + new DOCs for GetTempPathW(): + - The returned string ends with a backslash. + - The maximum possible return value is MAX_PATH+1 (261). + */ + + const unsigned kBufSize = MAX_PATH + 16; + DWORD len; #ifndef _UNICODE if (!g_IsNT) { - TCHAR s[MAX_PATH + 2]; + TCHAR s[kBufSize + 1]; s[0] = 0; - needLength = ::GetTempPath(MAX_PATH + 1, s); + len = ::GetTempPath(kBufSize, s); path = fas2fs(s); } else #endif { - WCHAR s[MAX_PATH + 2]; + WCHAR s[kBufSize + 1]; s[0] = 0; - needLength = ::GetTempPathW(MAX_PATH + 1, s);; + len = ::GetTempPathW(kBufSize, s); path = us2fs(s); } - return (needLength > 0 && needLength <= MAX_PATH); + /* win10: GetTempPathW() doesn't set backslash at the end of path, + if (buffer_size == len_of(path_with_backslash)). + So we normalize path here: */ + NormalizeDirPathPrefix(path); + return (len != 0 && len < kBufSize); - #else + #else // !_WIN32 // FIXME: improve that code - path = "/tmp/"; - if (!NFind::DoesDirExist_FollowLink(path)) - path = "./"; + path = STRING_PATH_SEPARATOR "tmp"; + const char *s; + if (NFind::DoesDirExist_FollowLink(path)) + s = STRING_PATH_SEPARATOR "tmp" STRING_PATH_SEPARATOR; + else + s = "." STRING_PATH_SEPARATOR; + path = s; return true; + #endif } -static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) +bool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFile *outFile) { UInt32 d = #ifdef _WIN32 @@ -693,7 +772,7 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu for (unsigned i = 0; i < 100; i++) { - path = prefix; + postfix.Empty(); if (addRandom) { char s[16]; @@ -701,14 +780,14 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu unsigned k; for (k = 0; k < 8; k++) { - unsigned t = val & 0xF; + const unsigned t = val & 0xF; val >>= 4; s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[k] = '\0'; if (outFile) - path += '.'; - path += s; + postfix.Add_Dot(); + postfix += s; UInt32 step = GetTickCount() + 2; if (step == 0) step = 1; @@ -716,7 +795,9 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu } addRandom = true; if (outFile) - path += ".tmp"; + postfix += ".tmp"; + FString path (prefix); + path += postfix; if (NFind::DoesFileOrDirExist(path)) { SetLastError(ERROR_ALREADY_EXISTS); @@ -732,12 +813,12 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu if (CreateDir(path)) return true; } - DWORD error = GetLastError(); + const DWORD error = GetLastError(); if (error != ERROR_FILE_EXISTS && error != ERROR_ALREADY_EXISTS) break; } - path.Empty(); + postfix.Empty(); return false; } @@ -745,8 +826,12 @@ bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) { if (!Remove()) return false; - if (!CreateTempFile(prefix, false, _path, outFile)) + _path.Empty(); + AString postfix; + if (!CreateTempFile2(prefix, false, postfix, outFile)) return false; + _path = prefix; + _path += postfix; _mustBeDeleted = true; return true; } @@ -755,11 +840,16 @@ bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFil { if (!Remove()) return false; + _path.Empty(); FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile)) + AString postfix; + tempPath += namePrefix; + if (!CreateTempFile2(tempPath, true, postfix, outFile)) return false; + _path = tempPath; + _path += postfix; _mustBeDeleted = true; return true; } @@ -802,11 +892,16 @@ bool CTempDir::Create(CFSTR prefix) { if (!Remove()) return false; + _path.Empty(); FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (!CreateTempFile(tempPath + prefix, true, _path, NULL)) + tempPath += prefix; + AString postfix; + if (!CreateTempFile2(tempPath, true, postfix, NULL)) return false; + _path = tempPath; + _path += postfix; _mustBeDeleted = true; return true; } @@ -830,7 +925,7 @@ bool RemoveDir(CFSTR path) } -static BOOL My__CopyFile(CFSTR oldFile, CFSTR newFile) +static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) { NWindows::NFile::NIO::COutFile outFile; if (!outFile.Create(newFile, false)) @@ -865,7 +960,7 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) return false; - if (My__CopyFile(oldFile, newFile) == FALSE) + if (My_CopyFile(oldFile, newFile) == FALSE) return false; struct stat info_file; @@ -906,11 +1001,11 @@ bool GetCurrentDir(FString &path) { path.Empty(); - #define MY__PATH_MAX PATH_MAX - // #define MY__PATH_MAX 1024 + #define MY_PATH_MAX PATH_MAX + // #define MY_PATH_MAX 1024 - char s[MY__PATH_MAX + 1]; - char *res = getcwd(s, MY__PATH_MAX); + char s[MY_PATH_MAX + 1]; + char *res = getcwd(s, MY_PATH_MAX); if (res) { path = fas2fs(s); @@ -1035,10 +1130,10 @@ static C_umask g_umask; #define PRF(x) #define TRACE_SetFileAttrib(msg) \ - PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg)); + PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg);) #define TRACE_chmod(s, mode) \ - PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode))); + PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode));) int my_chown(CFSTR path, uid_t owner, gid_t group) { @@ -1047,7 +1142,7 @@ int my_chown(CFSTR path, uid_t owner, gid_t group) bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) { - TRACE_SetFileAttrib(""); + TRACE_SetFileAttrib("") struct stat st; @@ -1056,7 +1151,7 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) { if (lstat(path, &st) != 0) { - TRACE_SetFileAttrib("bad lstat()"); + TRACE_SetFileAttrib("bad lstat()") return false; } // TRACE_chmod("lstat", st.st_mode); @@ -1065,14 +1160,14 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) { if (stat(path, &st) != 0) { - TRACE_SetFileAttrib("bad stat()"); + TRACE_SetFileAttrib("bad stat()") return false; } } if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) { - TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION"); + TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION") st.st_mode = attrib >> 16; if (S_ISDIR(st.st_mode)) { @@ -1092,7 +1187,7 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) } else { - TRACE_SetFileAttrib("Only Windows Attributes"); + TRACE_SetFileAttrib("Only Windows Attributes") // Only Windows Attributes if (S_ISDIR(st.st_mode) || (attrib & FILE_ATTRIBUTE_READONLY) == 0) @@ -1105,7 +1200,7 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) if (S_ISLNK(st.st_mode)) { printf("\nfchmodat()\n"); - TRACE_chmod(path, (st.st_mode) & g_umask.mask); + TRACE_chmod(path, (st.st_mode) & g_umask.mask) // AT_SYMLINK_NOFOLLOW is not implemted still in Linux. res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask, S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0); @@ -1113,7 +1208,7 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) else */ { - TRACE_chmod(path, (st.st_mode) & g_umask.mask); + TRACE_chmod(path, (st.st_mode) & g_umask.mask) res = chmod(path, (st.st_mode) & g_umask.mask); } // TRACE_SetFileAttrib("End") @@ -1123,7 +1218,7 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName) { - PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName)); + PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName);) return (link(existFileName, newFileName) == 0); } |