summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/Windows/FileDir.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lzma/CPP/Windows/FileDir.cpp')
-rw-r--r--3rdparty/lzma/CPP/Windows/FileDir.cpp587
1 files changed, 587 insertions, 0 deletions
diff --git a/3rdparty/lzma/CPP/Windows/FileDir.cpp b/3rdparty/lzma/CPP/Windows/FileDir.cpp
new file mode 100644
index 00000000000..88215faa2ad
--- /dev/null
+++ b/3rdparty/lzma/CPP/Windows/FileDir.cpp
@@ -0,0 +1,587 @@
+// Windows/FileDir.cpp
+
+#include "StdAfx.h"
+
+#ifndef _UNICODE
+#include "../Common/StringConvert.h"
+#endif
+
+#include "FileDir.h"
+#include "FileFind.h"
+#include "FileName.h"
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+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 {
+
+#ifndef UNDER_CE
+
+bool MyGetWindowsDirectory(FString &path)
+{
+ UINT needLength;
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ TCHAR s[MAX_PATH + 2];
+ s[0] = 0;
+ needLength = ::GetWindowsDirectory(s, MAX_PATH + 1);
+ path = fas2fs(s);
+ }
+ else
+ #endif
+ {
+ WCHAR s[MAX_PATH + 2];
+ s[0] = 0;
+ needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1);
+ path = us2fs(s);
+ }
+ return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+
+bool MyGetSystemDirectory(FString &path)
+{
+ UINT needLength;
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ TCHAR s[MAX_PATH + 2];
+ s[0] = 0;
+ needLength = ::GetSystemDirectory(s, MAX_PATH + 1);
+ path = fas2fs(s);
+ }
+ else
+ #endif
+ {
+ WCHAR s[MAX_PATH + 2];
+ s[0] = 0;
+ needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1);
+ path = us2fs(s);
+ }
+ return (needLength > 0 && needLength <= MAX_PATH);
+}
+#endif
+
+bool SetDirTime(CFSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return false;
+ }
+ #endif
+ HANDLE hDir = ::CreateFileW(fs2us(fileName), 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)
+ {
+ UString longPath;
+ if (GetLongPath(fileName, longPath))
+ hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ }
+ #endif
+
+ bool res = false;
+ if (hDir != INVALID_HANDLE_VALUE)
+ {
+ res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime));
+ ::CloseHandle(hDir);
+ }
+ 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)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ if (::SetFileAttributes(fs2fas(fileName), fileAttributes))
+ return true;
+ }
+ else
+ #endif
+ {
+ if (::SetFileAttributesW(fs2us(fileName), fileAttributes))
+ return true;
+ #ifdef WIN_LONG_PATH
+ UString longPath;
+ if (GetLongPath(fileName, longPath))
+ return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));
+ #endif
+ }
+ return false;
+}
+
+bool MyRemoveDirectory(CFSTR path)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ if (::RemoveDirectory(fs2fas(path)))
+ return true;
+ }
+ else
+ #endif
+ {
+ if (::RemoveDirectoryW(fs2us(path)))
+ return true;
+ #ifdef WIN_LONG_PATH
+ UString longPath;
+ if (GetLongPath(path, longPath))
+ return BOOLToBool(::RemoveDirectoryW(longPath));
+ #endif
+ }
+ return false;
+}
+
+bool MyMoveFile(CFSTR existFileName, CFSTR newFileName)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ if (::MoveFile(fs2fas(existFileName), fs2fas(newFileName)))
+ return true;
+ }
+ else
+ #endif
+ {
+ if (::MoveFileW(fs2us(existFileName), fs2us(newFileName)))
+ return true;
+ #ifdef WIN_LONG_PATH
+ UString d1, d2;
+ if (GetLongPaths(existFileName, newFileName, d1, d2))
+ return BOOLToBool(::MoveFileW(d1, d2));
+ #endif
+ }
+ return false;
+}
+
+bool MyCreateDirectory(CFSTR path)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ if (::CreateDirectory(fs2fas(path), NULL))
+ return true;
+ }
+ else
+ #endif
+ {
+ if (::CreateDirectoryW(fs2us(path), NULL))
+ return true;
+ #ifdef WIN_LONG_PATH
+ if (::GetLastError() != ERROR_ALREADY_EXISTS)
+ {
+ UString longPath;
+ if (GetLongPath(path, longPath))
+ return BOOLToBool(::CreateDirectoryW(longPath, NULL));
+ }
+ #endif
+ }
+ return false;
+}
+
+bool CreateComplexDirectory(CFSTR _aPathName)
+{
+ FString pathName = _aPathName;
+ int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);
+ if (pos > 0 && pos == pathName.Length() - 1)
+ {
+ if (pathName.Length() == 3 && pathName[1] == L':')
+ return true; // Disk folder;
+ pathName.Delete(pos);
+ }
+ FString pathName2 = pathName;
+ pos = pathName.Length();
+ for (;;)
+ {
+ if (MyCreateDirectory(pathName))
+ break;
+ if (::GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ NFind::CFileInfo fileInfo;
+ if (!fileInfo.Find(pathName)) // For network folders
+ return true;
+ if (!fileInfo.IsDir())
+ return false;
+ break;
+ }
+ pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR);
+ if (pos < 0 || pos == 0)
+ return false;
+ if (pathName[pos - 1] == L':')
+ return false;
+ pathName = pathName.Left(pos);
+ }
+ pathName = pathName2;
+ while (pos < pathName.Length())
+ {
+ pos = pathName.Find(FCHAR_PATH_SEPARATOR, pos + 1);
+ if (pos < 0)
+ pos = pathName.Length();
+ if (!MyCreateDirectory(pathName.Left(pos)))
+ return false;
+ }
+ return true;
+}
+
+bool DeleteFileAlways(CFSTR name)
+{
+ if (!MySetFileAttributes(name, 0))
+ return false;
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ if (::DeleteFile(fs2fas(name)))
+ return true;
+ }
+ else
+ #endif
+ {
+ if (::DeleteFileW(fs2us(name)))
+ return true;
+ #ifdef WIN_LONG_PATH
+ UString longPath;
+ if (GetLongPath(name, longPath))
+ return BOOLToBool(::DeleteFileW(longPath));
+ #endif
+ }
+ return false;
+}
+
+static bool RemoveDirectorySubItems2(const FString pathPrefix, const NFind::CFileInfo &fileInfo)
+{
+ 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;
+ {
+ NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK);
+ while (enumerator.Next(fileInfo))
+ if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
+ return false;
+ }
+ if (!MySetFileAttributes(path, 0))
+ return false;
+ return MyRemoveDirectory(path);
+}
+
+#ifdef UNDER_CE
+
+bool MyGetFullPathName(CFSTR fileName, FString &resFullPath)
+{
+ resFullPath = fileName;
+ return true;
+}
+
+#else
+
+#ifdef WIN_LONG_PATH
+
+static FString GetLastPart(CFSTR path)
+{
+ int i = MyStringLen(path);
+ for (; i > 0; i--)
+ {
+ FChar c = path[i - 1];
+ if (c == FCHAR_PATH_SEPARATOR || c == '/')
+ break;
+ }
+ return path + i;
+}
+
+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)
+{
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ return BOOLToBool(::SetCurrentDirectory(fs2fas(path)));
+ }
+ else
+ #endif
+ {
+ return BOOLToBool(::SetCurrentDirectoryW(fs2us(path)));
+ }
+}
+
+bool MyGetCurrentDirectory(FString &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 = fas2fs(s);
+ }
+ else
+ #endif
+ {
+ WCHAR s[MAX_PATH + 2];
+ s[0] = 0;
+ needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s);
+ path = us2fs(s);
+ }
+ return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+#endif
+
+bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName)
+{
+ bool res = MyGetFullPathName(path, resFileName);
+ if (!res)
+ resFileName = path;
+ int pos = resFileName.ReverseFind(FCHAR_PATH_SEPARATOR);
+ if (pos >= 0)
+ {
+ resDirPrefix = resFileName.Left(pos + 1);
+ resFileName = resFileName.Mid(pos + 1);
+ }
+ return res;
+}
+
+bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix)
+{
+ FString resFileName;
+ return GetFullPathAndSplit(path, resDirPrefix, resFileName);
+}
+
+bool MyGetTempPath(FString &path)
+{
+ path.Empty();
+ DWORD needLength;
+ #ifndef _UNICODE
+ if (!g_IsNT)
+ {
+ TCHAR s[MAX_PATH + 2];
+ s[0] = 0;
+ needLength = ::GetTempPath(MAX_PATH + 1, s);
+ path = fas2fs(s);
+ }
+ else
+ #endif
+ {
+ WCHAR s[MAX_PATH + 2];
+ s[0] = 0;
+ needLength = ::GetTempPathW(MAX_PATH + 1, s);;
+ path = us2fs(s);
+ }
+ return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile)
+{
+ UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();
+ for (unsigned i = 0; i < 100; i++)
+ {
+ path = prefix;
+ if (addRandom)
+ {
+ FChar s[16];
+ UInt32 value = d;
+ unsigned k;
+ for (k = 0; k < 8; k++)
+ {
+ unsigned t = value & 0xF;
+ value >>= 4;
+ s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ }
+ s[k] = '\0';
+ if (outFile)
+ path += FChar('.');
+ path += s;
+ UInt32 step = GetTickCount() + 2;
+ if (step == 0)
+ step = 1;
+ d += step;
+ }
+ addRandom = true;
+ if (outFile)
+ path += FTEXT(".tmp");
+ if (NFind::DoesFileOrDirExist(path))
+ {
+ SetLastError(ERROR_ALREADY_EXISTS);
+ continue;
+ }
+ if (outFile)
+ {
+ if (outFile->Create(path, false))
+ return true;
+ }
+ else
+ {
+ if (MyCreateDirectory(path))
+ return true;
+ }
+ DWORD error = GetLastError();
+ if (error != ERROR_FILE_EXISTS &&
+ error != ERROR_ALREADY_EXISTS)
+ break;
+ }
+ path.Empty();
+ return false;
+}
+
+bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile)
+{
+ if (!Remove())
+ return false;
+ if (!CreateTempFile(prefix, false, _path, outFile))
+ return false;
+ _mustBeDeleted = true;
+ return true;
+}
+
+bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile)
+{
+ if (!Remove())
+ return false;
+ FString tempPath;
+ if (!MyGetTempPath(tempPath))
+ return false;
+ if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile))
+ return false;
+ _mustBeDeleted = true;
+ return true;
+}
+
+bool CTempFile::Remove()
+{
+ if (!_mustBeDeleted)
+ return true;
+ _mustBeDeleted = !DeleteFileAlways(_path);
+ return !_mustBeDeleted;
+}
+
+bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore)
+{
+ if (deleteDestBefore)
+ if (NFind::DoesFileExist(name))
+ if (!DeleteFileAlways(name))
+ return false;
+ DisableDeleting();
+ return MyMoveFile(_path, name);
+}
+
+bool CTempDir::Create(CFSTR prefix)
+{
+ if (!Remove())
+ return false;
+ FString tempPath;
+ if (!MyGetTempPath(tempPath))
+ return false;
+ if (!CreateTempFile(tempPath + prefix, true, _path, NULL))
+ return false;
+ _mustBeDeleted = true;
+ return true;
+}
+
+bool CTempDir::Remove()
+{
+ if (!_mustBeDeleted)
+ return true;
+ _mustBeDeleted = !RemoveDirectoryWithSubItems(_path);
+ return !_mustBeDeleted;
+}
+
+}}}