summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/Windows/FileDir.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2023-12-06 07:58:49 +1100
committer Vas Crabb <vas@vastheman.com>2023-12-06 07:58:49 +1100
commit79bef1e23049fdac25f1fefd132e0b6c7d2cc3a1 (patch)
tree643e9313fe86f583c4022c338677cbc12b761df7 /3rdparty/lzma/CPP/Windows/FileDir.cpp
parent512ccf0c7c9b4f08e41038b2ed2de220e140385b (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.cpp235
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);
}