This commit is contained in:
Igor Pavlov
2023-12-22 17:17:05 +00:00
committed by Kornel
parent ec44a8a070
commit a36c48cece
954 changed files with 42199 additions and 25482 deletions

View File

@@ -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);
}