mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 13:14:59 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
358
CPP/Windows/FileDir.cpp
Executable file → Normal file
358
CPP/Windows/FileDir.cpp
Executable file → Normal file
@@ -14,21 +14,17 @@
|
||||
extern bool g_IsNT;
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NName;
|
||||
|
||||
namespace NWindows {
|
||||
namespace NFile {
|
||||
|
||||
// SetCurrentDirectory doesn't support \\?\ prefix
|
||||
|
||||
#ifdef WIN_LONG_PATH
|
||||
bool GetLongPathBase(CFSTR fileName, UString &res);
|
||||
bool GetLongPath(CFSTR fileName, UString &res);
|
||||
#endif
|
||||
|
||||
namespace NDirectory {
|
||||
namespace NDir {
|
||||
|
||||
#ifndef UNDER_CE
|
||||
|
||||
bool MyGetWindowsDirectory(FString &path)
|
||||
bool GetWindowsDir(FString &path)
|
||||
{
|
||||
UINT needLength;
|
||||
#ifndef _UNICODE
|
||||
@@ -50,8 +46,7 @@ bool MyGetWindowsDirectory(FString &path)
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
}
|
||||
|
||||
|
||||
bool MyGetSystemDirectory(FString &path)
|
||||
bool GetSystemDir(FString &path)
|
||||
{
|
||||
UINT needLength;
|
||||
#ifndef _UNICODE
|
||||
@@ -74,7 +69,7 @@ bool MyGetSystemDirectory(FString &path)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
@@ -83,13 +78,16 @@ bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, co
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
HANDLE hDir = ::CreateFileW(fs2us(fileName), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
|
||||
HANDLE hDir = INVALID_HANDLE_VALUE;
|
||||
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
|
||||
if (hDir == INVALID_HANDLE_VALUE)
|
||||
if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetLongPath(fileName, longPath))
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
}
|
||||
@@ -104,43 +102,33 @@ bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, co
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef WIN_LONG_PATH
|
||||
bool GetLongPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2)
|
||||
{
|
||||
if (!GetLongPathBase(s1, d1) ||
|
||||
!GetLongPathBase(s2, d2))
|
||||
return false;
|
||||
if (d1.IsEmpty() && d2.IsEmpty())
|
||||
return false;
|
||||
if (d1.IsEmpty()) d1 = fs2us(s1);
|
||||
if (d2.IsEmpty()) d2 = fs2us(s2);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MySetFileAttributes(CFSTR fileName, DWORD fileAttributes)
|
||||
bool SetFileAttrib(CFSTR path, DWORD attrib)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
if (::SetFileAttributes(fs2fas(fileName), fileAttributes))
|
||||
if (::SetFileAttributes(fs2fas(path), attrib))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (::SetFileAttributesW(fs2us(fileName), fileAttributes))
|
||||
return true;
|
||||
IF_USE_MAIN_PATH
|
||||
if (::SetFileAttributesW(fs2us(path), attrib))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
UString longPath;
|
||||
if (GetLongPath(fileName, longPath))
|
||||
return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::SetFileAttributesW(longPath, attrib));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MyRemoveDirectory(CFSTR path)
|
||||
bool RemoveDir(CFSTR path)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
@@ -151,40 +139,94 @@ bool MyRemoveDirectory(CFSTR path)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (::RemoveDirectoryW(fs2us(path)))
|
||||
return true;
|
||||
IF_USE_MAIN_PATH
|
||||
if (::RemoveDirectoryW(fs2us(path)))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
UString longPath;
|
||||
if (GetLongPath(path, longPath))
|
||||
return BOOLToBool(::RemoveDirectoryW(longPath));
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::RemoveDirectoryW(longPath));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MyMoveFile(CFSTR existFileName, CFSTR newFileName)
|
||||
bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
if (::MoveFile(fs2fas(existFileName), fs2fas(newFileName)))
|
||||
if (::MoveFile(fs2fas(oldFile), fs2fas(newFile)))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (::MoveFileW(fs2us(existFileName), fs2us(newFileName)))
|
||||
return true;
|
||||
IF_USE_MAIN_PATH_2(oldFile, newFile)
|
||||
if (::MoveFileW(fs2us(oldFile), fs2us(newFile)))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
UString d1, d2;
|
||||
if (GetLongPaths(existFileName, newFileName, d1, d2))
|
||||
return BOOLToBool(::MoveFileW(d1, d2));
|
||||
if (USE_SUPER_PATH_2)
|
||||
{
|
||||
UString d1, d2;
|
||||
if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))
|
||||
return BOOLToBool(::MoveFileW(d1, d2));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MyCreateDirectory(CFSTR path)
|
||||
#ifndef UNDER_CE
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
typedef BOOL (WINAPI *Func_CreateHardLinkW)(
|
||||
LPCWSTR lpFileName,
|
||||
LPCWSTR lpExistingFileName,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
||||
);
|
||||
EXTERN_C_END
|
||||
|
||||
bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return false;
|
||||
/*
|
||||
if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL))
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW)
|
||||
::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW");
|
||||
if (!my_CreateHardLinkW)
|
||||
return false;
|
||||
IF_USE_MAIN_PATH_2(newFileName, existFileName)
|
||||
if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (USE_SUPER_PATH_2)
|
||||
{
|
||||
UString d1, d2;
|
||||
if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2))
|
||||
return BOOLToBool(my_CreateHardLinkW(d1, d2, NULL));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool CreateDir(CFSTR path)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
@@ -195,13 +237,14 @@ bool MyCreateDirectory(CFSTR path)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (::CreateDirectoryW(fs2us(path), NULL))
|
||||
return true;
|
||||
IF_USE_MAIN_PATH
|
||||
if (::CreateDirectoryW(fs2us(path), NULL))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
if (::GetLastError() != ERROR_ALREADY_EXISTS)
|
||||
if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetLongPath(path, longPath))
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::CreateDirectoryW(longPath, NULL));
|
||||
}
|
||||
#endif
|
||||
@@ -209,21 +252,22 @@ bool MyCreateDirectory(CFSTR path)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CreateComplexDirectory(CFSTR _aPathName)
|
||||
bool CreateComplexDir(CFSTR _aPathName)
|
||||
{
|
||||
FString pathName = _aPathName;
|
||||
int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);
|
||||
if (pos > 0 && pos == pathName.Length() - 1)
|
||||
if (pos > 0 && (unsigned)pos == pathName.Len() - 1)
|
||||
{
|
||||
if (pathName.Length() == 3 && pathName[1] == L':')
|
||||
if (pathName.Len() == 3 && pathName[1] == L':')
|
||||
return true; // Disk folder;
|
||||
pathName.Delete(pos);
|
||||
}
|
||||
FString pathName2 = pathName;
|
||||
pos = pathName.Length();
|
||||
const FString pathName2 = pathName;
|
||||
pos = pathName.Len();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (MyCreateDirectory(pathName))
|
||||
if (CreateDir(pathName))
|
||||
break;
|
||||
if (::GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
@@ -239,156 +283,111 @@ bool CreateComplexDirectory(CFSTR _aPathName)
|
||||
return false;
|
||||
if (pathName[pos - 1] == L':')
|
||||
return false;
|
||||
pathName = pathName.Left(pos);
|
||||
pathName.DeleteFrom(pos);
|
||||
}
|
||||
pathName = pathName2;
|
||||
while (pos < pathName.Length())
|
||||
|
||||
while (pos < (int)pathName2.Len())
|
||||
{
|
||||
pos = pathName.Find(FCHAR_PATH_SEPARATOR, pos + 1);
|
||||
pos = pathName2.Find(FCHAR_PATH_SEPARATOR, pos + 1);
|
||||
if (pos < 0)
|
||||
pos = pathName.Length();
|
||||
if (!MyCreateDirectory(pathName.Left(pos)))
|
||||
pos = pathName2.Len();
|
||||
pathName.SetFrom(pathName2, pos);
|
||||
if (!CreateDir(pathName))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeleteFileAlways(CFSTR name)
|
||||
bool DeleteFileAlways(CFSTR path)
|
||||
{
|
||||
if (!MySetFileAttributes(name, 0))
|
||||
if (!SetFileAttrib(path, 0))
|
||||
return false;
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
if (::DeleteFile(fs2fas(name)))
|
||||
if (::DeleteFile(fs2fas(path)))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (::DeleteFileW(fs2us(name)))
|
||||
return true;
|
||||
IF_USE_MAIN_PATH
|
||||
if (::DeleteFileW(fs2us(path)))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
UString longPath;
|
||||
if (GetLongPath(name, longPath))
|
||||
return BOOLToBool(::DeleteFileW(longPath));
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString longPath;
|
||||
if (GetSuperPath(path, longPath, USE_MAIN_PATH))
|
||||
return BOOLToBool(::DeleteFileW(longPath));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool RemoveDirectorySubItems2(const FString pathPrefix, const NFind::CFileInfo &fileInfo)
|
||||
bool RemoveDirWithSubItems(const FString &path)
|
||||
{
|
||||
if (fileInfo.IsDir())
|
||||
return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
|
||||
return DeleteFileAlways(pathPrefix + fileInfo.Name);
|
||||
}
|
||||
bool RemoveDirectoryWithSubItems(const FString &path)
|
||||
{
|
||||
NFind::CFileInfo fileInfo;
|
||||
FString pathPrefix = path + FCHAR_PATH_SEPARATOR;
|
||||
bool needRemoveSubItems = true;
|
||||
{
|
||||
NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK);
|
||||
while (enumerator.Next(fileInfo))
|
||||
if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
|
||||
return false;
|
||||
NFind::CFileInfo fi;
|
||||
if (!fi.Find(path))
|
||||
return false;
|
||||
if (!fi.IsDir())
|
||||
{
|
||||
::SetLastError(ERROR_DIRECTORY);
|
||||
return false;
|
||||
}
|
||||
if (fi.HasReparsePoint())
|
||||
needRemoveSubItems = false;
|
||||
}
|
||||
if (!MySetFileAttributes(path, 0))
|
||||
|
||||
if (needRemoveSubItems)
|
||||
{
|
||||
FString s = path;
|
||||
s += FCHAR_PATH_SEPARATOR;
|
||||
unsigned prefixSize = s.Len();
|
||||
s += FCHAR_ANY_MASK;
|
||||
NFind::CEnumerator enumerator(s);
|
||||
NFind::CFileInfo fi;
|
||||
while (enumerator.Next(fi))
|
||||
{
|
||||
s.DeleteFrom(prefixSize);
|
||||
s += fi.Name;
|
||||
if (fi.IsDir())
|
||||
{
|
||||
if (!RemoveDirWithSubItems(s))
|
||||
return false;
|
||||
}
|
||||
else if (!DeleteFileAlways(s))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetFileAttrib(path, 0))
|
||||
return false;
|
||||
return MyRemoveDirectory(path);
|
||||
return RemoveDir(path);
|
||||
}
|
||||
|
||||
#ifdef UNDER_CE
|
||||
|
||||
bool MyGetFullPathName(CFSTR fileName, FString &resFullPath)
|
||||
bool MyGetFullPathName(CFSTR path, FString &resFullPath)
|
||||
{
|
||||
resFullPath = fileName;
|
||||
resFullPath = path;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef WIN_LONG_PATH
|
||||
|
||||
static FString GetLastPart(CFSTR path)
|
||||
bool MyGetFullPathName(CFSTR path, FString &resFullPath)
|
||||
{
|
||||
int i = MyStringLen(path);
|
||||
for (; i > 0; i--)
|
||||
{
|
||||
FChar c = path[i - 1];
|
||||
if (c == FCHAR_PATH_SEPARATOR || c == '/')
|
||||
break;
|
||||
}
|
||||
return path + i;
|
||||
return GetFullPath(path, resFullPath);
|
||||
}
|
||||
|
||||
static void AddTrailingDots(CFSTR oldPath, FString &newPath)
|
||||
{
|
||||
int len = MyStringLen(oldPath);
|
||||
int i;
|
||||
for (i = len; i > 0 && oldPath[i - 1] == '.'; i--);
|
||||
if (i == 0 || i == len)
|
||||
return;
|
||||
FString oldName = GetLastPart(oldPath);
|
||||
FString newName = GetLastPart(newPath);
|
||||
int nonDotsLen = oldName.Length() - (len - i);
|
||||
if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0)
|
||||
return;
|
||||
for (; i != len; i++)
|
||||
newPath += '.';
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool MyGetFullPathName(CFSTR fileName, FString &resFullPath)
|
||||
{
|
||||
resFullPath.Empty();
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
TCHAR s[MAX_PATH + 2];
|
||||
s[0] = 0;
|
||||
LPTSTR fileNamePointer = 0;
|
||||
DWORD needLength = ::GetFullPathName(fs2fas(fileName), MAX_PATH + 1, s, &fileNamePointer);
|
||||
if (needLength == 0 || needLength > MAX_PATH)
|
||||
return false;
|
||||
resFullPath = fas2fs(s);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
LPWSTR fileNamePointer = 0;
|
||||
WCHAR s[MAX_PATH + 2];
|
||||
s[0] = 0;
|
||||
DWORD needLength = ::GetFullPathNameW(fs2us(fileName), MAX_PATH + 1, s, &fileNamePointer);
|
||||
if (needLength == 0)
|
||||
return false;
|
||||
if (needLength <= MAX_PATH)
|
||||
{
|
||||
resFullPath = us2fs(s);
|
||||
return true;
|
||||
}
|
||||
#ifdef WIN_LONG_PATH
|
||||
needLength++;
|
||||
UString temp;
|
||||
LPWSTR buffer = temp.GetBuffer(needLength + 1);
|
||||
buffer[0] = 0;
|
||||
DWORD needLength2 = ::GetFullPathNameW(fs2us(fileName), needLength, buffer, &fileNamePointer);
|
||||
temp.ReleaseBuffer();
|
||||
if (needLength2 > 0 && needLength2 <= needLength)
|
||||
{
|
||||
resFullPath = us2fs(temp);
|
||||
AddTrailingDots(fileName, resFullPath);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MySetCurrentDirectory(CFSTR path)
|
||||
bool SetCurrentDir(CFSTR path)
|
||||
{
|
||||
// SetCurrentDirectory doesn't support \\?\ prefix
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
@@ -401,7 +400,7 @@ bool MySetCurrentDirectory(CFSTR path)
|
||||
}
|
||||
}
|
||||
|
||||
bool MyGetCurrentDirectory(FString &path)
|
||||
bool GetCurrentDir(FString &path)
|
||||
{
|
||||
path.Empty();
|
||||
DWORD needLength;
|
||||
@@ -428,15 +427,12 @@ bool MyGetCurrentDirectory(FString &path)
|
||||
|
||||
bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName)
|
||||
{
|
||||
bool res = MyGetFullPathName(path, resFileName);
|
||||
bool res = MyGetFullPathName(path, resDirPrefix);
|
||||
if (!res)
|
||||
resFileName = path;
|
||||
int pos = resFileName.ReverseFind(FCHAR_PATH_SEPARATOR);
|
||||
if (pos >= 0)
|
||||
{
|
||||
resDirPrefix = resFileName.Left(pos + 1);
|
||||
resFileName = resFileName.Mid(pos + 1);
|
||||
}
|
||||
resDirPrefix = path;
|
||||
int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR);
|
||||
resFileName = resDirPrefix.Ptr(pos + 1);
|
||||
resDirPrefix.DeleteFrom(pos + 1);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -510,7 +506,7 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MyCreateDirectory(path))
|
||||
if (CreateDir(path))
|
||||
return true;
|
||||
}
|
||||
DWORD error = GetLastError();
|
||||
@@ -580,7 +576,7 @@ bool CTempDir::Remove()
|
||||
{
|
||||
if (!_mustBeDeleted)
|
||||
return true;
|
||||
_mustBeDeleted = !RemoveDirectoryWithSubItems(_path);
|
||||
_mustBeDeleted = !RemoveDirWithSubItems(_path);
|
||||
return !_mustBeDeleted;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user