From be3b47d0d504a3409ce66bd77bb8c0acff87c4f5 Mon Sep 17 00:00:00 2001 From: kh1 Date: Thu, 15 Mar 2012 14:53:47 +0100 Subject: Reorganize the tree, have better ifw.pri. Shadow build support. Change-Id: I01fb12537f863ed0744979973c7e4153889cc5cb Reviewed-by: Tim Jenssen --- .../7zip/win/CPP/7zip/Archive/Hfs/HfsHandler.cpp | 243 +++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Hfs/HfsHandler.cpp (limited to 'src/libs/7zip/win/CPP/7zip/Archive/Hfs/HfsHandler.cpp') diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Hfs/HfsHandler.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Hfs/HfsHandler.cpp new file mode 100644 index 000000000..f226458d4 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Hfs/HfsHandler.cpp @@ -0,0 +1,243 @@ +// HfsHandler.cpp + +#include "StdAfx.h" + +#include "Common/ComTry.h" +#include "Windows/PropVariant.h" +#include "../../Common/StreamUtils.h" +#include "HfsHandler.h" + +namespace NArchive { +namespace NHfs { + +STATPROPSTG kProps[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsDir, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackSize, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME}, + { NULL, kpidATime, VT_FILETIME} +}; + +STATPROPSTG kArcProps[] = +{ + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidClusterSize, VT_UI4}, + { NULL, kpidFreeSpace, VT_UI8}, + { NULL, kpidCTime, VT_FILETIME}, + { NULL, kpidMTime, VT_FILETIME} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps + +static void HfsTimeToProp(UInt32 hfsTime, NWindows::NCOM::CPropVariant &prop) +{ + FILETIME ft; + HfsTimeToFileTime(hfsTime, ft); + prop = ft; +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidMethod: prop = _db.Header.IsHfsX() ? L"HFSX" : L"HFS+"; break; + case kpidClusterSize: prop = (UInt32)1 << _db.Header.BlockSizeLog; break; + case kpidFreeSpace: prop = (UInt64)_db.Header.NumFreeBlocks << _db.Header.BlockSizeLog; break; + case kpidMTime: HfsTimeToProp(_db.Header.MTime, prop); break; + case kpidCTime: + { + FILETIME localFt, ft; + HfsTimeToFileTime(_db.Header.CTime, localFt); + if (LocalFileTimeToFileTime(&localFt, &ft)) + prop = ft; + break; + } + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant prop; + const CItem &item = _db.Items[index]; + switch(propID) + { + case kpidPath: prop = _db.GetItemPath(index); break; + case kpidIsDir: prop = item.IsDir(); break; + + case kpidCTime: HfsTimeToProp(item.CTime, prop); break; + case kpidMTime: HfsTimeToProp(item.MTime, prop); break; + case kpidATime: HfsTimeToProp(item.ATime, prop); break; + + case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumBlocks << _db.Header.BlockSizeLog; break; + case kpidSize: if (!item.IsDir()) prop = item.Size; break; + } + prop.Detach(value); + return S_OK; + COM_TRY_END +} + +class CProgressImp: public CProgressVirt +{ + CMyComPtr _callback; +public: + HRESULT SetTotal(UInt64 numFiles); + HRESULT SetCompleted(UInt64 numFiles); + CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {} +}; + +HRESULT CProgressImp::SetTotal(UInt64 numFiles) +{ + if (_callback) + return _callback->SetTotal(&numFiles, NULL); + return S_OK; +} + +HRESULT CProgressImp::SetCompleted(UInt64 numFiles) +{ + if (_callback) + return _callback->SetCompleted(&numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback *callback) +{ + COM_TRY_BEGIN + Close(); + try + { + CProgressImp progressImp(callback); + HRESULT res = _db.Open(inStream, &progressImp); + if (res == E_ABORT) + return res; + if (res != S_OK) + return S_FALSE; + _stream = inStream; + } + catch(...) { return S_FALSE; } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _stream.Release(); + _db.Clear(); + return S_OK; +} + +STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == (UInt32)-1); + if (allFilesMode) + numItems = _db.Items.Size(); + if (numItems == 0) + return S_OK; + UInt32 i; + UInt64 totalSize = 0; + for (i = 0; i < numItems; i++) + { + const CItem &item = _db.Items[allFilesMode ? i : indices[i]]; + if (!item.IsDir()) + totalSize += item.Size; + } + RINOK(extractCallback->SetTotal(totalSize)); + + UInt64 currentTotalSize = 0, currentItemSize = 0; + + CByteBuffer buf; + const UInt32 kBufSize = (1 << 16); + buf.SetCapacity(kBufSize); + + for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + Int32 index = allFilesMode ? i : indices[i]; + const CItem &item = _db.Items[index]; + currentItemSize = 0; + if (!item.IsDir()) + currentItemSize = item.Size; + + CMyComPtr realOutStream; + Int32 askMode = testMode ? + NExtract::NAskMode::kTest : + NExtract::NAskMode::kExtract; + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + if (item.IsDir()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); + continue; + } + if (!testMode && !realOutStream) + continue; + RINOK(extractCallback->PrepareOperation(askMode)); + UInt64 pos = 0; + int res = NExtract::NOperationResult::kOK; + int i; + for (i = 0; i < item.Extents.Size(); i++) + { + if (item.Size == pos) + break; + if (res != NExtract::NOperationResult::kOK) + break; + const CExtent &e = item.Extents[i]; + RINOK(_stream->Seek((UInt64)e.Pos << _db.Header.BlockSizeLog, STREAM_SEEK_SET, NULL)); + UInt64 extentSize = (UInt64)e.NumBlocks << _db.Header.BlockSizeLog; + for (;;) + { + if (extentSize == 0) + break; + UInt64 rem = item.Size - pos; + if (rem == 0) + { + if (extentSize >= (UInt64)((UInt32)1 << _db.Header.BlockSizeLog)) + res = NExtract::NOperationResult::kDataError; + break; + } + UInt32 curSize = kBufSize; + if (curSize > rem) + curSize = (UInt32)rem; + if (curSize > extentSize) + curSize = (UInt32)extentSize; + RINOK(ReadStream_FALSE(_stream, buf, curSize)); + if (realOutStream) + { + RINOK(WriteStream(realOutStream, buf, curSize)); + } + pos += curSize; + extentSize -= curSize; + UInt64 processed = currentTotalSize + pos; + RINOK(extractCallback->SetCompleted(&processed)); + } + } + if (i != item.Extents.Size() || item.Size != pos) + res = NExtract::NOperationResult::kDataError; + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(res)); + } + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _db.Items.Size(); + return S_OK; +} + +}} -- cgit v1.2.3