NtfsHandler.cpp (p7zip_15.14.1_src_all) | : | NtfsHandler.cpp (p7zip_16.02_src_all) | ||
---|---|---|---|---|
skipping to change at line 631 | skipping to change at line 631 | |||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); | STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); | |||
}; | }; | |||
static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen) | static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen) | |||
{ | { | |||
size_t destSize = 0; | size_t destSize = 0; | |||
while (destSize < destLen) | while (destSize < destLen) | |||
{ | { | |||
if (srcLen < 2 || (destSize & 0xFFF) != 0) | if (srcLen < 2 || (destSize & 0xFFF) != 0) | |||
break; | break; | |||
UInt32 v = Get16(src); | UInt32 comprSize; | |||
if (v == 0) | ||||
break; | ||||
src += 2; | ||||
srcLen -= 2; | ||||
UInt32 comprSize = (v & 0xFFF) + 1; | ||||
if (comprSize > srcLen) | ||||
break; | ||||
srcLen -= comprSize; | ||||
if ((v & 0x8000) == 0) | ||||
{ | { | |||
if (comprSize != (1 << 12)) | const UInt32 v = Get16(src); | |||
if (v == 0) | ||||
break; | ||||
src += 2; | ||||
srcLen -= 2; | ||||
comprSize = (v & 0xFFF) + 1; | ||||
if (comprSize > srcLen) | ||||
break; | break; | |||
memcpy(dest + destSize, src, comprSize); | srcLen -= comprSize; | |||
src += comprSize; | if ((v & 0x8000) == 0) | |||
destSize += comprSize; | { | |||
if (comprSize != (1 << 12)) | ||||
break; | ||||
memcpy(dest + destSize, src, comprSize); | ||||
src += comprSize; | ||||
destSize += comprSize; | ||||
continue; | ||||
} | ||||
} | } | |||
else | ||||
{ | { | |||
if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0) | if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0) | |||
return 0; | return 0; | |||
unsigned numDistBits = 4; | unsigned numDistBits = 4; | |||
UInt32 sbOffset = 0; | UInt32 sbOffset = 0; | |||
UInt32 pos = 0; | UInt32 pos = 0; | |||
do | do | |||
{ | { | |||
comprSize--; | comprSize--; | |||
skipping to change at line 673 | skipping to change at line 676 | |||
if (sbOffset >= (1 << 12)) | if (sbOffset >= (1 << 12)) | |||
return 0; | return 0; | |||
dest[destSize++] = src[pos++]; | dest[destSize++] = src[pos++]; | |||
sbOffset++; | sbOffset++; | |||
comprSize--; | comprSize--; | |||
} | } | |||
else | else | |||
{ | { | |||
if (comprSize < 2) | if (comprSize < 2) | |||
return 0; | return 0; | |||
UInt32 v = Get16(src + pos); | const UInt32 v = Get16(src + pos); | |||
pos += 2; | pos += 2; | |||
comprSize -= 2; | comprSize -= 2; | |||
while (((sbOffset - 1) >> numDistBits) != 0) | while (((sbOffset - 1) >> numDistBits) != 0) | |||
numDistBits++; | numDistBits++; | |||
UInt32 len = (v & (0xFFFF >> numDistBits)) + 3; | UInt32 len = (v & (0xFFFF >> numDistBits)) + 3; | |||
if (sbOffset + len > (1 << 12)) | if (sbOffset + len > (1 << 12)) | |||
return 0; | return 0; | |||
UInt32 dist = (v >> (16 - numDistBits)); | UInt32 dist = (v >> (16 - numDistBits)); | |||
skipping to change at line 710 | skipping to change at line 713 | |||
} | } | |||
STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) | STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
{ | { | |||
if (processedSize) | if (processedSize) | |||
*processedSize = 0; | *processedSize = 0; | |||
if (_virtPos >= Size) | if (_virtPos >= Size) | |||
return (Size == _virtPos) ? S_OK: E_FAIL; | return (Size == _virtPos) ? S_OK: E_FAIL; | |||
if (size == 0) | if (size == 0) | |||
return S_OK; | return S_OK; | |||
UInt64 rem = Size - _virtPos; | { | |||
if (size > rem) | const UInt64 rem = Size - _virtPos; | |||
size = (UInt32)rem; | if (size > rem) | |||
size = (UInt32)rem; | ||||
} | ||||
if (_virtPos >= InitializedSize) | if (_virtPos >= InitializedSize) | |||
{ | { | |||
memset((Byte *)data, 0, size); | memset((Byte *)data, 0, size); | |||
_virtPos += size; | _virtPos += size; | |||
*processedSize = size; | *processedSize = size; | |||
return S_OK; | return S_OK; | |||
} | } | |||
rem = InitializedSize - _virtPos; | ||||
if (size > rem) | { | |||
size = (UInt32)rem; | const UInt64 rem = InitializedSize - _virtPos; | |||
if (size > rem) | ||||
size = (UInt32)rem; | ||||
} | ||||
while (_curRem == 0) | while (_curRem == 0) | |||
{ | { | |||
UInt64 cacheTag = _virtPos >> _chunkSizeLog; | UInt64 cacheTag = _virtPos >> _chunkSizeLog; | |||
UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1); | UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1); | |||
if (_tags[cacheIndex] == cacheTag) | if (_tags[cacheIndex] == cacheTag) | |||
{ | { | |||
UInt32 chunkSize = (UInt32)1 << _chunkSizeLog; | UInt32 chunkSize = (UInt32)1 << _chunkSizeLog; | |||
UInt32 offset = (UInt32)_virtPos & (chunkSize - 1); | UInt32 offset = (UInt32)_virtPos & (chunkSize - 1); | |||
UInt32 cur = MyMin(chunkSize - offset, size); | UInt32 cur = MyMin(chunkSize - offset, size); | |||
skipping to change at line 839 | skipping to change at line 848 | |||
if (curVirt + numChunks > virtBlock2End) | if (curVirt + numChunks > virtBlock2End) | |||
numChunks = virtBlock2End - curVirt; | numChunks = virtBlock2End - curVirt; | |||
size_t compressed = (size_t)numChunks << BlockSizeLog; | size_t compressed = (size_t)numChunks << BlockSizeLog; | |||
RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed)); | RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed)); | |||
curVirt += numChunks; | curVirt += numChunks; | |||
_physPos += compressed; | _physPos += compressed; | |||
offs += compressed; | offs += compressed; | |||
} | } | |||
size_t destLenMax = GetCuSize(); | size_t destLenMax = GetCuSize(); | |||
size_t destLen = destLenMax; | size_t destLen = destLenMax; | |||
UInt64 rem = Size - (virtBlock2 << BlockSizeLog); | const UInt64 rem = Size - (virtBlock2 << BlockSizeLog); | |||
if (destLen > rem) | if (destLen > rem) | |||
destLen = (size_t)rem; | destLen = (size_t)rem; | |||
Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog); | Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog); | |||
size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs); | size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs); | |||
_tags[cacheIndex] = cacheTag; | _tags[cacheIndex] = cacheTag; | |||
// some files in Vista have destSize > destLen | // some files in Vista have destSize > destLen | |||
if (destSizeRes < destLen) | if (destSizeRes < destLen) | |||
{ | { | |||
skipping to change at line 896 | skipping to change at line 905 | |||
_virtPos = offset; | _virtPos = offset; | |||
} | } | |||
if (newPosition) | if (newPosition) | |||
*newPosition = offset; | *newPosition = offset; | |||
return S_OK; | return S_OK; | |||
} | } | |||
static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAt tr> &attrs, | static HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAt tr> &attrs, | |||
unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVe ctor<CExtent> &Extents) | unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVe ctor<CExtent> &Extents) | |||
{ | { | |||
CExtent e; | { | |||
e.Virt = 0; | CExtent e; | |||
e.Phy = kEmptyExtent; | e.Virt = 0; | |||
Extents.Add(e); | e.Phy = kEmptyExtent; | |||
Extents.Add(e); | ||||
} | ||||
const CAttr &attr0 = attrs[attrIndex]; | const CAttr &attr0 = attrs[attrIndex]; | |||
if (attr0.AllocatedSize < attr0.Size || | if (attr0.AllocatedSize < attr0.Size || | |||
(attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSi zeLog) || | (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSi zeLog) || | |||
(attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0) | (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0) | |||
return S_FALSE; | return S_FALSE; | |||
for (unsigned i = attrIndex; i < attrIndexLim; i++) | for (unsigned i = attrIndex; i < attrIndexLim; i++) | |||
if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit)) | if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit)) | |||
return S_FALSE; | return S_FALSE; | |||
skipping to change at line 1076 | skipping to change at line 1088 | |||
for (i = ref.Start; i < ref.Start + ref.Num; i++) | for (i = ref.Start; i < ref.Start + ref.Num; i++) | |||
if (DataAttrs[i].NonResident) | if (DataAttrs[i].NonResident) | |||
numNonResident++; | numNonResident++; | |||
const CAttr &attr0 = DataAttrs[ref.Start]; | const CAttr &attr0 = DataAttrs[ref.Start]; | |||
if (numNonResident != 0 || ref.Num != 1) | if (numNonResident != 0 || ref.Num != 1) | |||
{ | { | |||
if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported()) | if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported()) | |||
return S_FALSE; | return S_FALSE; | |||
CInStream *streamSpec = new CInStream; | CInStream *ss = new CInStream; | |||
CMyComPtr<IInStream> streamTemp = streamSpec; | CMyComPtr<IInStream> streamTemp2 = ss; | |||
RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + r | RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + r | |||
ef.Num, numPhysClusters, streamSpec->Extents)); | ef.Num, numPhysClusters, ss->Extents)); | |||
streamSpec->Size = attr0.Size; | ss->Size = attr0.Size; | |||
streamSpec->InitializedSize = attr0.InitializedSize; | ss->InitializedSize = attr0.InitializedSize; | |||
streamSpec->Stream = mainStream; | ss->Stream = mainStream; | |||
streamSpec->BlockSizeLog = clusterSizeLog; | ss->BlockSizeLog = clusterSizeLog; | |||
streamSpec->InUse = InUse(); | ss->InUse = InUse(); | |||
RINOK(streamSpec->InitAndSeek(attr0.CompressionUnit)); | RINOK(ss->InitAndSeek(attr0.CompressionUnit)); | |||
*destStream = streamTemp.Detach(); | *destStream = streamTemp2.Detach(); | |||
return S_OK; | return S_OK; | |||
} | } | |||
streamSpec->Buf = attr0.Data; | streamSpec->Buf = attr0.Data; | |||
} | } | |||
streamSpec->Init(); | streamSpec->Init(); | |||
*destStream = streamTemp.Detach(); | *destStream = streamTemp.Detach(); | |||
return S_OK; | return S_OK; | |||
} | } | |||
unsigned CMftRec::GetNumExtents(int dataIndex, unsigned clusterSizeLog, UInt64 n umPhysClusters) const | unsigned CMftRec::GetNumExtents(int dataIndex, unsigned clusterSizeLog, UInt64 n umPhysClusters) const | |||
{ | { | |||
if (dataIndex < 0) | if (dataIndex < 0) | |||
return 0; | return 0; | |||
{ | { | |||
skipping to change at line 1148 | skipping to change at line 1162 | |||
Original values of these two bytes are stored in table. | Original values of these two bytes are stored in table. | |||
So we restore original data from table */ | So we restore original data from table */ | |||
if ((usaOffset & 1) != 0 | if ((usaOffset & 1) != 0 | |||
|| usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 | || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 | |||
|| numUsaItems == 0 | || numUsaItems == 0 | |||
|| numUsaItems - 1 != numSectors) | || numUsaItems - 1 != numSectors) | |||
return false; | return false; | |||
if (usaOffset >= 0x30) // NTFS 3.1+ | if (usaOffset >= 0x30) // NTFS 3.1+ | |||
if (Get32(p + 0x2C) != recNumber) | { | |||
return false; | UInt32 iii = Get32(p + 0x2C); | |||
if (iii != recNumber) | ||||
{ | ||||
// ntfs-3g probably writes 0 (that probably is incorrect value) to this | ||||
field for unused records. | ||||
// so we support that "bad" case. | ||||
if (iii != 0) | ||||
return false; | ||||
} | ||||
} | ||||
UInt16 usn = Get16(p + usaOffset); | UInt16 usn = Get16(p + usaOffset); | |||
// PRF(printf("\nusn = %d", usn)); | // PRF(printf("\nusn = %d", usn)); | |||
for (UInt32 i = 1; i < numUsaItems; i++) | for (UInt32 i = 1; i < numUsaItems; i++) | |||
{ | { | |||
void *pp = p + (i << sectorSizeLog) - 2; | void *pp = p + (i << sectorSizeLog) - 2; | |||
if (Get16(pp) != usn) | if (Get16(pp) != usn) | |||
return false; | return false; | |||
SetUi16(pp, Get16(p + usaOffset + i * 2)); | SetUi16(pp, Get16(p + usaOffset + i * 2)); | |||
} | } | |||
skipping to change at line 1683 | skipping to change at line 1705 | |||
if (!mftStream) | if (!mftStream) | |||
return S_FALSE; | return S_FALSE; | |||
} | } | |||
// CObjectVector<CAttr> SecurityAttrs; | // CObjectVector<CAttr> SecurityAttrs; | |||
UInt64 mftSize = mftRec.DataAttrs[0].Size; | UInt64 mftSize = mftRec.DataAttrs[0].Size; | |||
if ((mftSize >> 4) > Header.GetPhySize_Clusters()) | if ((mftSize >> 4) > Header.GetPhySize_Clusters()) | |||
return S_FALSE; | return S_FALSE; | |||
UInt64 numFiles = mftSize >> RecSizeLog; | ||||
if (numFiles > (1 << 30)) | ||||
return S_FALSE; | ||||
if (OpenCallback) | ||||
{ | ||||
RINOK(OpenCallback->SetTotal(&numFiles, &mftSize)); | ||||
} | ||||
const size_t kBufSize = (1 << 15); | const size_t kBufSize = (1 << 15); | |||
const size_t recSize = ((size_t)1 << RecSizeLog); | const size_t recSize = ((size_t)1 << RecSizeLog); | |||
if (kBufSize < recSize) | if (kBufSize < recSize) | |||
return S_FALSE; | return S_FALSE; | |||
ByteBuf.Alloc(kBufSize); | { | |||
Recs.ClearAndReserve((unsigned)numFiles); | const UInt64 numFiles = mftSize >> RecSizeLog; | |||
if (numFiles > (1 << 30)) | ||||
return S_FALSE; | ||||
if (OpenCallback) | ||||
{ | ||||
RINOK(OpenCallback->SetTotal(&numFiles, &mftSize)); | ||||
} | ||||
ByteBuf.Alloc(kBufSize); | ||||
Recs.ClearAndReserve((unsigned)numFiles); | ||||
} | ||||
for (UInt64 pos64 = 0;;) | for (UInt64 pos64 = 0;;) | |||
{ | { | |||
if (OpenCallback) | if (OpenCallback) | |||
{ | { | |||
UInt64 numFiles = Recs.Size(); | const UInt64 numFiles = Recs.Size(); | |||
if ((numFiles & 0x3FF) == 0) | if ((numFiles & 0x3FF) == 0) | |||
{ | { | |||
RINOK(OpenCallback->SetCompleted(&numFiles, &pos64)); | RINOK(OpenCallback->SetCompleted(&numFiles, &pos64)); | |||
} | } | |||
} | } | |||
size_t readSize = kBufSize; | size_t readSize = kBufSize; | |||
UInt64 rem = mftSize - pos64; | { | |||
if (readSize > rem) | const UInt64 rem = mftSize - pos64; | |||
readSize = (size_t)rem; | if (readSize > rem) | |||
readSize = (size_t)rem; | ||||
} | ||||
if (readSize < recSize) | if (readSize < recSize) | |||
break; | break; | |||
RINOK(ReadStream_FALSE(mftStream, ByteBuf, readSize)); | RINOK(ReadStream_FALSE(mftStream, ByteBuf, readSize)); | |||
pos64 += readSize; | pos64 += readSize; | |||
for (size_t i = 0; readSize >= recSize; i += recSize, readSize -= recSize) | for (size_t i = 0; readSize >= recSize; i += recSize, readSize -= recSize) | |||
{ | { | |||
PRF(printf("\n---------------------")); | PRF(printf("\n---------------------")); | |||
PRF(printf("\n%5d:", Recs.Size())); | PRF(printf("\n%5d:", Recs.Size())); | |||
skipping to change at line 2660 | skipping to change at line 2686 | |||
{ | { | |||
CMyComPtr<IInStream> inStream; | CMyComPtr<IInStream> inStream; | |||
HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeL og, Header.NumClusters, &inStream); | HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeL og, Header.NumClusters, &inStream); | |||
if (hres == S_FALSE) | if (hres == S_FALSE) | |||
res = NExtract::NOperationResult::kUnsupportedMethod; | res = NExtract::NOperationResult::kUnsupportedMethod; | |||
else | else | |||
{ | { | |||
RINOK(hres); | RINOK(hres); | |||
if (inStream) | if (inStream) | |||
{ | { | |||
HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progre ss); | hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress); | |||
if (hres != S_OK && hres != S_FALSE) | if (hres != S_OK && hres != S_FALSE) | |||
{ | { | |||
RINOK(hres); | RINOK(hres); | |||
} | } | |||
if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK) | if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK) | |||
res = NExtract::NOperationResult::kOK; | res = NExtract::NOperationResult::kOK; | |||
} | } | |||
} | } | |||
} | } | |||
if (item.DataIndex >= 0) | if (item.DataIndex >= 0) | |||
End of changes. 18 change blocks. | ||||
55 lines changed or deleted | 82 lines changed or added |