summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp')
-rw-r--r--3rdparty/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp303
1 files changed, 271 insertions, 32 deletions
diff --git a/3rdparty/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/3rdparty/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index fd2807ac149..4e5f1f56041 100644
--- a/3rdparty/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/3rdparty/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -6,14 +6,54 @@
#include "../../../Windows/FileName.h"
#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/System.h"
-#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
#include "ArchiveOpenCallback.h"
+// #define DEBUG_VOLUMES
+
+#ifdef DEBUG_VOLUMES
+#include <stdio.h>
+#endif
+
+
+#ifdef DEBUG_VOLUMES
+ #define PRF(x) x
+#else
+ #define PRF(x)
+#endif
+
using namespace NWindows;
-STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
+HRESULT COpenCallbackImp::Init2(const FString &folderPrefix, const FString &fileName)
+{
+ Volumes.Init();
+ FileNames.Clear();
+ FileNames_WasUsed.Clear();
+ FileSizes.Clear();
+ _subArchiveMode = false;
+ // TotalSize = 0;
+ PasswordWasAsked = false;
+ _folderPrefix = folderPrefix;
+ if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName))
+ {
+ // throw 20121118;
+ return GetLastError_noZero_HRESULT();
+ }
+ return S_OK;
+}
+
+Z7_COM7F_IMF(COpenCallbackImp::SetSubArchiveName(const wchar_t *name))
+{
+ _subArchiveMode = true;
+ _subArchiveName = name;
+ // TotalSize = 0;
+ return S_OK;
+}
+
+Z7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes))
{
COM_TRY_BEGIN
if (ReOpenCallback)
@@ -24,7 +64,7 @@ STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes
COM_TRY_END
}
-STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
+Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes))
{
COM_TRY_BEGIN
if (ReOpenCallback)
@@ -34,8 +74,9 @@ STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *b
return Callback->Open_SetCompleted(files, bytes);
COM_TRY_END
}
-
-STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
+
+
+Z7_COM7F_IMF(COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value))
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
@@ -48,37 +89,194 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
else
switch (propID)
{
- case kpidName: prop = _fileInfo.Name; break;
+ case kpidName: prop = fs2us(_fileInfo.Name); break;
case kpidIsDir: prop = _fileInfo.IsDir(); break;
case kpidSize: prop = _fileInfo.Size; break;
- case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break;
- case kpidCTime: prop = _fileInfo.CTime; break;
- case kpidATime: prop = _fileInfo.ATime; break;
- case kpidMTime: prop = _fileInfo.MTime; break;
+ case kpidAttrib: prop = (UInt32)_fileInfo.GetWinAttrib(); break;
+ case kpidPosixAttrib: prop = (UInt32)_fileInfo.GetPosixAttrib(); break;
+ case kpidCTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.CTime); break;
+ case kpidATime: PropVariant_SetFrom_FiTime(prop, _fileInfo.ATime); break;
+ case kpidMTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.MTime); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
-struct CInFileStreamVol: public CInFileStream
-{
- int FileNameIndex;
+
+// ---------- CInFileStreamVol ----------
+
+Z7_CLASS_IMP_COM_2(
+ CInFileStreamVol
+ , IInStream
+ , IStreamGetSize
+)
+ Z7_IFACE_COM7_IMP(ISequentialInStream)
+public:
+ unsigned FileIndex;
COpenCallbackImp *OpenCallbackImp;
CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
-
+
+ HRESULT EnsureOpen()
+ {
+ return OpenCallbackImp->Volumes.EnsureOpen(FileIndex);
+ }
+
~CInFileStreamVol()
{
if (OpenCallbackRef)
- OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false;
+ OpenCallbackImp->AtCloseFile(FileIndex);
}
};
+void CMultiStreams::InsertToList(unsigned index)
+{
+ {
+ CSubStream &s = Streams[index];
+ s.Next = Head;
+ s.Prev = -1;
+ }
+ if (Head != -1)
+ Streams[(unsigned)Head].Prev = (int)index;
+ else
+ {
+ // if (Tail != -1) throw 1;
+ Tail = (int)index;
+ }
+ Head = (int)index;
+ NumListItems++;
+}
+
+// s must bee in List
+void CMultiStreams::RemoveFromList(CSubStream &s)
+{
+ if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev;
+ if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next;
+ s.Next = -1; // optional
+ s.Prev = -1; // optional
+ NumListItems--;
+}
+
+void CMultiStreams::CloseFile(unsigned index)
+{
+ CSubStream &s = Streams[index];
+ if (s.Stream)
+ {
+ s.Stream.Release();
+ RemoveFromList(s);
+ // s.InFile->Close();
+ // s.IsOpen = false;
+ #ifdef DEBUG_VOLUMES
+ static int numClosing = 0;
+ numClosing++;
+ printf("\nCloseFile %u, total_closes = %u, num_open_files = %u\n", index, numClosing, NumListItems);
+ #endif
+ }
+}
+
+void CMultiStreams::Init()
+{
+ Head = -1;
+ Tail = -1;
+ NumListItems = 0;
+ Streams.Clear();
+}
+
+CMultiStreams::CMultiStreams():
+ Head(-1),
+ Tail(-1),
+ NumListItems(0)
+{
+ NumOpenFiles_AllowedMax = NSystem::Get_File_OPEN_MAX_Reduced_for_3_tasks();
+ PRF(printf("\nNumOpenFiles_Limit = %u\n", NumOpenFiles_AllowedMax));
+}
+
+
+HRESULT CMultiStreams::PrepareToOpenNew()
+{
+ if (NumListItems < NumOpenFiles_AllowedMax)
+ return S_OK;
+ if (Tail == -1)
+ return E_FAIL;
+ CMultiStreams::CSubStream &tailStream = Streams[(unsigned)Tail];
+ RINOK(InStream_GetPos(tailStream.Stream, tailStream.LocalPos))
+ CloseFile((unsigned)Tail);
+ return S_OK;
+}
+
+
+HRESULT CMultiStreams::EnsureOpen(unsigned index)
+{
+ CMultiStreams::CSubStream &s = Streams[index];
+ if (s.Stream)
+ {
+ if ((int)index != Head)
+ {
+ RemoveFromList(s);
+ InsertToList(index);
+ }
+ }
+ else
+ {
+ RINOK(PrepareToOpenNew())
+ {
+ CInFileStream *inFile = new CInFileStream;
+ CMyComPtr<IInStream> inStreamTemp = inFile;
+ if (!inFile->Open(s.Path))
+ return GetLastError_noZero_HRESULT();
+ s.FileSpec = inFile;
+ s.Stream = s.FileSpec;
+ InsertToList(index);
+ }
+ // s.IsOpen = true;
+ if (s.LocalPos != 0)
+ {
+ RINOK(s.Stream->Seek((Int64)s.LocalPos, STREAM_SEEK_SET, &s.LocalPos))
+ }
+ #ifdef DEBUG_VOLUMES
+ static int numOpens = 0;
+ numOpens++;
+ printf("\n-- %u, ReOpen, total_reopens = %u, num_open_files = %u\n", index, numOpens, NumListItems);
+ #endif
+ }
+ return S_OK;
+}
+
+
+Z7_COM7F_IMF(CInFileStreamVol::Read(void *data, UInt32 size, UInt32 *processedSize))
+{
+ if (processedSize)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ RINOK(EnsureOpen())
+ CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
+ PRF(printf("\n== %u, Read =%u \n", FileIndex, size));
+ return s.Stream->Read(data, size, processedSize);
+}
+
+Z7_COM7F_IMF(CInFileStreamVol::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
+{
+ // if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION;
+ RINOK(EnsureOpen())
+ CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
+ PRF(printf("\n-- %u, Seek seekOrigin=%u Seek =%u\n", FileIndex, seekOrigin, (unsigned)offset));
+ return s.Stream->Seek(offset, seekOrigin, newPosition);
+}
+
+Z7_COM7F_IMF(CInFileStreamVol::GetSize(UInt64 *size))
+{
+ RINOK(EnsureOpen())
+ CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
+ return s.FileSpec->GetSize(size);
+}
+
+
// from ArchiveExtractCallback.cpp
bool IsSafePath(const UString &path);
-STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
+Z7_COM7F_IMF(COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream))
{
COM_TRY_BEGIN
*inStream = NULL;
@@ -87,13 +285,13 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre
return S_FALSE;
if (Callback)
{
- RINOK(Callback->Open_CheckBreak());
+ RINOK(Callback->Open_CheckBreak())
}
UString name2 = name;
- #ifndef _SFX
+ #ifndef Z7_SFX
#ifdef _WIN32
name2.Replace(L'/', WCHAR_PATH_SEPARATOR);
@@ -102,30 +300,58 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre
// if (!allowAbsVolPaths)
if (!IsSafePath(name2))
return S_FALSE;
-
+
+ #ifdef _WIN32
+ /* WIN32 allows wildcards in Find() function
+ and doesn't allow wildcard in File.Open()
+ so we can work without the following wildcard check here */
+ if (name2.Find(L'*') >= 0)
+ return S_FALSE;
+ {
+ unsigned startPos = 0;
+ if (name2.IsPrefixedBy_Ascii_NoCase("\\\\?\\"))
+ startPos = 3;
+ if (name2.Find(L'?', startPos) >= 0)
+ return S_FALSE;
+ }
+ #endif
+
#endif
FString fullPath;
if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath))
return S_FALSE;
- if (!_fileInfo.Find(fullPath))
+ if (!_fileInfo.Find_FollowLink(fullPath))
return S_FALSE;
if (_fileInfo.IsDir())
return S_FALSE;
- CInFileStreamVol *inFile = new CInFileStreamVol;
- CMyComPtr<IInStream> inStreamTemp = inFile;
- if (!inFile->Open(fullPath))
+
+ CMultiStreams::CSubStream s;
+
{
- DWORD lastError = ::GetLastError();
- if (lastError == 0)
- return E_FAIL;
- return HRESULT_FROM_WIN32(lastError);
+ CInFileStream *inFile = new CInFileStream;
+ CMyComPtr<IInStream> inStreamTemp = inFile;
+ if (!inFile->Open(fullPath))
+ return GetLastError_noZero_HRESULT();
+ RINOK(Volumes.PrepareToOpenNew())
+ s.FileSpec = inFile;
+ s.Stream = s.FileSpec;
+ s.Path = fullPath;
+ // s.Size = _fileInfo.Size;
+ // s.IsOpen = true;
}
+ const unsigned fileIndex = Volumes.Streams.Add(s);
+ Volumes.InsertToList(fileIndex);
+
FileSizes.Add(_fileInfo.Size);
FileNames.Add(name2);
- inFile->FileNameIndex = FileNames_WasUsed.Add(true);
+ FileNames_WasUsed.Add(true);
+
+ CInFileStreamVol *inFile = new CInFileStreamVol;
+ CMyComPtr<IInStream> inStreamTemp = inFile;
+ inFile->FileIndex = fileIndex;
inFile->OpenCallbackImp = this;
inFile->OpenCallbackRef = this;
// TotalSize += _fileInfo.Size;
@@ -134,14 +360,16 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre
COM_TRY_END
}
-#ifndef _NO_CRYPTO
-STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
+
+#ifndef Z7_NO_CRYPTO
+Z7_COM7F_IMF(COpenCallbackImp::CryptoGetTextPassword(BSTR *password))
{
COM_TRY_BEGIN
if (ReOpenCallback)
{
- CMyComPtr<ICryptoGetTextPassword> getTextPassword;
- ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+ Z7_DECL_CMyComPtr_QI_FROM(
+ ICryptoGetTextPassword,
+ getTextPassword, ReOpenCallback)
if (getTextPassword)
return getTextPassword->CryptoGetTextPassword(password);
}
@@ -152,3 +380,14 @@ STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
COM_TRY_END
}
#endif
+
+// IProgress
+Z7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 /* total */))
+{
+ return S_OK;
+}
+
+Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 * /* completed */))
+{
+ return S_OK;
+}