diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2026-09-04 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2026-09-04 12:17:40 +0500 |
| commit | 0766b733fe3e06dd2a7f9a3cfbf2108ac73abd17 (patch) | |
| tree | 3a8ca8ef8e855c41476499484ae3f3596e842ac2 /CPP | |
| parent | f9d78aff31a5f2521ae7ddbdc97c4a8855808959 (diff) | |
| download | 7zip-0766b733fe3e06dd2a7f9a3cfbf2108ac73abd17.tar.gz 7zip-0766b733fe3e06dd2a7f9a3cfbf2108ac73abd17.tar.bz2 7zip-0766b733fe3e06dd2a7f9a3cfbf2108ac73abd17.zip | |
Diffstat (limited to 'CPP')
78 files changed, 2374 insertions, 1306 deletions
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 71d1ddb..049cc17 100644 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp | |||
| @@ -323,20 +323,16 @@ HRESULT CEncoder::Encode1( | |||
| 323 | ICompressProgressInfo *compressProgress) | 323 | ICompressProgressInfo *compressProgress) |
| 324 | { | 324 | { |
| 325 | RINOK(EncoderConstr()) | 325 | RINOK(EncoderConstr()) |
| 326 | |||
| 327 | if (!_mixerRef) | 326 | if (!_mixerRef) |
| 328 | { | 327 | { |
| 329 | RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)) | 328 | RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)) |
| 330 | } | 329 | } |
| 331 | |||
| 332 | RINOK(_mixer->ReInit2()) | 330 | RINOK(_mixer->ReInit2()) |
| 333 | 331 | ||
| 334 | CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress; | 332 | CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress; |
| 335 | CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify; | 333 | CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify; |
| 336 | |||
| 337 | CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs; | 334 | CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs; |
| 338 | CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; | 335 | CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; |
| 339 | |||
| 340 | unsigned i; | 336 | unsigned i; |
| 341 | 337 | ||
| 342 | for (i = 1; i < _bindInfo.PackStreams.Size(); i++) | 338 | for (i = 1; i < _bindInfo.PackStreams.Size(); i++) |
| @@ -348,34 +344,21 @@ HRESULT CEncoder::Encode1( | |||
| 348 | } | 344 | } |
| 349 | 345 | ||
| 350 | const unsigned numMethods = _bindInfo.Coders.Size(); | 346 | const unsigned numMethods = _bindInfo.Coders.Size(); |
| 351 | |||
| 352 | for (i = 0; i < numMethods; i++) | 347 | for (i = 0; i < numMethods; i++) |
| 353 | _mixer->SetCoderInfo(i, NULL, NULL, false); | 348 | _mixer->SetCoderInfo(i, NULL, NULL, false); |
| 354 | 349 | ||
| 355 | |||
| 356 | /* inStreamSize can be used by BCJ2 to set optimal range of conversion. | 350 | /* inStreamSize can be used by BCJ2 to set optimal range of conversion. |
| 357 | But current BCJ2 encoder uses also another way to check exact size of current file. | 351 | But current BCJ2 encoder uses also another way to check exact size of current file. |
| 358 | So inStreamSize is not required. */ | 352 | So inStreamSize is not required. */ |
| 359 | |||
| 360 | /* | 353 | /* |
| 361 | if (inStreamSize) | 354 | if (inStreamSize) |
| 362 | _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL); | 355 | _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL); |
| 363 | */ | 356 | */ |
| 364 | 357 | // CMyComPtr2_Create<ISequentialInStream, CSequentialInStreamSizeCount2> inStreamSizeCount; | |
| 365 | 358 | CMyComPtr2_Create<ISequentialOutStream, CSequentialOutStreamSizeCount> outStreamSizeCount; | |
| 366 | /* | ||
| 367 | CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; | ||
| 368 | CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; | ||
| 369 | */ | ||
| 370 | |||
| 371 | CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; | ||
| 372 | CMyComPtr<ISequentialOutStream> outStreamSizeCount; | ||
| 373 | |||
| 374 | // inStreamSizeCountSpec->Init(inStream); | 359 | // inStreamSizeCountSpec->Init(inStream); |
| 375 | |||
| 376 | // ISequentialInStream *inStreamPointer = inStreamSizeCount; | 360 | // ISequentialInStream *inStreamPointer = inStreamSizeCount; |
| 377 | ISequentialInStream *inStreamPointer = inStream; | 361 | ISequentialInStream *inStreamPointer = inStream; |
| 378 | |||
| 379 | CRecordVector<ISequentialOutStream *> outStreamPointers; | 362 | CRecordVector<ISequentialOutStream *> outStreamPointers; |
| 380 | 363 | ||
| 381 | SetFolder(folderItem); | 364 | SetFolder(folderItem); |
| @@ -466,11 +449,9 @@ HRESULT CEncoder::Encode1( | |||
| 466 | 449 | ||
| 467 | if (_bindInfo.PackStreams.Size() != 0) | 450 | if (_bindInfo.PackStreams.Size() != 0) |
| 468 | { | 451 | { |
| 469 | outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; | 452 | outStreamSizeCount->SetStream(mtOutStreamNotify.IsDefined() ? |
| 470 | outStreamSizeCount = outStreamSizeCountSpec; | ||
| 471 | outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ? | ||
| 472 | mtOutStreamNotify.Interface() : outStream); | 453 | mtOutStreamNotify.Interface() : outStream); |
| 473 | outStreamSizeCountSpec->Init(); | 454 | outStreamSizeCount->Init(); |
| 474 | outStreamPointers.Add(outStreamSizeCount); | 455 | outStreamPointers.Add(outStreamSizeCount); |
| 475 | } | 456 | } |
| 476 | 457 | ||
| @@ -486,7 +467,7 @@ HRESULT CEncoder::Encode1( | |||
| 486 | compressProgress, dataAfterEnd_Error)) | 467 | compressProgress, dataAfterEnd_Error)) |
| 487 | 468 | ||
| 488 | if (_bindInfo.PackStreams.Size() != 0) | 469 | if (_bindInfo.PackStreams.Size() != 0) |
| 489 | packSizes.Add(outStreamSizeCountSpec->GetSize()); | 470 | packSizes.Add(outStreamSizeCount->GetSize()); |
| 490 | 471 | ||
| 491 | for (i = 1; i < _bindInfo.PackStreams.Size(); i++) | 472 | for (i = 1; i < _bindInfo.PackStreams.Size(); i++) |
| 492 | { | 473 | { |
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index 81dd966..a81f5df 100644 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp | |||
| @@ -309,6 +309,11 @@ bool CHandler::IsFolderEncrypted(CNum folderIndex) const | |||
| 309 | inByte.SkipDataNoCheck(idSize); | 309 | inByte.SkipDataNoCheck(idSize); |
| 310 | if (id64 == k_AES) | 310 | if (id64 == k_AES) |
| 311 | return true; | 311 | return true; |
| 312 | if ((mainByte & 0x10) != 0) | ||
| 313 | { | ||
| 314 | inByte.ReadNum(); // NumInStreams | ||
| 315 | inByte.ReadNum(); // NumOutStreams | ||
| 316 | } | ||
| 312 | if ((mainByte & 0x20) != 0) | 317 | if ((mainByte & 0x20) != 0) |
| 313 | inByte.SkipDataNoCheck(inByte.ReadNum()); | 318 | inByte.SkipDataNoCheck(inByte.ReadNum()); |
| 314 | } | 319 | } |
| @@ -455,7 +460,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const | |||
| 455 | const UInt32 lp = d % 5; | 460 | const UInt32 lp = d % 5; |
| 456 | if (lc != 3) dest = AddProp32(dest, "lc", lc); | 461 | if (lc != 3) dest = AddProp32(dest, "lc", lc); |
| 457 | if (lp != 0) dest = AddProp32(dest, "lp", lp); | 462 | if (lp != 0) dest = AddProp32(dest, "lp", lp); |
| 458 | if (pb != 2) dest = AddProp32(dest, "pb", pb); | 463 | if (pb != 2) /* dest = */ AddProp32(dest, "pb", pb); |
| 459 | } | 464 | } |
| 460 | } | 465 | } |
| 461 | } | 466 | } |
diff --git a/CPP/7zip/Archive/ApfsHandler.cpp b/CPP/7zip/Archive/ApfsHandler.cpp index 2876991..0f367f9 100644 --- a/CPP/7zip/Archive/ApfsHandler.cpp +++ b/CPP/7zip/Archive/ApfsHandler.cpp | |||
| @@ -3829,7 +3829,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3829 | #ifdef APFS_SHOW_ALT_STREAMS | 3829 | #ifdef APFS_SHOW_ALT_STREAMS |
| 3830 | if (ref.IsAltStream()) | 3830 | if (ref.IsAltStream()) |
| 3831 | { | 3831 | { |
| 3832 | // if (inode) | 3832 | if (inode) |
| 3833 | { | 3833 | { |
| 3834 | const CAttr &attr = inode->Attrs[(unsigned)ref.AttrIndex]; | 3834 | const CAttr &attr = inode->Attrs[(unsigned)ref.AttrIndex]; |
| 3835 | ConvertUTF8ToUnicode(attr.Name, s); | 3835 | ConvertUTF8ToUnicode(attr.Name, s); |
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp index e88d2fe..ca46eb1 100644 --- a/CPP/7zip/Archive/ApmHandler.cpp +++ b/CPP/7zip/Archive/ApmHandler.cpp | |||
| @@ -253,9 +253,10 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
| 253 | numBlocks = finish; | 253 | numBlocks = finish; |
| 254 | 254 | ||
| 255 | _items.Add(item); | 255 | _items.Add(item); |
| 256 | if (numPadSectors != 0) | ||
| 257 | { | 256 | { |
| 258 | RINOK(stream->Seek(numPadSectors << 9, STREAM_SEEK_CUR, NULL)) | 257 | const unsigned offset = numPadSectors << 9; |
| 258 | if (offset) | ||
| 259 | RINOK(stream->Seek(offset, STREAM_SEEK_CUR, NULL)) | ||
| 259 | } | 260 | } |
| 260 | if (++i == numBlocksInMap) | 261 | if (++i == numBlocksInMap) |
| 261 | break; | 262 | break; |
diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp index 9f672a9..e9afb1b 100644 --- a/CPP/7zip/Archive/ArHandler.cpp +++ b/CPP/7zip/Archive/ArHandler.cpp | |||
| @@ -249,7 +249,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, bool &filled) | |||
| 249 | RIF(DecimalToNumber32(cur, kUserSize, item.User)) cur += kUserSize; | 249 | RIF(DecimalToNumber32(cur, kUserSize, item.User)) cur += kUserSize; |
| 250 | RIF(DecimalToNumber32(cur, kUserSize, item.Group)) cur += kUserSize; | 250 | RIF(DecimalToNumber32(cur, kUserSize, item.Group)) cur += kUserSize; |
| 251 | RIF(OctalToNumber32(cur, kModeSize, item.Mode)) cur += kModeSize; | 251 | RIF(OctalToNumber32(cur, kModeSize, item.Mode)) cur += kModeSize; |
| 252 | RIF(DecimalToNumber(cur, kSizeSize, item.Size)) cur += kSizeSize; | 252 | RIF(DecimalToNumber(cur, kSizeSize, item.Size)) // cur += kSizeSize; |
| 253 | 253 | ||
| 254 | if (longNameLen != 0 && longNameLen <= item.Size) | 254 | if (longNameLen != 0 && longNameLen <= item.Size) |
| 255 | { | 255 | { |
diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp index 1d641e4..1a06781 100644 --- a/CPP/7zip/Archive/ArjHandler.cpp +++ b/CPP/7zip/Archive/ArjHandler.cpp | |||
| @@ -352,7 +352,7 @@ HRESULT CArcHeader::Parse(const Byte *p, unsigned size) | |||
| 352 | pos += size1; | 352 | pos += size1; |
| 353 | size1 = size - pos; | 353 | size1 = size - pos; |
| 354 | RINOK(ReadString(p + pos, size1, Comment)) | 354 | RINOK(ReadString(p + pos, size1, Comment)) |
| 355 | pos += size1; | 355 | // pos += size1; |
| 356 | return S_OK; | 356 | return S_OK; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| @@ -462,8 +462,7 @@ HRESULT CItem::Parse(const Byte *p, unsigned size) | |||
| 462 | pos += size1; | 462 | pos += size1; |
| 463 | size1 = size - pos; | 463 | size1 = size - pos; |
| 464 | RINOK(ReadString(p + pos, size1, Comment)) | 464 | RINOK(ReadString(p + pos, size1, Comment)) |
| 465 | pos += size1; | 465 | // pos += size1; |
| 466 | |||
| 467 | return S_OK; | 466 | return S_OK; |
| 468 | } | 467 | } |
| 469 | 468 | ||
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 0ad2a0e..f97c686 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp | |||
| @@ -145,10 +145,13 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 145 | // case kpidSolid: prop = _database.IsSolid(); break; | 145 | // case kpidSolid: prop = _database.IsSolid(); break; |
| 146 | case kpidNumBlocks: | 146 | case kpidNumBlocks: |
| 147 | { | 147 | { |
| 148 | /* | ||
| 148 | UInt32 numFolders = 0; | 149 | UInt32 numFolders = 0; |
| 149 | FOR_VECTOR (v, m_Database.Volumes) | 150 | FOR_VECTOR (v, m_Database.Volumes) |
| 150 | numFolders += m_Database.Volumes[v].Folders.Size(); | 151 | numFolders += m_Database.Volumes[v].Folders.Size(); |
| 151 | prop = numFolders; | 152 | prop = numFolders; |
| 153 | */ | ||
| 154 | prop = (UInt32)m_Database.FolderStartFileIndex.Size(); | ||
| 152 | break; | 155 | break; |
| 153 | } | 156 | } |
| 154 | 157 | ||
| @@ -292,7 +295,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 292 | break; | 295 | break; |
| 293 | } | 296 | } |
| 294 | 297 | ||
| 295 | case kpidIsDir: prop = item.IsDir(); break; | 298 | // case kpidIsDir: prop = false; break; |
| 296 | case kpidSize: prop = item.Size; break; | 299 | case kpidSize: prop = item.Size; break; |
| 297 | case kpidAttrib: prop = item.GetWinAttrib(); break; | 300 | case kpidAttrib: prop = item.GetWinAttrib(); break; |
| 298 | 301 | ||
| @@ -315,7 +318,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 315 | break; | 318 | break; |
| 316 | } | 319 | } |
| 317 | 320 | ||
| 318 | case kpidBlock: prop.Set_Int32((Int32)m_Database.GetFolderIndex(&mvItem)); break; | 321 | case kpidBlock: prop.Set_Int32((Int32)m_Database.GetGlobalFolderIndex(mvItem)); break; |
| 319 | 322 | ||
| 320 | #ifdef CAB_DETAILS | 323 | #ifdef CAB_DETAILS |
| 321 | 324 | ||
| @@ -516,8 +519,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, | |||
| 516 | return S_FALSE; | 519 | return S_FALSE; |
| 517 | else | 520 | else |
| 518 | { | 521 | { |
| 519 | m_Database.FillSortAndShrink(); | 522 | if (!m_Database.Fill_Sort_Shrink_and_Check()) |
| 520 | if (!m_Database.Check()) | ||
| 521 | return S_FALSE; | 523 | return S_FALSE; |
| 522 | } | 524 | } |
| 523 | } | 525 | } |
| @@ -921,9 +923,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 921 | const unsigned index = allFilesMode ? i : indices[i]; | 923 | const unsigned index = allFilesMode ? i : indices[i]; |
| 922 | const CMvItem &mvItem = m_Database.Items[index]; | 924 | const CMvItem &mvItem = m_Database.Items[index]; |
| 923 | const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; | 925 | const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; |
| 924 | if (item.IsDir()) | 926 | const int folderIndex = m_Database.GetGlobalFolderIndex(mvItem); |
| 925 | continue; | ||
| 926 | const int folderIndex = m_Database.GetFolderIndex(&mvItem); | ||
| 927 | if (folderIndex != lastFolder) | 927 | if (folderIndex != lastFolder) |
| 928 | totalUnPacked += lastFolderSize; | 928 | totalUnPacked += lastFolderSize; |
| 929 | lastFolder = folderIndex; | 929 | lastFolder = folderIndex; |
| @@ -967,20 +967,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 967 | const CItem &item = db.Items[itemIndex]; | 967 | const CItem &item = db.Items[itemIndex]; |
| 968 | 968 | ||
| 969 | i++; | 969 | i++; |
| 970 | if (item.IsDir()) | ||
| 971 | { | ||
| 972 | const Int32 askMode = testMode ? | ||
| 973 | NExtract::NAskMode::kTest : | ||
| 974 | NExtract::NAskMode::kExtract; | ||
| 975 | CMyComPtr<ISequentialOutStream> realOutStream; | ||
| 976 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) | ||
| 977 | RINOK(extractCallback->PrepareOperation(askMode)) | ||
| 978 | realOutStream.Release(); | ||
| 979 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) | ||
| 980 | continue; | ||
| 981 | } | ||
| 982 | 970 | ||
| 983 | const int folderIndex = m_Database.GetFolderIndex(&mvItem); | 971 | const int folderIndex = m_Database.GetGlobalFolderIndex(mvItem); |
| 984 | 972 | ||
| 985 | if (folderIndex < 0) | 973 | if (folderIndex < 0) |
| 986 | { | 974 | { |
| @@ -992,7 +980,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 992 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) | 980 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) |
| 993 | RINOK(extractCallback->PrepareOperation(askMode)) | 981 | RINOK(extractCallback->PrepareOperation(askMode)) |
| 994 | realOutStream.Release(); | 982 | realOutStream.Release(); |
| 995 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError)) | 983 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable)) |
| 996 | continue; | 984 | continue; |
| 997 | } | 985 | } |
| 998 | 986 | ||
| @@ -1010,9 +998,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1010 | const unsigned indexNext = allFilesMode ? i : indices[i]; | 998 | const unsigned indexNext = allFilesMode ? i : indices[i]; |
| 1011 | const CMvItem &mvItem2 = m_Database.Items[indexNext]; | 999 | const CMvItem &mvItem2 = m_Database.Items[indexNext]; |
| 1012 | const CItem &item2 = m_Database.Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex]; | 1000 | const CItem &item2 = m_Database.Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex]; |
| 1013 | if (item2.IsDir()) | 1001 | const int newFolderIndex = m_Database.GetGlobalFolderIndex(mvItem2); |
| 1014 | continue; | ||
| 1015 | const int newFolderIndex = m_Database.GetFolderIndex(&mvItem2); | ||
| 1016 | 1002 | ||
| 1017 | if (newFolderIndex != folderIndex) | 1003 | if (newFolderIndex != folderIndex) |
| 1018 | break; | 1004 | break; |
| @@ -1073,6 +1059,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1073 | bool keepHistory = false; | 1059 | bool keepHistory = false; |
| 1074 | bool keepInputBuffer = false; | 1060 | bool keepInputBuffer = false; |
| 1075 | bool thereWasNotAlignedChunk = false; | 1061 | bool thereWasNotAlignedChunk = false; |
| 1062 | |||
| 1063 | // printf(" -locFolderIndex=%5i\n", locFolderIndex); | ||
| 1076 | 1064 | ||
| 1077 | for (UInt32 bl = 0; cabFolderOutStream->NeedMoreWrite();) | 1065 | for (UInt32 bl = 0; cabFolderOutStream->NeedMoreWrite();) |
| 1078 | { | 1066 | { |
| @@ -1085,6 +1073,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1085 | const CDatabaseEx &db2 = m_Database.Volumes[volIndex]; | 1073 | const CDatabaseEx &db2 = m_Database.Volumes[volIndex]; |
| 1086 | if (locFolderIndex < 0) | 1074 | if (locFolderIndex < 0) |
| 1087 | return E_FAIL; | 1075 | return E_FAIL; |
| 1076 | if ((unsigned)locFolderIndex >= db2.Folders.Size()) | ||
| 1077 | { | ||
| 1078 | res = S_FALSE; | ||
| 1079 | break; | ||
| 1080 | } | ||
| 1088 | const CFolder &folder2 = db2.Folders[(unsigned)locFolderIndex]; | 1081 | const CFolder &folder2 = db2.Folders[(unsigned)locFolderIndex]; |
| 1089 | 1082 | ||
| 1090 | if (bl == 0) | 1083 | if (bl == 0) |
| @@ -1092,7 +1085,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1092 | RINOK(InStream_SeekSet(db2.Stream, db2.StartPosition + folder2.DataStart)) | 1085 | RINOK(InStream_SeekSet(db2.Stream, db2.StartPosition + folder2.DataStart)) |
| 1093 | } | 1086 | } |
| 1094 | 1087 | ||
| 1095 | if (bl == folder2.NumDataBlocks) | 1088 | if (bl >= folder2.NumDataBlocks) |
| 1096 | { | 1089 | { |
| 1097 | /* | 1090 | /* |
| 1098 | CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit. | 1091 | CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit. |
| @@ -1105,13 +1098,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1105 | if (m_Database.Volumes.Size() > 1) | 1098 | if (m_Database.Volumes.Size() > 1) |
| 1106 | { | 1099 | { |
| 1107 | volIndex++; | 1100 | volIndex++; |
| 1101 | // printf(" -volIndex=%5u\n", volIndex); | ||
| 1108 | locFolderIndex = 0; | 1102 | locFolderIndex = 0; |
| 1109 | bl = 0; | 1103 | bl = 0; |
| 1110 | continue; | 1104 | continue; |
| 1111 | } | 1105 | } |
| 1112 | } | 1106 | } |
| 1113 | 1107 | else | |
| 1114 | bl++; | 1108 | bl++; |
| 1115 | 1109 | ||
| 1116 | if (!keepInputBuffer) | 1110 | if (!keepInputBuffer) |
| 1117 | blockPackData.InitForNewBlock(); | 1111 | blockPackData.InitForNewBlock(); |
| @@ -1120,6 +1114,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1120 | res = blockPackData.Read(db2.Stream, db2.ArcInfo.GetDataBlockReserveSize(), packSize, unpackSize); | 1114 | res = blockPackData.Read(db2.Stream, db2.ArcInfo.GetDataBlockReserveSize(), packSize, unpackSize); |
| 1121 | if (res == S_FALSE) | 1115 | if (res == S_FALSE) |
| 1122 | break; | 1116 | break; |
| 1117 | // if folder is Continued_To_Next volume, then (unpackSize == 0) in last chunk of volume, but (packSize != 0) | ||
| 1118 | // printf(" -block=%5u unpackSize=%5u packSize=%5u\n", bl - 1, unpackSize, packSize); | ||
| 1123 | RINOK(res) | 1119 | RINOK(res) |
| 1124 | keepInputBuffer = (unpackSize == 0); | 1120 | keepInputBuffer = (unpackSize == 0); |
| 1125 | if (keepInputBuffer) | 1121 | if (keepInputBuffer) |
diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp index bd6969a..a20d3b0 100644 --- a/CPP/7zip/Archive/Cab/CabIn.cpp +++ b/CPP/7zip/Archive/Cab/CabIn.cpp | |||
| @@ -31,9 +31,11 @@ void CInArchive::Read(Byte *data, unsigned size) | |||
| 31 | throw CUnexpectedEndException(); | 31 | throw CUnexpectedEndException(); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static const size_t k_Name_Size_Limit = 1 << 13; | ||
| 35 | |||
| 34 | void CInArchive::ReadName(AString &s) | 36 | void CInArchive::ReadName(AString &s) |
| 35 | { | 37 | { |
| 36 | for (size_t i = 0; i < ((size_t)1 << 13); i++) | 38 | for (size_t i = 0; i < k_Name_Size_Limit; i++) |
| 37 | { | 39 | { |
| 38 | Byte b; | 40 | Byte b; |
| 39 | if (!_inBuffer.ReadByte(b)) | 41 | if (!_inBuffer.ReadByte(b)) |
| @@ -43,8 +45,6 @@ void CInArchive::ReadName(AString &s) | |||
| 43 | s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i); | 45 | s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i); |
| 44 | return; | 46 | return; |
| 45 | } | 47 | } |
| 46 | if (_tempBuf.Size() == i) | ||
| 47 | _tempBuf.ChangeSize_KeepData(i * 2, i); | ||
| 48 | _tempBuf[i] = b; | 48 | _tempBuf[i] = b; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| @@ -58,7 +58,7 @@ void CInArchive::ReadName(AString &s) | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | ErrorInNames = true; | 60 | ErrorInNames = true; |
| 61 | s = "[ERROR-LONG-PATH]"; | 61 | s = "[LONG_PATH_FILE]"; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | void CInArchive::ReadOtherArc(COtherArc &oa) | 64 | void CInArchive::ReadOtherArc(COtherArc &oa) |
| @@ -268,14 +268,14 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) | |||
| 268 | IsArc = true; | 268 | IsArc = true; |
| 269 | 269 | ||
| 270 | _inBuffer.SetStream(limitedStream); | 270 | _inBuffer.SetStream(limitedStream); |
| 271 | if (_tempBuf.Size() == 0) | 271 | _tempBuf.Alloc(k_Name_Size_Limit); |
| 272 | _tempBuf.Alloc(1 << 12); | ||
| 273 | 272 | ||
| 274 | Byte p[16]; | 273 | Byte p[16]; |
| 275 | const unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0); | 274 | const unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0); |
| 276 | Read(p, nextSize); | 275 | Read(p, nextSize); |
| 277 | ai.SetID = Get16(p); | 276 | ai.SetID = Get16(p); |
| 278 | ai.CabinetNumber = Get16(p + 2); | 277 | ai.CabinetNumber = Get16(p + 2); |
| 278 | // printf("CabinetNumber=%5u \n", ai.CabinetNumber); | ||
| 279 | 279 | ||
| 280 | if (ai.ReserveBlockPresent()) | 280 | if (ai.ReserveBlockPresent()) |
| 281 | { | 281 | { |
| @@ -302,10 +302,9 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) | |||
| 302 | folder.MethodMinor = p[7]; | 302 | folder.MethodMinor = p[7]; |
| 303 | Skip(ai.PerFolder_AreaSize); | 303 | Skip(ai.PerFolder_AreaSize); |
| 304 | db.Folders.AddInReserved(folder); | 304 | db.Folders.AddInReserved(folder); |
| 305 | // printf("folder=%5u DataStart=%8u numBlocks=%8u\n", i, folder.DataStart, folder.NumDataBlocks); | ||
| 305 | } | 306 | } |
| 306 | 307 | ||
| 307 | // for (int iii = 0; iii < 10000; iii++) { | ||
| 308 | |||
| 309 | if (_inBuffer.GetProcessedSize() - startInBuf != ai.FileHeadersOffset) | 308 | if (_inBuffer.GetProcessedSize() - startInBuf != ai.FileHeadersOffset) |
| 310 | { | 309 | { |
| 311 | // printf("\n!!! Seek Error !!!!\n"); | 310 | // printf("\n!!! Seek Error !!!!\n"); |
| @@ -315,8 +314,14 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) | |||
| 315 | _inBuffer.Init(); | 314 | _inBuffer.Init(); |
| 316 | } | 315 | } |
| 317 | 316 | ||
| 317 | /* | ||
| 318 | if (FolderIndex == kContinuedFromPrev || FolderIndex == kContinuedPrevAndNext), | ||
| 319 | then there are no (FolderIndex == 0) items in that cab volume. | ||
| 320 | But (FolderIndex == kContinuedToNext) and (FolderIndex == numFolders - 1) items are possible in same volume. | ||
| 321 | if there are multiple files with (FolderIndex == kContinuedToNext), then they are duplicated | ||
| 322 | in next volume with (FolderIndex == kContinuedFromPrev or kContinuedPrevAndNext). | ||
| 323 | */ | ||
| 318 | db.Items.ClearAndReserve(ai.NumFiles); | 324 | db.Items.ClearAndReserve(ai.NumFiles); |
| 319 | |||
| 320 | for (i = 0; i < ai.NumFiles; i++) | 325 | for (i = 0; i < ai.NumFiles; i++) |
| 321 | { | 326 | { |
| 322 | Read(p, 16); | 327 | Read(p, 16); |
| @@ -328,18 +333,15 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) | |||
| 328 | const UInt16 pureTime = Get16(p + 12); | 333 | const UInt16 pureTime = Get16(p + 12); |
| 329 | item.Time = (((UInt32)pureDate << 16)) | pureTime; | 334 | item.Time = (((UInt32)pureDate << 16)) | pureTime; |
| 330 | item.Attributes = Get16(p + 14); | 335 | item.Attributes = Get16(p + 14); |
| 331 | |||
| 332 | ReadName(item.Name); | 336 | ReadName(item.Name); |
| 333 | 337 | // printf(" -file=%5u Folder=%5x Offset=%10u size=%10u %s\n", i, item.FolderIndex, item.Offset, item.Size, item.Name.Ptr()); | |
| 334 | if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size()) | 338 | const unsigned numFolders = db.Folders.Size(); |
| 339 | if (numFolders == 0 || item.GetFolderIndex(numFolders) >= (int)numFolders) | ||
| 335 | { | 340 | { |
| 336 | HeaderError = true; | 341 | HeaderError = true; |
| 337 | return S_FALSE; | 342 | return S_FALSE; |
| 338 | } | 343 | } |
| 339 | } | 344 | } |
| 340 | |||
| 341 | // } | ||
| 342 | |||
| 343 | return S_OK; | 345 | return S_OK; |
| 344 | } | 346 | } |
| 345 | 347 | ||
| @@ -365,12 +367,8 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) | |||
| 365 | const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex]; | 367 | const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex]; |
| 366 | const CItem &item1 = db1.Items[p1->ItemIndex]; | 368 | const CItem &item1 = db1.Items[p1->ItemIndex]; |
| 367 | const CItem &item2 = db2.Items[p2->ItemIndex]; | 369 | const CItem &item2 = db2.Items[p2->ItemIndex]; |
| 368 | const bool isDir1 = item1.IsDir(); | 370 | const int f1 = mvDb.GetGlobalFolderIndex(*p1); |
| 369 | const bool isDir2 = item2.IsDir(); | 371 | const int f2 = mvDb.GetGlobalFolderIndex(*p2); |
| 370 | if (isDir1 && !isDir2) return -1; | ||
| 371 | if (isDir2 && !isDir1) return 1; | ||
| 372 | const int f1 = mvDb.GetFolderIndex(p1); | ||
| 373 | const int f2 = mvDb.GetFolderIndex(p2); | ||
| 374 | RINOZ(MyCompare(f1, f2)) | 372 | RINOZ(MyCompare(f1, f2)) |
| 375 | RINOZ(MyCompare(item1.Offset, item2.Offset)) | 373 | RINOZ(MyCompare(item1.Offset, item2.Offset)) |
| 376 | RINOZ(MyCompare(item1.Size, item2.Size)) | 374 | RINOZ(MyCompare(item1.Size, item2.Size)) |
| @@ -379,37 +377,39 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) | |||
| 379 | } | 377 | } |
| 380 | 378 | ||
| 381 | 379 | ||
| 382 | bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2) | 380 | bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2) const |
| 383 | { | 381 | { |
| 384 | const CMvItem *p1 = &Items[i1]; | 382 | const CMvItem &p1 = Items[i1]; |
| 385 | const CMvItem *p2 = &Items[i2]; | 383 | const CMvItem &p2 = Items[i2]; |
| 386 | const CDatabaseEx &db1 = Volumes[p1->VolumeIndex]; | 384 | const CDatabaseEx &db1 = Volumes[p1.VolumeIndex]; |
| 387 | const CDatabaseEx &db2 = Volumes[p2->VolumeIndex]; | 385 | const CDatabaseEx &db2 = Volumes[p2.VolumeIndex]; |
| 388 | const CItem &item1 = db1.Items[p1->ItemIndex]; | 386 | const CItem &item1 = db1.Items[p1.ItemIndex]; |
| 389 | const CItem &item2 = db2.Items[p2->ItemIndex]; | 387 | const CItem &item2 = db2.Items[p2.ItemIndex]; |
| 390 | return GetFolderIndex(p1) == GetFolderIndex(p2) | 388 | return GetGlobalFolderIndex(p1) == GetGlobalFolderIndex(p2) |
| 391 | && item1.Offset == item2.Offset | 389 | && item1.Offset == item2.Offset |
| 392 | && item1.Size == item2.Size | 390 | && item1.Size == item2.Size |
| 393 | && item1.Name == item2.Name; | 391 | && item1.Name == item2.Name; |
| 394 | } | 392 | } |
| 395 | 393 | ||
| 396 | 394 | ||
| 397 | void CMvDatabaseEx::FillSortAndShrink() | 395 | bool CMvDatabaseEx::Fill_Sort_Shrink_and_Check() |
| 396 | { | ||
| 398 | { | 397 | { |
| 399 | Items.Clear(); | 398 | Items.Clear(); |
| 400 | StartFolderOfVol.Clear(); | ||
| 401 | FolderStartFileIndex.Clear(); | 399 | FolderStartFileIndex.Clear(); |
| 402 | 400 | ||
| 403 | int offset = 0; | 401 | int offset = 0; |
| 404 | 402 | ||
| 405 | FOR_VECTOR (v, Volumes) | 403 | FOR_VECTOR (v, Volumes) |
| 406 | { | 404 | { |
| 407 | const CDatabaseEx &db = Volumes[v]; | 405 | CDatabaseEx &db = Volumes[v]; |
| 408 | int curOffset = offset; | ||
| 409 | if (db.IsTherePrevFolder()) | 406 | if (db.IsTherePrevFolder()) |
| 410 | curOffset--; | 407 | offset--; |
| 411 | StartFolderOfVol.Add(curOffset); | 408 | db.StartGlobalFolderIndex = offset; |
| 412 | offset += db.GetNumberOfNewFolders(); | 409 | // printf("vol=%5u StartGlobalFolderIndex=%8d\n", v, offset); |
| 410 | offset += (int)db.Folders.Size(); | ||
| 411 | if (offset < -1) // overflow | ||
| 412 | return false; | ||
| 413 | 413 | ||
| 414 | CMvItem mvItem; | 414 | CMvItem mvItem; |
| 415 | mvItem.VolumeIndex = v; | 415 | mvItem.VolumeIndex = v; |
| @@ -433,15 +433,12 @@ void CMvDatabaseEx::FillSortAndShrink() | |||
| 433 | 433 | ||
| 434 | FOR_VECTOR (i, Items) | 434 | FOR_VECTOR (i, Items) |
| 435 | { | 435 | { |
| 436 | const int folderIndex = GetFolderIndex(&Items[i]); | 436 | const int folderIndex = GetGlobalFolderIndex(Items[i]); |
| 437 | while (folderIndex >= (int)FolderStartFileIndex.Size()) | 437 | while (folderIndex >= (int)FolderStartFileIndex.Size()) |
| 438 | FolderStartFileIndex.Add(i); | 438 | FolderStartFileIndex.Add(i); |
| 439 | } | 439 | } |
| 440 | } | 440 | } |
| 441 | 441 | ||
| 442 | |||
| 443 | bool CMvDatabaseEx::Check() | ||
| 444 | { | ||
| 445 | for (unsigned v = 1; v < Volumes.Size(); v++) | 442 | for (unsigned v = 1; v < Volumes.Size(); v++) |
| 446 | { | 443 | { |
| 447 | const CDatabaseEx &db1 = Volumes[v]; | 444 | const CDatabaseEx &db1 = Volumes[v]; |
| @@ -465,14 +462,12 @@ bool CMvDatabaseEx::Check() | |||
| 465 | FOR_VECTOR (i, Items) | 462 | FOR_VECTOR (i, Items) |
| 466 | { | 463 | { |
| 467 | const CMvItem &mvItem = Items[i]; | 464 | const CMvItem &mvItem = Items[i]; |
| 468 | const int fIndex = GetFolderIndex(&mvItem); | 465 | const int fIndex = GetGlobalFolderIndex(mvItem); |
| 469 | if (fIndex >= (int)FolderStartFileIndex.Size()) | 466 | if (fIndex >= (int)FolderStartFileIndex.Size()) |
| 470 | return false; | 467 | return false; |
| 471 | const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; | 468 | const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; |
| 472 | if (item.IsDir()) | ||
| 473 | continue; | ||
| 474 | 469 | ||
| 475 | const int folderIndex = GetFolderIndex(&mvItem); | 470 | const int folderIndex = GetGlobalFolderIndex(mvItem); |
| 476 | 471 | ||
| 477 | if (folderIndex != prevFolder) | 472 | if (folderIndex != prevFolder) |
| 478 | prevFolder = folderIndex; | 473 | prevFolder = folderIndex; |
diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h index 06aa34c..1c22bef 100644 --- a/CPP/7zip/Archive/Cab/CabIn.h +++ b/CPP/7zip/Archive/Cab/CabIn.h | |||
| @@ -97,20 +97,15 @@ struct CDatabase | |||
| 97 | return true; | 97 | return true; |
| 98 | return false; | 98 | return false; |
| 99 | } | 99 | } |
| 100 | |||
| 101 | int GetNumberOfNewFolders() const | ||
| 102 | { | ||
| 103 | int res = (int)Folders.Size(); | ||
| 104 | if (IsTherePrevFolder()) | ||
| 105 | res--; | ||
| 106 | return res; | ||
| 107 | } | ||
| 108 | }; | 100 | }; |
| 109 | 101 | ||
| 110 | 102 | ||
| 111 | struct CDatabaseEx: public CDatabase | 103 | struct CDatabaseEx: public CDatabase |
| 112 | { | 104 | { |
| 113 | CMyComPtr<IInStream> Stream; | 105 | CMyComPtr<IInStream> Stream; |
| 106 | int StartGlobalFolderIndex; // == (-1), if there are links to a previous volume that is missing or contains an error | ||
| 107 | |||
| 108 | CDatabaseEx(): StartGlobalFolderIndex(-1) {} | ||
| 114 | }; | 109 | }; |
| 115 | 110 | ||
| 116 | 111 | ||
| @@ -123,31 +118,29 @@ struct CMvItem | |||
| 123 | 118 | ||
| 124 | class CMvDatabaseEx | 119 | class CMvDatabaseEx |
| 125 | { | 120 | { |
| 126 | bool AreItemsEqual(unsigned i1, unsigned i2); | 121 | bool AreItemsEqual(unsigned i1, unsigned i2) const; |
| 127 | 122 | ||
| 128 | public: | 123 | public: |
| 129 | CObjectVector<CDatabaseEx> Volumes; | 124 | CObjectVector<CDatabaseEx> Volumes; |
| 130 | CRecordVector<CMvItem> Items; | 125 | CRecordVector<CMvItem> Items; |
| 131 | CRecordVector<int> StartFolderOfVol; // can be negative | 126 | CRecordVector<unsigned> FolderStartFileIndex; // GlobalFolderIndex to Items[] index |
| 132 | CRecordVector<unsigned> FolderStartFileIndex; | ||
| 133 | 127 | ||
| 134 | int GetFolderIndex(const CMvItem *mvi) const | 128 | // out: (returned_value == -1) is possible, if (mvi) refers to a previous volume that is missing or contains an error |
| 129 | int GetGlobalFolderIndex(const CMvItem &mvi) const | ||
| 135 | { | 130 | { |
| 136 | const CDatabaseEx &db = Volumes[mvi->VolumeIndex]; | 131 | const CDatabaseEx &db = Volumes[mvi.VolumeIndex]; |
| 137 | return StartFolderOfVol[mvi->VolumeIndex] + | 132 | return db.StartGlobalFolderIndex + |
| 138 | db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size()); | 133 | db.Items[mvi.ItemIndex].GetFolderIndex(db.Folders.Size()); |
| 139 | } | 134 | } |
| 140 | 135 | ||
| 141 | void Clear() | 136 | void Clear() |
| 142 | { | 137 | { |
| 143 | Volumes.Clear(); | 138 | Volumes.Clear(); |
| 144 | Items.Clear(); | 139 | Items.Clear(); |
| 145 | StartFolderOfVol.Clear(); | ||
| 146 | FolderStartFileIndex.Clear(); | 140 | FolderStartFileIndex.Clear(); |
| 147 | } | 141 | } |
| 148 | 142 | ||
| 149 | void FillSortAndShrink(); | 143 | bool Fill_Sort_Shrink_and_Check(); |
| 150 | bool Check(); | ||
| 151 | }; | 144 | }; |
| 152 | 145 | ||
| 153 | 146 | ||
diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h index b7e07d1..8f24ed7 100644 --- a/CPP/7zip/Archive/Cab/CabItem.h +++ b/CPP/7zip/Archive/Cab/CabItem.h | |||
| @@ -28,14 +28,17 @@ struct CItem | |||
| 28 | UInt32 Offset; | 28 | UInt32 Offset; |
| 29 | UInt32 Size; | 29 | UInt32 Size; |
| 30 | UInt32 Time; | 30 | UInt32 Time; |
| 31 | UInt32 FolderIndex; | 31 | unsigned FolderIndex; |
| 32 | UInt16 Flags; | 32 | UInt16 Flags; |
| 33 | UInt16 Attributes; | 33 | UInt16 Attributes; |
| 34 | 34 | ||
| 35 | UInt64 GetEndOffset() const { return (UInt64)Offset + Size; } | 35 | UInt64 GetEndOffset() const { return (UInt64)Offset + Size; } |
| 36 | UInt32 GetWinAttrib() const { return (UInt32)Attributes & ~(UInt32)NHeader::kFileNameIsUtf8_Mask; } | 36 | /* v26.03: we show all items as files, as original cab extracting software does. |
| 37 | Also we disable FILE_ATTRIBUTE_DIRECTORY in GetWinAttrib(), because some client | ||
| 38 | software of 7zip still can parse FILE_ATTRIBUTE_DIRECTORY flag from returned Attributes. */ | ||
| 39 | UInt32 GetWinAttrib() const { return (UInt32)Attributes & ~((UInt32)NHeader::kFileNameIsUtf8_Mask | (UInt32)FILE_ATTRIBUTE_DIRECTORY); } | ||
| 37 | bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUtf8_Mask) != 0; } | 40 | bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUtf8_Mask) != 0; } |
| 38 | bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } | 41 | // bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } |
| 39 | 42 | ||
| 40 | bool ContinuedFromPrev() const | 43 | bool ContinuedFromPrev() const |
| 41 | { | 44 | { |
| @@ -43,21 +46,21 @@ struct CItem | |||
| 43 | FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev || | 46 | FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev || |
| 44 | FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext; | 47 | FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext; |
| 45 | } | 48 | } |
| 46 | 49 | // in: (numFolders > 0) is expected | |
| 47 | bool ContinuedToNext() const | 50 | // out: (returned_value >= 0) is expected |
| 48 | { | ||
| 49 | return | ||
| 50 | FolderIndex == NHeader::NFolderIndex::kContinuedToNext || | ||
| 51 | FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext; | ||
| 52 | } | ||
| 53 | |||
| 54 | int GetFolderIndex(unsigned numFolders) const | 51 | int GetFolderIndex(unsigned numFolders) const |
| 55 | { | 52 | { |
| 56 | if (ContinuedFromPrev()) | 53 | const unsigned folderIndex = FolderIndex; |
| 57 | return 0; | 54 | switch (folderIndex) |
| 58 | if (ContinuedToNext()) | 55 | { |
| 59 | return (int)numFolders - 1; | 56 | case NHeader::NFolderIndex::kContinuedFromPrev: |
| 60 | return (int)FolderIndex; | 57 | case NHeader::NFolderIndex::kContinuedPrevAndNext: |
| 58 | return 0; | ||
| 59 | case NHeader::NFolderIndex::kContinuedToNext: | ||
| 60 | return (int)numFolders - 1; | ||
| 61 | default: | ||
| 62 | return (int)folderIndex; | ||
| 63 | } | ||
| 61 | } | 64 | } |
| 62 | }; | 65 | }; |
| 63 | 66 | ||
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index 5bbdf07..7706e5d 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp | |||
| @@ -579,7 +579,7 @@ HRESULT CDatabase::Check_Item(unsigned index) | |||
| 579 | const unsigned subBits = SectorSizeBits - k_MiniSectorSizeBits; | 579 | const unsigned subBits = SectorSizeBits - k_MiniSectorSizeBits; |
| 580 | const UInt32 fid = sid >> subBits; | 580 | const UInt32 fid = sid >> subBits; |
| 581 | if (fid >= NumSectors_in_MiniStream) | 581 | if (fid >= NumSectors_in_MiniStream) |
| 582 | return false; | 582 | return S_FALSE; |
| 583 | sid = Mat[sid]; | 583 | sid = Mat[sid]; |
| 584 | if (size <= clusterSize) | 584 | if (size <= clusterSize) |
| 585 | break; | 585 | break; |
| @@ -887,12 +887,16 @@ HRESULT CDatabase::Open(IInStream *inStream) | |||
| 887 | } | 887 | } |
| 888 | else if (item.IsStorage()) | 888 | else if (item.IsStorage()) |
| 889 | { | 889 | { |
| 890 | if (item.Size != 0) // by specification | 890 | /* some old compound archives don't comply specification for (Size) and (Sid) fields for kStorage items. |
| 891 | return S_FALSE; | 891 | But original Windows code ignores these errors. |
| 892 | if (item.Sid != 0 // by specification | 892 | We also ignore these errors: */ |
| 893 | #if 0 | ||
| 894 | if (item.Size != 0 // by specification | ||
| 895 | || ( item.Sid != 0 // by specification | ||
| 893 | && item.Sid != NFatID::kFree // NFatID::kFree is used in some AAF files | 896 | && item.Sid != NFatID::kFree // NFatID::kFree is used in some AAF files |
| 894 | && item.Sid != NFatID::kEndOfChain) // NFatID::kEndOfChain is used in QuickSet (selinc) file | 897 | && item.Sid != NFatID::kEndOfChain)) // NFatID::kEndOfChain is used in QuickSet (selinc) file |
| 895 | return S_FALSE; | 898 | HeadersWarning = true; |
| 899 | #endif | ||
| 896 | } | 900 | } |
| 897 | // else if (item.Type == NItemType::kRootStorage) return S_FALSE; | 901 | // else if (item.Type == NItemType::kRootStorage) return S_FALSE; |
| 898 | else if (item.IsEmptyType()) | 902 | else if (item.IsEmptyType()) |
| @@ -1375,9 +1379,10 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 1375 | const unsigned subBits = _db.SectorSizeBits - k_MiniSectorSizeBits; | 1379 | const unsigned subBits = _db.SectorSizeBits - k_MiniSectorSizeBits; |
| 1376 | const UInt32 fid = sid >> subBits; | 1380 | const UInt32 fid = sid >> subBits; |
| 1377 | if (fid >= _db.NumSectors_in_MiniStream) | 1381 | if (fid >= _db.NumSectors_in_MiniStream) |
| 1378 | return false; | 1382 | return S_FALSE; |
| 1383 | const UInt32 temp = ((sid & ((1u << subBits) - 1)) << k_MiniSectorSizeBits); | ||
| 1379 | const UInt64 offset = (((UInt64)_db.MiniSids[fid] + 1) << _db.SectorSizeBits) + | 1384 | const UInt64 offset = (((UInt64)_db.MiniSids[fid] + 1) << _db.SectorSizeBits) + |
| 1380 | ((sid & ((1u << subBits) - 1)) << k_MiniSectorSizeBits); | 1385 | temp; |
| 1381 | if (phyPos != offset) | 1386 | if (phyPos != offset) |
| 1382 | { | 1387 | { |
| 1383 | RINOK(InStream_SeekSet(_stream, offset)) | 1388 | RINOK(InStream_SeekSet(_stream, offset)) |
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 5a11e30..58770f8 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp | |||
| @@ -98,7 +98,7 @@ bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIAN | |||
| 98 | 98 | ||
| 99 | if (name.IsPrefixedBy_Ascii_NoCase("memuse")) | 99 | if (name.IsPrefixedBy_Ascii_NoCase("memuse")) |
| 100 | { | 100 | { |
| 101 | UInt64 v; | 101 | UInt64 v = 0; |
| 102 | if (!ParseSizeString(name.Ptr(6), value, _memAvail, v)) | 102 | if (!ParseSizeString(name.Ptr(6), value, _memAvail, v)) |
| 103 | hres = E_INVALIDARG; | 103 | hres = E_INVALIDARG; |
| 104 | _memUsage_Decompress = v; | 104 | _memUsage_Decompress = v; |
diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp index d379373..27ae94e 100644 --- a/CPP/7zip/Archive/ExtHandler.cpp +++ b/CPP/7zip/Archive/ExtHandler.cpp | |||
| @@ -2167,9 +2167,9 @@ public: | |||
| 2167 | _curRem = 0; | 2167 | _curRem = 0; |
| 2168 | _virtPos = 0; | 2168 | _virtPos = 0; |
| 2169 | _physPos = 0; | 2169 | _physPos = 0; |
| 2170 | if (Vector.Size() > 0) | 2170 | if (Vector.Size()) |
| 2171 | { | 2171 | { |
| 2172 | _physPos = (Vector[0] << BlockBits); | 2172 | _physPos = (UInt64)Vector[0] << BlockBits; |
| 2173 | return SeekToPhys(); | 2173 | return SeekToPhys(); |
| 2174 | } | 2174 | } |
| 2175 | return S_OK; | 2175 | return S_OK; |
diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp index 18fce91..7a0774c 100644 --- a/CPP/7zip/Archive/FatHandler.cpp +++ b/CPP/7zip/Archive/FatHandler.cpp | |||
| @@ -497,7 +497,8 @@ HRESULT CDatabase::OpenProgressFat(bool changeTotal) | |||
| 497 | return S_OK; | 497 | return S_OK; |
| 498 | if (changeTotal) | 498 | if (changeTotal) |
| 499 | { | 499 | { |
| 500 | const UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) + | 500 | const UInt32 fatBytes = Header.CalcFatSizeInSectors() << Header.SectorSizeLog; |
| 501 | const UInt64 numTotalBytes = fatBytes + | ||
| 501 | ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog); | 502 | ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog); |
| 502 | RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes)) | 503 | RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes)) |
| 503 | } | 504 | } |
| @@ -938,7 +939,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 938 | CClusterInStream *streamSpec = new CClusterInStream; | 939 | CClusterInStream *streamSpec = new CClusterInStream; |
| 939 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; | 940 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; |
| 940 | streamSpec->Stream = InStream; | 941 | streamSpec->Stream = InStream; |
| 941 | streamSpec->StartOffset = Header.DataSector << Header.SectorSizeLog; | 942 | streamSpec->StartOffset = (UInt64)Header.DataSector << Header.SectorSizeLog; |
| 942 | streamSpec->BlockSizeLog = Header.ClusterSizeLog; | 943 | streamSpec->BlockSizeLog = Header.ClusterSizeLog; |
| 943 | streamSpec->Size = item.Size; | 944 | streamSpec->Size = item.Size; |
| 944 | 945 | ||
diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp index ca9d246..9c85bf3 100644 --- a/CPP/7zip/Archive/GzHandler.cpp +++ b/CPP/7zip/Archive/GzHandler.cpp | |||
| @@ -838,8 +838,6 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 838 | 838 | ||
| 839 | // outStream.Release(); | 839 | // outStream.Release(); |
| 840 | 840 | ||
| 841 | retResult = NExtract::NOperationResult::kDataError; | ||
| 842 | |||
| 843 | if (!_isArc) | 841 | if (!_isArc) |
| 844 | retResult = NExtract::NOperationResult::kIsNotArc; | 842 | retResult = NExtract::NOperationResult::kIsNotArc; |
| 845 | else if (_needMoreInput) | 843 | else if (_needMoreInput) |
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index 5df00ed..1d6492e 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp | |||
| @@ -1429,7 +1429,10 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress) | |||
| 1429 | const unsigned sector_of_FirstBlock = Get16a(p + 0x1c); // drAlBlSt : first allocation block in volume | 1429 | const unsigned sector_of_FirstBlock = Get16a(p + 0x1c); // drAlBlSt : first allocation block in volume |
| 1430 | const UInt32 startBlock = Get16a(p + 0x7c + 2); | 1430 | const UInt32 startBlock = Get16a(p + 0x7c + 2); |
| 1431 | const UInt32 blockCount = Get16a(p + 0x7c + 4); | 1431 | const UInt32 blockCount = Get16a(p + 0x7c + 4); |
| 1432 | SpecOffset = (UInt32)sector_of_FirstBlock << 9; // it's 32-bit here | 1432 | { |
| 1433 | const UInt32 temp = (UInt32)sector_of_FirstBlock << 9; // it's 32-bit here | ||
| 1434 | SpecOffset = temp; | ||
| 1435 | } | ||
| 1433 | PhySize2 = SpecOffset + (UInt64)numBlocks * blockSize; | 1436 | PhySize2 = SpecOffset + (UInt64)numBlocks * blockSize; |
| 1434 | SpecOffset += (UInt64)startBlock * blockSize; | 1437 | SpecOffset += (UInt64)startBlock * blockSize; |
| 1435 | // before v24.09: // SpecOffset = (UInt64)(1 + startBlock) * blockSize; | 1438 | // before v24.09: // SpecOffset = (UInt64)(1 + startBlock) * blockSize; |
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index c085386..20937bb 100644 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp | |||
| @@ -51,12 +51,12 @@ IMP_IInArchive_ArcProps | |||
| 51 | 51 | ||
| 52 | Z7_COM7F_IMF(CHandler::Open(IInStream *stream, | 52 | Z7_COM7F_IMF(CHandler::Open(IInStream *stream, |
| 53 | const UInt64 * /* maxCheckStartPosition */, | 53 | const UInt64 * /* maxCheckStartPosition */, |
| 54 | IArchiveOpenCallback * /* openArchiveCallback */)) | 54 | IArchiveOpenCallback *openCallback)) |
| 55 | { | 55 | { |
| 56 | COM_TRY_BEGIN | 56 | COM_TRY_BEGIN |
| 57 | Close(); | 57 | Close(); |
| 58 | { | 58 | { |
| 59 | RINOK(_archive.Open(stream)) | 59 | RINOK(_archive.Open(stream, openCallback)) |
| 60 | _stream = stream; | 60 | _stream = stream; |
| 61 | } | 61 | } |
| 62 | return S_OK; | 62 | return S_OK; |
| @@ -165,6 +165,8 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 165 | AddErrorMessage(s, "Self-linked directory"); | 165 | AddErrorMessage(s, "Self-linked directory"); |
| 166 | if (_archive.TooDeepDirs) | 166 | if (_archive.TooDeepDirs) |
| 167 | AddErrorMessage(s, "Too deep directory levels"); | 167 | AddErrorMessage(s, "Too deep directory levels"); |
| 168 | if (_archive.TooBigMetadata) | ||
| 169 | AddErrorMessage(s, "Too big headers"); | ||
| 168 | if (!s.IsEmpty()) | 170 | if (!s.IsEmpty()) |
| 169 | prop = s; | 171 | prop = s; |
| 170 | break; | 172 | break; |
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index 0054abf..b775dfc 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp | |||
| @@ -94,7 +94,8 @@ Byte CInArchive::ReadByte() | |||
| 94 | throw CSystemException(res); | 94 | throw CSystemException(res); |
| 95 | if (processed != kBlockSize) | 95 | if (processed != kBlockSize) |
| 96 | throw CUnexpectedEndException(); | 96 | throw CUnexpectedEndException(); |
| 97 | UInt64 end = _position + processed; | 97 | _processedBytes += processed; |
| 98 | const UInt64 end = _position + processed; | ||
| 98 | if (PhySize < end) | 99 | if (PhySize < end) |
| 99 | PhySize = end; | 100 | PhySize = end; |
| 100 | } | 101 | } |
| @@ -172,22 +173,30 @@ UInt32 CInArchive::ReadUInt32() | |||
| 172 | return val; | 173 | return val; |
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | UInt32 CInArchive::ReadDigits(int numDigits) | 176 | unsigned CInArchive::ReadDigits(unsigned numDigits) |
| 176 | { | 177 | { |
| 177 | UInt32 res = 0; | 178 | unsigned res = 0; |
| 178 | for (int i = 0; i < numDigits; i++) | 179 | unsigned mode = 0; |
| 180 | for (unsigned i = 0; i < numDigits; i++) | ||
| 179 | { | 181 | { |
| 180 | Byte b = ReadByte(); | 182 | const Byte b = ReadByte(); |
| 181 | if (b < '0' || b > '9') | 183 | if (mode == 2) |
| 184 | continue; | ||
| 185 | const unsigned d = (unsigned)b - (unsigned)'0'; | ||
| 186 | if (d > 9) | ||
| 182 | { | 187 | { |
| 183 | if (b == 0 || b == ' ') // it's bug in some CD's | 188 | // what exact cases are possible here? |
| 184 | b = '0'; | 189 | if (b != 0 && b != ' ') |
| 185 | else | ||
| 186 | throw CHeaderErrorException(); | 190 | throw CHeaderErrorException(); |
| 191 | if (mode == 1) | ||
| 192 | mode = 2; | ||
| 193 | } | ||
| 194 | else | ||
| 195 | { | ||
| 196 | mode = 1; | ||
| 197 | res *= 10; | ||
| 198 | res += d; | ||
| 187 | } | 199 | } |
| 188 | UInt32 d = (UInt32)(b - '0'); | ||
| 189 | res *= 10; | ||
| 190 | res += d; | ||
| 191 | } | 200 | } |
| 192 | return res; | 201 | return res; |
| 193 | } | 202 | } |
| @@ -222,7 +231,7 @@ void CInArchive::ReadRecordingDateTime(CRecordingDateTime &t) | |||
| 222 | t.GmtOffset = (signed char)ReadByte(); | 231 | t.GmtOffset = (signed char)ReadByte(); |
| 223 | } | 232 | } |
| 224 | 233 | ||
| 225 | void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) | 234 | void CInArchive::ReadDirRecord(CDirRecord &r, unsigned len, bool isJolietDescriptor) |
| 226 | { | 235 | { |
| 227 | r.ExtendedAttributeRecordLen = ReadByte(); | 236 | r.ExtendedAttributeRecordLen = ReadByte(); |
| 228 | if (r.ExtendedAttributeRecordLen != 0) | 237 | if (r.ExtendedAttributeRecordLen != 0) |
| @@ -234,29 +243,28 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) | |||
| 234 | r.FileUnitSize = ReadByte(); | 243 | r.FileUnitSize = ReadByte(); |
| 235 | r.InterleaveGapSize = ReadByte(); | 244 | r.InterleaveGapSize = ReadByte(); |
| 236 | r.VolSequenceNumber = ReadUInt16(); | 245 | r.VolSequenceNumber = ReadUInt16(); |
| 237 | Byte idLen = ReadByte(); | 246 | unsigned idLen = ReadByte(); |
| 247 | /* for Descriptor Root Directory Record: | ||
| 248 | idLen == 1 : by ISO Specification | ||
| 249 | idLen == 1 : for some Joliet archives | ||
| 250 | idLen == 2 : for some Joliet archives for UCS-2 (UTF-16BE). | ||
| 251 | but (len == 34) is fixed for Descriptor Root Directory Record | ||
| 252 | so we ignore idLen == 2 value in Joliet Descriptor. | ||
| 253 | */ | ||
| 254 | if (isJolietDescriptor && idLen == 2) // v26.03 : we support Joliet cases | ||
| 255 | idLen = 0; | ||
| 238 | r.FileId.Alloc(idLen); | 256 | r.FileId.Alloc(idLen); |
| 239 | ReadBytes((Byte *)r.FileId, idLen); | 257 | ReadBytes((Byte *)r.FileId, idLen); |
| 240 | unsigned padSize = 1 - (idLen & 1); | 258 | idLen += 33; |
| 241 | 259 | const unsigned padSize = idLen & 1; | |
| 242 | // SkipZeros(padSize); | 260 | // SkipZeros(padSize); |
| 243 | Skip(padSize); // it's bug in some cd's. Must be zeros | 261 | Skip(padSize); // it's bug in some cd's. Must be zeros |
| 244 | 262 | idLen += padSize; | |
| 245 | unsigned curPos = 33 + idLen + padSize; | 263 | if (len < idLen) |
| 246 | if (curPos > len) | ||
| 247 | throw CHeaderErrorException(); | 264 | throw CHeaderErrorException(); |
| 248 | unsigned rem = len - curPos; | 265 | len -= idLen; |
| 249 | r.SystemUse.Alloc(rem); | 266 | r.SystemUse.Alloc(len); |
| 250 | ReadBytes((Byte *)r.SystemUse, rem); | 267 | ReadBytes((Byte *)r.SystemUse, len); |
| 251 | } | ||
| 252 | |||
| 253 | void CInArchive::ReadDirRecord(CDirRecord &r) | ||
| 254 | { | ||
| 255 | Byte len = ReadByte(); | ||
| 256 | // Some CDs can have incorrect value len = 48 ('0') in VolumeDescriptor. | ||
| 257 | // But maybe we must use real "len" for other records. | ||
| 258 | len = 34; | ||
| 259 | ReadDirRecord2(r, len); | ||
| 260 | } | 268 | } |
| 261 | 269 | ||
| 262 | void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) | 270 | void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) |
| @@ -275,7 +283,16 @@ void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d) | |||
| 275 | d.LOptionalPathTableLocation = ReadUInt32Le(); | 283 | d.LOptionalPathTableLocation = ReadUInt32Le(); |
| 276 | d.MPathTableLocation = ReadUInt32Be(); | 284 | d.MPathTableLocation = ReadUInt32Be(); |
| 277 | d.MOptionalPathTableLocation = ReadUInt32Be(); | 285 | d.MOptionalPathTableLocation = ReadUInt32Be(); |
| 278 | ReadDirRecord(d.RootDirRecord); | 286 | { |
| 287 | unsigned len; | ||
| 288 | /* len = */ ReadByte(); | ||
| 289 | // len == 34 is expected by ISO specification | ||
| 290 | // len == 36 is possible for some Joliet archives | ||
| 291 | // len == 48 is possible for Rock Ridge? | ||
| 292 | len = 34; // we ignore (len) value from header because | ||
| 293 | // next field (VolumeSetId) always starts after 34 bytes | ||
| 294 | ReadDirRecord(d.RootDirRecord, len, d.IsJoliet()); | ||
| 295 | } | ||
| 279 | ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId)); | 296 | ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId)); |
| 280 | ReadBytes(d.PublisherId, sizeof(d.PublisherId)); | 297 | ReadBytes(d.PublisherId, sizeof(d.PublisherId)); |
| 281 | ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId)); | 298 | ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId)); |
| @@ -330,16 +347,16 @@ void CInArchive::SeekToBlock(UInt32 blockIndex) | |||
| 330 | m_BufferPos = 0; | 347 | m_BufferPos = 0; |
| 331 | } | 348 | } |
| 332 | 349 | ||
| 333 | static const int kNumLevelsMax = 256; | 350 | static const unsigned kNumLevelsMax = 256; |
| 334 | 351 | ||
| 335 | void CInArchive::ReadDir(CDir &d, int level) | 352 | HRESULT CInArchive::ReadDir(CDir &d, unsigned level) |
| 336 | { | 353 | { |
| 337 | if (!d.IsDir()) | 354 | if (!d.IsDir()) |
| 338 | return; | 355 | return S_OK; |
| 339 | if (level > kNumLevelsMax) | 356 | if (level > kNumLevelsMax) |
| 340 | { | 357 | { |
| 341 | TooDeepDirs = true; | 358 | TooDeepDirs = true; |
| 342 | return; | 359 | return S_OK; |
| 343 | } | 360 | } |
| 344 | 361 | ||
| 345 | { | 362 | { |
| @@ -347,7 +364,7 @@ void CInArchive::ReadDir(CDir &d, int level) | |||
| 347 | if (UniqStartLocations[i] == d.ExtentLocation) | 364 | if (UniqStartLocations[i] == d.ExtentLocation) |
| 348 | { | 365 | { |
| 349 | SelfLinkedDirs = true; | 366 | SelfLinkedDirs = true; |
| 350 | return; | 367 | return S_OK; |
| 351 | } | 368 | } |
| 352 | UniqStartLocations.Add(d.ExtentLocation); | 369 | UniqStartLocations.Add(d.ExtentLocation); |
| 353 | } | 370 | } |
| @@ -358,26 +375,47 @@ void CInArchive::ReadDir(CDir &d, int level) | |||
| 358 | bool firstItem = true; | 375 | bool firstItem = true; |
| 359 | for (;;) | 376 | for (;;) |
| 360 | { | 377 | { |
| 361 | UInt64 offset = _position - startPos; | 378 | const UInt64 offset = _position - startPos; |
| 362 | if (offset >= d.Size) | 379 | if (offset >= d.Size) |
| 363 | break; | 380 | break; |
| 364 | Byte len = ReadByte(); | 381 | const unsigned len = ReadByte(); |
| 365 | if (len == 0) | 382 | if (len == 0) |
| 366 | continue; | 383 | continue; |
| 367 | CDir subItem; | 384 | CDir subItem; |
| 368 | ReadDirRecord2(subItem, len); | 385 | ReadDirRecord(subItem, len); |
| 369 | if (firstItem && level == 0) | 386 | if (firstItem && level == 0) |
| 370 | IsSusp = subItem.CheckSusp(SuspSkipSize); | 387 | IsSusp = subItem.CheckSusp(SuspSkipSize); |
| 371 | 388 | ||
| 372 | if (!subItem.IsSystemItem()) | 389 | if (!subItem.IsSystemItem()) |
| 390 | { | ||
| 391 | if (_numFiles >= (1u << 30)) | ||
| 392 | { | ||
| 393 | TooBigMetadata = true; // Too many files | ||
| 394 | return S_FALSE; | ||
| 395 | } | ||
| 373 | d._subItems.Add(subItem); | 396 | d._subItems.Add(subItem); |
| 397 | _numFiles++; | ||
| 398 | } | ||
| 374 | 399 | ||
| 400 | if (_openCallback && _processedBytes - _processedBytes_prev >= (1 << 24)) | ||
| 401 | { | ||
| 402 | _processedBytes_prev = _processedBytes; | ||
| 403 | RINOK(_openCallback->SetTotal(&_numFiles, &_processedBytes)) | ||
| 404 | } | ||
| 405 | if (_processedBytes > _fileSize + (1u << 24)) | ||
| 406 | { | ||
| 407 | TooBigMetadata = true; | ||
| 408 | return S_FALSE; | ||
| 409 | } | ||
| 375 | firstItem = false; | 410 | firstItem = false; |
| 376 | } | 411 | } |
| 377 | FOR_VECTOR (i, d._subItems) | 412 | FOR_VECTOR (i, d._subItems) |
| 378 | ReadDir(d._subItems[i], level + 1); | 413 | { |
| 414 | RINOK(ReadDir(d._subItems[i], level + 1)) | ||
| 415 | } | ||
| 379 | 416 | ||
| 380 | UniqStartLocations.DeleteBack(); | 417 | UniqStartLocations.DeleteBack(); |
| 418 | return S_OK; | ||
| 381 | } | 419 | } |
| 382 | 420 | ||
| 383 | void CInArchive::CreateRefs(CDir &d) | 421 | void CInArchive::CreateRefs(CDir &d) |
| @@ -614,7 +652,7 @@ HRESULT CInArchive::Open2() | |||
| 614 | IsArc = true; | 652 | IsArc = true; |
| 615 | 653 | ||
| 616 | (CDirRecord &)_rootDir = vd.RootDirRecord; | 654 | (CDirRecord &)_rootDir = vd.RootDirRecord; |
| 617 | ReadDir(_rootDir, 0); | 655 | RINOK(ReadDir(_rootDir, 0)) |
| 618 | CreateRefs(_rootDir); | 656 | CreateRefs(_rootDir); |
| 619 | ReadBootInfo(); | 657 | ReadBootInfo(); |
| 620 | 658 | ||
| @@ -671,10 +709,12 @@ HRESULT CInArchive::Open2() | |||
| 671 | return S_OK; | 709 | return S_OK; |
| 672 | } | 710 | } |
| 673 | 711 | ||
| 674 | HRESULT CInArchive::Open(IInStream *inStream) | 712 | HRESULT CInArchive::Open(IInStream *inStream, IArchiveOpenCallback *openCallback) |
| 675 | { | 713 | { |
| 676 | Clear(); | 714 | Clear(); |
| 677 | _stream = inStream; | 715 | _stream = inStream; |
| 716 | _openCallback = openCallback; | ||
| 717 | _numFiles = _processedBytes = _processedBytes_prev = 0; | ||
| 678 | try { return Open2(); } | 718 | try { return Open2(); } |
| 679 | catch(const CSystemException &e) { return e.ErrorCode; } | 719 | catch(const CSystemException &e) { return e.ErrorCode; } |
| 680 | catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; } | 720 | catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; } |
| @@ -689,6 +729,7 @@ void CInArchive::Clear() | |||
| 689 | HeadersError = false; | 729 | HeadersError = false; |
| 690 | IncorrectBigEndian = false; | 730 | IncorrectBigEndian = false; |
| 691 | TooDeepDirs = false; | 731 | TooDeepDirs = false; |
| 732 | TooBigMetadata = false; | ||
| 692 | SelfLinkedDirs = false; | 733 | SelfLinkedDirs = false; |
| 693 | 734 | ||
| 694 | UniqStartLocations.Clear(); | 735 | UniqStartLocations.Clear(); |
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index e7d1fee..6a031ba 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h | |||
| @@ -237,14 +237,12 @@ struct CRef | |||
| 237 | UInt64 TotalSize; | 237 | UInt64 TotalSize; |
| 238 | }; | 238 | }; |
| 239 | 239 | ||
| 240 | const UInt32 kBlockSize = 1 << 11; | 240 | const unsigned kBlockSize = 1 << 11; |
| 241 | 241 | ||
| 242 | class CInArchive | 242 | class CInArchive |
| 243 | { | 243 | { |
| 244 | IInStream *_stream; | ||
| 245 | UInt64 _position; | 244 | UInt64 _position; |
| 246 | 245 | unsigned m_BufferPos; | |
| 247 | UInt32 m_BufferPos; | ||
| 248 | 246 | ||
| 249 | void Skip(size_t size); | 247 | void Skip(size_t size); |
| 250 | void SkipZeros(size_t size); | 248 | void SkipZeros(size_t size); |
| @@ -255,23 +253,22 @@ class CInArchive | |||
| 255 | UInt32 ReadUInt32Be(); | 253 | UInt32 ReadUInt32Be(); |
| 256 | UInt32 ReadUInt32(); | 254 | UInt32 ReadUInt32(); |
| 257 | UInt64 ReadUInt64(); | 255 | UInt64 ReadUInt64(); |
| 258 | UInt32 ReadDigits(int numDigits); | 256 | unsigned ReadDigits(unsigned numDigits); |
| 259 | void ReadDateTime(CDateTime &d); | 257 | void ReadDateTime(CDateTime &d); |
| 260 | void ReadRecordingDateTime(CRecordingDateTime &t); | 258 | void ReadRecordingDateTime(CRecordingDateTime &t); |
| 261 | void ReadDirRecord2(CDirRecord &r, Byte len); | 259 | void ReadDirRecord(CDirRecord &r, unsigned len, bool isJolietDescriptor = false); |
| 262 | void ReadDirRecord(CDirRecord &r); | ||
| 263 | 260 | ||
| 264 | void ReadBootRecordDescriptor(CBootRecordDescriptor &d); | 261 | void ReadBootRecordDescriptor(CBootRecordDescriptor &d); |
| 265 | void ReadVolumeDescriptor(CVolumeDescriptor &d); | 262 | void ReadVolumeDescriptor(CVolumeDescriptor &d); |
| 266 | 263 | ||
| 267 | void SeekToBlock(UInt32 blockIndex); | 264 | void SeekToBlock(UInt32 blockIndex); |
| 268 | void ReadDir(CDir &d, int level); | 265 | HRESULT ReadDir(CDir &d, unsigned level); |
| 269 | void CreateRefs(CDir &d); | 266 | void CreateRefs(CDir &d); |
| 270 | 267 | ||
| 271 | void ReadBootInfo(); | 268 | void ReadBootInfo(); |
| 272 | HRESULT Open2(); | 269 | HRESULT Open2(); |
| 273 | public: | 270 | public: |
| 274 | HRESULT Open(IInStream *inStream); | 271 | HRESULT Open(IInStream *inStream, IArchiveOpenCallback *openCallback); |
| 275 | void Clear(); | 272 | void Clear(); |
| 276 | 273 | ||
| 277 | UInt64 _fileSize; | 274 | UInt64 _fileSize; |
| @@ -291,10 +288,12 @@ public: | |||
| 291 | bool HeadersError; | 288 | bool HeadersError; |
| 292 | bool IncorrectBigEndian; | 289 | bool IncorrectBigEndian; |
| 293 | bool TooDeepDirs; | 290 | bool TooDeepDirs; |
| 291 | bool TooBigMetadata; | ||
| 294 | bool SelfLinkedDirs; | 292 | bool SelfLinkedDirs; |
| 295 | bool IsSusp; | 293 | bool IsSusp; |
| 296 | unsigned SuspSkipSize; | 294 | unsigned SuspSkipSize; |
| 297 | 295 | ||
| 296 | private: | ||
| 298 | int _expand_BootEntries_index; | 297 | int _expand_BootEntries_index; |
| 299 | 298 | ||
| 300 | CRecordVector<UInt32> UniqStartLocations; | 299 | CRecordVector<UInt32> UniqStartLocations; |
| @@ -307,12 +306,19 @@ public: | |||
| 307 | PhySize = end; | 306 | PhySize = end; |
| 308 | } | 307 | } |
| 309 | 308 | ||
| 309 | public: | ||
| 310 | bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } | 310 | bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } |
| 311 | 311 | ||
| 312 | UInt64 GetBootItemSize(unsigned index) const; | 312 | UInt64 GetBootItemSize(unsigned index) const; |
| 313 | 313 | ||
| 314 | private: | 314 | private: |
| 315 | CDir _rootDir; | 315 | CDir _rootDir; |
| 316 | IInStream *_stream; | ||
| 317 | IArchiveOpenCallback *_openCallback; | ||
| 318 | UInt64 _numFiles; | ||
| 319 | UInt64 _processedBytes; | ||
| 320 | UInt64 _processedBytes_prev; | ||
| 321 | |||
| 316 | Byte m_Buffer[kBlockSize]; | 322 | Byte m_Buffer[kBlockSize]; |
| 317 | CBootRecordDescriptor _bootDesc; | 323 | CBootRecordDescriptor _bootDesc; |
| 318 | }; | 324 | }; |
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index 65829d0..ef3832a 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h | |||
| @@ -81,8 +81,7 @@ struct CDirRecord | |||
| 81 | bool AreMultiPartEqualWith(const CDirRecord &a) const | 81 | bool AreMultiPartEqualWith(const CDirRecord &a) const |
| 82 | { | 82 | { |
| 83 | return FileId == a.FileId | 83 | return FileId == a.FileId |
| 84 | && (FileFlags & (~NFileFlags::kNonFinalExtent)) == | 84 | && ((FileFlags ^ a.FileFlags) & ~NFileFlags::kNonFinalExtent) == 0; |
| 85 | (a.FileFlags & (~NFileFlags::kNonFinalExtent)); | ||
| 86 | } | 85 | } |
| 87 | 86 | ||
| 88 | bool IsDir() const { return (FileFlags & NFileFlags::kDirectory) != 0; } | 87 | bool IsDir() const { return (FileFlags & NFileFlags::kDirectory) != 0; } |
| @@ -90,10 +89,7 @@ struct CDirRecord | |||
| 90 | 89 | ||
| 91 | bool IsSystemItem() const | 90 | bool IsSystemItem() const |
| 92 | { | 91 | { |
| 93 | if (FileId.Size() != 1) | 92 | return FileId.Size() == 1 && *(const Byte *)FileId < 2; |
| 94 | return false; | ||
| 95 | Byte b = *(const Byte *)FileId; | ||
| 96 | return (b == 0 || b == 1); | ||
| 97 | } | 93 | } |
| 98 | 94 | ||
| 99 | 95 | ||
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp index 7cbabf4..a0c5021 100644 --- a/CPP/7zip/Archive/LzmaHandler.cpp +++ b/CPP/7zip/Archive/LzmaHandler.cpp | |||
| @@ -185,7 +185,7 @@ Z7_CLASS_IMP_CHandler_IInArchive_1( | |||
| 185 | UInt64 _unpackSize; | 185 | UInt64 _unpackSize; |
| 186 | UInt64 _numStreams; | 186 | UInt64 _numStreams; |
| 187 | 187 | ||
| 188 | void GetMethod(NCOM::CPropVariant &prop); | 188 | void GetMethod(NCOM::CPropVariant &prop) const; |
| 189 | 189 | ||
| 190 | unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); } | 190 | unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); } |
| 191 | public: | 191 | public: |
| @@ -249,7 +249,7 @@ static char *AddProp32(char *s, const char *name, UInt32 v) | |||
| 249 | return ::ConvertUInt32ToString(v, s); | 249 | return ::ConvertUInt32ToString(v, s); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | void CHandler::GetMethod(NCOM::CPropVariant &prop) | 252 | void CHandler::GetMethod(NCOM::CPropVariant &prop) const |
| 253 | { | 253 | { |
| 254 | if (!_stream) | 254 | if (!_stream) |
| 255 | return; | 255 | return; |
| @@ -270,7 +270,7 @@ void CHandler::GetMethod(NCOM::CPropVariant &prop) | |||
| 270 | UInt32 lp = d % 5; | 270 | UInt32 lp = d % 5; |
| 271 | if (lc != 3) s = AddProp32(s, "lc", lc); | 271 | if (lc != 3) s = AddProp32(s, "lc", lc); |
| 272 | if (lp != 0) s = AddProp32(s, "lp", lp); | 272 | if (lp != 0) s = AddProp32(s, "lp", lp); |
| 273 | if (pb != 2) s = AddProp32(s, "pb", pb); | 273 | if (pb != 2) /* s = */ AddProp32(s, "pb", pb); |
| 274 | } | 274 | } |
| 275 | prop = sz; | 275 | prop = sz; |
| 276 | } | 276 | } |
| @@ -568,9 +568,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 568 | opResult = NExtract::NOperationResult::kDataAfterEnd; | 568 | opResult = NExtract::NOperationResult::kDataAfterEnd; |
| 569 | else if (hres == S_FALSE) | 569 | else if (hres == S_FALSE) |
| 570 | opResult = NExtract::NOperationResult::kDataError; | 570 | opResult = NExtract::NOperationResult::kDataError; |
| 571 | else if (hres == S_OK) | 571 | else if (hres != S_OK) |
| 572 | opResult = NExtract::NOperationResult::kOK; | ||
| 573 | else | ||
| 574 | return hres; | 572 | return hres; |
| 575 | 573 | ||
| 576 | // outStream.Release(); | 574 | // outStream.Release(); |
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp index 7ce2e8e..d17dca7 100644 --- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp +++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp | |||
| @@ -148,7 +148,17 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 148 | prop = v; | 148 | prop = v; |
| 149 | break; | 149 | break; |
| 150 | } | 150 | } |
| 151 | 151 | case kpidWarningFlags: | |
| 152 | { | ||
| 153 | UInt32 flags = 0; | ||
| 154 | if (_archive.CREATEDIR_processing_WasStopped | ||
| 155 | || _archive.FILENAME_processing_WasStopped) | ||
| 156 | flags |= kpv_ErrorFlags_HeadersError; | ||
| 157 | if (flags != 0) | ||
| 158 | prop = flags; | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | |||
| 152 | case kpidName: | 162 | case kpidName: |
| 153 | { | 163 | { |
| 154 | AString s; | 164 | AString s; |
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index 577062e..b6ff749 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | namespace NArchive { | 17 | namespace NArchive { |
| 18 | namespace NNsis { | 18 | namespace NNsis { |
| 19 | 19 | ||
| 20 | struct CInArchiveException {}; | ||
| 21 | |||
| 20 | static const size_t kInputBufSize = 1 << 20; | 22 | static const size_t kInputBufSize = 1 << 20; |
| 21 | 23 | ||
| 22 | const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE; | 24 | const Byte kSignature[kSignatureSize] = NSIS_SIGNATURE; |
| @@ -591,7 +593,7 @@ void CInArchive::GetVar2(AString &res, UInt32 index) | |||
| 591 | { | 593 | { |
| 592 | if (index >= 10) | 594 | if (index >= 10) |
| 593 | { | 595 | { |
| 594 | res += 'R'; | 596 | res.Add_Char('R'); |
| 595 | index -= 10; | 597 | index -= 10; |
| 596 | } | 598 | } |
| 597 | UIntToString(res, index); | 599 | UIntToString(res, index); |
| @@ -607,16 +609,16 @@ void CInArchive::GetVar2(AString &res, UInt32 index) | |||
| 607 | } | 609 | } |
| 608 | else | 610 | else |
| 609 | { | 611 | { |
| 610 | res += '_'; | 612 | res.Add_Char('_'); |
| 611 | UIntToString(res, index - numInternalVars); | 613 | UIntToString(res, index - numInternalVars); |
| 612 | res += '_'; | 614 | res.Add_Char('_'); |
| 613 | } | 615 | } |
| 614 | } | 616 | } |
| 615 | } | 617 | } |
| 616 | 618 | ||
| 617 | void CInArchive::GetVar(AString &res, UInt32 index) | 619 | void CInArchive::GetVar(AString &res, UInt32 index) |
| 618 | { | 620 | { |
| 619 | res += '$'; | 621 | res.Add_Char('$'); |
| 620 | GetVar2(res, index); | 622 | GetVar2(res, index); |
| 621 | } | 623 | } |
| 622 | 624 | ||
| @@ -737,7 +739,7 @@ void CInArchive::GetShellString(AString &s, unsigned index1, unsigned index2) | |||
| 737 | 739 | ||
| 738 | if (id < 0) | 740 | if (id < 0) |
| 739 | { | 741 | { |
| 740 | s += '('; | 742 | s.Add_Char('('); |
| 741 | if (IsUnicode) | 743 | if (IsUnicode) |
| 742 | { | 744 | { |
| 743 | for (unsigned i = 0; i < 256; i++) | 745 | for (unsigned i = 0; i < 256; i++) |
| @@ -751,12 +753,12 @@ void CInArchive::GetShellString(AString &s, unsigned index1, unsigned index2) | |||
| 751 | } | 753 | } |
| 752 | else | 754 | else |
| 753 | s += (const char *)p; | 755 | s += (const char *)p; |
| 754 | s += ')'; | 756 | s.Add_Char(')'); |
| 755 | } | 757 | } |
| 756 | return; | 758 | return; |
| 757 | } | 759 | } |
| 758 | 760 | ||
| 759 | s += '$'; | 761 | s.Add_Char('$'); |
| 760 | if (index1 < Z7_ARRAY_SIZE(kShellStrings)) | 762 | if (index1 < Z7_ARRAY_SIZE(kShellStrings)) |
| 761 | { | 763 | { |
| 762 | const char *sz = kShellStrings[index1]; | 764 | const char *sz = kShellStrings[index1]; |
| @@ -776,11 +778,11 @@ void CInArchive::GetShellString(AString &s, unsigned index1, unsigned index2) | |||
| 776 | } | 778 | } |
| 777 | } | 779 | } |
| 778 | s += "_ERROR_UNSUPPORTED_SHELL_"; | 780 | s += "_ERROR_UNSUPPORTED_SHELL_"; |
| 779 | s += '['; | 781 | s.Add_Char('['); |
| 780 | UIntToString(s, index1); | 782 | UIntToString(s, index1); |
| 781 | s += ','; | 783 | s.Add_Char(','); |
| 782 | UIntToString(s, index2); | 784 | UIntToString(s, index2); |
| 783 | s += ']'; | 785 | s.Add_Char(']'); |
| 784 | } | 786 | } |
| 785 | 787 | ||
| 786 | #ifdef NSIS_SCRIPT | 788 | #ifdef NSIS_SCRIPT |
| @@ -800,9 +802,16 @@ void CInArchive::Add_LangStr(AString &res, UInt32 id) | |||
| 800 | #endif | 802 | #endif |
| 801 | res += "$(LSTR_"; | 803 | res += "$(LSTR_"; |
| 802 | UIntToString(res, id); | 804 | UIntToString(res, id); |
| 803 | res += ')'; | 805 | res.Add_Char(')'); |
| 804 | } | 806 | } |
| 805 | 807 | ||
| 808 | static const unsigned k_StringLen_Limit = 1 << 16; | ||
| 809 | |||
| 810 | #define CHECK_STRING_LEN(s) \ | ||
| 811 | { if (s.Len() >= k_StringLen_Limit) \ | ||
| 812 | { /* s = "[LONG_PATH]"; return; */ throw CInArchiveException(); } } | ||
| 813 | |||
| 814 | |||
| 806 | void CInArchive::GetNsisString_Raw(const Byte *s) | 815 | void CInArchive::GetNsisString_Raw(const Byte *s) |
| 807 | { | 816 | { |
| 808 | Raw_AString.Empty(); | 817 | Raw_AString.Empty(); |
| @@ -811,6 +820,7 @@ void CInArchive::GetNsisString_Raw(const Byte *s) | |||
| 811 | { | 820 | { |
| 812 | for (;;) | 821 | for (;;) |
| 813 | { | 822 | { |
| 823 | CHECK_STRING_LEN(Raw_AString) | ||
| 814 | Byte c = *s++; | 824 | Byte c = *s++; |
| 815 | if (c == 0) | 825 | if (c == 0) |
| 816 | return; | 826 | return; |
| @@ -846,6 +856,7 @@ void CInArchive::GetNsisString_Raw(const Byte *s) | |||
| 846 | // NSIS-3 ANSI | 856 | // NSIS-3 ANSI |
| 847 | for (;;) | 857 | for (;;) |
| 848 | { | 858 | { |
| 859 | CHECK_STRING_LEN(Raw_AString) | ||
| 849 | Byte c = *s++; | 860 | Byte c = *s++; |
| 850 | if (c <= NS_3_CODE_SKIP) | 861 | if (c <= NS_3_CODE_SKIP) |
| 851 | { | 862 | { |
| @@ -973,6 +984,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p) | |||
| 973 | { | 984 | { |
| 974 | for (;;) | 985 | for (;;) |
| 975 | { | 986 | { |
| 987 | CHECK_STRING_LEN(Raw_UString) | ||
| 976 | unsigned c = Get16(p); | 988 | unsigned c = Get16(p); |
| 977 | p += 2; | 989 | p += 2; |
| 978 | if (c == 0) | 990 | if (c == 0) |
| @@ -1017,6 +1029,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p) | |||
| 1017 | // NSIS-3 Unicode | 1029 | // NSIS-3 Unicode |
| 1018 | for (;;) | 1030 | for (;;) |
| 1019 | { | 1031 | { |
| 1032 | CHECK_STRING_LEN(Raw_UString) | ||
| 1020 | unsigned c = Get16(p); | 1033 | unsigned c = Get16(p); |
| 1021 | p += 2; | 1034 | p += 2; |
| 1022 | if (c > NS_3_CODE_SKIP) | 1035 | if (c > NS_3_CODE_SKIP) |
| @@ -2124,7 +2137,7 @@ bool CInArchive::PrintSectionBegin(const CSection §, unsigned index) | |||
| 2124 | { | 2137 | { |
| 2125 | AString name; | 2138 | AString name; |
| 2126 | if (sect.Flags & SF_BOLD) | 2139 | if (sect.Flags & SF_BOLD) |
| 2127 | name += '!'; | 2140 | name.Add_Char('!'); |
| 2128 | AString s2; | 2141 | AString s2; |
| 2129 | ReadString2(s2, sect.Name); | 2142 | ReadString2(s2, sect.Name); |
| 2130 | if (!IsInstaller) | 2143 | if (!IsInstaller) |
| @@ -2330,9 +2343,9 @@ void CInArchive::MessageBox_MB_Part(UInt32 param) | |||
| 2330 | static const Byte k_InitPluginDir_Commands[] = | 2343 | static const Byte k_InitPluginDir_Commands[] = |
| 2331 | { 13, 26, 31, 13, 19, 21, 11, 14, 25, 31, 1, 22, 4, 1 }; | 2344 | { 13, 26, 31, 13, 19, 21, 11, 14, 25, 31, 1, 22, 4, 1 }; |
| 2332 | 2345 | ||
| 2333 | bool CInArchive::CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands) | 2346 | bool CInArchive::CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands) const |
| 2334 | { | 2347 | { |
| 2335 | for (UInt32 kkk = 0; kkk < numCommands; kkk++, rawCmds += kCmdSize) | 2348 | for (size_t kkk = 0; kkk < numCommands; kkk++, rawCmds += kCmdSize) |
| 2336 | if (GetCmd(Get32(rawCmds)) != sequence[kkk]) | 2349 | if (GetCmd(Get32(rawCmds)) != sequence[kkk]) |
| 2337 | return false; | 2350 | return false; |
| 2338 | return true; | 2351 | return true; |
| @@ -2410,7 +2423,7 @@ unsigned CInArchive::GetNumSupportedCommands() const | |||
| 2410 | 2423 | ||
| 2411 | #endif | 2424 | #endif |
| 2412 | 2425 | ||
| 2413 | UInt32 CInArchive::GetCmd(UInt32 a) | 2426 | UInt32 CInArchive::GetCmd(UInt32 a) const |
| 2414 | { | 2427 | { |
| 2415 | if (!IsPark()) | 2428 | if (!IsPark()) |
| 2416 | { | 2429 | { |
| @@ -2875,21 +2888,58 @@ static bool IsAbsolutePath(const char *s) | |||
| 2875 | return (s[0] == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) || IsDrivePath(s); | 2888 | return (s[0] == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) || IsDrivePath(s); |
| 2876 | } | 2889 | } |
| 2877 | 2890 | ||
| 2878 | void CInArchive::SetItemName(CItem &item, UInt32 strPos) | 2891 | |
| 2892 | static const unsigned k_PathLen_Small_Limit = 60 + 260 * 4; // we reserve some space for multibyte encoding and for prefix | ||
| 2893 | static const unsigned k_PathLen_Break_Limit = 1 << 12; // must be >= k_PathLen_Small_Limit | ||
| 2894 | |||
| 2895 | #define k_LONG_PATH_DIR "[LONG_PATH]" | ||
| 2896 | #define k_UNKNOWN_PATH_DIR "[UNKNOWN_PATH]" | ||
| 2897 | #define k_LONG_PATH_FILE "[LONG_PATH_FILE]" | ||
| 2898 | #define k_UNKNOWN_PATH_FILE "[UNKNOWN_PATH_FILE]" | ||
| 2899 | |||
| 2900 | void CInArchive::SetItemName(CItem &item, const UInt32 strPos) | ||
| 2879 | { | 2901 | { |
| 2880 | ReadString2_Raw(strPos); | 2902 | item.Prefix = -1; |
| 2881 | const bool isAbs = IsAbsolutePathVar(strPos); | 2903 | if (FILENAME_processing_WasStopped) |
| 2882 | if (IsUnicode) | ||
| 2883 | { | 2904 | { |
| 2884 | item.NameU = Raw_UString; | 2905 | if (IsUnicode) |
| 2885 | if (!isAbs && !IsAbsolutePath(Raw_UString)) | 2906 | item.NameU = k_UNKNOWN_PATH_FILE; |
| 2886 | item.Prefix = (int)UPrefixes.Size() - 1; | 2907 | else |
| 2908 | item.NameA = k_UNKNOWN_PATH_FILE; | ||
| 2887 | } | 2909 | } |
| 2888 | else | 2910 | else |
| 2889 | { | 2911 | { |
| 2890 | item.NameA = Raw_AString; | 2912 | ReadString2_Raw(strPos); |
| 2891 | if (!isAbs && !IsAbsolutePath(Raw_AString)) | 2913 | const bool isAbs = IsAbsolutePathVar(strPos); |
| 2892 | item.Prefix = (int)APrefixes.Size() - 1; | 2914 | if (IsUnicode) |
| 2915 | { | ||
| 2916 | if (Raw_UString.Len() >= k_PathLen_Small_Limit) | ||
| 2917 | item.NameU = k_LONG_PATH_FILE; | ||
| 2918 | else | ||
| 2919 | { | ||
| 2920 | item.NameU = Raw_UString; | ||
| 2921 | if (!isAbs && !IsAbsolutePath(Raw_UString)) | ||
| 2922 | item.Prefix = (int)UPrefixes.Size() - 1; | ||
| 2923 | } | ||
| 2924 | if (Raw_UString.Len() >= k_PathLen_Break_Limit) | ||
| 2925 | FILENAME_processing_WasStopped = true; | ||
| 2926 | } | ||
| 2927 | else | ||
| 2928 | { | ||
| 2929 | if (Raw_AString.Len() >= k_PathLen_Small_Limit) | ||
| 2930 | item.NameA = k_LONG_PATH_FILE; | ||
| 2931 | else | ||
| 2932 | { | ||
| 2933 | item.NameA = Raw_AString; | ||
| 2934 | if (!isAbs && !IsAbsolutePath(Raw_AString)) | ||
| 2935 | item.Prefix = (int)APrefixes.Size() - 1; | ||
| 2936 | } | ||
| 2937 | if (Raw_AString.Len() >= k_PathLen_Break_Limit) | ||
| 2938 | FILENAME_processing_WasStopped = true; | ||
| 2939 | } | ||
| 2940 | _memUsage_Files += item.NameA.Len() + item.NameU.Len() * 2 + 128; | ||
| 2941 | if (_memUsage_Files >= (1 << 29)) | ||
| 2942 | FILENAME_processing_WasStopped = true; | ||
| 2893 | } | 2943 | } |
| 2894 | } | 2944 | } |
| 2895 | 2945 | ||
| @@ -3387,14 +3437,14 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) | |||
| 3387 | { | 3437 | { |
| 3388 | case EW_CREATEDIR: | 3438 | case EW_CREATEDIR: |
| 3389 | { | 3439 | { |
| 3390 | bool isSetOutPath = (params[1] != 0); | 3440 | const bool isSetOutPath = (params[1] != 0); |
| 3391 | 3441 | ||
| 3392 | if (isSetOutPath) | 3442 | if (isSetOutPath && !CREATEDIR_processing_WasStopped) |
| 3393 | { | 3443 | { |
| 3394 | UInt32 par0 = params[0]; | 3444 | UInt32 par0 = params[0]; |
| 3395 | 3445 | ||
| 3396 | UInt32 resOffset; | 3446 | UInt32 resOffset; |
| 3397 | Int32 idx = GetVarIndex(par0, resOffset); | 3447 | const Int32 idx = GetVarIndex(par0, resOffset); |
| 3398 | if (idx == (Int32)spec_outdir_VarIndex || | 3448 | if (idx == (Int32)spec_outdir_VarIndex || |
| 3399 | idx == kVar_OUTDIR) | 3449 | idx == kVar_OUTDIR) |
| 3400 | par0 += resOffset; | 3450 | par0 += resOffset; |
| @@ -3407,7 +3457,11 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) | |||
| 3407 | Raw_UString.Insert(0, spec_outdir_U); | 3457 | Raw_UString.Insert(0, spec_outdir_U); |
| 3408 | else if (idx == kVar_OUTDIR) | 3458 | else if (idx == kVar_OUTDIR) |
| 3409 | Raw_UString.Insert(0, UPrefixes.Back()); | 3459 | Raw_UString.Insert(0, UPrefixes.Back()); |
| 3410 | UPrefixes.Add(Raw_UString); | 3460 | if (Raw_UString.Len() >= k_PathLen_Break_Limit) |
| 3461 | CREATEDIR_processing_WasStopped = true; | ||
| 3462 | if (Raw_UString.Len() >= k_PathLen_Small_Limit) | ||
| 3463 | Raw_UString = k_LONG_PATH_DIR; | ||
| 3464 | _memUsage_Dirs += Raw_UString.Len() * 2; | ||
| 3411 | } | 3465 | } |
| 3412 | else | 3466 | else |
| 3413 | { | 3467 | { |
| @@ -3415,11 +3469,30 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) | |||
| 3415 | Raw_AString.Insert(0, spec_outdir_A); | 3469 | Raw_AString.Insert(0, spec_outdir_A); |
| 3416 | else if (idx == kVar_OUTDIR) | 3470 | else if (idx == kVar_OUTDIR) |
| 3417 | Raw_AString.Insert(0, APrefixes.Back()); | 3471 | Raw_AString.Insert(0, APrefixes.Back()); |
| 3418 | APrefixes.Add(Raw_AString); | 3472 | if (Raw_AString.Len() >= k_PathLen_Break_Limit) |
| 3473 | CREATEDIR_processing_WasStopped = true; | ||
| 3474 | if (Raw_AString.Len() >= k_PathLen_Small_Limit) | ||
| 3475 | Raw_AString = k_LONG_PATH_DIR; | ||
| 3476 | _memUsage_Dirs += Raw_AString.Len(); | ||
| 3477 | } | ||
| 3478 | _memUsage_Dirs += 64; | ||
| 3479 | if (_memUsage_Dirs >= (1 << 25)) | ||
| 3480 | { | ||
| 3481 | CREATEDIR_processing_WasStopped = true; | ||
| 3482 | if (IsUnicode) | ||
| 3483 | Raw_UString = k_UNKNOWN_PATH_DIR; | ||
| 3484 | else | ||
| 3485 | Raw_AString = k_UNKNOWN_PATH_DIR; | ||
| 3419 | } | 3486 | } |
| 3487 | if (IsUnicode) | ||
| 3488 | UPrefixes.Add(Raw_UString); | ||
| 3489 | else | ||
| 3490 | APrefixes.Add(Raw_AString); | ||
| 3420 | } | 3491 | } |
| 3421 | 3492 | ||
| 3422 | #ifdef NSIS_SCRIPT | 3493 | #ifdef NSIS_SCRIPT |
| 3494 | if (!s.IsError()) | ||
| 3495 | { | ||
| 3423 | s += isSetOutPath ? "SetOutPath" : "CreateDirectory"; | 3496 | s += isSetOutPath ? "SetOutPath" : "CreateDirectory"; |
| 3424 | AddParam(params[0]); | 3497 | AddParam(params[0]); |
| 3425 | if (params[2] != 0) // 2.51+ & 3.0b3+ | 3498 | if (params[2] != 0) // 2.51+ & 3.0b3+ |
| @@ -3427,6 +3500,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) | |||
| 3427 | SmallSpaceComment(); | 3500 | SmallSpaceComment(); |
| 3428 | s += "CreateRestrictedDirectory"; | 3501 | s += "CreateRestrictedDirectory"; |
| 3429 | } | 3502 | } |
| 3503 | } | ||
| 3430 | #endif | 3504 | #endif |
| 3431 | 3505 | ||
| 3432 | break; | 3506 | break; |
| @@ -5242,7 +5316,7 @@ HRESULT CInArchive::Parse() | |||
| 5242 | } | 5316 | } |
| 5243 | } | 5317 | } |
| 5244 | 5318 | ||
| 5245 | if (bhEntries.Num > (1 << 25)) | 5319 | if (bhEntries.Num > (1 << 24)) |
| 5246 | return S_FALSE; | 5320 | return S_FALSE; |
| 5247 | if (bhEntries.Num * kCmdSize > _size - bhEntries.Offset) | 5321 | if (bhEntries.Num * kCmdSize > _size - bhEntries.Offset) |
| 5248 | return S_FALSE; | 5322 | return S_FALSE; |
| @@ -5495,7 +5569,12 @@ HRESULT CInArchive::Parse() | |||
| 5495 | return E_NOTIMPL; // maybe it's old NSIS archive() | 5569 | return E_NOTIMPL; // maybe it's old NSIS archive() |
| 5496 | 5570 | ||
| 5497 | if (langtable_size < 10) | 5571 | if (langtable_size < 10) |
| 5498 | return S_FALSE; | 5572 | { |
| 5573 | // return S_FALSE; | ||
| 5574 | } | ||
| 5575 | else | ||
| 5576 | { | ||
| 5577 | |||
| 5499 | if (bhLangTables.Num > (_size - bhLangTables.Offset) / langtable_size) | 5578 | if (bhLangTables.Num > (_size - bhLangTables.Offset) / langtable_size) |
| 5500 | return S_FALSE; | 5579 | return S_FALSE; |
| 5501 | 5580 | ||
| @@ -5610,6 +5689,7 @@ HRESULT CInArchive::Parse() | |||
| 5610 | AddLF(); | 5689 | AddLF(); |
| 5611 | } | 5690 | } |
| 5612 | ClearLangComment(); | 5691 | ClearLangComment(); |
| 5692 | } | ||
| 5613 | } | 5693 | } |
| 5614 | 5694 | ||
| 5615 | { | 5695 | { |
| @@ -6077,6 +6157,7 @@ HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *maxCheckStartPositio | |||
| 6077 | DataStreamOffset -= pos; | 6157 | DataStreamOffset -= pos; |
| 6078 | res = Open2(buf + kStartHeaderSize, bufSize - kStartHeaderSize); | 6158 | res = Open2(buf + kStartHeaderSize, bufSize - kStartHeaderSize); |
| 6079 | } | 6159 | } |
| 6160 | catch(CInArchiveException &) { res = S_FALSE; } | ||
| 6080 | catch(...) | 6161 | catch(...) |
| 6081 | { | 6162 | { |
| 6082 | _stream.Release(); | 6163 | _stream.Release(); |
| @@ -6112,6 +6193,10 @@ void CInArchive::Clear2() | |||
| 6112 | LogCmdIsEnabled = false; | 6193 | LogCmdIsEnabled = false; |
| 6113 | BadCmd = -1; | 6194 | BadCmd = -1; |
| 6114 | Is64Bit = false; | 6195 | Is64Bit = false; |
| 6196 | CREATEDIR_processing_WasStopped = false; | ||
| 6197 | FILENAME_processing_WasStopped = false; | ||
| 6198 | _memUsage_Dirs = 0; | ||
| 6199 | _memUsage_Files = 0; | ||
| 6115 | 6200 | ||
| 6116 | #ifdef NSIS_SCRIPT | 6201 | #ifdef NSIS_SCRIPT |
| 6117 | Name.Empty(); | 6202 | Name.Empty(); |
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 1f8c967..772f13f 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h | |||
| @@ -165,8 +165,11 @@ public: | |||
| 165 | #endif | 165 | #endif |
| 166 | CByteBuffer _data; | 166 | CByteBuffer _data; |
| 167 | CObjectVector<CItem> Items; | 167 | CObjectVector<CItem> Items; |
| 168 | bool IsArc; | ||
| 168 | bool IsUnicode; | 169 | bool IsUnicode; |
| 169 | bool Is64Bit; | 170 | bool Is64Bit; |
| 171 | bool CREATEDIR_processing_WasStopped; | ||
| 172 | bool FILENAME_processing_WasStopped; | ||
| 170 | private: | 173 | private: |
| 171 | UInt32 _stringsPos; // relative to _data | 174 | UInt32 _stringsPos; // relative to _data |
| 172 | UInt32 NumStringChars; | 175 | UInt32 NumStringChars; |
| @@ -217,13 +220,14 @@ private: | |||
| 217 | #endif | 220 | #endif |
| 218 | 221 | ||
| 219 | 222 | ||
| 223 | UInt32 _memUsage_Dirs; | ||
| 224 | UInt32 _memUsage_Files; | ||
| 225 | |||
| 220 | public: | 226 | public: |
| 221 | CMyComPtr<IInStream> _stream; // it's limited stream that contains only NSIS archive | 227 | CMyComPtr<IInStream> _stream; // it's limited stream that contains only NSIS archive |
| 222 | UInt64 StartOffset; // offset in original stream. | 228 | UInt64 StartOffset; // offset in original stream. |
| 223 | UInt64 DataStreamOffset; // = sizeof(FirstHeader) = offset of Header in _stream | 229 | UInt64 DataStreamOffset; // = sizeof(FirstHeader) = offset of Header in _stream |
| 224 | 230 | ||
| 225 | bool IsArc; | ||
| 226 | |||
| 227 | CDecoder Decoder; | 231 | CDecoder Decoder; |
| 228 | CByteBuffer ExeStub; | 232 | CByteBuffer ExeStub; |
| 229 | CFirstHeader FirstHeader; | 233 | CFirstHeader FirstHeader; |
| @@ -322,7 +326,7 @@ private: | |||
| 322 | void PrintNumComment(const char *name, UInt32 value); | 326 | void PrintNumComment(const char *name, UInt32 value); |
| 323 | void Add_QuStr(const AString &s); | 327 | void Add_QuStr(const AString &s); |
| 324 | void SpaceQuStr(const AString &s); | 328 | void SpaceQuStr(const AString &s); |
| 325 | bool CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands); | 329 | bool CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands) const; |
| 326 | 330 | ||
| 327 | #endif | 331 | #endif |
| 328 | 332 | ||
| @@ -330,7 +334,7 @@ private: | |||
| 330 | unsigned GetNumSupportedCommands() const; | 334 | unsigned GetNumSupportedCommands() const; |
| 331 | #endif | 335 | #endif |
| 332 | 336 | ||
| 333 | UInt32 GetCmd(UInt32 a); | 337 | UInt32 GetCmd(UInt32 a) const; |
| 334 | void FindBadCmd(const CBlockHeader &bh, const Byte *); | 338 | void FindBadCmd(const CBlockHeader &bh, const Byte *); |
| 335 | void DetectNsisType(const CBlockHeader &bh, const Byte *); | 339 | void DetectNsisType(const CBlockHeader &bh, const Byte *); |
| 336 | 340 | ||
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index 006f0ad..baf6a4d 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp | |||
| @@ -813,7 +813,8 @@ Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) | |||
| 813 | { | 813 | { |
| 814 | memset((Byte *)data, 0, size); | 814 | memset((Byte *)data, 0, size); |
| 815 | _virtPos += size; | 815 | _virtPos += size; |
| 816 | *processedSize = size; | 816 | if (processedSize) |
| 817 | *processedSize = size; | ||
| 817 | return S_OK; | 818 | return S_OK; |
| 818 | } | 819 | } |
| 819 | 820 | ||
| @@ -836,7 +837,8 @@ Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) | |||
| 836 | if (cur > size) | 837 | if (cur > size) |
| 837 | cur = size; | 838 | cur = size; |
| 838 | memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur); | 839 | memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur); |
| 839 | *processedSize = (UInt32)cur; | 840 | if (processedSize) |
| 841 | *processedSize = (UInt32)cur; | ||
| 840 | _virtPos += cur; | 842 | _virtPos += cur; |
| 841 | return S_OK; | 843 | return S_OK; |
| 842 | } | 844 | } |
| @@ -1311,7 +1313,7 @@ bool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 r | |||
| 1311 | // PRF(printf("\nusn = %d", usn)); | 1313 | // PRF(printf("\nusn = %d", usn)); |
| 1312 | for (UInt32 i = 1; i < numUsaItems; i++) | 1314 | for (UInt32 i = 1; i < numUsaItems; i++) |
| 1313 | { | 1315 | { |
| 1314 | void *pp = p + (i << sectorSizeLog) - 2; | 1316 | void *pp = p + ((size_t)i << sectorSizeLog) - 2; |
| 1315 | if (Get16(pp) != usn) | 1317 | if (Get16(pp) != usn) |
| 1316 | return false; | 1318 | return false; |
| 1317 | SetUi16(pp, Get16(p + usaOffset + i * 2)) | 1319 | SetUi16(pp, Get16(p + usaOffset + i * 2)) |
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index f5f66b0..7d78234 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp | |||
| @@ -1562,8 +1562,8 @@ struct CMy_VS_FIXEDFILEINFO | |||
| 1562 | UInt32 OS; | 1562 | UInt32 OS; |
| 1563 | UInt32 Type; | 1563 | UInt32 Type; |
| 1564 | UInt32 Subtype; | 1564 | UInt32 Subtype; |
| 1565 | UInt32 DateMS; | 1565 | // UInt32 DateMS; |
| 1566 | UInt32 DateLS; | 1566 | // UInt32 DateLS; |
| 1567 | 1567 | ||
| 1568 | bool Parse(const Byte *p); | 1568 | bool Parse(const Byte *p); |
| 1569 | void PrintToTextFile(CTextFile &f, CObjectVector<CStringKeyValue> &keys); | 1569 | void PrintToTextFile(CTextFile &f, CObjectVector<CStringKeyValue> &keys); |
| @@ -1583,8 +1583,8 @@ bool CMy_VS_FIXEDFILEINFO::Parse(const Byte *p) | |||
| 1583 | G32(0x20, OS); | 1583 | G32(0x20, OS); |
| 1584 | G32(0x24, Type); | 1584 | G32(0x24, Type); |
| 1585 | G32(0x28, Subtype); | 1585 | G32(0x28, Subtype); |
| 1586 | G32(0x2C, DateMS); | 1586 | // G32(0x2C, DateMS); |
| 1587 | G32(0x40, DateLS); | 1587 | // G32(0x30, DateLS); |
| 1588 | return true; | 1588 | return true; |
| 1589 | } | 1589 | } |
| 1590 | 1590 | ||
diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp index 5f9e1c3..b3b1cdb 100644 --- a/CPP/7zip/Archive/PpmdHandler.cpp +++ b/CPP/7zip/Archive/PpmdHandler.cpp | |||
| @@ -27,7 +27,7 @@ using namespace NWindows; | |||
| 27 | namespace NArchive { | 27 | namespace NArchive { |
| 28 | namespace NPpmd { | 28 | namespace NPpmd { |
| 29 | 29 | ||
| 30 | static const UInt32 kBufSize = (1 << 20); | 30 | static const size_t kBufSize = 1 << 20; |
| 31 | 31 | ||
| 32 | struct CBuf | 32 | struct CBuf |
| 33 | { | 33 | { |
| @@ -220,58 +220,74 @@ Z7_COM7F_IMF(CHandler::Close()) | |||
| 220 | 220 | ||
| 221 | struct CPpmdCpp | 221 | struct CPpmdCpp |
| 222 | { | 222 | { |
| 223 | unsigned Ver; | 223 | CPpmd7 *_ppmd7; |
| 224 | CPpmd7 _ppmd7; | 224 | CPpmd8 *_ppmd8; |
| 225 | CPpmd8 _ppmd8; | ||
| 226 | 225 | ||
| 227 | CPpmdCpp(unsigned version) | 226 | CPpmdCpp(unsigned version): |
| 227 | _ppmd7(NULL), | ||
| 228 | _ppmd8(NULL) | ||
| 228 | { | 229 | { |
| 229 | Ver = version; | 230 | if (version == 7) |
| 230 | Ppmd7_Construct(&_ppmd7); | 231 | { |
| 231 | Ppmd8_Construct(&_ppmd8); | 232 | _ppmd7 = new CPpmd7(); |
| 233 | Ppmd7_Construct(_ppmd7); | ||
| 234 | } | ||
| 235 | else | ||
| 236 | { | ||
| 237 | _ppmd8 = new CPpmd8(); | ||
| 238 | Ppmd8_Construct(_ppmd8); | ||
| 239 | } | ||
| 232 | } | 240 | } |
| 233 | 241 | ||
| 234 | ~CPpmdCpp() | 242 | ~CPpmdCpp() |
| 235 | { | 243 | { |
| 236 | Ppmd7_Free(&_ppmd7, &g_BigAlloc); | 244 | if (_ppmd7) |
| 237 | Ppmd8_Free(&_ppmd8, &g_BigAlloc); | 245 | { |
| 246 | Ppmd7_Free(_ppmd7, &g_BigAlloc); | ||
| 247 | delete _ppmd7; | ||
| 248 | } | ||
| 249 | if (_ppmd8) | ||
| 250 | { | ||
| 251 | Ppmd8_Free(_ppmd8, &g_BigAlloc); | ||
| 252 | delete _ppmd8; | ||
| 253 | } | ||
| 238 | } | 254 | } |
| 239 | 255 | ||
| 240 | bool Alloc(UInt32 memInMB) | 256 | BoolInt Alloc(UInt32 memInMB) |
| 241 | { | 257 | { |
| 242 | memInMB <<= 20; | 258 | memInMB <<= 20; |
| 243 | if (Ver == 7) | 259 | if (_ppmd7) |
| 244 | return Ppmd7_Alloc(&_ppmd7, memInMB, &g_BigAlloc) != 0; | 260 | return Ppmd7_Alloc(_ppmd7, memInMB, &g_BigAlloc); |
| 245 | return Ppmd8_Alloc(&_ppmd8, memInMB, &g_BigAlloc) != 0; | 261 | return Ppmd8_Alloc(_ppmd8, memInMB, &g_BigAlloc); |
| 246 | } | 262 | } |
| 247 | 263 | ||
| 248 | void Init(unsigned order, unsigned restor) | 264 | void Init(unsigned order, unsigned restor) |
| 249 | { | 265 | { |
| 250 | if (Ver == 7) | 266 | if (_ppmd7) |
| 251 | Ppmd7_Init(&_ppmd7, order); | 267 | Ppmd7_Init(_ppmd7, order); |
| 252 | else | 268 | else |
| 253 | Ppmd8_Init(&_ppmd8, order, restor); | 269 | Ppmd8_Init(_ppmd8, order, restor); |
| 254 | } | 270 | } |
| 255 | 271 | ||
| 256 | bool InitRc(CByteInBufWrap *inStream) | 272 | bool InitRc(CByteInBufWrap *inStream) |
| 257 | { | 273 | { |
| 258 | if (Ver == 7) | 274 | if (_ppmd7) |
| 259 | { | 275 | { |
| 260 | _ppmd7.rc.dec.Stream = &inStream->vt; | 276 | _ppmd7->rc.dec.Stream = &inStream->vt; |
| 261 | return (Ppmd7a_RangeDec_Init(&_ppmd7.rc.dec) != 0); | 277 | return (Ppmd7a_RangeDec_Init(&_ppmd7->rc.dec) != 0); |
| 262 | } | 278 | } |
| 263 | else | 279 | else |
| 264 | { | 280 | { |
| 265 | _ppmd8.Stream.In = &inStream->vt; | 281 | _ppmd8->Stream.In = &inStream->vt; |
| 266 | return Ppmd8_Init_RangeDec(&_ppmd8) != 0; | 282 | return Ppmd8_Init_RangeDec(_ppmd8) != 0; |
| 267 | } | 283 | } |
| 268 | } | 284 | } |
| 269 | 285 | ||
| 270 | bool IsFinishedOK() | 286 | bool IsFinishedOK() |
| 271 | { | 287 | { |
| 272 | if (Ver == 7) | 288 | if (_ppmd7) |
| 273 | return Ppmd7z_RangeDec_IsFinishedOK(&_ppmd7.rc.dec); | 289 | return Ppmd7z_RangeDec_IsFinishedOK(&_ppmd7->rc.dec); |
| 274 | return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8); | 290 | return Ppmd8_RangeDec_IsFinishedOK(_ppmd8); |
| 275 | } | 291 | } |
| 276 | }; | 292 | }; |
| 277 | 293 | ||
| @@ -311,14 +327,14 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 311 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; | 327 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; |
| 312 | lps->Init(extractCallback, true); | 328 | lps->Init(extractCallback, true); |
| 313 | 329 | ||
| 314 | CPpmdCpp ppmd(_item.Ver); | ||
| 315 | if (!ppmd.Alloc(_item.MemInMB)) | ||
| 316 | return E_OUTOFMEMORY; | ||
| 317 | |||
| 318 | opRes = NExtract::NOperationResult::kUnsupportedMethod; | 330 | opRes = NExtract::NOperationResult::kUnsupportedMethod; |
| 319 | 331 | ||
| 320 | if (_item.IsSupported()) | 332 | if (_item.IsSupported()) |
| 321 | { | 333 | { |
| 334 | CPpmdCpp ppmd(_item.Ver); | ||
| 335 | if (!ppmd.Alloc(_item.MemInMB)) | ||
| 336 | return E_OUTOFMEMORY; | ||
| 337 | |||
| 322 | opRes = NExtract::NOperationResult::kDataError; | 338 | opRes = NExtract::NOperationResult::kDataError; |
| 323 | 339 | ||
| 324 | ppmd.Init(_item.Order, _item.Restor); | 340 | ppmd.Init(_item.Order, _item.Restor); |
| @@ -336,11 +352,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 336 | int sym = 0; | 352 | int sym = 0; |
| 337 | 353 | ||
| 338 | Byte *buf = outBuf.Buf; | 354 | Byte *buf = outBuf.Buf; |
| 339 | if (ppmd.Ver == 7) | 355 | if (ppmd._ppmd7) |
| 340 | { | 356 | { |
| 341 | for (i = 0; i < kBufSize; i++) | 357 | for (i = 0; i < kBufSize; i++) |
| 342 | { | 358 | { |
| 343 | sym = Ppmd7a_DecodeSymbol(&ppmd._ppmd7); | 359 | sym = Ppmd7a_DecodeSymbol(ppmd._ppmd7); |
| 344 | if (inBuf.Extra || sym < 0) | 360 | if (inBuf.Extra || sym < 0) |
| 345 | break; | 361 | break; |
| 346 | buf[i] = (Byte)sym; | 362 | buf[i] = (Byte)sym; |
| @@ -350,7 +366,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 350 | { | 366 | { |
| 351 | for (i = 0; i < kBufSize; i++) | 367 | for (i = 0; i < kBufSize; i++) |
| 352 | { | 368 | { |
| 353 | sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8); | 369 | sym = Ppmd8_DecodeSymbol(ppmd._ppmd8); |
| 354 | if (inBuf.Extra || sym < 0) | 370 | if (inBuf.Extra || sym < 0) |
| 355 | break; | 371 | break; |
| 356 | buf[i] = (Byte)sym; | 372 | buf[i] = (Byte)sym; |
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index c15ff52..1e01134 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp | |||
| @@ -1673,7 +1673,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 1673 | case kpidExtension: | 1673 | case kpidExtension: |
| 1674 | if (_arcs.Size() == 1) | 1674 | if (_arcs.Size() == 1) |
| 1675 | { | 1675 | { |
| 1676 | if (arcInfo->IsVolume()) | 1676 | if (arcInfo && arcInfo->IsVolume()) |
| 1677 | { | 1677 | { |
| 1678 | AString s ("part"); | 1678 | AString s ("part"); |
| 1679 | UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1; | 1679 | UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1; |
| @@ -1809,14 +1809,14 @@ static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CProp | |||
| 1809 | size -= num; | 1809 | size -= num; |
| 1810 | } | 1810 | } |
| 1811 | 1811 | ||
| 1812 | if ((flags & (NTimeRecord::NFlags::kMTime << stampIndex)) == 0) | 1812 | if (((UInt32)flags & (NTimeRecord::NFlags::kMTime << stampIndex)) == 0) |
| 1813 | return; | 1813 | return; |
| 1814 | 1814 | ||
| 1815 | unsigned numStamps = 0; | 1815 | unsigned numStamps = 0; |
| 1816 | unsigned curStamp = 0; | 1816 | unsigned curStamp = 0; |
| 1817 | 1817 | ||
| 1818 | for (unsigned i = 0; i < 3; i++) | 1818 | for (unsigned i = 0; i < 3; i++) |
| 1819 | if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0) | 1819 | if (((UInt32)flags & (NTimeRecord::NFlags::kMTime << i)) != 0) |
| 1820 | { | 1820 | { |
| 1821 | if (i == stampIndex) | 1821 | if (i == stampIndex) |
| 1822 | curStamp = numStamps; | 1822 | curStamp = numStamps; |
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index 6c53847..4f181f4 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp | |||
| @@ -150,8 +150,7 @@ class CInArchive | |||
| 150 | CByteBuffer _comment; | 150 | CByteBuffer _comment; |
| 151 | CByteBuffer m_FileHeaderData; | 151 | CByteBuffer m_FileHeaderData; |
| 152 | NHeader::NBlock::CBlock m_BlockHeader; | 152 | NHeader::NBlock::CBlock m_BlockHeader; |
| 153 | NCrypto::NRar3::CDecoder *m_RarAESSpec; | 153 | CMyComPtr2<ICompressFilter, NCrypto::NRar3::CDecoder> m_RarAES; |
| 154 | CMyComPtr<ICompressFilter> m_RarAES; | ||
| 155 | CAlignedBuffer m_DecryptedDataAligned; | 154 | CAlignedBuffer m_DecryptedDataAligned; |
| 156 | UInt32 m_DecryptedDataSize; | 155 | UInt32 m_DecryptedDataSize; |
| 157 | bool m_CryptoMode; | 156 | bool m_CryptoMode; |
| @@ -532,12 +531,8 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass | |||
| 532 | error = k_ErrorType_DecryptionError; | 531 | error = k_ErrorType_DecryptionError; |
| 533 | return S_OK; // return S_FALSE; | 532 | return S_OK; // return S_FALSE; |
| 534 | } | 533 | } |
| 535 | if (!m_RarAES) | 534 | m_RarAES.Create_if_Empty(); |
| 536 | { | 535 | // m_RarAES->SetRar350Mode(ArcInfo.IsEncryptOld()); |
| 537 | m_RarAESSpec = new NCrypto::NRar3::CDecoder; | ||
| 538 | m_RarAES = m_RarAESSpec; | ||
| 539 | } | ||
| 540 | // m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld()); | ||
| 541 | 536 | ||
| 542 | { | 537 | { |
| 543 | // Salt | 538 | // Salt |
| @@ -546,7 +541,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass | |||
| 546 | if (!ReadBytesAndTestSize(salt, kSaltSize)) | 541 | if (!ReadBytesAndTestSize(salt, kSaltSize)) |
| 547 | return S_FALSE; | 542 | return S_FALSE; |
| 548 | m_Position += kSaltSize; | 543 | m_Position += kSaltSize; |
| 549 | RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize)) | 544 | RINOK(m_RarAES->SetDecoderProperties2(salt, kSaltSize)) |
| 550 | } | 545 | } |
| 551 | 546 | ||
| 552 | { | 547 | { |
| @@ -567,7 +562,7 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass | |||
| 567 | ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); | 562 | ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); |
| 568 | } | 563 | } |
| 569 | 564 | ||
| 570 | m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2); | 565 | m_RarAES->SetPassword((const Byte *)buffer, len * 2); |
| 571 | } | 566 | } |
| 572 | 567 | ||
| 573 | const UInt32 kDecryptedBufferSize = (1 << 12); | 568 | const UInt32 kDecryptedBufferSize = (1 << 12); |
| @@ -1477,22 +1472,17 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1477 | 1472 | ||
| 1478 | CObjectVector<CMethodItem> methodItems; | 1473 | CObjectVector<CMethodItem> methodItems; |
| 1479 | 1474 | ||
| 1480 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; | 1475 | CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder; |
| 1481 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | ||
| 1482 | 1476 | ||
| 1483 | CFilterCoder *filterStreamSpec = new CFilterCoder(false); | 1477 | CFilterCoder *filterStreamSpec = new CFilterCoder(false); |
| 1484 | CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec; | 1478 | CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec; |
| 1485 | 1479 | ||
| 1486 | NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL; | 1480 | CMyComPtr2<ICompressFilter, NCrypto::NRar2::CDecoder> rar20CryptoDecoder; |
| 1487 | CMyComPtr<ICompressFilter> rar20CryptoDecoder; | 1481 | CMyComPtr2<ICompressFilter, NCrypto::NRar3::CDecoder> rar3CryptoDecoder; |
| 1488 | NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL; | ||
| 1489 | CMyComPtr<ICompressFilter> rar3CryptoDecoder; | ||
| 1490 | 1482 | ||
| 1491 | CVolsInStream *volsInStreamSpec = NULL; | 1483 | CMyComPtr2<ISequentialInStream, CVolsInStream> volsInStream; |
| 1492 | CMyComPtr<ISequentialInStream> volsInStream; | ||
| 1493 | 1484 | ||
| 1494 | CLocalProgress *lps = new CLocalProgress; | 1485 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; |
| 1495 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
| 1496 | lps->Init(extractCallback, false); | 1486 | lps->Init(extractCallback, false); |
| 1497 | 1487 | ||
| 1498 | bool solidStart = true; | 1488 | bool solidStart = true; |
| @@ -1572,13 +1562,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1572 | outStreamSpec->Init(); | 1562 | outStreamSpec->Init(); |
| 1573 | realOutStream.Release(); | 1563 | realOutStream.Release(); |
| 1574 | 1564 | ||
| 1575 | if (!volsInStream) | 1565 | volsInStream.Create_if_Empty(); |
| 1576 | { | 1566 | volsInStream->Init(&_arcs, &_items, refItem); |
| 1577 | volsInStreamSpec = new CVolsInStream; | ||
| 1578 | volsInStream = volsInStreamSpec; | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | volsInStreamSpec->Init(&_arcs, &_items, refItem); | ||
| 1582 | 1567 | ||
| 1583 | UInt64 packSize = currentPackSize; | 1568 | UInt64 packSize = currentPackSize; |
| 1584 | 1569 | ||
| @@ -1593,27 +1578,19 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1593 | 1578 | ||
| 1594 | if (item.UnPackVersion >= 29) | 1579 | if (item.UnPackVersion >= 29) |
| 1595 | { | 1580 | { |
| 1596 | if (!rar3CryptoDecoder) | 1581 | rar3CryptoDecoder.Create_if_Empty(); |
| 1597 | { | 1582 | // rar3CryptoDecoder->SetRar350Mode(item.UnPackVersion < 36); |
| 1598 | rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder; | ||
| 1599 | rar3CryptoDecoder = rar3CryptoDecoderSpec; | ||
| 1600 | } | ||
| 1601 | // rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36); | ||
| 1602 | /* | 1583 | /* |
| 1603 | CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties; | 1584 | CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties; |
| 1604 | RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, | 1585 | RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, |
| 1605 | &cryptoProperties)); | 1586 | &cryptoProperties)); |
| 1606 | */ | 1587 | */ |
| 1607 | RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)) | 1588 | RINOK(rar3CryptoDecoder->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0)) |
| 1608 | filterStreamSpec->Filter = rar3CryptoDecoder; | 1589 | filterStreamSpec->Filter = rar3CryptoDecoder; |
| 1609 | } | 1590 | } |
| 1610 | else if (item.UnPackVersion >= 20) | 1591 | else if (item.UnPackVersion >= 20) |
| 1611 | { | 1592 | { |
| 1612 | if (!rar20CryptoDecoder) | 1593 | rar20CryptoDecoder.Create_if_Empty(); |
| 1613 | { | ||
| 1614 | rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder; | ||
| 1615 | rar20CryptoDecoder = rar20CryptoDecoderSpec; | ||
| 1616 | } | ||
| 1617 | filterStreamSpec->Filter = rar20CryptoDecoder; | 1594 | filterStreamSpec->Filter = rar20CryptoDecoder; |
| 1618 | } | 1595 | } |
| 1619 | else | 1596 | else |
| @@ -1654,7 +1631,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1654 | ((Byte *)buffer)[k * 2] = (Byte)c; | 1631 | ((Byte *)buffer)[k * 2] = (Byte)c; |
| 1655 | ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8); | 1632 | ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8); |
| 1656 | } | 1633 | } |
| 1657 | rar3CryptoDecoderSpec->SetPassword((const Byte *)buffer, len * 2); | 1634 | rar3CryptoDecoder->SetPassword((const Byte *)buffer, len * 2); |
| 1658 | } | 1635 | } |
| 1659 | else | 1636 | else |
| 1660 | { | 1637 | { |
| @@ -1667,7 +1644,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1667 | unicode.DeleteFrom(kPasswordLen_MAX); | 1644 | unicode.DeleteFrom(kPasswordLen_MAX); |
| 1668 | UnicodeStringToMultiByte2(oemPassword, unicode, CP_OEMCP); | 1645 | UnicodeStringToMultiByte2(oemPassword, unicode, CP_OEMCP); |
| 1669 | } | 1646 | } |
| 1670 | rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()); | 1647 | rar20CryptoDecoder->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len()); |
| 1671 | } | 1648 | } |
| 1672 | } | 1649 | } |
| 1673 | /* | 1650 | /* |
| @@ -1757,7 +1734,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1757 | continue; | 1734 | continue; |
| 1758 | } | 1735 | } |
| 1759 | 1736 | ||
| 1760 | HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &outSize, progress); | 1737 | HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &outSize, lps); |
| 1761 | 1738 | ||
| 1762 | if (item.IsEncrypted()) | 1739 | if (item.IsEncrypted()) |
| 1763 | filterStreamSpec->ReleaseInStream(); | 1740 | filterStreamSpec->ReleaseInStream(); |
| @@ -1765,7 +1742,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1765 | if (outSize == (UInt64)(Int64)-1) | 1742 | if (outSize == (UInt64)(Int64)-1) |
| 1766 | currentUnPackSize = outStreamSpec->GetSize(); | 1743 | currentUnPackSize = outStreamSpec->GetSize(); |
| 1767 | 1744 | ||
| 1768 | int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ? | 1745 | int opRes = (volsInStream->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ? |
| 1769 | NExtract::NOperationResult::kOK: | 1746 | NExtract::NOperationResult::kOK: |
| 1770 | NExtract::NOperationResult::kCRCError; | 1747 | NExtract::NOperationResult::kCRCError; |
| 1771 | outStream.Release(); | 1748 | outStream.Release(); |
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index 83cb1cf..e841879 100644 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp | |||
| @@ -1634,11 +1634,13 @@ HRESULT CHandler::Open2(IInStream *inStream) | |||
| 1634 | RINOK(Seek2(offset)) | 1634 | RINOK(Seek2(offset)) |
| 1635 | RINOK(ReadMetadataBlock2()) | 1635 | RINOK(ReadMetadataBlock2()) |
| 1636 | const UInt32 unpackSize = (UInt32)_dynOutStream->GetSize(); | 1636 | const UInt32 unpackSize = (UInt32)_dynOutStream->GetSize(); |
| 1637 | if (unpackSize != kMetadataBlockSize) | 1637 | UInt32 remSize = (_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1); |
| 1638 | if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1))) | 1638 | if (remSize == 0 || i != numBlocks - 1) |
| 1639 | return S_FALSE; | 1639 | remSize = kMetadataBlockSize; |
| 1640 | if (unpackSize != remSize) | ||
| 1641 | return S_FALSE; | ||
| 1640 | const Byte *buf = _dynOutStream->GetBuffer(); | 1642 | const Byte *buf = _dynOutStream->GetBuffer(); |
| 1641 | for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;) | 1643 | for (UInt32 j = 0; j < unpackSize;) |
| 1642 | { | 1644 | { |
| 1643 | CFrag frag; | 1645 | CFrag frag; |
| 1644 | if (bigFrag) | 1646 | if (bigFrag) |
| @@ -1723,8 +1725,9 @@ HRESULT CHandler::Open2(IInStream *inStream) | |||
| 1723 | // RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize)); | 1725 | // RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize)); |
| 1724 | RINOK(ReadMetadataBlock2()) | 1726 | RINOK(ReadMetadataBlock2()) |
| 1725 | const size_t unpackSize = _dynOutStream->GetSize(); | 1727 | const size_t unpackSize = _dynOutStream->GetSize(); |
| 1726 | const UInt32 remSize = (i == numBlocks - 1) ? | 1728 | UInt32 remSize = size & (kMetadataBlockSize - 1); |
| 1727 | (size & (kMetadataBlockSize - 1)) : kMetadataBlockSize; | 1729 | if (remSize == 0 || i != numBlocks - 1) |
| 1730 | remSize = kMetadataBlockSize; | ||
| 1728 | if (unpackSize != remSize) | 1731 | if (unpackSize != remSize) |
| 1729 | return S_FALSE; | 1732 | return S_FALSE; |
| 1730 | memcpy(_uids + kMetadataBlockSize * i, _dynOutStream->GetBuffer(), remSize); | 1733 | memcpy(_uids + kMetadataBlockSize * i, _dynOutStream->GetBuffer(), remSize); |
| @@ -2171,8 +2174,8 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) | |||
| 2171 | if (compressed) | 2174 | if (compressed) |
| 2172 | { | 2175 | { |
| 2173 | _outStream->Init((Byte *)_cachedBlock, _h.BlockSize); | 2176 | _outStream->Init((Byte *)_cachedBlock, _h.BlockSize); |
| 2174 | bool outBufWasWritten; | 2177 | bool outBufWasWritten = false; |
| 2175 | UInt32 outBufWasWrittenSize; | 2178 | UInt32 outBufWasWrittenSize = 0; |
| 2176 | HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize); | 2179 | HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize); |
| 2177 | RINOK(res) | 2180 | RINOK(res) |
| 2178 | if (outBufWasWritten) | 2181 | if (outBufWasWritten) |
diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp index b143d9a..9586f7d 100644 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp | |||
| @@ -412,6 +412,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 412 | if (_item.IsZlib()) | 412 | if (_item.IsZlib()) |
| 413 | { | 413 | { |
| 414 | _packSizeDefined = true; | 414 | _packSizeDefined = true; |
| 415 | if (!_decoderZlibSpec) | ||
| 416 | return E_FAIL; | ||
| 415 | _packSize = _decoderZlibSpec->GetInputProcessedSize(); | 417 | _packSize = _decoderZlibSpec->GetInputProcessedSize(); |
| 416 | opRes = NExtract::NOperationResult::kOK; | 418 | opRes = NExtract::NOperationResult::kOK; |
| 417 | } | 419 | } |
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index e5332b5..c8ea56e 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp | |||
| @@ -859,8 +859,10 @@ HRESULT CInArchive::Open2() | |||
| 859 | } | 859 | } |
| 860 | } | 860 | } |
| 861 | } | 861 | } |
| 862 | 862 | { | |
| 863 | PhySize = (UInt32)(256 + 1) << SecLogSize; | 863 | const UInt32 temp = (UInt32)(256 + 1) << SecLogSize; |
| 864 | PhySize = temp; | ||
| 865 | } | ||
| 864 | IsArc = true; | 866 | IsArc = true; |
| 865 | 867 | ||
| 866 | // UDF 2.2.3 AnchorVolumeDescriptorPointer | 868 | // UDF 2.2.3 AnchorVolumeDescriptorPointer |
diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp index 2fef079..8101c4c 100644 --- a/CPP/7zip/Archive/VhdHandler.cpp +++ b/CPP/7zip/Archive/VhdHandler.cpp | |||
| @@ -157,10 +157,11 @@ struct CDynHeader | |||
| 157 | CParentLocatorEntry ParentLocators[8]; | 157 | CParentLocatorEntry ParentLocators[8]; |
| 158 | 158 | ||
| 159 | bool Parse(const Byte *p); | 159 | bool Parse(const Byte *p); |
| 160 | UInt32 NumBitMapSectors() const | 160 | UInt32 NumBitMapBytes() const |
| 161 | { | 161 | { |
| 162 | UInt32 numSectorsInBlock = (1 << (BlockSizeLog - kSectorSize_Log)); | 162 | const UInt32 numSectorsInBlock = (UInt32)1 << (BlockSizeLog - kSectorSize_Log); |
| 163 | return (numSectorsInBlock + kSectorSize * 8 - 1) / (kSectorSize * 8); | 163 | const UInt32 NumBitMapSectors = (numSectorsInBlock + kSectorSize * 8 - 1) / (kSectorSize * 8); |
| 164 | return NumBitMapSectors << kSectorSize_Log; | ||
| 164 | } | 165 | } |
| 165 | void Clear() | 166 | void Clear() |
| 166 | { | 167 | { |
| @@ -325,7 +326,7 @@ HRESULT CHandler::InitAndSeek() | |||
| 325 | } | 326 | } |
| 326 | _virtPos = _posInArc = 0; | 327 | _virtPos = _posInArc = 0; |
| 327 | BitMapTag = kUnusedBlock; | 328 | BitMapTag = kUnusedBlock; |
| 328 | BitMap.Alloc(Dyn.NumBitMapSectors() << kSectorSize_Log); | 329 | BitMap.Alloc(Dyn.NumBitMapBytes()); |
| 329 | return Seek2(0); | 330 | return Seek2(0); |
| 330 | } | 331 | } |
| 331 | 332 | ||
| @@ -463,7 +464,7 @@ HRESULT CHandler::Open3() | |||
| 463 | 464 | ||
| 464 | Bat.ClearAndReserve(Dyn.NumBlocks); | 465 | Bat.ClearAndReserve(Dyn.NumBlocks); |
| 465 | 466 | ||
| 466 | UInt32 bitmapSize = Dyn.NumBitMapSectors() << kSectorSize_Log; | 467 | const UInt32 bitmapSize = Dyn.NumBitMapBytes(); |
| 467 | 468 | ||
| 468 | while ((UInt32)Bat.Size() < Dyn.NumBlocks) | 469 | while ((UInt32)Bat.Size() < Dyn.NumBlocks) |
| 469 | { | 470 | { |
diff --git a/CPP/7zip/Archive/VhdxHandler.cpp b/CPP/7zip/Archive/VhdxHandler.cpp index ca450e5..64e6273 100644 --- a/CPP/7zip/Archive/VhdxHandler.cpp +++ b/CPP/7zip/Archive/VhdxHandler.cpp | |||
| @@ -1170,6 +1170,7 @@ HRESULT CHandler::Open3() | |||
| 1170 | 1170 | ||
| 1171 | HeadersSize = (UInt32)1 << 20; | 1171 | HeadersSize = (UInt32)1 << 20; |
| 1172 | CHeader headers[2]; | 1172 | CHeader headers[2]; |
| 1173 | Z7_memset_0_ARRAY(headers); | ||
| 1173 | { | 1174 | { |
| 1174 | Byte header[kHeader2Size]; | 1175 | Byte header[kHeader2Size]; |
| 1175 | for (unsigned i = 0; i < 2; i++) | 1176 | for (unsigned i = 0; i < 2; i++) |
| @@ -1224,6 +1225,7 @@ HRESULT CHandler::Open3() | |||
| 1224 | } | 1225 | } |
| 1225 | } | 1226 | } |
| 1226 | CRegion regions[2]; | 1227 | CRegion regions[2]; |
| 1228 | Z7_memset_0_ARRAY(regions); | ||
| 1227 | int correctRegionIndex = -1; | 1229 | int correctRegionIndex = -1; |
| 1228 | 1230 | ||
| 1229 | { | 1231 | { |
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index cc24697..d08e060 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp | |||
| @@ -164,15 +164,12 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 164 | 164 | ||
| 165 | case kpidUnpackVer: | 165 | case kpidUnpackVer: |
| 166 | { | 166 | { |
| 167 | UInt32 ver1 = _version >> 16; | ||
| 168 | UInt32 ver2 = (_version >> 8) & 0xFF; | ||
| 169 | UInt32 ver3 = (_version) & 0xFF; | ||
| 170 | |||
| 171 | AString res; | 167 | AString res; |
| 172 | res.Add_UInt32(ver1); | 168 | res.Add_UInt32(_version >> 16); |
| 173 | res.Add_Dot(); | 169 | res.Add_Dot(); |
| 174 | res.Add_UInt32(ver2); | 170 | res.Add_UInt32((_version >> 8) & 0xFF); |
| 175 | if (ver3 != 0) | 171 | const UInt32 ver3 = _version & 0xFF; |
| 172 | if (ver3) | ||
| 176 | { | 173 | { |
| 177 | res.Add_Dot(); | 174 | res.Add_Dot(); |
| 178 | res.Add_UInt32(ver3); | 175 | res.Add_UInt32(ver3); |
| @@ -182,27 +179,33 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 182 | } | 179 | } |
| 183 | 180 | ||
| 184 | case kpidIsVolume: | 181 | case kpidIsVolume: |
| 185 | if (_xmls.Size() > 0) | 182 | if (!_xmls.IsEmpty()) |
| 186 | { | 183 | { |
| 187 | UInt16 volIndex = _xmls[0].VolIndex; | 184 | const unsigned volIndex = _xmls[0].VolIndex; |
| 188 | if (volIndex < _volumes.Size()) | 185 | if (volIndex < _volumes.Size()) |
| 189 | prop = (_volumes[volIndex].Header.NumParts > 1); | 186 | prop = (_volumes[volIndex].Header.NumParts > 1); |
| 190 | } | 187 | } |
| 191 | break; | 188 | break; |
| 192 | case kpidVolume: | 189 | case kpidVolume: |
| 193 | if (_xmls.Size() > 0) | 190 | if (!_xmls.IsEmpty()) |
| 194 | { | 191 | { |
| 195 | UInt16 volIndex = _xmls[0].VolIndex; | 192 | const unsigned volIndex = _xmls[0].VolIndex; |
| 196 | if (volIndex < _volumes.Size()) | 193 | if (volIndex < _volumes.Size()) |
| 197 | prop = (UInt32)_volumes[volIndex].Header.PartNumber; | 194 | prop = (UInt32)_volumes[volIndex].Header.PartNumber; |
| 198 | } | 195 | } |
| 199 | break; | 196 | break; |
| 200 | case kpidNumVolumes: if (_volumes.Size() > 0) prop = (UInt32)(_volumes.Size() - 1); break; | 197 | case kpidNumVolumes: |
| 198 | { | ||
| 199 | const unsigned n = _volumes.Size(); | ||
| 200 | if (n) | ||
| 201 | prop = (UInt32)(n - 1); | ||
| 202 | break; | ||
| 203 | } | ||
| 201 | 204 | ||
| 202 | case kpidClusterSize: | 205 | case kpidClusterSize: |
| 203 | if (_xmls.Size() > 0) | 206 | if (!_xmls.IsEmpty()) |
| 204 | { | 207 | { |
| 205 | UInt16 volIndex = _xmls[0].VolIndex; | 208 | const unsigned volIndex = _xmls[0].VolIndex; |
| 206 | if (volIndex < _volumes.Size()) | 209 | if (volIndex < _volumes.Size()) |
| 207 | { | 210 | { |
| 208 | const CHeader &h = _volumes[volIndex].Header; | 211 | const CHeader &h = _volumes[volIndex].Header; |
| @@ -318,7 +321,8 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 318 | { | 321 | { |
| 319 | UInt32 flags = 0; | 322 | UInt32 flags = 0; |
| 320 | if (!_isArc) flags |= kpv_ErrorFlags_IsNotArc; | 323 | if (!_isArc) flags |= kpv_ErrorFlags_IsNotArc; |
| 321 | if (_db.HeadersError) flags |= kpv_ErrorFlags_HeadersError; | 324 | if (_db.HeadersError || _volError || _error_in_PartNumber) |
| 325 | flags |= kpv_ErrorFlags_HeadersError; | ||
| 322 | if (_unsupported) flags |= kpv_ErrorFlags_UnsupportedMethod; | 326 | if (_unsupported) flags |= kpv_ErrorFlags_UnsupportedMethod; |
| 323 | prop = flags; | 327 | prop = flags; |
| 324 | break; | 328 | break; |
| @@ -364,19 +368,14 @@ static void MethodToProp(int method, int chunksSizeBits, NCOM::CPropVariant &pro | |||
| 364 | if (method >= 0) | 368 | if (method >= 0) |
| 365 | { | 369 | { |
| 366 | char temp[32]; | 370 | char temp[32]; |
| 367 | 371 | char *dest = ((unsigned)method < Z7_ARRAY_SIZE(k_Methods)) ? | |
| 368 | if ((unsigned)method < Z7_ARRAY_SIZE(k_Methods)) | 372 | MyStpCpy(temp, k_Methods[(unsigned)method]) : |
| 369 | MyStringCopy(temp, k_Methods[(unsigned)method]); | 373 | ConvertUInt32ToString((UInt32)(unsigned)method, temp); |
| 370 | else | ||
| 371 | ConvertUInt32ToString((UInt32)(unsigned)method, temp); | ||
| 372 | |||
| 373 | if (chunksSizeBits >= 0) | 374 | if (chunksSizeBits >= 0) |
| 374 | { | 375 | { |
| 375 | size_t pos = strlen(temp); | 376 | *dest++ = ':'; |
| 376 | temp[pos++] = ':'; | 377 | ConvertUInt32ToString((unsigned)chunksSizeBits, dest); |
| 377 | ConvertUInt32ToString((unsigned)chunksSizeBits, temp + pos); | ||
| 378 | } | 378 | } |
| 379 | |||
| 380 | prop = temp; | 379 | prop = temp; |
| 381 | } | 380 | } |
| 382 | } | 381 | } |
| @@ -389,14 +388,15 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 389 | 388 | ||
| 390 | if (index < _db.SortedItems.Size()) | 389 | if (index < _db.SortedItems.Size()) |
| 391 | { | 390 | { |
| 392 | unsigned realIndex = _db.SortedItems[index]; | 391 | const unsigned realIndex = _db.SortedItems[index]; |
| 393 | const CItem &item = _db.Items[realIndex]; | 392 | const CItem &item = _db.Items[realIndex]; |
| 394 | const CStreamInfo *si = NULL; | 393 | const CStreamInfo *si = NULL; |
| 395 | const CVolume *vol = NULL; | 394 | const CVolume *vol = NULL; |
| 396 | if (item.StreamIndex >= 0) | 395 | if (item.StreamIndex >= 0) |
| 397 | { | 396 | { |
| 398 | si = &_db.DataStreams[item.StreamIndex]; | 397 | si = &_db.DataStreams[item.StreamIndex]; |
| 399 | vol = &_volumes[si->PartNumber]; | 398 | if (si->PartNumber < _volumes.Size()) |
| 399 | vol = &_volumes[si->PartNumber]; | ||
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | const CItem *mainItem = &item; | 402 | const CItem *mainItem = &item; |
| @@ -501,7 +501,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 501 | case kpidIsAltStream: prop = item.IsAltStream; break; | 501 | case kpidIsAltStream: prop = item.IsAltStream; break; |
| 502 | case kpidNumAltStreams: | 502 | case kpidNumAltStreams: |
| 503 | { | 503 | { |
| 504 | if (!item.IsAltStream && mainItem->HasMetadata()) | 504 | if (!item.IsAltStream && metadata /* mainItem->HasMetadata() */) |
| 505 | { | 505 | { |
| 506 | UInt32 dirRecordSize = _db.IsOldVersion ? kDirRecordSizeOld : kDirRecordSize; | 506 | UInt32 dirRecordSize = _db.IsOldVersion ? kDirRecordSizeOld : kDirRecordSize; |
| 507 | UInt32 numAltStreams = Get16(metadata + dirRecordSize - 6); | 507 | UInt32 numAltStreams = Get16(metadata + dirRecordSize - 6); |
| @@ -525,12 +525,12 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 525 | prop = (UInt32)Get32(metadata + 8); | 525 | prop = (UInt32)Get32(metadata + 8); |
| 526 | } | 526 | } |
| 527 | break; | 527 | break; |
| 528 | case kpidCTime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x18: 0x28), prop); break; | 528 | case kpidCTime: if (metadata /* mainItem->HasMetadata() */ ) GetFileTime(metadata + (_db.IsOldVersion ? 0x18: 0x28), prop); break; |
| 529 | case kpidATime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x20: 0x30), prop); break; | 529 | case kpidATime: if (metadata /* mainItem->HasMetadata() */ ) GetFileTime(metadata + (_db.IsOldVersion ? 0x20: 0x30), prop); break; |
| 530 | case kpidMTime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x28: 0x38), prop); break; | 530 | case kpidMTime: if (metadata /* mainItem->HasMetadata() */ ) GetFileTime(metadata + (_db.IsOldVersion ? 0x28: 0x38), prop); break; |
| 531 | 531 | ||
| 532 | case kpidINode: | 532 | case kpidINode: |
| 533 | if (mainItem->HasMetadata() && !_isOldVersion) | 533 | if (metadata /* mainItem->HasMetadata() */ && !_isOldVersion) |
| 534 | { | 534 | { |
| 535 | UInt32 attrib = (UInt32)Get32(metadata + 8); | 535 | UInt32 attrib = (UInt32)Get32(metadata + 8); |
| 536 | if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0) | 536 | if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0) |
| @@ -552,26 +552,26 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 552 | case kpidMethod: | 552 | case kpidMethod: |
| 553 | if (si) | 553 | if (si) |
| 554 | { | 554 | { |
| 555 | int method = -1; | ||
| 556 | int chunkSizeBits = -1; | ||
| 555 | const CResource &r = si->Resource; | 557 | const CResource &r = si->Resource; |
| 556 | if (r.IsSolid()) | 558 | if (r.IsSolid()) |
| 557 | { | 559 | { |
| 558 | if (r.SolidIndex >= 0) | 560 | if (r.SolidIndex >= 0) |
| 559 | { | 561 | { |
| 560 | CSolid &ss = _db.Solids[r.SolidIndex]; | 562 | const CSolid &ss = _db.Solids[r.SolidIndex]; |
| 561 | MethodToProp(ss.Method, (int)ss.ChunkSizeBits, prop); | 563 | method = ss.Method; |
| 564 | chunkSizeBits = (int)ss.ChunkSizeBits; | ||
| 562 | } | 565 | } |
| 563 | } | 566 | } |
| 564 | else | 567 | else if (!r.IsCompressed()) |
| 568 | method = 0; | ||
| 569 | else if (vol) | ||
| 565 | { | 570 | { |
| 566 | int method = 0; | 571 | method = (int)vol->Header.GetMethod(); |
| 567 | int chunkSizeBits = -1; | 572 | chunkSizeBits = (int)vol->Header.ChunkSizeBits; |
| 568 | if (r.IsCompressed()) | ||
| 569 | { | ||
| 570 | method = (int)vol->Header.GetMethod(); | ||
| 571 | chunkSizeBits = (int)vol->Header.ChunkSizeBits; | ||
| 572 | } | ||
| 573 | MethodToProp(method, chunkSizeBits, prop); | ||
| 574 | } | 573 | } |
| 574 | MethodToProp(method, chunkSizeBits, prop); | ||
| 575 | } | 575 | } |
| 576 | break; | 576 | break; |
| 577 | 577 | ||
| @@ -891,8 +891,14 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal | |||
| 891 | } | 891 | } |
| 892 | 892 | ||
| 893 | CHeader header; | 893 | CHeader header; |
| 894 | HRESULT res = NWim::ReadHeader(curStream, header, _phySize); | 894 | |
| 895 | 895 | _db.PhySize = 0; | |
| 896 | HRESULT res; | ||
| 897 | { | ||
| 898 | res = NWim::ReadHeader(curStream, header, _db.PhySize); | ||
| 899 | if (i == 1) | ||
| 900 | _phySize = _db.PhySize; | ||
| 901 | } | ||
| 896 | if (res != S_OK) | 902 | if (res != S_OK) |
| 897 | { | 903 | { |
| 898 | if (i != 1 && res == S_FALSE) | 904 | if (i != 1 && res == S_FALSE) |
| @@ -901,12 +907,20 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal | |||
| 901 | } | 907 | } |
| 902 | 908 | ||
| 903 | _isArc = true; | 909 | _isArc = true; |
| 904 | _bootIndex = header.BootIndex; | 910 | if (i == 1) |
| 905 | _version = header.Version; | 911 | { |
| 906 | _isOldVersion = header.IsOldVersion(); | 912 | _bootIndex = header.BootIndex; |
| 913 | _version = header.Version; | ||
| 914 | _isOldVersion = header.IsOldVersion(); | ||
| 915 | } | ||
| 916 | |||
| 907 | if (_firstVolumeIndex >= 0) | 917 | if (_firstVolumeIndex >= 0) |
| 908 | if (!header.AreFromOnArchive(_volumes[_firstVolumeIndex].Header)) | 918 | if (!header.AreFromOnArchive(_volumes[_firstVolumeIndex].Header)) |
| 909 | break; | 919 | break; |
| 920 | |||
| 921 | if (i != 1 && _isOldVersion != header.IsOldVersion()) | ||
| 922 | _volError = true; | ||
| 923 | |||
| 910 | if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream) | 924 | if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream) |
| 911 | break; | 925 | break; |
| 912 | CWimXml xml; | 926 | CWimXml xml; |
| @@ -924,17 +938,24 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal | |||
| 924 | return S_FALSE; | 938 | return S_FALSE; |
| 925 | } | 939 | } |
| 926 | 940 | ||
| 927 | UInt64 totalFiles = xml.GetTotalFilesAndDirs() + xml.Images.Size(); | 941 | UInt64 totalFiles = xml.GetTotalFilesAndDirs(); |
| 942 | if (totalFiles >= ((UInt32)1 << 30)) | ||
| 943 | totalFiles = 0; | ||
| 928 | totalFiles += 16 + xml.Images.Size() * 4; // we reserve some additional items | 944 | totalFiles += 16 + xml.Images.Size() * 4; // we reserve some additional items |
| 929 | if (totalFiles >= ((UInt32)1 << 30)) | 945 | if (totalFiles >= ((UInt32)1 << 30)) |
| 930 | totalFiles = 0; | 946 | totalFiles = 0; |
| 931 | res = _db.Open(curStream, header, (unsigned)totalFiles, callback); | 947 | res = _db.Open(curStream, header, (unsigned)totalFiles, callback); |
| 948 | if (i == 1) | ||
| 949 | _phySize = _db.PhySize; | ||
| 932 | } | 950 | } |
| 933 | 951 | ||
| 934 | if (res != S_OK) | 952 | if (res != S_OK) |
| 935 | { | 953 | { |
| 936 | if (i != 1 && res == S_FALSE) | 954 | if (i != 1 && res == S_FALSE) |
| 955 | { | ||
| 956 | _volError = true; | ||
| 937 | continue; | 957 | continue; |
| 958 | } | ||
| 938 | return res; | 959 | return res; |
| 939 | } | 960 | } |
| 940 | 961 | ||
| @@ -985,6 +1006,8 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal | |||
| 985 | 1006 | ||
| 986 | RINOK(_db.GenerateSortedItems(defaultImageIndex, showImageNumber)) | 1007 | RINOK(_db.GenerateSortedItems(defaultImageIndex, showImageNumber)) |
| 987 | RINOK(_db.ExtractReparseStreams(_volumes, callback)) | 1008 | RINOK(_db.ExtractReparseStreams(_volumes, callback)) |
| 1009 | if (!_db.Check_PartNumber_in_Items(_volumes.Size())) | ||
| 1010 | _error_in_PartNumber = true; | ||
| 988 | 1011 | ||
| 989 | /* | 1012 | /* |
| 990 | wchar_t sz[16]; | 1013 | wchar_t sz[16]; |
| @@ -1012,7 +1035,7 @@ Z7_COM7F_IMF(CHandler::Close()) | |||
| 1012 | _xmlInComments = false; | 1035 | _xmlInComments = false; |
| 1013 | _numXmlItems = 0; | 1036 | _numXmlItems = 0; |
| 1014 | _numIgnoreItems = 0; | 1037 | _numIgnoreItems = 0; |
| 1015 | _xmlError = false; | 1038 | ClearErrors(); |
| 1016 | _isArc = false; | 1039 | _isArc = false; |
| 1017 | _unsupported = false; | 1040 | _unsupported = false; |
| 1018 | return S_OK; | 1041 | return S_OK; |
| @@ -1127,7 +1150,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1127 | RINOK(extractCallback->PrepareOperation(askMode)) | 1150 | RINOK(extractCallback->PrepareOperation(askMode)) |
| 1128 | Int32 opRes = NExtract::NOperationResult::kOK; | 1151 | Int32 opRes = NExtract::NOperationResult::kOK; |
| 1129 | 1152 | ||
| 1130 | if (streamIndex != prevSuccessStreamIndex || realOutStream) | 1153 | if (si.PartNumber >= _volumes.Size()) |
| 1154 | opRes = NExtract::NOperationResult::kUnavailable; | ||
| 1155 | else if (streamIndex != prevSuccessStreamIndex || realOutStream) | ||
| 1131 | { | 1156 | { |
| 1132 | Byte digest[kHashSize]; | 1157 | Byte digest[kHashSize]; |
| 1133 | const CVolume &vol = _volumes[si.PartNumber]; | 1158 | const CVolume &vol = _volumes[si.PartNumber]; |
| @@ -1172,7 +1197,7 @@ CHandler::CHandler() | |||
| 1172 | { | 1197 | { |
| 1173 | _keepMode_ShowImageNumber = false; | 1198 | _keepMode_ShowImageNumber = false; |
| 1174 | InitDefaults(); | 1199 | InitDefaults(); |
| 1175 | _xmlError = false; | 1200 | ClearErrors(); |
| 1176 | } | 1201 | } |
| 1177 | 1202 | ||
| 1178 | Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) | 1203 | Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) |
diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h index 126d233..b477d8e 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.h +++ b/CPP/7zip/Archive/Wim/WimHandler.h | |||
| @@ -35,6 +35,8 @@ Z7_CLASS_IMP_CHandler_IInArchive_5( | |||
| 35 | bool _isOldVersion; | 35 | bool _isOldVersion; |
| 36 | bool _xmlInComments; | 36 | bool _xmlInComments; |
| 37 | 37 | ||
| 38 | bool _error_in_PartNumber; | ||
| 39 | bool _volError; | ||
| 38 | bool _xmlError; | 40 | bool _xmlError; |
| 39 | bool _isArc; | 41 | bool _isArc; |
| 40 | bool _unsupported; | 42 | bool _unsupported; |
| @@ -81,7 +83,18 @@ Z7_CLASS_IMP_CHandler_IInArchive_5( | |||
| 81 | return true; | 83 | return true; |
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | bool ThereIsError() const { return _xmlError || _db.ThereIsError(); } | 86 | void ClearErrors() |
| 87 | { | ||
| 88 | _error_in_PartNumber = false; | ||
| 89 | _volError = false; | ||
| 90 | _xmlError = false; | ||
| 91 | } | ||
| 92 | |||
| 93 | bool ThereIsError() const | ||
| 94 | { | ||
| 95 | return _error_in_PartNumber || _volError || _xmlError | ||
| 96 | || _db.ThereIsError(); | ||
| 97 | } | ||
| 85 | HRESULT GetSecurity(UInt32 realIndex, const void **data, UInt32 *dataSize, UInt32 *propType); | 98 | HRESULT GetSecurity(UInt32 realIndex, const void **data, UInt32 *dataSize, UInt32 *propType); |
| 86 | 99 | ||
| 87 | HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value); | 100 | HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value); |
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index 33fbe82..b2470e1 100644 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp | |||
| @@ -1094,6 +1094,7 @@ HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, unsigned numItems | |||
| 1094 | 1094 | ||
| 1095 | if (h.PartNumber != 1 || si.PartNumber != h.PartNumber) | 1095 | if (h.PartNumber != 1 || si.PartNumber != h.PartNumber) |
| 1096 | continue; | 1096 | continue; |
| 1097 | si.Resource.UpdatePhySize(PhySize); | ||
| 1097 | 1098 | ||
| 1098 | const unsigned userImage = Images.Size() + GetStartImageIndex(); | 1099 | const unsigned userImage = Images.Size() + GetStartImageIndex(); |
| 1099 | CImage &image = Images.AddNew(); | 1100 | CImage &image = Images.AddNew(); |
| @@ -1623,6 +1624,22 @@ static void IntVector_SetMinusOne_IfNeed(CIntVector &v, unsigned size) | |||
| 1623 | } | 1624 | } |
| 1624 | 1625 | ||
| 1625 | 1626 | ||
| 1627 | bool CDatabase::Check_PartNumber_in_Items(unsigned numVolumes) const | ||
| 1628 | { | ||
| 1629 | // maybe it's better to check all Items[] or all DataStreams[] items instead | ||
| 1630 | FOR_VECTOR(indexInSorted, SortedItems) | ||
| 1631 | { | ||
| 1632 | const unsigned itemIndex = SortedItems[indexInSorted]; | ||
| 1633 | const CItem &item = Items[itemIndex]; | ||
| 1634 | if (item.StreamIndex < 0) | ||
| 1635 | continue; | ||
| 1636 | const CStreamInfo &si = DataStreams[item.StreamIndex]; | ||
| 1637 | if (si.PartNumber >= numVolumes) | ||
| 1638 | return false; | ||
| 1639 | } | ||
| 1640 | return true; | ||
| 1641 | } | ||
| 1642 | |||
| 1626 | HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes, IArchiveOpenCallback *openCallback) | 1643 | HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes, IArchiveOpenCallback *openCallback) |
| 1627 | { | 1644 | { |
| 1628 | ItemToReparse.Clear(); | 1645 | ItemToReparse.Clear(); |
| @@ -1639,7 +1656,7 @@ HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes, | |||
| 1639 | FOR_VECTOR(indexInSorted, SortedItems) | 1656 | FOR_VECTOR(indexInSorted, SortedItems) |
| 1640 | { | 1657 | { |
| 1641 | // we use sorted items for faster access | 1658 | // we use sorted items for faster access |
| 1642 | unsigned itemIndex = SortedItems[indexInSorted]; | 1659 | const unsigned itemIndex = SortedItems[indexInSorted]; |
| 1643 | const CItem &item = Items[itemIndex]; | 1660 | const CItem &item = Items[itemIndex]; |
| 1644 | 1661 | ||
| 1645 | if (!item.HasMetadata() || item.IsAltStream) | 1662 | if (!item.HasMetadata() || item.IsAltStream) |
| @@ -1692,10 +1709,8 @@ HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes, | |||
| 1692 | } | 1709 | } |
| 1693 | else | 1710 | else |
| 1694 | { | 1711 | { |
| 1695 | /* | ||
| 1696 | if (si.PartNumber >= volumes.Size()) | 1712 | if (si.PartNumber >= volumes.Size()) |
| 1697 | continue; | 1713 | continue; |
| 1698 | */ | ||
| 1699 | const CVolume &vol = volumes[si.PartNumber]; | 1714 | const CVolume &vol = volumes[si.PartNumber]; |
| 1700 | /* | 1715 | /* |
| 1701 | if (!vol.Stream) | 1716 | if (!vol.Stream) |
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h index ae7cd6b..53a088b 100644 --- a/CPP/7zip/Archive/Wim/WimIn.h +++ b/CPP/7zip/Archive/Wim/WimIn.h | |||
| @@ -163,12 +163,16 @@ struct CResource | |||
| 163 | 163 | ||
| 164 | UInt64 GetEndLimit() const { return Offset + PackSize; } | 164 | UInt64 GetEndLimit() const { return Offset + PackSize; } |
| 165 | void Parse(const Byte *p); | 165 | void Parse(const Byte *p); |
| 166 | void ParseAndUpdatePhySize(const Byte *p, UInt64 &phySize) | 166 | void UpdatePhySize(UInt64 &phySize) const |
| 167 | { | 167 | { |
| 168 | Parse(p); | ||
| 169 | UInt64 v = GetEndLimit(); | 168 | UInt64 v = GetEndLimit(); |
| 170 | if (phySize < v) | 169 | if (phySize < v) |
| 171 | phySize = v; | 170 | phySize = v; |
| 171 | } | ||
| 172 | void ParseAndUpdatePhySize(const Byte *p, UInt64 &phySize) | ||
| 173 | { | ||
| 174 | Parse(p); | ||
| 175 | UpdatePhySize(phySize); | ||
| 172 | } | 176 | } |
| 173 | 177 | ||
| 174 | void WriteTo(Byte *p) const; | 178 | void WriteTo(Byte *p) const; |
| @@ -391,7 +395,13 @@ struct CImageInfo | |||
| 391 | 395 | ||
| 392 | int ItemIndexInXml; | 396 | int ItemIndexInXml; |
| 393 | 397 | ||
| 394 | UInt64 GetTotalFilesAndDirs() const { return DirCount + FileCount; } | 398 | UInt64 GetTotalFilesAndDirs() const |
| 399 | { | ||
| 400 | UInt64 v = DirCount + FileCount; | ||
| 401 | if (v < DirCount) | ||
| 402 | v = 0; | ||
| 403 | return v; | ||
| 404 | } | ||
| 395 | 405 | ||
| 396 | CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false), | 406 | CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false), |
| 397 | IndexDefined(false), ItemIndexInXml(-1) {} | 407 | IndexDefined(false), ItemIndexInXml(-1) {} |
| @@ -405,16 +415,21 @@ struct CWimXml | |||
| 405 | CXml Xml; | 415 | CXml Xml; |
| 406 | 416 | ||
| 407 | UInt16 VolIndex; | 417 | UInt16 VolIndex; |
| 418 | bool IsEncrypted; | ||
| 408 | CObjectVector<CImageInfo> Images; | 419 | CObjectVector<CImageInfo> Images; |
| 409 | 420 | ||
| 410 | UString FileName; | 421 | UString FileName; |
| 411 | bool IsEncrypted; | ||
| 412 | 422 | ||
| 413 | UInt64 GetTotalFilesAndDirs() const | 423 | UInt64 GetTotalFilesAndDirs() const |
| 414 | { | 424 | { |
| 415 | UInt64 sum = 0; | 425 | UInt64 sum = 0; |
| 416 | FOR_VECTOR (i, Images) | 426 | FOR_VECTOR (i, Images) |
| 417 | sum += Images[i].GetTotalFilesAndDirs(); | 427 | { |
| 428 | const UInt64 v = Images[i].GetTotalFilesAndDirs(); | ||
| 429 | sum += v; | ||
| 430 | if (sum < v) | ||
| 431 | return 0; | ||
| 432 | } | ||
| 418 | return sum; | 433 | return sum; |
| 419 | } | 434 | } |
| 420 | 435 | ||
| @@ -474,6 +489,7 @@ public: | |||
| 474 | int ExludedItem; // -1 : if there are no exclude items | 489 | int ExludedItem; // -1 : if there are no exclude items |
| 475 | CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives | 490 | CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives |
| 476 | 491 | ||
| 492 | UInt64 PhySize; | ||
| 477 | bool ThereIsError() const { return RefCountError || HeadersError; } | 493 | bool ThereIsError() const { return RefCountError || HeadersError; } |
| 478 | 494 | ||
| 479 | unsigned GetNumUserItemsInImage(unsigned imageIndex) const | 495 | unsigned GetNumUserItemsInImage(unsigned imageIndex) const |
| @@ -530,6 +546,7 @@ public: | |||
| 530 | 546 | ||
| 531 | void Clear() | 547 | void Clear() |
| 532 | { | 548 | { |
| 549 | PhySize = 0; | ||
| 533 | DataStreams.Clear(); | 550 | DataStreams.Clear(); |
| 534 | MetaStreams.Clear(); | 551 | MetaStreams.Clear(); |
| 535 | Solids.Clear(); | 552 | Solids.Clear(); |
| @@ -572,6 +589,7 @@ public: | |||
| 572 | */ | 589 | */ |
| 573 | HRESULT GenerateSortedItems(int imageIndex, bool showImageNumber); | 590 | HRESULT GenerateSortedItems(int imageIndex, bool showImageNumber); |
| 574 | 591 | ||
| 592 | bool Check_PartNumber_in_Items(unsigned numVolumes) const; | ||
| 575 | HRESULT ExtractReparseStreams(const CObjectVector<CVolume> &volumes, IArchiveOpenCallback *openCallback); | 593 | HRESULT ExtractReparseStreams(const CObjectVector<CVolume> &volumes, IArchiveOpenCallback *openCallback); |
| 576 | }; | 594 | }; |
| 577 | 595 | ||
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp index 43d68c7..ba61710 100644 --- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp | |||
| @@ -410,7 +410,7 @@ HRESULT CAddCommon::Compress( | |||
| 410 | } | 410 | } |
| 411 | } | 411 | } |
| 412 | } | 412 | } |
| 413 | if (method == NCompressionMethod::kLZMA) | 413 | if (method == NCompressionMethod::kLZMA && _lzmaEncoder) |
| 414 | _isLzmaEos = _lzmaEncoder->Encoder->IsWriteEndMark(); | 414 | _isLzmaEos = _lzmaEncoder->Encoder->IsWriteEndMark(); |
| 415 | } | 415 | } |
| 416 | 416 | ||
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 9d77e87..3bcbe22 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp | |||
| @@ -2393,10 +2393,7 @@ HRESULT CInArchive::ReadVols() | |||
| 2393 | { | 2393 | { |
| 2394 | // get volumes required for cd. | 2394 | // get volumes required for cd. |
| 2395 | RINOK(ReadVols2(volCallback, (unsigned)cdDisk, zipDisk, zipDisk, 0, numMissingVols)) | 2395 | RINOK(ReadVols2(volCallback, (unsigned)cdDisk, zipDisk, zipDisk, 0, numMissingVols)) |
| 2396 | if (numMissingVols != 0) | 2396 | // if (numMissingVols) cdOK = false; |
| 2397 | { | ||
| 2398 | // cdOK = false; | ||
| 2399 | } | ||
| 2400 | } | 2397 | } |
| 2401 | } | 2398 | } |
| 2402 | else if (res != S_FALSE) | 2399 | else if (res != S_FALSE) |
diff --git a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp index e43e8b1..28ac2ea 100644 --- a/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp +++ b/CPP/7zip/Bundles/LzmaCon/LzmaAlone.cpp | |||
| @@ -534,11 +534,9 @@ static int main2(int numArgs, const char *args[]) | |||
| 534 | dict = (UInt32)1 << kDictSizeLog; | 534 | dict = (UInt32)1 << kDictSizeLog; |
| 535 | if (fileSizeDefined) | 535 | if (fileSizeDefined) |
| 536 | { | 536 | { |
| 537 | unsigned i; | 537 | for (dict = 1 << 16; dict < ((UInt32)1 << kDictSizeLog); dict <<= 1) |
| 538 | for (i = 16; i < kDictSizeLog; i++) | 538 | if (dict >= fileSize) |
| 539 | if ((UInt32)((UInt32)1 << i) >= fileSize) | ||
| 540 | break; | 539 | break; |
| 541 | dict = (UInt32)1 << i; | ||
| 542 | } | 540 | } |
| 543 | } | 541 | } |
| 544 | 542 | ||
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index b7e4fbe..37c1f49 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp | |||
| @@ -882,7 +882,7 @@ Z7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro | |||
| 882 | 882 | ||
| 883 | UInt32 realProcessedSize; | 883 | UInt32 realProcessedSize; |
| 884 | BOOL res = TRUE; | 884 | BOOL res = TRUE; |
| 885 | if (size > 0) | 885 | if (size) |
| 886 | { | 886 | { |
| 887 | // Seems that Windows doesn't like big amounts writing to stdout. | 887 | // Seems that Windows doesn't like big amounts writing to stdout. |
| 888 | // So we limit portions by 32KB. | 888 | // So we limit portions by 32KB. |
| @@ -892,8 +892,8 @@ Z7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro | |||
| 892 | res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), | 892 | res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), |
| 893 | data, sizeTemp, (DWORD *)&realProcessedSize, NULL); | 893 | data, sizeTemp, (DWORD *)&realProcessedSize, NULL); |
| 894 | _size += realProcessedSize; | 894 | _size += realProcessedSize; |
| 895 | size -= realProcessedSize; | 895 | // size -= realProcessedSize; |
| 896 | data = (const void *)((const Byte *)data + realProcessedSize); | 896 | // data = (const void *)((const Byte *)data + realProcessedSize); |
| 897 | if (processedSize) | 897 | if (processedSize) |
| 898 | *processedSize += realProcessedSize; | 898 | *processedSize += realProcessedSize; |
| 899 | } | 899 | } |
diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index 664cd0c..e2b536d 100644 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp | |||
| @@ -105,18 +105,20 @@ Z7_COM7F_IMF(CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi | |||
| 105 | const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog); | 105 | const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog); |
| 106 | const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); | 106 | const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1); |
| 107 | const UInt32 phyBlock = Vector[virtBlock]; | 107 | const UInt32 phyBlock = Vector[virtBlock]; |
| 108 | 108 | const UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock; | |
| 109 | UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock; | ||
| 110 | if (newPos != _physPos) | 109 | if (newPos != _physPos) |
| 111 | { | 110 | { |
| 112 | _physPos = newPos; | 111 | _physPos = newPos; |
| 113 | RINOK(SeekToPhys()) | 112 | RINOK(SeekToPhys()) |
| 114 | } | 113 | } |
| 115 | |||
| 116 | _curRem = blockSize - offsetInBlock; | 114 | _curRem = blockSize - offsetInBlock; |
| 117 | 115 | for (unsigned i = 1; i < 64 | |
| 118 | for (unsigned i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) | 116 | && _curRem < size |
| 119 | _curRem += (UInt32)1 << BlockSizeLog; | 117 | && _curRem < ((UInt32)1 << 31) - blockSize |
| 118 | && virtBlock + i < Vector.Size() | ||
| 119 | && phyBlock + i == Vector[virtBlock + i] | ||
| 120 | ; i++) | ||
| 121 | _curRem += blockSize; | ||
| 120 | } | 122 | } |
| 121 | 123 | ||
| 122 | if (size > _curRem) | 124 | if (size > _curRem) |
diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h index 69fcdcd..328efb3 100644 --- a/CPP/7zip/Common/LimitedStreams.h +++ b/CPP/7zip/Common/LimitedStreams.h | |||
| @@ -14,18 +14,18 @@ Z7_CLASS_IMP_COM_1( | |||
| 14 | CLimitedSequentialInStream | 14 | CLimitedSequentialInStream |
| 15 | , ISequentialInStream | 15 | , ISequentialInStream |
| 16 | ) | 16 | ) |
| 17 | bool _wasFinished; | ||
| 17 | CMyComPtr<ISequentialInStream> _stream; | 18 | CMyComPtr<ISequentialInStream> _stream; |
| 18 | UInt64 _size; | 19 | UInt64 _size; |
| 19 | UInt64 _pos; | 20 | UInt64 _pos; |
| 20 | bool _wasFinished; | ||
| 21 | public: | 21 | public: |
| 22 | void SetStream(ISequentialInStream *stream) { _stream = stream; } | 22 | void SetStream(ISequentialInStream *stream) { _stream = stream; } |
| 23 | void ReleaseStream() { _stream.Release(); } | 23 | void ReleaseStream() { _stream.Release(); } |
| 24 | void Init(UInt64 streamSize) | 24 | void Init(UInt64 streamSize) |
| 25 | { | 25 | { |
| 26 | _wasFinished = false; | ||
| 26 | _size = streamSize; | 27 | _size = streamSize; |
| 27 | _pos = 0; | 28 | _pos = 0; |
| 28 | _wasFinished = false; | ||
| 29 | } | 29 | } |
| 30 | UInt64 GetSize() const { return _pos; } | 30 | UInt64 GetSize() const { return _pos; } |
| 31 | UInt64 GetRem() const { return _size - _pos; } | 31 | UInt64 GetRem() const { return _size - _pos; } |
| @@ -79,9 +79,9 @@ public: | |||
| 79 | _curRem = 0; | 79 | _curRem = 0; |
| 80 | _virtPos = 0; | 80 | _virtPos = 0; |
| 81 | _physPos = StartOffset; | 81 | _physPos = StartOffset; |
| 82 | if (Vector.Size() > 0) | 82 | if (Vector.Size()) |
| 83 | { | 83 | { |
| 84 | _physPos = StartOffset + (Vector[0] << BlockSizeLog); | 84 | _physPos = StartOffset + ((UInt64)Vector[0] << BlockSizeLog); |
| 85 | return SeekToPhys(); | 85 | return SeekToPhys(); |
| 86 | } | 86 | } |
| 87 | return S_OK; | 87 | return S_OK; |
| @@ -105,9 +105,9 @@ struct CSeekExtent | |||
| 105 | Z7_CLASS_IMP_IInStream( | 105 | Z7_CLASS_IMP_IInStream( |
| 106 | CExtentsStream | 106 | CExtentsStream |
| 107 | ) | 107 | ) |
| 108 | unsigned _prevExtentIndex; | ||
| 108 | UInt64 _virtPos; | 109 | UInt64 _virtPos; |
| 109 | UInt64 _phyPos; | 110 | UInt64 _phyPos; |
| 110 | unsigned _prevExtentIndex; | ||
| 111 | public: | 111 | public: |
| 112 | CMyComPtr<IInStream> Stream; | 112 | CMyComPtr<IInStream> Stream; |
| 113 | CRecordVector<CSeekExtent> Extents; | 113 | CRecordVector<CSeekExtent> Extents; |
| @@ -115,9 +115,9 @@ public: | |||
| 115 | void ReleaseStream() { Stream.Release(); } | 115 | void ReleaseStream() { Stream.Release(); } |
| 116 | void Init() | 116 | void Init() |
| 117 | { | 117 | { |
| 118 | _prevExtentIndex = 0; | ||
| 118 | _virtPos = 0; | 119 | _virtPos = 0; |
| 119 | _phyPos = (UInt64)0 - 1; // we need Seek() for Stream | 120 | _phyPos = (UInt64)0 - 1; // we need Seek() for Stream |
| 120 | _prevExtentIndex = 0; | ||
| 121 | } | 121 | } |
| 122 | }; | 122 | }; |
| 123 | 123 | ||
| @@ -127,10 +127,10 @@ Z7_CLASS_IMP_COM_1( | |||
| 127 | CLimitedSequentialOutStream | 127 | CLimitedSequentialOutStream |
| 128 | , ISequentialOutStream | 128 | , ISequentialOutStream |
| 129 | ) | 129 | ) |
| 130 | CMyComPtr<ISequentialOutStream> _stream; | ||
| 131 | UInt64 _size; | ||
| 132 | bool _overflow; | 130 | bool _overflow; |
| 133 | bool _overflowIsAllowed; | 131 | bool _overflowIsAllowed; |
| 132 | CMyComPtr<ISequentialOutStream> _stream; | ||
| 133 | UInt64 _size; | ||
| 134 | public: | 134 | public: |
| 135 | void SetStream(ISequentialOutStream *stream) { _stream = stream; } | 135 | void SetStream(ISequentialOutStream *stream) { _stream = stream; } |
| 136 | void ReleaseStream() { _stream.Release(); } | 136 | void ReleaseStream() { _stream.Release(); } |
diff --git a/CPP/7zip/Compress/BZip2Encoder.cpp b/CPP/7zip/Compress/BZip2Encoder.cpp index af0b312..bc93dd5 100644 --- a/CPP/7zip/Compress/BZip2Encoder.cpp +++ b/CPP/7zip/Compress/BZip2Encoder.cpp | |||
| @@ -436,7 +436,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize) | |||
| 436 | WriteBits2(origPtr, kNumOrigBits + 1); // + 1 for additional high bit flag (Randomised = false) | 436 | WriteBits2(origPtr, kNumOrigBits + 1); // + 1 for additional high bit flag (Randomised = false) |
| 437 | } | 437 | } |
| 438 | Byte mtfBuf[256]; | 438 | Byte mtfBuf[256]; |
| 439 | // memset(mtfBuf, 0, sizeof(mtfBuf)); // to disable MSVC warning | 439 | Z7_memset_0_ARRAY(mtfBuf); // to suppress MSVC warning in -analyze mode |
| 440 | unsigned numInUse; | 440 | unsigned numInUse; |
| 441 | { | 441 | { |
| 442 | Byte inUse[256]; | 442 | Byte inUse[256]; |
diff --git a/CPP/7zip/Compress/HuffmanDecoder.h b/CPP/7zip/Compress/HuffmanDecoder.h index 318190d..b05f389 100644 --- a/CPP/7zip/Compress/HuffmanDecoder.h +++ b/CPP/7zip/Compress/HuffmanDecoder.h | |||
| @@ -481,25 +481,26 @@ public: | |||
| 481 | if (len == 0) | 481 | if (len == 0) |
| 482 | continue; | 482 | continue; |
| 483 | const unsigned offset = counts[len]++; | 483 | const unsigned offset = counts[len]++; |
| 484 | { | 484 | const unsigned temp = (offset - _poses[len]) << (kNumBitsMax - len); |
| 485 | Byte *dest = _lens + _limits[(size_t)len - 1] | 485 | Byte *dest = _lens + _limits[(size_t)len - 1] + temp; |
| 486 | + ((offset - _poses[len]) << (kNumBitsMax - len)); | 486 | unsigned num = 1u << (kNumBitsMax - len); |
| 487 | const unsigned num = (unsigned)1 << (kNumBitsMax - len); | 487 | const unsigned val = (i << 3) + len; |
| 488 | const unsigned val = (i << 3) + len; | 488 | do |
| 489 | for (unsigned k = 0; k < num; k++) | 489 | *dest++ = (Byte)val; |
| 490 | dest[k] = (Byte)val; | 490 | while (--num); |
| 491 | } | ||
| 492 | } | 491 | } |
| 493 | 492 | ||
| 494 | if (!full) | 493 | if (!full) |
| 495 | { | 494 | { |
| 496 | const unsigned limit = _limits[kNumBitsMax]; | 495 | const unsigned limit = _limits[kNumBitsMax]; |
| 497 | const unsigned num = ((unsigned)1 << kNumBitsMax) - limit; | 496 | unsigned num = (1u << kNumBitsMax) - limit; |
| 498 | Byte *dest = _lens + limit; | 497 | if (num) |
| 499 | for (unsigned k = 0; k < num; k++) | 498 | { |
| 500 | dest[k] = (Byte) | 499 | Byte *dest = _lens + limit; |
| 501 | // (0x1f << 3); | 500 | do |
| 502 | ((0x1f << 3) + 0x7); | 501 | *dest++ = (0x1f << 3) + 7; |
| 502 | while (--num); | ||
| 503 | } | ||
| 503 | } | 504 | } |
| 504 | 505 | ||
| 505 | return true; | 506 | return true; |
diff --git a/CPP/7zip/Compress/LzmaEncoder.cpp b/CPP/7zip/Compress/LzmaEncoder.cpp index bca2eee..8b7a79f 100644 --- a/CPP/7zip/Compress/LzmaEncoder.cpp +++ b/CPP/7zip/Compress/LzmaEncoder.cpp | |||
| @@ -43,7 +43,7 @@ CEncoder::~CEncoder() | |||
| 43 | 43 | ||
| 44 | static inline wchar_t GetLowCharFast(wchar_t c) | 44 | static inline wchar_t GetLowCharFast(wchar_t c) |
| 45 | { | 45 | { |
| 46 | return c |= 0x20; | 46 | return (wchar_t)(c | 0x20); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) | 49 | static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) |
diff --git a/CPP/7zip/Compress/Rar3Decoder.cpp b/CPP/7zip/Compress/Rar3Decoder.cpp index c17d46d..7e4fb2f 100644 --- a/CPP/7zip/Compress/Rar3Decoder.cpp +++ b/CPP/7zip/Compress/Rar3Decoder.cpp | |||
| @@ -454,7 +454,7 @@ HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing) | |||
| 454 | } | 454 | } |
| 455 | } | 455 | } |
| 456 | if (InputEofError_Fast()) | 456 | if (InputEofError_Fast()) |
| 457 | return false; | 457 | return S_FALSE; |
| 458 | const int c = DecodePpmSymbol(); | 458 | const int c = DecodePpmSymbol(); |
| 459 | if (c < 0) | 459 | if (c < 0) |
| 460 | { | 460 | { |
diff --git a/CPP/7zip/Crypto/Rar5Aes.cpp b/CPP/7zip/Crypto/Rar5Aes.cpp index 34ea4ff..ef9607b 100644 --- a/CPP/7zip/Crypto/Rar5Aes.cpp +++ b/CPP/7zip/Crypto/Rar5Aes.cpp | |||
| @@ -209,6 +209,7 @@ bool CDecoder::CalcKey_and_CheckPassword() | |||
| 209 | { | 209 | { |
| 210 | MY_ALIGN_FOR_SHA256 | 210 | MY_ALIGN_FOR_SHA256 |
| 211 | UInt32 pswCheck[SHA256_NUM_DIGEST_WORDS]; | 211 | UInt32 pswCheck[SHA256_NUM_DIGEST_WORDS]; |
| 212 | Z7_memset_0_ARRAY(pswCheck); | ||
| 212 | { | 213 | { |
| 213 | // Pbkdf HMAC-SHA-256 | 214 | // Pbkdf HMAC-SHA-256 |
| 214 | MY_ALIGN_FOR_SHA256 | 215 | MY_ALIGN_FOR_SHA256 |
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp index 46b740a..b7815c6 100644 --- a/CPP/7zip/UI/Agent/Agent.cpp +++ b/CPP/7zip/UI/Agent/Agent.cpp | |||
| @@ -11,11 +11,14 @@ | |||
| 11 | #include "../../../Windows/FileDir.h" | 11 | #include "../../../Windows/FileDir.h" |
| 12 | #include "../../../Windows/FileName.h" | 12 | #include "../../../Windows/FileName.h" |
| 13 | #include "../../../Windows/PropVariantConv.h" | 13 | #include "../../../Windows/PropVariantConv.h" |
| 14 | #include "../../../Windows/System.h" | ||
| 14 | 15 | ||
| 15 | #ifndef Z7_ST | 16 | #ifndef Z7_ST |
| 16 | #include "../../../Windows/Synchronization.h" | 17 | #include "../../../Windows/Synchronization.h" |
| 17 | #endif | 18 | #endif |
| 18 | 19 | ||
| 20 | #include "../../Archive/Common/ItemNameUtils.h" | ||
| 21 | |||
| 19 | #include "../Common/ArchiveExtractCallback.h" | 22 | #include "../Common/ArchiveExtractCallback.h" |
| 20 | #include "../FileManager/RegistryUtils.h" | 23 | #include "../FileManager/RegistryUtils.h" |
| 21 | 24 | ||
| @@ -109,28 +112,48 @@ Z7_COM7F_IMF(CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)) | |||
| 109 | return S_OK; | 112 | return S_OK; |
| 110 | } | 113 | } |
| 111 | 114 | ||
| 112 | void CAgentFolder::LoadFolder(unsigned proxyDirIndex) | 115 | void CAgentFolder::LoadFolder(unsigned dirIndex) |
| 113 | { | 116 | { |
| 114 | CProxyItem item; | 117 | CProxyItem item; |
| 115 | item.DirIndex = proxyDirIndex; | ||
| 116 | 118 | ||
| 117 | if (_proxy2) | 119 | if (_proxy2) |
| 118 | { | 120 | { |
| 119 | const CProxyDir2 &dir = _proxy2->Dirs[proxyDirIndex]; | 121 | CUIntVector vec; |
| 120 | FOR_VECTOR (i, dir.Items) | 122 | unsigned i = 0; |
| 123 | for (;;) | ||
| 121 | { | 124 | { |
| 125 | const CProxyDir2 &dir = _proxy2->Dirs[dirIndex]; | ||
| 126 | if (i == dir.Items.Size()) | ||
| 127 | { | ||
| 128 | const unsigned num = vec.Size(); | ||
| 129 | if (num < 2) | ||
| 130 | return; | ||
| 131 | dirIndex = vec[num - 2]; | ||
| 132 | i = vec[num - 1]; | ||
| 133 | vec.DeleteFrom(num - 2); | ||
| 134 | continue; | ||
| 135 | } | ||
| 136 | |||
| 137 | item.DirIndex = dirIndex; | ||
| 122 | item.Index = i; | 138 | item.Index = i; |
| 123 | _items.Add(item); | 139 | _items.Add(item); |
| 124 | const CProxyFile2 &file = _proxy2->Files[dir.Items[i]]; | 140 | const unsigned index = dir.Items[i]; |
| 125 | if (file.DirIndex != -1) | 141 | i++; |
| 126 | LoadFolder((unsigned)file.DirIndex); | 142 | const CProxyFile2 &file = _proxy2->Files[index]; |
| 127 | if (_loadAltStreams && file.AltDirIndex != -1) | 143 | if (_loadAltStreams && file.AltDirIndex != -1) |
| 128 | LoadFolder((unsigned)file.AltDirIndex); | 144 | LoadFolder((unsigned)file.AltDirIndex); |
| 145 | if (file.DirIndex != -1) | ||
| 146 | { | ||
| 147 | vec.Add(dirIndex); | ||
| 148 | vec.Add(i); | ||
| 149 | dirIndex = (unsigned)file.DirIndex; | ||
| 150 | i = 0; | ||
| 151 | } | ||
| 129 | } | 152 | } |
| 130 | return; | ||
| 131 | } | 153 | } |
| 132 | 154 | ||
| 133 | const CProxyDir &dir = _proxy->Dirs[proxyDirIndex]; | 155 | item.DirIndex = dirIndex; |
| 156 | const CProxyDir &dir = _proxy->Dirs[dirIndex]; | ||
| 134 | unsigned i; | 157 | unsigned i; |
| 135 | for (i = 0; i < dir.SubDirs.Size(); i++) | 158 | for (i = 0; i < dir.SubDirs.Size(); i++) |
| 136 | { | 159 | { |
| @@ -139,7 +162,7 @@ void CAgentFolder::LoadFolder(unsigned proxyDirIndex) | |||
| 139 | LoadFolder(dir.SubDirs[i]); | 162 | LoadFolder(dir.SubDirs[i]); |
| 140 | } | 163 | } |
| 141 | 164 | ||
| 142 | unsigned start = dir.SubDirs.Size(); | 165 | const unsigned start = dir.SubDirs.Size(); |
| 143 | for (i = 0; i < dir.SubFiles.Size(); i++) | 166 | for (i = 0; i < dir.SubFiles.Size(); i++) |
| 144 | { | 167 | { |
| 145 | item.Index = start + i; | 168 | item.Index = start + i; |
| @@ -201,79 +224,39 @@ UString CAgentFolder::GetName(UInt32 index) const | |||
| 201 | return _proxy->Files[dir->SubFiles[realIndex - dir->SubDirs.Size()]].Name; | 224 | return _proxy->Files[dir->SubFiles[realIndex - dir->SubDirs.Size()]].Name; |
| 202 | } | 225 | } |
| 203 | 226 | ||
| 204 | void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const | 227 | |
| 228 | /* called for (_flatMode == true) from: | ||
| 229 | CAgentFolder::GetProperty(kpidPrefix) | ||
| 230 | CAgentFolder::CompareItems(kpidPrefix) | ||
| 231 | */ | ||
| 232 | void CAgentFolder::GetPrefix(const UInt32 index, UString &prefix) const | ||
| 205 | { | 233 | { |
| 234 | prefix.Empty(); | ||
| 206 | if (!_flatMode) | 235 | if (!_flatMode) |
| 207 | { | ||
| 208 | prefix.Empty(); | ||
| 209 | return; | 236 | return; |
| 210 | } | 237 | const unsigned itemDirIndex = _items[index].DirIndex; |
| 211 | 238 | if (itemDirIndex == _proxyDirIndex) | |
| 212 | const CProxyItem &item = _items[index]; | 239 | return; |
| 213 | unsigned proxyIndex = item.DirIndex; | ||
| 214 | |||
| 215 | if (_proxy2) | 240 | if (_proxy2) |
| 216 | { | 241 | { |
| 217 | // that code is unused. 7-Zip gets prefix via GetItemPrefix() . | 242 | const unsigned kLenLimit = 1u << 12; |
| 218 | 243 | _proxy2->GetDirPath_as_Prefix_from_Base(itemDirIndex, prefix, _proxyDirIndex, kLenLimit); | |
| 219 | unsigned len = 0; | ||
| 220 | while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs) | ||
| 221 | { | ||
| 222 | const CProxyFile2 &file = _proxy2->Files[(unsigned)_proxy2->Dirs[proxyIndex].ArcIndex]; | ||
| 223 | len += file.NameLen + 1; | ||
| 224 | proxyIndex = (file.Parent == -1) ? 0 : (unsigned)_proxy2->Files[(unsigned)file.Parent].GetDirIndex(file.IsAltStream); | ||
| 225 | } | ||
| 226 | |||
| 227 | wchar_t *p = prefix.GetBuf_SetEnd(len) + len; | ||
| 228 | proxyIndex = item.DirIndex; | ||
| 229 | while (proxyIndex != _proxyDirIndex && proxyIndex >= k_Proxy2_NumRootDirs) | ||
| 230 | { | ||
| 231 | const CProxyFile2 &file = _proxy2->Files[(unsigned)_proxy2->Dirs[proxyIndex].ArcIndex]; | ||
| 232 | p--; | ||
| 233 | *p = WCHAR_PATH_SEPARATOR; | ||
| 234 | p -= file.NameLen; | ||
| 235 | wmemcpy(p, file.Name, file.NameLen); | ||
| 236 | proxyIndex = (file.Parent == -1) ? 0 : (unsigned)_proxy2->Files[(unsigned)file.Parent].GetDirIndex(file.IsAltStream); | ||
| 237 | } | ||
| 238 | } | 244 | } |
| 239 | else | 245 | else |
| 240 | { | 246 | _proxy->GetDirPath_as_Prefix_from_Base(itemDirIndex, prefix, _proxyDirIndex); |
| 241 | unsigned len = 0; | ||
| 242 | while (proxyIndex != _proxyDirIndex) | ||
| 243 | { | ||
| 244 | const CProxyDir *dir = &_proxy->Dirs[proxyIndex]; | ||
| 245 | len += dir->NameLen + 1; | ||
| 246 | proxyIndex = (unsigned)dir->ParentDir; | ||
| 247 | } | ||
| 248 | |||
| 249 | wchar_t *p = prefix.GetBuf_SetEnd(len) + len; | ||
| 250 | proxyIndex = item.DirIndex; | ||
| 251 | while (proxyIndex != _proxyDirIndex) | ||
| 252 | { | ||
| 253 | const CProxyDir *dir = &_proxy->Dirs[proxyIndex]; | ||
| 254 | p--; | ||
| 255 | *p = WCHAR_PATH_SEPARATOR; | ||
| 256 | p -= dir->NameLen; | ||
| 257 | wmemcpy(p, dir->Name, dir->NameLen); | ||
| 258 | proxyIndex = (unsigned)dir->ParentDir; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | 247 | } |
| 262 | 248 | ||
| 263 | UString CAgentFolder::GetFullPrefix(UInt32 index) const | 249 | UString CAgentFolder::GetFullPrefix(const UInt32 index) const |
| 264 | { | 250 | { |
| 265 | unsigned foldIndex = _proxyDirIndex; | 251 | unsigned foldIndex = _proxyDirIndex; |
| 266 | |||
| 267 | if (_flatMode) | 252 | if (_flatMode) |
| 268 | foldIndex = _items[index].DirIndex; | 253 | foldIndex = _items[index].DirIndex; |
| 269 | |||
| 270 | if (_proxy2) | 254 | if (_proxy2) |
| 271 | return _proxy2->Dirs[foldIndex].PathPrefix; | 255 | return _proxy2->GetDirPath_as_Prefix(foldIndex); |
| 272 | else | 256 | return _proxy->GetDirPath_as_Prefix(foldIndex); |
| 273 | return _proxy->GetDirPath_as_Prefix(foldIndex); | ||
| 274 | } | 257 | } |
| 275 | 258 | ||
| 276 | Z7_COM7F_IMF2(UInt64, CAgentFolder::GetItemSize(UInt32 index)) | 259 | Z7_COM7F_IMF2(UInt64, CAgentFolder::GetItemSize(const UInt32 index)) |
| 277 | { | 260 | { |
| 278 | unsigned arcIndex; | 261 | unsigned arcIndex; |
| 279 | if (_proxy2) | 262 | if (_proxy2) |
| @@ -471,29 +454,48 @@ Z7_COM7F_IMF(CAgentFolder::GetItemName(UInt32 index, const wchar_t **name, unsig | |||
| 471 | } | 454 | } |
| 472 | } | 455 | } |
| 473 | 456 | ||
| 457 | |||
| 458 | /* called for (_flatMode == true) from: | ||
| 459 | CPanel::RefreshListCtrl() : to check selected items and focused item. | ||
| 460 | CPanel::SetItemText() : to show prefix column | ||
| 461 | */ | ||
| 474 | Z7_COM7F_IMF(CAgentFolder::GetItemPrefix(UInt32 index, const wchar_t **name, unsigned *len)) | 462 | Z7_COM7F_IMF(CAgentFolder::GetItemPrefix(UInt32 index, const wchar_t **name, unsigned *len)) |
| 475 | { | 463 | { |
| 476 | *name = NULL; | 464 | *name = NULL; |
| 477 | *len = 0; | 465 | *len = 0; |
| 466 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | ||
| 478 | if (!_flatMode) | 467 | if (!_flatMode) |
| 479 | return S_OK; | 468 | return S_OK; |
| 480 | 469 | ||
| 481 | if (_proxy2) | 470 | if (_proxy2) |
| 482 | { | 471 | { |
| 483 | const CProxyItem &item = _items[index]; | 472 | const CProxyItem &item = _items[index]; |
| 484 | const UString &s = _proxy2->Dirs[item.DirIndex].PathPrefix; | 473 | const CProxyDir2 &dir = _proxy2->Dirs[item.DirIndex]; |
| 485 | unsigned baseLen = _proxy2->Dirs[_proxyDirIndex].PathPrefix.Len(); | 474 | const CProxyDir2 &baseDir = _proxy2->Dirs[_proxyDirIndex]; |
| 486 | if (baseLen <= s.Len()) | 475 | const UString &s = dir.PathPrefix; |
| 476 | if (dir.IsLongPath) | ||
| 487 | { | 477 | { |
| 488 | *name = (const wchar_t *)s + baseLen; | 478 | // in case of IsLongPath we can return reduced prefix or return nothing. |
| 489 | *len = s.Len() - baseLen; | 479 | // so caller will call it with full prefix. |
| 480 | #if 1 // 1 - for fast processing of long strings, 0 - for full processing | ||
| 481 | *name = (const wchar_t *)s; | ||
| 482 | *len = s.Len(); | ||
| 483 | #endif | ||
| 490 | } | 484 | } |
| 491 | else | 485 | else |
| 492 | { | 486 | { |
| 493 | return E_FAIL; | 487 | if (baseDir.IsLongPath) |
| 494 | // throw 111l; | 488 | return E_FAIL; // throw 1; |
| 489 | const unsigned baseLen = baseDir.PathPrefix.Len(); | ||
| 490 | if (s.Len() < baseLen) | ||
| 491 | return E_FAIL; // throw 1; | ||
| 492 | *name = (const wchar_t *)s + baseLen; | ||
| 493 | *len = s.Len() - baseLen; | ||
| 495 | } | 494 | } |
| 496 | } | 495 | } |
| 496 | #else | ||
| 497 | UNUSED_VAR(index) | ||
| 498 | #endif | ||
| 497 | return S_OK; | 499 | return S_OK; |
| 498 | } | 500 | } |
| 499 | 501 | ||
| @@ -552,6 +554,15 @@ int CAgentFolder::CompareItems3(UInt32 index1, UInt32 index2, PROPID propID) | |||
| 552 | return prop1.Compare(prop2); | 554 | return prop1.Compare(prop2); |
| 553 | } | 555 | } |
| 554 | 556 | ||
| 557 | int CAgentFolder::ComparePrefixes(const UInt32 index1, const UInt32 index2) | ||
| 558 | { | ||
| 559 | // we use CAgentFolder::_temp1 instead of local vaiables for faster execution. | ||
| 560 | // it's not allowed to call ComparePrefixes() from different threads simultaneously. | ||
| 561 | // UString _temp1, _temp2; | ||
| 562 | GetPrefix(index1, _temp1); | ||
| 563 | GetPrefix(index2, _temp2); | ||
| 564 | return CompareFileNames_ForFolderList(_temp1, _temp2); | ||
| 565 | } | ||
| 555 | 566 | ||
| 556 | int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) | 567 | int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) |
| 557 | { | 568 | { |
| @@ -591,9 +602,13 @@ int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int | |||
| 591 | { | 602 | { |
| 592 | if (!_flatMode) | 603 | if (!_flatMode) |
| 593 | return 0; | 604 | return 0; |
| 605 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | ||
| 594 | return CompareFileNames_ForFolderList( | 606 | return CompareFileNames_ForFolderList( |
| 595 | _proxy2->Dirs[_items[index1].DirIndex].PathPrefix, | 607 | _proxy2->Dirs[_items[index1].DirIndex].PathPrefix, |
| 596 | _proxy2->Dirs[_items[index2].DirIndex].PathPrefix); | 608 | _proxy2->Dirs[_items[index2].DirIndex].PathPrefix); |
| 609 | #else | ||
| 610 | return ComparePrefixes(index1, index2); | ||
| 611 | #endif | ||
| 597 | } | 612 | } |
| 598 | 613 | ||
| 599 | if (propID == kpidExtension) | 614 | if (propID == kpidExtension) |
| @@ -714,10 +729,7 @@ Z7_COM7F_IMF2(Int32, CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PR | |||
| 714 | { | 729 | { |
| 715 | if (!_flatMode) | 730 | if (!_flatMode) |
| 716 | return 0; | 731 | return 0; |
| 717 | UString prefix1, prefix2; | 732 | return ComparePrefixes(index1, index2); |
| 718 | GetPrefix(index1, prefix1); | ||
| 719 | GetPrefix(index2, prefix2); | ||
| 720 | return CompareFileNames_ForFolderList(prefix1, prefix2); | ||
| 721 | } | 733 | } |
| 722 | 734 | ||
| 723 | UInt32 arcIndex1; | 735 | UInt32 arcIndex1; |
| @@ -1004,10 +1016,10 @@ Z7_COM7F_IMF(CAgentFolder::BindToAltStreams(const wchar_t *name, IFolderFolder * | |||
| 1004 | return BindToAltStreams((UInt32)(Int32)-1, resultFolder); | 1016 | return BindToAltStreams((UInt32)(Int32)-1, resultFolder); |
| 1005 | 1017 | ||
| 1006 | { | 1018 | { |
| 1007 | const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex]; | 1019 | const CUIntVector &subFiles = _proxy2->Dirs[_proxyDirIndex].Items; |
| 1008 | FOR_VECTOR (i, dir.Items) | 1020 | FOR_VECTOR (i, subFiles) |
| 1009 | { | 1021 | { |
| 1010 | const CProxyFile2 &file = _proxy2->Files[dir.Items[i]]; | 1022 | const CProxyFile2 &file = _proxy2->Files[subFiles[i]]; |
| 1011 | if (file.AltDirIndex != -1) | 1023 | if (file.AltDirIndex != -1) |
| 1012 | if (CompareFileNames(file.Name, name) == 0) | 1024 | if (CompareFileNames(file.Name, name) == 0) |
| 1013 | return BindToAltStreams_Internal((unsigned)file.AltDirIndex, resultFolder); | 1025 | return BindToAltStreams_Internal((unsigned)file.AltDirIndex, resultFolder); |
| @@ -1234,7 +1246,8 @@ Z7_COM7F_IMF(CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)) | |||
| 1234 | 1246 | ||
| 1235 | if (propID == kpidReadOnly) | 1247 | if (propID == kpidReadOnly) |
| 1236 | { | 1248 | { |
| 1237 | if (_agentSpec->Is_Attrib_ReadOnly()) | 1249 | if ((_agentSpec->_proxy && _agentSpec->_proxy->Are_Changed_LongPaths) |
| 1250 | || _agentSpec->Is_Attrib_ReadOnly()) | ||
| 1238 | prop = true; | 1251 | prop = true; |
| 1239 | else | 1252 | else |
| 1240 | prop = _agentSpec->IsThere_ReadOnlyArc(); | 1253 | prop = _agentSpec->IsThere_ReadOnlyArc(); |
| @@ -1253,8 +1266,8 @@ Z7_COM7F_IMF(CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)) | |||
| 1253 | } | 1266 | } |
| 1254 | else if (propID == kpidPath) | 1267 | else if (propID == kpidPath) |
| 1255 | { | 1268 | { |
| 1256 | bool isAltStreamFolder = false; | 1269 | // Here we allow the return of reduced path: |
| 1257 | prop = _proxy2->GetDirPath_as_Prefix(_proxyDirIndex, isAltStreamFolder); | 1270 | prop = _proxy2->GetDirPath_as_Prefix(_proxyDirIndex, true); // canReducePath |
| 1258 | } | 1271 | } |
| 1259 | else switch (propID) | 1272 | else switch (propID) |
| 1260 | { | 1273 | { |
| @@ -1406,17 +1419,20 @@ int CAgentFolder::GetRealIndex(unsigned index) const | |||
| 1406 | } | 1419 | } |
| 1407 | } | 1420 | } |
| 1408 | 1421 | ||
| 1409 | void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const | 1422 | void CAgentFolder::GetRealIndices( |
| 1423 | const UInt32 *indices, const UInt32 numItems, | ||
| 1424 | const bool includeAltStreams, const bool includeFolderSubItemsInFlatMode, | ||
| 1425 | CUIntVector &realIndices) const | ||
| 1410 | { | 1426 | { |
| 1411 | if (!_flatMode) | 1427 | if (!_flatMode) |
| 1412 | { | 1428 | { |
| 1413 | if (_proxy2) | 1429 | if (_proxy2) |
| 1414 | _proxy2->GetRealIndices(_proxyDirIndex, indices, numItems, includeAltStreams, realIndices); | 1430 | _proxy2->GetRealIndices_Unsorted(_proxyDirIndex, indices, numItems, includeAltStreams, realIndices); |
| 1415 | else | 1431 | else |
| 1416 | _proxy->GetRealIndices(_proxyDirIndex, indices, numItems, realIndices); | 1432 | _proxy->GetRealIndices_Unsorted(_proxyDirIndex, indices, numItems, realIndices); |
| 1417 | return; | ||
| 1418 | } | 1433 | } |
| 1419 | 1434 | else | |
| 1435 | { | ||
| 1420 | realIndices.Clear(); | 1436 | realIndices.Clear(); |
| 1421 | 1437 | ||
| 1422 | for (UInt32 i = 0; i < numItems; i++) | 1438 | for (UInt32 i = 0; i < numItems; i++) |
| @@ -1425,13 +1441,14 @@ void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool i | |||
| 1425 | if (_proxy2) | 1441 | if (_proxy2) |
| 1426 | { | 1442 | { |
| 1427 | const CProxyDir2 *dir = &_proxy2->Dirs[item.DirIndex]; | 1443 | const CProxyDir2 *dir = &_proxy2->Dirs[item.DirIndex]; |
| 1428 | _proxy2->AddRealIndices_of_ArcItem(dir->Items[item.Index], includeAltStreams, realIndices); | 1444 | _proxy2->AddRealIndices_of_ArcItem(dir->Items[item.Index], |
| 1445 | includeAltStreams, includeFolderSubItemsInFlatMode, realIndices); | ||
| 1429 | continue; | 1446 | continue; |
| 1430 | } | 1447 | } |
| 1431 | UInt32 arcIndex; | 1448 | UInt32 arcIndex; |
| 1432 | { | 1449 | { |
| 1433 | const CProxyDir *dir = &_proxy->Dirs[item.DirIndex]; | 1450 | const CProxyDir *dir = &_proxy->Dirs[item.DirIndex]; |
| 1434 | unsigned realIndex = item.Index; | 1451 | const unsigned realIndex = item.Index; |
| 1435 | if (realIndex < dir->SubDirs.Size()) | 1452 | if (realIndex < dir->SubDirs.Size()) |
| 1436 | { | 1453 | { |
| 1437 | if (includeFolderSubItemsInFlatMode) | 1454 | if (includeFolderSubItemsInFlatMode) |
| @@ -1449,6 +1466,7 @@ void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool i | |||
| 1449 | } | 1466 | } |
| 1450 | realIndices.Add(arcIndex); | 1467 | realIndices.Add(arcIndex); |
| 1451 | } | 1468 | } |
| 1469 | } | ||
| 1452 | 1470 | ||
| 1453 | HeapSort(realIndices.NonConstData(), realIndices.Size()); | 1471 | HeapSort(realIndices.NonConstData(), realIndices.Size()); |
| 1454 | } | 1472 | } |
| @@ -1472,11 +1490,13 @@ Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices, | |||
| 1472 | CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; | 1490 | CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; |
| 1473 | UStringVector pathParts; | 1491 | UStringVector pathParts; |
| 1474 | bool isAltStreamFolder = false; | 1492 | bool isAltStreamFolder = false; |
| 1493 | bool isChangedPath = false; | ||
| 1475 | if (_proxy2) | 1494 | if (_proxy2) |
| 1476 | _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder); | 1495 | _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder); |
| 1477 | else | 1496 | else |
| 1478 | _proxy->GetDirPathParts(_proxyDirIndex, pathParts); | 1497 | _proxy->GetDirPathParts_isChanged(_proxyDirIndex, pathParts, isChangedPath); |
| 1479 | 1498 | if (isChangedPath) | |
| 1499 | return E_NOTIMPL; | ||
| 1480 | /* | 1500 | /* |
| 1481 | if (_flatMode) | 1501 | if (_flatMode) |
| 1482 | pathMode = NExtract::NPathMode::kNoPathnames; | 1502 | pathMode = NExtract::NPathMode::kNoPathnames; |
| @@ -1538,7 +1558,8 @@ Z7_COM7F_IMF(CAgentFolder::Extract(const UInt32 *indices, | |||
| 1538 | extractCallbackSpec->DirPathPrefix_for_HashFiles = _agentSpec->_hashBaseFolderPrefix; | 1558 | extractCallbackSpec->DirPathPrefix_for_HashFiles = _agentSpec->_hashBaseFolderPrefix; |
| 1539 | 1559 | ||
| 1540 | CUIntVector realIndices; | 1560 | CUIntVector realIndices; |
| 1541 | GetRealIndices(indices, numItems, IntToBool(includeAltStreams), | 1561 | GetRealIndices(indices, numItems, |
| 1562 | (_loadAltStreams && _flatMode) ? false : IntToBool(includeAltStreams), // v26.03 | ||
| 1542 | false, // includeFolderSubItemsInFlatMode | 1563 | false, // includeFolderSubItemsInFlatMode |
| 1543 | realIndices); // | 1564 | realIndices); // |
| 1544 | 1565 | ||
| @@ -1574,7 +1595,8 @@ CAgent::CAgent(): | |||
| 1574 | _proxy2(NULL), | 1595 | _proxy2(NULL), |
| 1575 | _updatePathPrefix_is_AltFolder(false), | 1596 | _updatePathPrefix_is_AltFolder(false), |
| 1576 | _isDeviceFile(false), | 1597 | _isDeviceFile(false), |
| 1577 | _isHashHandler(false) | 1598 | _isHashHandler(false), |
| 1599 | _progress_for_Open(NULL) | ||
| 1578 | { | 1600 | { |
| 1579 | } | 1601 | } |
| 1580 | 1602 | ||
| @@ -1588,6 +1610,8 @@ CAgent::~CAgent() | |||
| 1588 | 1610 | ||
| 1589 | bool CAgent::CanUpdate() const | 1611 | bool CAgent::CanUpdate() const |
| 1590 | { | 1612 | { |
| 1613 | if (_proxy && _proxy->Are_Changed_LongPaths) | ||
| 1614 | return false; | ||
| 1591 | // FAR plugin uses empty agent to create new archive !!! | 1615 | // FAR plugin uses empty agent to create new archive !!! |
| 1592 | if (_archiveLink.Arcs.Size() == 0) | 1616 | if (_archiveLink.Arcs.Size() == 0) |
| 1593 | return true; | 1617 | return true; |
| @@ -1746,6 +1770,16 @@ HRESULT CAgent::ReadItems() | |||
| 1746 | else | 1770 | else |
| 1747 | _proxy = new CProxyArc(); | 1771 | _proxy = new CProxyArc(); |
| 1748 | 1772 | ||
| 1773 | size_t ramSize; | ||
| 1774 | if (NWindows::NSystem::GetRamSize(ramSize)) | ||
| 1775 | { | ||
| 1776 | ramSize = ramSize / 4 * 3; | ||
| 1777 | if (_proxy2) | ||
| 1778 | _proxy2->MemUsage_Limit = ramSize; | ||
| 1779 | else | ||
| 1780 | _proxy->MemUsage_Limit = ramSize; | ||
| 1781 | } | ||
| 1782 | |||
| 1749 | { | 1783 | { |
| 1750 | ThereIsPathProp = false; | 1784 | ThereIsPathProp = false; |
| 1751 | // ThereIsAltStreamProp = false; | 1785 | // ThereIsAltStreamProp = false; |
| @@ -1767,8 +1801,8 @@ HRESULT CAgent::ReadItems() | |||
| 1767 | } | 1801 | } |
| 1768 | 1802 | ||
| 1769 | if (_proxy2) | 1803 | if (_proxy2) |
| 1770 | return _proxy2->Load(GetArc(), NULL); | 1804 | return _proxy2->Load(GetArc(), _progress_for_Open); |
| 1771 | return _proxy->Load(GetArc(), NULL); | 1805 | return _proxy->Load(GetArc(), _progress_ArchiveOpenCallback_for_Open); |
| 1772 | } | 1806 | } |
| 1773 | 1807 | ||
| 1774 | Z7_COM7F_IMF(CAgent::BindToRootFolder(IFolderFolder **resultFolder)) | 1808 | Z7_COM7F_IMF(CAgent::BindToRootFolder(IFolderFolder **resultFolder)) |
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h index a63e459..e19ccd8 100644 --- a/CPP/7zip/UI/Agent/Agent.h +++ b/CPP/7zip/UI/Agent/Agent.h | |||
| @@ -107,11 +107,13 @@ public: | |||
| 107 | 107 | ||
| 108 | int CompareItems3(UInt32 index1, UInt32 index2, PROPID propID); | 108 | int CompareItems3(UInt32 index1, UInt32 index2, PROPID propID); |
| 109 | int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); | 109 | int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw); |
| 110 | int ComparePrefixes(UInt32 index1, UInt32 index2); | ||
| 110 | 111 | ||
| 111 | CAgentFolder(): | 112 | CAgentFolder(): |
| 112 | _isAltStreamFolder(false), | 113 | _isAltStreamFolder(false), |
| 113 | _flatMode(false), | 114 | _flatMode(false), |
| 114 | _loadAltStreams(false), // _loadAltStreams alt streams works in flat mode, but we don't use it now | 115 | _loadAltStreams(false), // _loadAltStreams alt streams works in flat mode, but we don't use it now |
| 116 | // _loadAltStreams(true), // for debug | ||
| 115 | _proxyDirIndex(0), | 117 | _proxyDirIndex(0), |
| 116 | _zoneMode(NExtract::NZoneIdMode::kNone) | 118 | _zoneMode(NExtract::NZoneIdMode::kNone) |
| 117 | /* , _replaceAltStreamCharsMode(0) */ | 119 | /* , _replaceAltStreamCharsMode(0) */ |
| @@ -161,6 +163,8 @@ public: | |||
| 161 | CMyComPtr<IInFolderArchive> _agent; | 163 | CMyComPtr<IInFolderArchive> _agent; |
| 162 | CAgent *_agentSpec; | 164 | CAgent *_agentSpec; |
| 163 | CRecordVector<CProxyItem> _items; | 165 | CRecordVector<CProxyItem> _items; |
| 166 | |||
| 167 | UString _temp1, _temp2; | ||
| 164 | }; | 168 | }; |
| 165 | 169 | ||
| 166 | 170 | ||
| @@ -241,6 +245,9 @@ public: | |||
| 241 | CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues; | 245 | CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues; |
| 242 | #endif | 246 | #endif |
| 243 | 247 | ||
| 248 | IArchiveOpenCallback *_progress_ArchiveOpenCallback_for_Open; // it's for parsing after archive openning | ||
| 249 | IProgress *_progress_for_Open; // it's for parsing after archive openning | ||
| 250 | |||
| 244 | CAgent(); | 251 | CAgent(); |
| 245 | ~CAgent(); | 252 | ~CAgent(); |
| 246 | 253 | ||
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index 265b943..3b2a8b7 100644 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp | |||
| @@ -42,7 +42,10 @@ Z7_COM7F_IMF(CAgent::SetFolder(IFolderFolder *folder)) | |||
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | if (_proxy2) | 44 | if (_proxy2) |
| 45 | _updatePathPrefix = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, _updatePathPrefix_is_AltFolder); | 45 | { |
| 46 | _updatePathPrefix = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex); | ||
| 47 | _updatePathPrefix_is_AltFolder = _proxy2->IsAltDir(_agentFolder->_proxyDirIndex); | ||
| 48 | } | ||
| 46 | else | 49 | else |
| 47 | _updatePathPrefix = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex); | 50 | _updatePathPrefix = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex); |
| 48 | return S_OK; | 51 | return S_OK; |
| @@ -58,86 +61,140 @@ Z7_COM7F_IMF(CAgent::SetFiles(const wchar_t *folderPrefix, | |||
| 58 | return S_OK; | 61 | return S_OK; |
| 59 | } | 62 | } |
| 60 | 63 | ||
| 61 | static HRESULT EnumerateArchiveItems(CAgent *agent, | 64 | |
| 62 | const CProxyDir &item, | 65 | static HRESULT EnumerateArchiveItems(const CAgent *agent, |
| 63 | const UString &prefix, | ||
| 64 | CObjectVector<CArcItem> &arcItems) | 66 | CObjectVector<CArcItem> &arcItems) |
| 65 | { | 67 | { |
| 66 | unsigned i; | 68 | CUIntVector vec; |
| 67 | 69 | CArcItem ai; | |
| 68 | for (i = 0; i < item.SubFiles.Size(); i++) | 70 | ai.Censored = true; // test it |
| 69 | { | 71 | unsigned prefixLen = 0; |
| 70 | unsigned arcIndex = item.SubFiles[i]; | 72 | unsigned dirIndex = k_Proxy_RootDirIndex; // 0 |
| 71 | const CProxyFile &fileItem = agent->_proxy->Files[arcIndex]; | 73 | unsigned i = 0; |
| 72 | CArcItem ai; | 74 | for (;;) |
| 73 | RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime)) | ||
| 74 | RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined)) | ||
| 75 | ai.IsDir = false; | ||
| 76 | ai.Name = prefix + fileItem.Name; | ||
| 77 | ai.Censored = true; // test it | ||
| 78 | ai.IndexInServer = arcIndex; | ||
| 79 | arcItems.Add(ai); | ||
| 80 | } | ||
| 81 | |||
| 82 | for (i = 0; i < item.SubDirs.Size(); i++) | ||
| 83 | { | 75 | { |
| 84 | const CProxyDir &dirItem = agent->_proxy->Dirs[item.SubDirs[i]]; | 76 | const CProxyDir &dir = agent->_proxy->Dirs[dirIndex]; |
| 85 | UString fullName = prefix + dirItem.Name; | 77 | |
| 86 | if (dirItem.IsLeaf()) | 78 | if (i == dir.SubDirs.Size()) // we fill SubFiles after SubDirs |
| 79 | { | ||
| 80 | ai.IsDir = false; | ||
| 81 | FOR_VECTOR (k, dir.SubFiles) | ||
| 82 | { | ||
| 83 | const unsigned arcIndex = dir.SubFiles[k]; | ||
| 84 | ai.IndexInServer = arcIndex; | ||
| 85 | RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime)) | ||
| 86 | RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined)) | ||
| 87 | RINOK(Archive_IsItem_AltStream(agent->GetArc().Archive, arcIndex, ai.IsAltStream)) | ||
| 88 | ai.Name.DeleteFrom(prefixLen); | ||
| 89 | const CProxyFile &file = agent->_proxy->Files[arcIndex]; | ||
| 90 | ai.Name += file.Name; | ||
| 91 | arcItems.Add(ai); | ||
| 92 | } | ||
| 93 | |||
| 94 | const unsigned num = vec.Size(); | ||
| 95 | if (num < 3) | ||
| 96 | return S_OK; | ||
| 97 | prefixLen = vec[num - 3]; | ||
| 98 | dirIndex = vec[num - 2]; | ||
| 99 | i = vec[num - 1]; | ||
| 100 | vec.DeleteFrom(num - 3); | ||
| 101 | continue; | ||
| 102 | } | ||
| 103 | |||
| 104 | const unsigned subDirIndex = dir.SubDirs[i]; | ||
| 105 | i++; | ||
| 106 | const CProxyDir &subDir = agent->_proxy->Dirs[subDirIndex]; | ||
| 107 | ai.Name.DeleteFrom(prefixLen); | ||
| 108 | ai.Name += subDir.Name; | ||
| 109 | if (subDir.IsLeaf()) | ||
| 87 | { | 110 | { |
| 88 | CArcItem ai; | 111 | ai.IndexInServer = (unsigned)subDir.ArcIndex; |
| 89 | RINOK(agent->GetArc().GetItem_MTime((unsigned)dirItem.ArcIndex, ai.MTime)) | 112 | RINOK(agent->GetArc().GetItem_MTime((unsigned)subDir.ArcIndex, ai.MTime)) |
| 90 | ai.IsDir = true; | 113 | ai.IsDir = true; |
| 114 | ai.IsAltStream = false; | ||
| 91 | ai.Size_Defined = false; | 115 | ai.Size_Defined = false; |
| 92 | ai.Name = fullName; | 116 | ai.Size = 0; |
| 93 | ai.Censored = true; // test it | ||
| 94 | ai.IndexInServer = (unsigned)dirItem.ArcIndex; | ||
| 95 | arcItems.Add(ai); | 117 | arcItems.Add(ai); |
| 96 | } | 118 | } |
| 97 | RINOK(EnumerateArchiveItems(agent, dirItem, fullName + WCHAR_PATH_SEPARATOR, arcItems)) | 119 | |
| 120 | vec.Add(prefixLen); | ||
| 121 | vec.Add(dirIndex); | ||
| 122 | vec.Add(i); | ||
| 123 | ai.Name.Add_PathSepar(); | ||
| 124 | prefixLen = ai.Name.Len(); | ||
| 125 | if (prefixLen >= (1 << 15) /* || vec.Size() >= (3 << 14) */ ) // NTFS limit | ||
| 126 | return E_NOTIMPL; | ||
| 127 | dirIndex = subDirIndex; | ||
| 128 | i = 0; | ||
| 98 | } | 129 | } |
| 99 | |||
| 100 | return S_OK; | ||
| 101 | } | 130 | } |
| 102 | 131 | ||
| 132 | |||
| 103 | static HRESULT EnumerateArchiveItems2(const CAgent *agent, | 133 | static HRESULT EnumerateArchiveItems2(const CAgent *agent, |
| 104 | unsigned dirIndex, | 134 | unsigned dirIndex, |
| 105 | const UString &prefix, | 135 | const UString &prefix, |
| 106 | CObjectVector<CArcItem> &arcItems) | 136 | CObjectVector<CArcItem> &arcItems) |
| 107 | { | 137 | { |
| 108 | const CProxyDir2 &dir = agent->_proxy2->Dirs[dirIndex]; | 138 | CUIntVector vec; |
| 109 | FOR_VECTOR (i, dir.Items) | 139 | CArcItem ai; |
| 140 | ai.Censored = true; // test it | ||
| 141 | ai.Name = prefix; | ||
| 142 | unsigned prefixLen = ai.Name.Len(); | ||
| 143 | unsigned i = 0; | ||
| 144 | for (;;) | ||
| 110 | { | 145 | { |
| 111 | unsigned arcIndex = dir.Items[i]; | 146 | const CProxyDir2 &dir = agent->_proxy2->Dirs[dirIndex]; |
| 147 | if (i == dir.Items.Size()) | ||
| 148 | { | ||
| 149 | const unsigned num = vec.Size(); | ||
| 150 | if (num < 3) | ||
| 151 | return S_OK; | ||
| 152 | prefixLen = vec[num - 3]; | ||
| 153 | dirIndex = vec[num - 2]; | ||
| 154 | i = vec[num - 1]; | ||
| 155 | vec.DeleteFrom(num - 3); | ||
| 156 | continue; | ||
| 157 | } | ||
| 158 | |||
| 159 | const unsigned arcIndex = dir.Items[i]; | ||
| 160 | i++; | ||
| 161 | ai.Name.DeleteFrom(prefixLen); | ||
| 112 | const CProxyFile2 &file = agent->_proxy2->Files[arcIndex]; | 162 | const CProxyFile2 &file = agent->_proxy2->Files[arcIndex]; |
| 113 | CArcItem ai; | 163 | ai.Name += file.Name; |
| 164 | // v23.03: we normalize slashes: | ||
| 165 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath( | ||
| 166 | ai.Name.Ptr_non_const() + (ai.Name.Len() - file.NameLen), file.NameLen); | ||
| 114 | ai.IndexInServer = arcIndex; | 167 | ai.IndexInServer = arcIndex; |
| 115 | ai.Name = prefix + file.Name; | ||
| 116 | ai.Censored = true; // test it | ||
| 117 | RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime)) | 168 | RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime)) |
| 118 | ai.IsDir = file.IsDir(); | 169 | ai.Size = 0; |
| 119 | ai.Size_Defined = false; | 170 | ai.Size_Defined = false; |
| 120 | ai.IsAltStream = file.IsAltStream; | 171 | ai.IsAltStream = file.IsAltStream; |
| 121 | if (!ai.IsDir) | 172 | ai.IsDir = file.IsDir(); |
| 122 | { | 173 | if (!file.IsDir()) |
| 123 | RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined)) | 174 | RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined)) |
| 124 | ai.IsDir = false; | ||
| 125 | } | ||
| 126 | arcItems.Add(ai); | ||
| 127 | 175 | ||
| 176 | arcItems.Add(ai); | ||
| 177 | |||
| 128 | if (file.AltDirIndex != -1) | 178 | if (file.AltDirIndex != -1) |
| 179 | RINOK(EnumerateArchiveItems2(agent, (unsigned)file.AltDirIndex, | ||
| 180 | ai.Name + L':', arcItems)) | ||
| 181 | |||
| 182 | if (file.IsDir()) | ||
| 129 | { | 183 | { |
| 130 | RINOK(EnumerateArchiveItems2(agent, (unsigned)file.AltDirIndex, ai.Name + L':', arcItems)) | 184 | vec.Add(prefixLen); |
| 131 | } | 185 | vec.Add(dirIndex); |
| 132 | 186 | vec.Add(i); | |
| 133 | if (ai.IsDir) | 187 | ai.Name.Add_PathSepar(); |
| 134 | { | 188 | prefixLen = ai.Name.Len(); |
| 135 | RINOK(EnumerateArchiveItems2(agent, (unsigned)file.DirIndex, ai.Name + WCHAR_PATH_SEPARATOR, arcItems)) | 189 | if (prefixLen >= (1 << 15) /* || vec.Size() >= (3 << 14) */ ) // NTFS limit |
| 190 | return E_NOTIMPL; | ||
| 191 | dirIndex = (unsigned)file.DirIndex; | ||
| 192 | i = 0; | ||
| 136 | } | 193 | } |
| 137 | } | 194 | } |
| 138 | return S_OK; | ||
| 139 | } | 195 | } |
| 140 | 196 | ||
| 197 | |||
| 141 | struct CAgUpCallbackImp Z7_final: public IUpdateProduceCallback | 198 | struct CAgUpCallbackImp Z7_final: public IUpdateProduceCallback |
| 142 | { | 199 | { |
| 143 | const CObjectVector<CArcItem> *_arcItems; | 200 | const CObjectVector<CArcItem> *_arcItems; |
| @@ -299,7 +356,7 @@ Z7_COM7F_IMF(CAgent::DoOperation( | |||
| 299 | } | 356 | } |
| 300 | else | 357 | else |
| 301 | { | 358 | { |
| 302 | RINOK(EnumerateArchiveItems(this, _proxy->Dirs[0], L"", arcItems)) | 359 | RINOK(EnumerateArchiveItems(this, arcItems)) |
| 303 | } | 360 | } |
| 304 | } | 361 | } |
| 305 | 362 | ||
| @@ -510,9 +567,8 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream, | |||
| 510 | 567 | ||
| 511 | di.Attrib = FILE_ATTRIBUTE_DIRECTORY; | 568 | di.Attrib = FILE_ATTRIBUTE_DIRECTORY; |
| 512 | di.Size = 0; | 569 | di.Size = 0; |
| 513 | bool isAltStreamFolder = false; | ||
| 514 | if (_proxy2) | 570 | if (_proxy2) |
| 515 | di.Name = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, isAltStreamFolder); | 571 | di.Name = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex /* , isAltStreamFolder */); |
| 516 | else | 572 | else |
| 517 | di.Name = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex); | 573 | di.Name = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex); |
| 518 | di.Name += folderName; | 574 | di.Name += folderName; |
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index c8edd19..71b01da 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include <ctype.h> | 9 | #include <ctype.h> |
| 10 | #endif | 10 | #endif |
| 11 | 11 | ||
| 12 | #include "../../../../C/Sort.h" | ||
| 13 | #include "../../../../C/CpuArch.h" | 12 | #include "../../../../C/CpuArch.h" |
| 14 | 13 | ||
| 15 | #include "../../../Common/UTFConvert.h" | 14 | #include "../../../Common/UTFConvert.h" |
| @@ -24,10 +23,12 @@ | |||
| 24 | 23 | ||
| 25 | using namespace NWindows; | 24 | using namespace NWindows; |
| 26 | 25 | ||
| 27 | int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const | 26 | #define CHECK_MEM_USAGE { if (MemUsage > MemUsage_Limit) return E_OUTOFMEMORY; } |
| 27 | |||
| 28 | int CProxyArc::FindSubDir(const unsigned *items, unsigned right, | ||
| 29 | const wchar_t *name, unsigned &insertPos) const | ||
| 28 | { | 30 | { |
| 29 | const CRecordVector<unsigned> &subDirs = Dirs[dirIndex].SubDirs; | 31 | unsigned left = 0; |
| 30 | unsigned left = 0, right = subDirs.Size(); | ||
| 31 | for (;;) | 32 | for (;;) |
| 32 | { | 33 | { |
| 33 | if (left == right) | 34 | if (left == right) |
| @@ -36,10 +37,13 @@ int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &inse | |||
| 36 | return -1; | 37 | return -1; |
| 37 | } | 38 | } |
| 38 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); | 39 | const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2); |
| 39 | const unsigned dirIndex2 = subDirs[mid]; | 40 | const unsigned dirIndex2 = items[mid]; |
| 40 | const int comp = CompareFileNames(name, Dirs[dirIndex2].Name); | 41 | const int comp = CompareFileNames(name, Dirs[dirIndex2].Name); |
| 41 | if (comp == 0) | 42 | if (comp == 0) |
| 43 | { | ||
| 44 | insertPos = mid; // not used, but we set it to suppress compiler warnings | ||
| 42 | return (int)dirIndex2; | 45 | return (int)dirIndex2; |
| 46 | } | ||
| 43 | if (comp < 0) | 47 | if (comp < 0) |
| 44 | right = mid; | 48 | right = mid; |
| 45 | else | 49 | else |
| @@ -50,88 +54,151 @@ int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &inse | |||
| 50 | int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const | 54 | int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const |
| 51 | { | 55 | { |
| 52 | unsigned insertPos; | 56 | unsigned insertPos; |
| 53 | return FindSubDir(dirIndex, name, insertPos); | 57 | const CUIntVector &dirs = Dirs[dirIndex].SubDirs; |
| 58 | return FindSubDir(dirs.ConstData(), dirs.Size(), name, insertPos); | ||
| 54 | } | 59 | } |
| 55 | 60 | ||
| 56 | static const wchar_t *AllocStringAndCopy(const wchar_t *s, size_t len) | 61 | static const wchar_t *AllocStringAndCopy(const wchar_t *s, size_t len) |
| 57 | { | 62 | { |
| 58 | wchar_t *p = new wchar_t[len + 1]; | 63 | ++len; |
| 59 | MyStringCopy(p, s); | 64 | wchar_t *p = new wchar_t[len]; |
| 60 | return p; | 65 | return wmemcpy(p, s, len); |
| 66 | // MyStringCopy(p, s); return p; | ||
| 61 | } | 67 | } |
| 62 | 68 | ||
| 63 | static const wchar_t *AllocStringAndCopy(const UString &s) | 69 | static const wchar_t *AllocStringAndCopy(const UString &s) |
| 64 | { | 70 | { |
| 65 | return AllocStringAndCopy(s, s.Len()); | 71 | return AllocStringAndCopy(s, s.Len()); |
| 66 | } | 72 | } |
| 67 | 73 | ||
| 68 | unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name) | 74 | |
| 75 | void CProxyArc::MergeSubDirs(CProxyDir &baseDir) | ||
| 69 | { | 76 | { |
| 77 | CUIntVector &dirs2 = baseDir.SubDirs2; | ||
| 78 | unsigned i = dirs2.Size(); | ||
| 79 | if (i == 0) | ||
| 80 | return; | ||
| 81 | CUIntVector &dirs = baseDir.SubDirs; | ||
| 82 | unsigned right = dirs.Size(); | ||
| 83 | unsigned total = right + i; | ||
| 84 | dirs.ChangeSize_KeepData_plus_AdditionalReserve(total); | ||
| 85 | unsigned * const items = dirs.NonConstData(); | ||
| 86 | do | ||
| 87 | { | ||
| 88 | const unsigned index = dirs2[--i]; | ||
| 89 | unsigned insertPos; | ||
| 90 | if (FindSubDir(items, right, Dirs[index].Name, insertPos) != -1) | ||
| 91 | throw 1; | ||
| 92 | const unsigned numItems = right - insertPos; | ||
| 93 | right = insertPos; | ||
| 94 | total -= numItems; | ||
| 95 | memmove(items + total, items + insertPos, numItems * sizeof(*items)); | ||
| 96 | items[--total] = index; | ||
| 97 | } | ||
| 98 | while (i); | ||
| 99 | dirs2.Clear(); | ||
| 100 | } | ||
| 101 | |||
| 102 | |||
| 103 | unsigned CProxyArc::AddDir(const unsigned dirIndex, const int arcIndex, const UString &name) | ||
| 104 | { | ||
| 105 | CProxyDir &baseDir = Dirs[dirIndex]; | ||
| 106 | CUIntVector &dirs = baseDir.SubDirs; | ||
| 107 | CUIntVector &dirs2 = baseDir.SubDirs2; | ||
| 108 | { | ||
| 109 | const unsigned numSmallDirs = dirs2.Size(); | ||
| 110 | if (numSmallDirs * numSmallDirs > dirs.Size()) | ||
| 111 | MergeSubDirs(baseDir); | ||
| 112 | } | ||
| 70 | unsigned insertPos; | 113 | unsigned insertPos; |
| 71 | int subDirIndex = FindSubDir(dirIndex, name, insertPos); | 114 | int subDirIndex = FindSubDir(dirs.ConstData(), dirs.Size(), name, insertPos); |
| 72 | if (subDirIndex != -1) | 115 | if (subDirIndex == -1) |
| 73 | { | 116 | { |
| 74 | if (arcIndex != -1) | 117 | unsigned insertPos2; |
| 118 | subDirIndex = FindSubDir(dirs2.ConstData(), dirs2.Size(), name, insertPos2); | ||
| 119 | if (subDirIndex == -1) | ||
| 75 | { | 120 | { |
| 76 | CProxyDir &item = Dirs[(unsigned)subDirIndex]; | 121 | CUIntVector *subDirsWork = &dirs; |
| 77 | if (item.ArcIndex == -1) | 122 | if (dirs.Size() - insertPos >= (1 << 12)) |
| 78 | item.ArcIndex = arcIndex; | 123 | { |
| 124 | subDirsWork = &dirs2; | ||
| 125 | insertPos = insertPos2; | ||
| 126 | } | ||
| 127 | subDirIndex = (int)Dirs.Size(); | ||
| 128 | subDirsWork->Insert(insertPos, (unsigned)subDirIndex); | ||
| 129 | CProxyDir &item = Dirs.AddNew(); | ||
| 130 | item.NameLen = name.Len(); | ||
| 131 | MemUsage += (size_t)item.NameLen * sizeof(*item.Name) | ||
| 132 | + sizeof(CProxyDir) + sizeof(void *) * 3 + 24; | ||
| 133 | item.Name = AllocStringAndCopy(name); | ||
| 134 | item.ArcIndex = arcIndex; | ||
| 135 | item.ParentDir = (int)dirIndex; | ||
| 136 | return (unsigned)subDirIndex; | ||
| 79 | } | 137 | } |
| 80 | return (unsigned)subDirIndex; | ||
| 81 | } | 138 | } |
| 82 | subDirIndex = (int)Dirs.Size(); | ||
| 83 | Dirs[dirIndex].SubDirs.Insert(insertPos, (unsigned)subDirIndex); | ||
| 84 | CProxyDir &item = Dirs.AddNew(); | ||
| 85 | |||
| 86 | item.NameLen = name.Len(); | ||
| 87 | item.Name = AllocStringAndCopy(name); | ||
| 88 | 139 | ||
| 89 | item.ArcIndex = arcIndex; | 140 | CProxyDir &item = Dirs[(unsigned)subDirIndex]; |
| 90 | item.ParentDir = (int)dirIndex; | 141 | if (item.ArcIndex == -1) |
| 142 | item.ArcIndex = arcIndex; | ||
| 91 | return (unsigned)subDirIndex; | 143 | return (unsigned)subDirIndex; |
| 92 | } | 144 | } |
| 93 | 145 | ||
| 94 | void CProxyDir::Clear() | ||
| 95 | { | ||
| 96 | SubDirs.Clear(); | ||
| 97 | SubFiles.Clear(); | ||
| 98 | } | ||
| 99 | 146 | ||
| 100 | void CProxyArc::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts) const | 147 | void CProxyArc::GetDirPathParts_isChanged(unsigned dirIndex, |
| 148 | UStringVector &pathParts, bool &isChangedPath) const | ||
| 101 | { | 149 | { |
| 150 | isChangedPath = false; | ||
| 102 | pathParts.Clear(); | 151 | pathParts.Clear(); |
| 103 | // while (dirIndex != -1) | 152 | while (dirIndex != k_Proxy_RootDirIndex) |
| 104 | for (;;) | ||
| 105 | { | 153 | { |
| 106 | const CProxyDir &dir = Dirs[dirIndex]; | 154 | const CProxyDir &dir = Dirs[dirIndex]; |
| 155 | if (dir.Is_Changed_LongPath) | ||
| 156 | isChangedPath = true; | ||
| 107 | dirIndex = (unsigned)dir.ParentDir; | 157 | dirIndex = (unsigned)dir.ParentDir; |
| 108 | if (dir.ParentDir == -1) | ||
| 109 | break; | ||
| 110 | pathParts.Insert(0, dir.Name); | 158 | pathParts.Insert(0, dir.Name); |
| 111 | // 22.00: we normalize name | 159 | // 22.00: we normalize name |
| 112 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(pathParts[0]); | 160 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(pathParts[0]); |
| 113 | } | 161 | } |
| 114 | } | 162 | } |
| 115 | 163 | ||
| 116 | UString CProxyArc::GetDirPath_as_Prefix(unsigned dirIndex) const | 164 | |
| 165 | void CProxyArc::GetDirPath_as_Prefix_from_Base(const unsigned dirIndex, | ||
| 166 | UString &prefix, const unsigned baseDirIndex) const | ||
| 117 | { | 167 | { |
| 118 | UString s; | 168 | prefix.Empty(); |
| 119 | // while (dirIndex != -1) | 169 | if (dirIndex == baseDirIndex) |
| 120 | for (;;) | 170 | return; |
| 171 | unsigned len = 0; | ||
| 172 | unsigned i = dirIndex; | ||
| 173 | do | ||
| 121 | { | 174 | { |
| 122 | const CProxyDir &dir = Dirs[dirIndex]; | 175 | const CProxyDir &dir = Dirs[i]; |
| 123 | dirIndex = (unsigned)dir.ParentDir; | 176 | len += dir.NameLen + 1; |
| 124 | if (dir.ParentDir == -1) | 177 | i = (unsigned)dir.ParentDir; |
| 125 | break; | 178 | } |
| 126 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); | 179 | while (i != baseDirIndex); |
| 127 | s.Insert(0, dir.Name); | 180 | |
| 128 | // 22.00: we normalize name | 181 | wchar_t *p = prefix.GetBuf_SetEnd(len) + len; |
| 129 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s.GetBuf(), MyStringLen(dir.Name)); | 182 | i = dirIndex; |
| 183 | do | ||
| 184 | { | ||
| 185 | const CProxyDir &dir = Dirs[i]; | ||
| 186 | *--p = WCHAR_PATH_SEPARATOR; | ||
| 187 | p -= dir.NameLen; | ||
| 188 | wmemcpy(p, dir.Name, dir.NameLen); | ||
| 189 | i = (unsigned)dir.ParentDir; | ||
| 130 | } | 190 | } |
| 191 | while (i != baseDirIndex); | ||
| 192 | } | ||
| 193 | |||
| 194 | UString CProxyArc::GetDirPath_as_Prefix(const unsigned dirIndex) const | ||
| 195 | { | ||
| 196 | UString s; | ||
| 197 | GetDirPath_as_Prefix_from_Base(dirIndex, s, k_Proxy_RootDirIndex); | ||
| 131 | return s; | 198 | return s; |
| 132 | } | 199 | } |
| 133 | 200 | ||
| 134 | void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const | 201 | void CProxyArc::AddRealIndices(const unsigned dirIndex, CUIntVector &realIndices) const |
| 135 | { | 202 | { |
| 136 | const CProxyDir &dir = Dirs[dirIndex]; | 203 | const CProxyDir &dir = Dirs[dirIndex]; |
| 137 | if (dir.IsLeaf()) | 204 | if (dir.IsLeaf()) |
| @@ -143,7 +210,7 @@ void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) cons | |||
| 143 | realIndices.Add(dir.SubFiles[i]); | 210 | realIndices.Add(dir.SubFiles[i]); |
| 144 | } | 211 | } |
| 145 | 212 | ||
| 146 | int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const | 213 | int CProxyArc::GetRealIndex(const unsigned dirIndex, const unsigned index) const |
| 147 | { | 214 | { |
| 148 | const CProxyDir &dir = Dirs[dirIndex]; | 215 | const CProxyDir &dir = Dirs[dirIndex]; |
| 149 | const unsigned numDirItems = dir.SubDirs.Size(); | 216 | const unsigned numDirItems = dir.SubDirs.Size(); |
| @@ -157,7 +224,8 @@ int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const | |||
| 157 | return (int)dir.SubFiles[index - numDirItems]; | 224 | return (int)dir.SubFiles[index - numDirItems]; |
| 158 | } | 225 | } |
| 159 | 226 | ||
| 160 | void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const | 227 | void CProxyArc::GetRealIndices_Unsorted(unsigned dirIndex, |
| 228 | const UInt32 *indices, const UInt32 numItems, CUIntVector &realIndices) const | ||
| 161 | { | 229 | { |
| 162 | const CProxyDir &dir = Dirs[dirIndex]; | 230 | const CProxyDir &dir = Dirs[dirIndex]; |
| 163 | realIndices.Clear(); | 231 | realIndices.Clear(); |
| @@ -170,11 +238,9 @@ void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 | |||
| 170 | else | 238 | else |
| 171 | realIndices.Add(dir.SubFiles[index - numDirItems]); | 239 | realIndices.Add(dir.SubFiles[index - numDirItems]); |
| 172 | } | 240 | } |
| 173 | HeapSort(realIndices.NonConstData(), realIndices.Size()); | 241 | // HeapSort(realIndices.NonConstData(), realIndices.Size()); |
| 174 | } | 242 | } |
| 175 | 243 | ||
| 176 | /////////////////////////////////////////////// | ||
| 177 | // CProxyArc | ||
| 178 | 244 | ||
| 179 | static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size) | 245 | static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size) |
| 180 | { | 246 | { |
| @@ -185,51 +251,68 @@ static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &si | |||
| 185 | return ConvertPropVariantToUInt64(prop, size); | 251 | return ConvertPropVariantToUInt64(prop, size); |
| 186 | } | 252 | } |
| 187 | 253 | ||
| 188 | void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive) | 254 | void CProxyArc::CalculateSizes(IInArchive *archive) |
| 189 | { | 255 | { |
| 190 | CProxyDir &dir = Dirs[dirIndex]; | 256 | CUIntVector vec; |
| 191 | dir.Size = dir.PackSize = 0; | 257 | unsigned dirIndex = 0, i = 0; |
| 192 | dir.NumSubDirs = dir.SubDirs.Size(); | 258 | for (;;) |
| 193 | dir.NumSubFiles = dir.SubFiles.Size(); | ||
| 194 | dir.CrcIsDefined = true; | ||
| 195 | dir.Crc = 0; | ||
| 196 | |||
| 197 | unsigned i; | ||
| 198 | |||
| 199 | for (i = 0; i < dir.SubFiles.Size(); i++) | ||
| 200 | { | 259 | { |
| 201 | const UInt32 index = (UInt32)dir.SubFiles[i]; | 260 | CProxyDir &dir = Dirs[dirIndex]; |
| 202 | UInt64 size, packSize; | 261 | if (i == 0) |
| 203 | const bool sizeDefined = GetSize(archive, index, kpidSize, size); | ||
| 204 | dir.Size += size; | ||
| 205 | GetSize(archive, index, kpidPackSize, packSize); | ||
| 206 | dir.PackSize += packSize; | ||
| 207 | { | 262 | { |
| 208 | NCOM::CPropVariant prop; | 263 | dir.Size = dir.PackSize = 0; |
| 209 | if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) | 264 | dir.NumSubDirs = dir.SubDirs.Size(); |
| 265 | dir.NumSubFiles = dir.SubFiles.Size(); | ||
| 266 | dir.CrcIsDefined = true; | ||
| 267 | dir.Crc = 0; | ||
| 268 | |||
| 269 | FOR_VECTOR (k, dir.SubFiles) | ||
| 210 | { | 270 | { |
| 211 | if (prop.vt == VT_UI4) | 271 | const UInt32 index = (UInt32)dir.SubFiles[k]; |
| 212 | dir.Crc += prop.ulVal; | 272 | UInt64 size, packSize; |
| 213 | else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined) | 273 | const bool sizeDefined = GetSize(archive, index, kpidSize, size); |
| 214 | dir.CrcIsDefined = false; | 274 | dir.Size += size; |
| 275 | GetSize(archive, index, kpidPackSize, packSize); | ||
| 276 | dir.PackSize += packSize; | ||
| 277 | { | ||
| 278 | NCOM::CPropVariant prop; | ||
| 279 | if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) | ||
| 280 | { | ||
| 281 | if (prop.vt == VT_UI4) | ||
| 282 | dir.Crc += prop.ulVal; | ||
| 283 | else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined) | ||
| 284 | dir.CrcIsDefined = false; | ||
| 285 | } | ||
| 286 | else | ||
| 287 | dir.CrcIsDefined = false; | ||
| 288 | } | ||
| 215 | } | 289 | } |
| 216 | else | ||
| 217 | dir.CrcIsDefined = false; | ||
| 218 | } | 290 | } |
| 219 | } | 291 | |
| 220 | 292 | if (i == dir.SubDirs.Size()) | |
| 221 | for (i = 0; i < dir.SubDirs.Size(); i++) | 293 | { |
| 222 | { | 294 | const unsigned num = vec.Size(); |
| 223 | unsigned subDirIndex = dir.SubDirs[i]; | 295 | if (num < 2) |
| 224 | CalculateSizes(subDirIndex, archive); | 296 | return; |
| 225 | CProxyDir &f = Dirs[subDirIndex]; | 297 | dirIndex = vec[num - 2]; |
| 226 | dir.Size += f.Size; | 298 | i = vec[num - 1]; |
| 227 | dir.PackSize += f.PackSize; | 299 | vec.DeleteFrom(num - 2); |
| 228 | dir.NumSubFiles += f.NumSubFiles; | 300 | |
| 229 | dir.NumSubDirs += f.NumSubDirs; | 301 | CProxyDir &dir2 = Dirs[dirIndex]; |
| 230 | dir.Crc += f.Crc; | 302 | dir2.Size += dir.Size; |
| 231 | if (!f.CrcIsDefined) | 303 | dir2.PackSize += dir.PackSize; |
| 232 | dir.CrcIsDefined = false; | 304 | dir2.NumSubFiles += dir.NumSubFiles; |
| 305 | dir2.NumSubDirs += dir.NumSubDirs; | ||
| 306 | dir2.Crc += dir.Crc; | ||
| 307 | if (!dir.CrcIsDefined) | ||
| 308 | dir2.CrcIsDefined = false; | ||
| 309 | continue; | ||
| 310 | } | ||
| 311 | |||
| 312 | vec.Add(dirIndex); | ||
| 313 | vec.Add(i + 1); | ||
| 314 | dirIndex = dir.SubDirs[i]; | ||
| 315 | i = 0; | ||
| 233 | } | 316 | } |
| 234 | } | 317 | } |
| 235 | 318 | ||
| @@ -246,42 +329,54 @@ void CProxyArc::FreeFiles() | |||
| 246 | Files = NULL; | 329 | Files = NULL; |
| 247 | } | 330 | } |
| 248 | 331 | ||
| 332 | |||
| 333 | static void SetPath_as_LONG_PATH(UString &s, | ||
| 334 | const unsigned fileIndex, const bool isDir) | ||
| 335 | { | ||
| 336 | s = isDir ? "[LONG_PATH_DIR_" : "[LONG_PATH_FILE_"; | ||
| 337 | s.Add_UInt32((UInt32)fileIndex); | ||
| 338 | s.Add_Char(']'); | ||
| 339 | } | ||
| 340 | |||
| 341 | |||
| 249 | static const UInt32 k_NumFiles_Max = 0x7fffffff - 15; | 342 | static const UInt32 k_NumFiles_Max = 0x7fffffff - 15; |
| 250 | 343 | ||
| 251 | HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | 344 | HRESULT CProxyArc::Load(const CArc &arc, IArchiveOpenCallback *progress) |
| 252 | { | 345 | { |
| 253 | // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { | 346 | // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { |
| 254 | |||
| 255 | FreeFiles(); | 347 | FreeFiles(); |
| 256 | Dirs.Clear(); | 348 | Dirs.Clear(); |
| 349 | Are_Changed_LongPaths = false; | ||
| 257 | 350 | ||
| 258 | Dirs.AddNew(); | 351 | Dirs.AddNew(); |
| 259 | IInArchive *archive = arc.Archive; | 352 | IInArchive *archive = arc.Archive; |
| 260 | |||
| 261 | UInt32 numItems; | 353 | UInt32 numItems; |
| 262 | RINOK(archive->GetNumberOfItems(&numItems)) | 354 | RINOK(archive->GetNumberOfItems(&numItems)) |
| 263 | if (numItems > k_NumFiles_Max) | 355 | if (numItems > k_NumFiles_Max) |
| 264 | return E_OUTOFMEMORY; | 356 | return E_OUTOFMEMORY; |
| 265 | |||
| 266 | if (progress) | 357 | if (progress) |
| 267 | RINOK(progress->SetTotal(numItems)) | 358 | { |
| 359 | const UInt64 numItems64 = numItems; | ||
| 360 | RINOK(progress->SetTotal(&numItems64, NULL)) | ||
| 361 | } | ||
| 268 | 362 | ||
| 363 | MemUsage = (UInt64)numItems * sizeof(*Files); | ||
| 364 | CHECK_MEM_USAGE | ||
| 269 | Z7_ARRAY_NEW(Files, CProxyFile, numItems) | 365 | Z7_ARRAY_NEW(Files, CProxyFile, numItems) |
| 270 | memset(Files, 0, (size_t)numItems * sizeof(*Files)); | 366 | memset(Files, 0, (size_t)numItems * sizeof(*Files)); |
| 271 | NumFiles = numItems; | 367 | NumFiles = numItems; |
| 272 | 368 | ||
| 273 | UString path; | 369 | UString path, name; |
| 274 | UString name; | ||
| 275 | NCOM::CPropVariant prop; | 370 | NCOM::CPropVariant prop; |
| 276 | 371 | ||
| 277 | for (UInt32 i = 0; i < numItems; i++) | 372 | for (UInt32 i = 0; i < numItems; i++) |
| 278 | { | 373 | { |
| 374 | CHECK_MEM_USAGE | ||
| 279 | if (progress && (i & 0xFFFF) == 0) | 375 | if (progress && (i & 0xFFFF) == 0) |
| 280 | { | 376 | { |
| 281 | const UInt64 currentItemIndex = i; | 377 | const UInt64 currentItemIndex = i; |
| 282 | RINOK(progress->SetCompleted(¤tItemIndex)) | 378 | RINOK(progress->SetCompleted(¤tItemIndex, NULL)) |
| 283 | } | 379 | } |
| 284 | |||
| 285 | const wchar_t *s = NULL; | 380 | const wchar_t *s = NULL; |
| 286 | unsigned len = 0; | 381 | unsigned len = 0; |
| 287 | bool isPtrName = false; | 382 | bool isPtrName = false; |
| @@ -313,6 +408,7 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 313 | if (!s) | 408 | if (!s) |
| 314 | #endif | 409 | #endif |
| 315 | { | 410 | { |
| 411 | len = 0; | ||
| 316 | prop.Clear(); | 412 | prop.Clear(); |
| 317 | RINOK(arc.Archive->GetProperty(i, kpidPath, &prop)) | 413 | RINOK(arc.Archive->GetProperty(i, kpidPath, &prop)) |
| 318 | if (prop.vt == VT_BSTR) | 414 | if (prop.vt == VT_BSTR) |
| @@ -328,7 +424,6 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 328 | len = path.Len(); | 424 | len = path.Len(); |
| 329 | s = path; | 425 | s = path; |
| 330 | } | 426 | } |
| 331 | |||
| 332 | /* | 427 | /* |
| 333 | RINOK(arc.GetItemPath(i, path)); | 428 | RINOK(arc.GetItemPath(i, path)); |
| 334 | len = path.Len(); | 429 | len = path.Len(); |
| @@ -337,7 +432,6 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 337 | } | 432 | } |
| 338 | 433 | ||
| 339 | unsigned curItem = 0; | 434 | unsigned curItem = 0; |
| 340 | |||
| 341 | /* | 435 | /* |
| 342 | if (arc.Ask_Deleted) | 436 | if (arc.Ask_Deleted) |
| 343 | { | 437 | { |
| @@ -347,12 +441,22 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 347 | curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]"); | 441 | curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]"); |
| 348 | } | 442 | } |
| 349 | */ | 443 | */ |
| 350 | |||
| 351 | unsigned namePos = 0; | 444 | unsigned namePos = 0; |
| 352 | |||
| 353 | unsigned numLevels = 0; | 445 | unsigned numLevels = 0; |
| 446 | bool is_Changed_LongPath = false; | ||
| 447 | bool isDir; | ||
| 448 | RINOK(Archive_IsItem_Dir(archive, i, isDir)) | ||
| 354 | 449 | ||
| 355 | for (unsigned j = 0; j < len; j++) | 450 | if (len >= (1 << 15)) |
| 451 | { | ||
| 452 | Are_Changed_LongPaths = true; | ||
| 453 | is_Changed_LongPath = true; | ||
| 454 | SetPath_as_LONG_PATH(path, i, isDir); | ||
| 455 | s = path; | ||
| 456 | len = path.Len(); | ||
| 457 | isPtrName = false; | ||
| 458 | } | ||
| 459 | else for (unsigned j = 0; j < len; j++) | ||
| 356 | { | 460 | { |
| 357 | const wchar_t c = s[j]; | 461 | const wchar_t c = s[j]; |
| 358 | if (c == L'/' | 462 | if (c == L'/' |
| @@ -365,12 +469,18 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 365 | if (numLevels <= kLevelLimit) | 469 | if (numLevels <= kLevelLimit) |
| 366 | { | 470 | { |
| 367 | if (numLevels == kLevelLimit) | 471 | if (numLevels == kLevelLimit) |
| 472 | { | ||
| 368 | name = "[LONG_PATH]"; | 473 | name = "[LONG_PATH]"; |
| 474 | Are_Changed_LongPaths = true; | ||
| 475 | is_Changed_LongPath = true; | ||
| 476 | } | ||
| 369 | else | 477 | else |
| 370 | name.SetFrom(s + namePos, j - namePos); | 478 | name.SetFrom(s + namePos, j - namePos); |
| 371 | // 22.00: we can normalize dir here | 479 | // 22.00: we can normalize dir here |
| 372 | // NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); | 480 | // NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); |
| 373 | curItem = AddDir(curItem, -1, name); | 481 | curItem = AddDir(curItem, -1, name); |
| 482 | if (is_Changed_LongPath) | ||
| 483 | Dirs[curItem].Is_Changed_LongPath = true; | ||
| 374 | } | 484 | } |
| 375 | namePos = j + 1; | 485 | namePos = j + 1; |
| 376 | numLevels++; | 486 | numLevels++; |
| @@ -378,24 +488,16 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 378 | } | 488 | } |
| 379 | 489 | ||
| 380 | /* | 490 | /* |
| 381 | that code must be implemeted to hide alt streams in list. | 491 | that code must be implemented to hide alt streams in list. |
| 382 | if (arc.Ask_AltStreams) | 492 | if (arc.Ask_AltStreams) |
| 383 | { | 493 | { |
| 384 | bool isAltStream; | 494 | bool isAltStream; |
| 385 | RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); | 495 | RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); |
| 386 | if (isAltStream) | 496 | if (isAltStream){} |
| 387 | { | ||
| 388 | |||
| 389 | } | ||
| 390 | } | 497 | } |
| 391 | */ | 498 | */ |
| 392 | |||
| 393 | bool isDir; | ||
| 394 | RINOK(Archive_IsItem_Dir(archive, i, isDir)) | ||
| 395 | |||
| 396 | CProxyFile &f = Files[i]; | 499 | CProxyFile &f = Files[i]; |
| 397 | f.Construct(); // optional because memset() in code above | 500 | f.Construct(); // optional because memset() in code above |
| 398 | |||
| 399 | f.NameLen = len - namePos; | 501 | f.NameLen = len - namePos; |
| 400 | s += namePos; | 502 | s += namePos; |
| 401 | 503 | ||
| @@ -403,6 +505,7 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 403 | f.Name = s; | 505 | f.Name = s; |
| 404 | else | 506 | else |
| 405 | { | 507 | { |
| 508 | MemUsage += 16 + (size_t)f.NameLen * sizeof(*f.Name); | ||
| 406 | f.Name = AllocStringAndCopy(s, f.NameLen); | 509 | f.Name = AllocStringAndCopy(s, f.NameLen); |
| 407 | f.NeedDeleteName = true; | 510 | f.NeedDeleteName = true; |
| 408 | } | 511 | } |
| @@ -412,16 +515,30 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 412 | name = s; | 515 | name = s; |
| 413 | // 22.00: we can normalize dir here | 516 | // 22.00: we can normalize dir here |
| 414 | // NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); | 517 | // NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); |
| 415 | AddDir(curItem, (int)i, name); | 518 | curItem = AddDir(curItem, (int)i, name); |
| 519 | if (is_Changed_LongPath) | ||
| 520 | Dirs[curItem].Is_Changed_LongPath = true; | ||
| 416 | } | 521 | } |
| 417 | else | 522 | else |
| 523 | { | ||
| 524 | MemUsage += Dirs[curItem].SubFiles.IsEmpty() ? 16u : 4u + 1; | ||
| 418 | Dirs[curItem].SubFiles.Add(i); | 525 | Dirs[curItem].SubFiles.Add(i); |
| 526 | } | ||
| 419 | } | 527 | } |
| 420 | |||
| 421 | CalculateSizes(0, archive); | ||
| 422 | 528 | ||
| 529 | FOR_VECTOR (k, Dirs) | ||
| 530 | { | ||
| 531 | MergeSubDirs(Dirs[k]); | ||
| 532 | Dirs[k].SubDirs2.ClearAndFree(); // these arryas are small | ||
| 533 | } | ||
| 534 | |||
| 535 | CalculateSizes(archive); | ||
| 536 | if (progress) | ||
| 537 | { | ||
| 538 | const UInt64 numItems64 = numItems; | ||
| 539 | RINOK(progress->SetCompleted(&numItems64, NULL)) | ||
| 540 | } | ||
| 423 | // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s); | 541 | // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s); |
| 424 | |||
| 425 | return S_OK; | 542 | return S_OK; |
| 426 | } | 543 | } |
| 427 | 544 | ||
| @@ -429,12 +546,38 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) | |||
| 429 | 546 | ||
| 430 | // ---------- for Tree-mode archive ---------- | 547 | // ---------- for Tree-mode archive ---------- |
| 431 | 548 | ||
| 432 | void CProxyArc2::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const | 549 | |
| 550 | void SetDirPrefix_as_LONG_PATH(UString &s, unsigned fileIndex, | ||
| 551 | const bool asAltDirPrefix, const bool isDir) | ||
| 552 | { | ||
| 553 | SetPath_as_LONG_PATH(s, fileIndex, isDir); | ||
| 554 | s.Add_Char(asAltDirPrefix ? ':' : CHAR_PATH_SEPARATOR); | ||
| 555 | } | ||
| 556 | |||
| 557 | |||
| 558 | bool CProxyArc2::IsAltDir(const unsigned dirIndex) const | ||
| 559 | { | ||
| 560 | if (dirIndex == k_Proxy2_RootDirIndex) | ||
| 561 | return false; | ||
| 562 | if (dirIndex == k_Proxy2_AltRootDirIndex) | ||
| 563 | return true; | ||
| 564 | const CProxyDir2 &dir = Dirs[dirIndex]; | ||
| 565 | if ((unsigned)dir.ArcIndex >= NumFiles) throw 1; // optional | ||
| 566 | return (int)dirIndex == Files[(unsigned)dir.ArcIndex].AltDirIndex; | ||
| 567 | } | ||
| 568 | |||
| 569 | |||
| 570 | /* called from: | ||
| 571 | Agent.cpp: | ||
| 572 | CAgentFolder::Extract() | ||
| 573 | ArchiveFolderOut.cpp: | ||
| 574 | CAgentFolder::GetPathParts() | ||
| 575 | CAgentFolder::CommonUpdateOperation() | ||
| 576 | */ | ||
| 577 | void CProxyArc2::GetDirPathParts(const unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const | ||
| 433 | { | 578 | { |
| 434 | pathParts.Clear(); | 579 | pathParts.Clear(); |
| 435 | |||
| 436 | isAltStreamDir = false; | 580 | isAltStreamDir = false; |
| 437 | |||
| 438 | if (dirIndex == k_Proxy2_RootDirIndex) | 581 | if (dirIndex == k_Proxy2_RootDirIndex) |
| 439 | return; | 582 | return; |
| 440 | if (dirIndex == k_Proxy2_AltRootDirIndex) | 583 | if (dirIndex == k_Proxy2_AltRootDirIndex) |
| @@ -442,94 +585,220 @@ void CProxyArc2::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bo | |||
| 442 | isAltStreamDir = true; | 585 | isAltStreamDir = true; |
| 443 | return; | 586 | return; |
| 444 | } | 587 | } |
| 445 | 588 | int fileIndex = Dirs[dirIndex].ArcIndex; | |
| 446 | while (dirIndex >= k_Proxy2_NumRootDirs) | 589 | do |
| 447 | { | 590 | { |
| 448 | const CProxyDir2 &dir = Dirs[dirIndex]; | 591 | if ((unsigned)fileIndex >= NumFiles) throw 1; // optional |
| 449 | const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex]; | 592 | const CProxyFile2 &file = Files[(unsigned)fileIndex]; |
| 450 | if (pathParts.IsEmpty() && (int)dirIndex == file.AltDirIndex) | 593 | // if (pathParts.Size() == 0) // optional |
| 594 | if ((int)dirIndex == file.AltDirIndex) | ||
| 451 | isAltStreamDir = true; | 595 | isAltStreamDir = true; |
| 596 | // that code is not optimized for big number of loop iterations. | ||
| 452 | pathParts.Insert(0, file.Name); | 597 | pathParts.Insert(0, file.Name); |
| 453 | const int par = file.Parent; | 598 | fileIndex = file.Parent; |
| 454 | if (par == -1) | ||
| 455 | break; | ||
| 456 | dirIndex = (unsigned)Files[(unsigned)par].DirIndex; | ||
| 457 | // if ((int)dirIndex == -1) break; | ||
| 458 | } | 599 | } |
| 600 | while (fileIndex != -1); | ||
| 459 | } | 601 | } |
| 460 | 602 | ||
| 461 | bool CProxyArc2::IsAltDir(unsigned dirIndex) const | 603 | |
| 604 | // if Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX is defined, | ||
| 605 | // { this code is unused mostly. 7-Zip gets prefix via GetItemPrefix(). } | ||
| 606 | void CProxyArc2::GetDirPath_as_Prefix_from_Base(const unsigned dirIndex, | ||
| 607 | UString &prefix, const unsigned baseDirIndex, const unsigned lenLimit) const | ||
| 462 | { | 608 | { |
| 463 | if (dirIndex == k_Proxy2_RootDirIndex) | 609 | prefix.Empty(); |
| 464 | return false; | 610 | if (dirIndex == baseDirIndex) |
| 611 | return; | ||
| 465 | if (dirIndex == k_Proxy2_AltRootDirIndex) | 612 | if (dirIndex == k_Proxy2_AltRootDirIndex) |
| 466 | return true; | 613 | { |
| 467 | const CProxyDir2 &dir = Dirs[dirIndex]; | 614 | // (baseDirIndex == k_Proxy2_RootDirIndex) is expected |
| 468 | const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex]; | 615 | prefix.Add_Colon(); |
| 469 | return ((int)dirIndex == file.AltDirIndex); | 616 | return; |
| 470 | } | 617 | } |
| 471 | 618 | ||
| 472 | UString CProxyArc2::GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const | ||
| 473 | { | ||
| 474 | isAltStreamDir = false; | ||
| 475 | const CProxyDir2 &dir = Dirs[dirIndex]; | 619 | const CProxyDir2 &dir = Dirs[dirIndex]; |
| 476 | if (dirIndex == k_Proxy2_AltRootDirIndex) | 620 | int arcIndex = dir.ArcIndex; |
| 477 | isAltStreamDir = true; | 621 | if (arcIndex != -1) |
| 478 | else if (dirIndex >= k_Proxy2_NumRootDirs) | ||
| 479 | { | 622 | { |
| 480 | const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex]; | 623 | const CProxyDir2 &baseDir = Dirs[baseDirIndex]; |
| 481 | isAltStreamDir = ((int)dirIndex == file.AltDirIndex); | 624 | unsigned len = dir.PrefixLen - baseDir.PrefixLen; |
| 625 | if (len >= lenLimit) | ||
| 626 | { | ||
| 627 | const CProxyFile2 &file = Files[(unsigned)arcIndex]; | ||
| 628 | SetDirPrefix_as_LONG_PATH(prefix, (unsigned)arcIndex, | ||
| 629 | (int)dirIndex == file.AltDirIndex, // asAltDir, | ||
| 630 | file.IsDir()); | ||
| 631 | return; | ||
| 632 | } | ||
| 633 | const int baseArcIndex = baseDir.ArcIndex; | ||
| 634 | wchar_t * const p = prefix.GetBuf_SetEnd(len); | ||
| 635 | do | ||
| 636 | { | ||
| 637 | const CProxyFile2 &file = Files[(unsigned)arcIndex]; | ||
| 638 | wchar_t c = CHAR_PATH_SEPARATOR; | ||
| 639 | if ((int)dirIndex == file.AltDirIndex) | ||
| 640 | c = ':'; | ||
| 641 | if (len <= file.NameLen) | ||
| 642 | break; | ||
| 643 | p[--len] = c; | ||
| 644 | len -= file.NameLen; | ||
| 645 | wmemcpy(p + len, file.Name, file.NameLen); | ||
| 646 | // slash normalization can be omitted, if we want max speed of sorting operation: | ||
| 647 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(p + len, file.NameLen); | ||
| 648 | arcIndex = file.Parent; | ||
| 649 | if (arcIndex == baseArcIndex) | ||
| 650 | { | ||
| 651 | if (len) | ||
| 652 | break; | ||
| 653 | return; | ||
| 654 | } | ||
| 655 | } | ||
| 656 | while (arcIndex != -1); | ||
| 482 | } | 657 | } |
| 483 | return dir.PathPrefix; | 658 | throw 1; |
| 484 | } | 659 | } |
| 485 | 660 | ||
| 486 | void CProxyArc2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const | 661 | |
| 662 | /* called from: | ||
| 663 | Agent.cpp: | ||
| 664 | CAgentFolder::GetFullPrefix() | ||
| 665 | CAgent::RenameItem() in AgentOut.cpp | ||
| 666 | CAgentFolder::GetFolderProperty(kpidPath) | ||
| 667 | GetFolderPath() in PanelFolderChange.cpp | ||
| 668 | LoadFullPath() | ||
| 669 | AgentOut.cpp: | ||
| 670 | CAgent::SetFolder() | ||
| 671 | CAgentFolder::CommonUpdateOperation() in ArchiveFolderOut.cpp | ||
| 672 | CAgent::CreateFolder() | ||
| 673 | */ | ||
| 674 | UString CProxyArc2::GetDirPath_as_Prefix(const unsigned dirIndex, const bool canReducePath) const | ||
| 675 | { | ||
| 676 | UString s; | ||
| 677 | const unsigned lenLimit = canReducePath ? (1u << 14) : (1u << 28); | ||
| 678 | GetDirPath_as_Prefix_from_Base(dirIndex, s, k_Proxy2_RootDirIndex, lenLimit); | ||
| 679 | return s; | ||
| 680 | } | ||
| 681 | |||
| 682 | |||
| 683 | void CProxyArc2::AddRealIndices_of_ArcItem(const unsigned arcIndex, | ||
| 684 | const bool includeAltStreams, const bool includeDirSubItems, | ||
| 685 | CUIntVector &realIndices) const | ||
| 487 | { | 686 | { |
| 488 | realIndices.Add(arcIndex); | 687 | realIndices.Add(arcIndex); |
| 489 | const CProxyFile2 &file = Files[arcIndex]; | 688 | const CProxyFile2 &file = Files[arcIndex]; |
| 490 | if (file.DirIndex != -1) | 689 | if (includeDirSubItems && file.DirIndex != -1) |
| 491 | AddRealIndices_of_Dir((unsigned)file.DirIndex, includeAltStreams, realIndices); | 690 | AddRealIndices_of_Dir((unsigned)file.DirIndex, includeAltStreams, realIndices); |
| 492 | if (includeAltStreams && file.AltDirIndex != -1) | 691 | if (includeAltStreams && file.AltDirIndex != -1) |
| 493 | AddRealIndices_of_Dir((unsigned)file.AltDirIndex, includeAltStreams, realIndices); | 692 | AddRealIndices_of_Dir((unsigned)file.AltDirIndex, includeAltStreams, realIndices); |
| 494 | } | 693 | } |
| 495 | 694 | ||
| 496 | void CProxyArc2::AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const | 695 | |
| 696 | void CProxyArc2::AddRealIndices_of_Dir(unsigned dirIndex, | ||
| 697 | const bool includeAltStreams, | ||
| 698 | CUIntVector &realIndices) const | ||
| 497 | { | 699 | { |
| 498 | const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items; | 700 | CUIntVector vec; |
| 499 | FOR_VECTOR (i, subFiles) | 701 | unsigned i = 0; |
| 702 | for (;;) | ||
| 500 | { | 703 | { |
| 501 | AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices); | 704 | const CProxyDir2 &dir = Dirs[dirIndex]; |
| 705 | if (i == dir.Items.Size()) | ||
| 706 | { | ||
| 707 | const unsigned num = vec.Size(); | ||
| 708 | if (num < 2) | ||
| 709 | return; | ||
| 710 | dirIndex = vec[num - 2]; | ||
| 711 | i = vec[num - 1]; | ||
| 712 | vec.DeleteFrom(num - 2); | ||
| 713 | continue; | ||
| 714 | } | ||
| 715 | |||
| 716 | const unsigned arcIndex = dir.Items[i]; | ||
| 717 | i++; | ||
| 718 | realIndices.Add(arcIndex); | ||
| 719 | const CProxyFile2 &file = Files[arcIndex]; | ||
| 720 | if (includeAltStreams && file.AltDirIndex != -1) | ||
| 721 | AddRealIndices_of_Dir((unsigned)file.AltDirIndex, includeAltStreams, realIndices); | ||
| 722 | if (file.DirIndex != -1) | ||
| 723 | { | ||
| 724 | vec.Add(dirIndex); | ||
| 725 | vec.Add(i); | ||
| 726 | dirIndex = (unsigned)file.DirIndex; | ||
| 727 | i = 0; | ||
| 728 | } | ||
| 502 | } | 729 | } |
| 503 | } | 730 | } |
| 504 | 731 | ||
| 505 | unsigned CProxyArc2::GetRealIndex(unsigned dirIndex, unsigned index) const | ||
| 506 | { | ||
| 507 | return Dirs[dirIndex].Items[index]; | ||
| 508 | } | ||
| 509 | 732 | ||
| 510 | void CProxyArc2::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const | 733 | void CProxyArc2::GetRealIndices_Unsorted(const unsigned dirIndex, |
| 734 | const UInt32 *indices, const UInt32 numItems, | ||
| 735 | const bool includeAltStreams, | ||
| 736 | CUIntVector &realIndices) const | ||
| 511 | { | 737 | { |
| 512 | const CProxyDir2 &dir = Dirs[dirIndex]; | 738 | const CUIntVector &items = Dirs[dirIndex].Items; |
| 513 | realIndices.Clear(); | 739 | realIndices.Clear(); |
| 514 | for (UInt32 i = 0; i < numItems; i++) | 740 | for (UInt32 i = 0; i < numItems; i++) |
| 515 | { | 741 | AddRealIndices_of_ArcItem(items[indices[i]], |
| 516 | AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices); | 742 | includeAltStreams, |
| 517 | } | 743 | true, // includeDirSubItems |
| 518 | HeapSort(realIndices.NonConstData(), realIndices.Size()); | 744 | realIndices); |
| 745 | // HeapSort(realIndices.NonConstData(), realIndices.Size()); | ||
| 519 | } | 746 | } |
| 520 | 747 | ||
| 521 | void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive) | 748 | |
| 522 | { | 749 | CProxyDir2::CProxyDir2(): |
| 523 | CProxyDir2 &dir = Dirs[dirIndex]; | 750 | ArcIndex(-1), |
| 524 | dir.Size = dir.PackSize = 0; | 751 | PrefixLen(0), |
| 525 | dir.NumSubDirs = 0; // dir.SubDirs.Size(); | 752 | Size(0), |
| 526 | dir.NumSubFiles = 0; // dir.Files.Size(); | 753 | PackSize(0), |
| 527 | dir.CrcIsDefined = true; | 754 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX |
| 528 | dir.Crc = 0; | 755 | IsLongPath(false), |
| 756 | #endif | ||
| 757 | CrcIsDefined(true), | ||
| 758 | Crc(0), | ||
| 759 | NumSubDirs(0), | ||
| 760 | NumSubFiles(0) | ||
| 761 | {} | ||
| 529 | 762 | ||
| 530 | FOR_VECTOR (i, dir.Items) | 763 | |
| 764 | HRESULT CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive | ||
| 765 | , IProgress *progress, const UInt64 *completed, unsigned &progressCounter) | ||
| 766 | { | ||
| 767 | CUIntVector vec; | ||
| 768 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | ||
| 769 | UString prefix, name; | ||
| 770 | #endif | ||
| 771 | unsigned i = 0; | ||
| 772 | for (;;) | ||
| 531 | { | 773 | { |
| 532 | UInt32 index = dir.Items[i]; | 774 | CProxyDir2 &dir = Dirs[dirIndex]; |
| 775 | // if (i == 0) {} // we can init some (dir) variables here instead of constructor | ||
| 776 | |||
| 777 | if (i == dir.Items.Size()) | ||
| 778 | { | ||
| 779 | const unsigned num = vec.Size(); | ||
| 780 | if (num < 2) | ||
| 781 | return S_OK; | ||
| 782 | dirIndex = vec[num - 2]; | ||
| 783 | i = vec[num - 1]; | ||
| 784 | vec.DeleteFrom(num - 2); | ||
| 785 | |||
| 786 | CProxyDir2 &dir2 = Dirs[dirIndex]; | ||
| 787 | dir2.Size += dir.Size; | ||
| 788 | dir2.PackSize += dir.PackSize; | ||
| 789 | dir2.NumSubFiles += dir.NumSubFiles; | ||
| 790 | dir2.NumSubDirs += dir.NumSubDirs; | ||
| 791 | dir2.Crc += dir.Crc; | ||
| 792 | if (!dir.CrcIsDefined) | ||
| 793 | dir2.CrcIsDefined = false; | ||
| 794 | continue; | ||
| 795 | } | ||
| 796 | |||
| 797 | if (progress && (++progressCounter & 0xfffff) == 0) | ||
| 798 | RINOK(progress->SetCompleted(completed)) | ||
| 799 | |||
| 800 | const UInt32 index = dir.Items[i]; | ||
| 801 | i++; | ||
| 533 | UInt64 size, packSize; | 802 | UInt64 size, packSize; |
| 534 | const bool sizeDefined = GetSize(archive, index, kpidSize, size); | 803 | const bool sizeDefined = GetSize(archive, index, kpidSize, size); |
| 535 | dir.Size += size; | 804 | dir.Size += size; |
| @@ -549,56 +818,77 @@ void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive) | |||
| 549 | } | 818 | } |
| 550 | 819 | ||
| 551 | const CProxyFile2 &subFile = Files[index]; | 820 | const CProxyFile2 &subFile = Files[index]; |
| 552 | if (subFile.DirIndex == -1) | 821 | |
| 553 | { | 822 | if (subFile.NameLen >= (1u << 30) - dir.PrefixLen) |
| 554 | dir.NumSubFiles++; | 823 | return E_NOTIMPL; |
| 555 | } | 824 | const unsigned prefixLen = dir.PrefixLen + subFile.NameLen + 1; |
| 556 | else | 825 | |
| 826 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | ||
| 827 | bool isLongPath = dir.IsLongPath; | ||
| 828 | if (subFile.AltDirIndex != -1 || subFile.DirIndex != -1) | ||
| 557 | { | 829 | { |
| 558 | // 22.00: we normalize name | 830 | // 22.00: we normalize name |
| 559 | UString s = subFile.Name; | 831 | name = subFile.Name; |
| 560 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s); | 832 | NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); |
| 561 | dir.NumSubDirs++; | 833 | if (!isLongPath) |
| 562 | CProxyDir2 &f = Dirs[subFile.DirIndex]; | 834 | { |
| 563 | f.PathPrefix = dir.PathPrefix + s + WCHAR_PATH_SEPARATOR; | 835 | prefix = dir.PathPrefix; |
| 564 | CalculateSizes((unsigned)subFile.DirIndex, archive); | 836 | prefix += name; |
| 565 | dir.Size += f.Size; | 837 | if (prefix.Len() >= (1u << 11)) // CProxyDir2::PathPrefix limit |
| 566 | dir.PackSize += f.PackSize; | 838 | isLongPath = true; |
| 567 | dir.NumSubFiles += f.NumSubFiles; | 839 | } |
| 568 | dir.NumSubDirs += f.NumSubDirs; | ||
| 569 | dir.Crc += f.Crc; | ||
| 570 | if (!f.CrcIsDefined) | ||
| 571 | dir.CrcIsDefined = false; | ||
| 572 | } | 840 | } |
| 841 | #endif | ||
| 573 | 842 | ||
| 574 | if (subFile.AltDirIndex == -1) | 843 | if (subFile.AltDirIndex != -1) |
| 575 | { | 844 | { |
| 576 | // dir.NumSubFiles++; | 845 | CProxyDir2 &f = Dirs[subFile.AltDirIndex]; |
| 846 | f.PrefixLen = prefixLen; | ||
| 847 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | ||
| 848 | f.IsLongPath = isLongPath; | ||
| 849 | if (isLongPath) | ||
| 850 | SetDirPrefix_as_LONG_PATH(prefix, index, | ||
| 851 | true, // asAltDirPrefix | ||
| 852 | subFile.IsDir()); | ||
| 853 | else | ||
| 854 | prefix.Add_Colon(); | ||
| 855 | f.PathPrefix = prefix; | ||
| 856 | UpdateMemUsage_with_StringLen(f.PathPrefix.Len()); | ||
| 857 | CHECK_MEM_USAGE | ||
| 858 | prefix.DeleteBack(); // we delete Colon character | ||
| 859 | #endif | ||
| 860 | RINOK(CalculateSizes((unsigned)subFile.AltDirIndex, archive, progress, completed, progressCounter)) | ||
| 577 | } | 861 | } |
| 862 | |||
| 863 | if (subFile.DirIndex == -1) | ||
| 864 | dir.NumSubFiles++; | ||
| 578 | else | 865 | else |
| 579 | { | 866 | { |
| 580 | // dir.NumSubDirs++; | 867 | CProxyDir2 &f = Dirs[subFile.DirIndex]; |
| 581 | CProxyDir2 &f = Dirs[subFile.AltDirIndex]; | 868 | f.PrefixLen = prefixLen; |
| 582 | f.PathPrefix = dir.PathPrefix + subFile.Name + L':'; | 869 | dir.NumSubDirs++; |
| 583 | CalculateSizes((unsigned)subFile.AltDirIndex, archive); | 870 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX |
| 871 | f.IsLongPath = isLongPath; | ||
| 872 | if (isLongPath) | ||
| 873 | SetDirPrefix_as_LONG_PATH(prefix, index, | ||
| 874 | false, // asAltDirPrefix | ||
| 875 | true); // isDir | ||
| 876 | else | ||
| 877 | prefix.Add_PathSepar(); | ||
| 878 | f.PathPrefix = prefix; | ||
| 879 | UpdateMemUsage_with_StringLen(f.PathPrefix.Len()); | ||
| 880 | CHECK_MEM_USAGE | ||
| 881 | #endif | ||
| 882 | if (vec.Size() >= (1u << 28)) // tree levels limit | ||
| 883 | return E_NOTIMPL; | ||
| 884 | vec.Add(dirIndex); | ||
| 885 | vec.Add(i); | ||
| 886 | dirIndex = (unsigned)subFile.DirIndex; | ||
| 887 | i = 0; | ||
| 584 | } | 888 | } |
| 585 | } | 889 | } |
| 586 | } | 890 | } |
| 587 | 891 | ||
| 588 | |||
| 589 | bool CProxyArc2::IsThere_SubDir(unsigned dirIndex, const UString &name) const | ||
| 590 | { | ||
| 591 | const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items; | ||
| 592 | FOR_VECTOR (i, subFiles) | ||
| 593 | { | ||
| 594 | const CProxyFile2 &file = Files[subFiles[i]]; | ||
| 595 | if (file.IsDir()) | ||
| 596 | if (CompareFileNames(name, file.Name) == 0) | ||
| 597 | return true; | ||
| 598 | } | ||
| 599 | return false; | ||
| 600 | } | ||
| 601 | |||
| 602 | 892 | ||
| 603 | void CProxyArc2::FreeFiles() | 893 | void CProxyArc2::FreeFiles() |
| 604 | { | 894 | { |
| @@ -612,54 +902,55 @@ void CProxyArc2::FreeFiles() | |||
| 612 | Files = NULL; | 902 | Files = NULL; |
| 613 | } | 903 | } |
| 614 | 904 | ||
| 905 | |||
| 906 | void CProxyArc2::AddDir(int arcIndex) | ||
| 907 | { | ||
| 908 | Dirs.AddNew().ArcIndex = arcIndex; | ||
| 909 | MemUsage += sizeof(Dirs[0]) + sizeof(void *) + 11; | ||
| 910 | } | ||
| 911 | |||
| 615 | HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) | 912 | HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) |
| 616 | { | 913 | { |
| 617 | if (!arc.GetRawProps) | 914 | if (!arc.GetRawProps) |
| 618 | return E_FAIL; | 915 | return E_FAIL; |
| 619 | |||
| 620 | // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { | 916 | // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { |
| 621 | 917 | ||
| 622 | Dirs.Clear(); | 918 | Dirs.Clear(); |
| 623 | FreeFiles(); | 919 | FreeFiles(); |
| 624 | 920 | ||
| 625 | IInArchive *archive = arc.Archive; | 921 | IInArchive *archive = arc.Archive; |
| 626 | |||
| 627 | UInt32 numItems; | 922 | UInt32 numItems; |
| 628 | RINOK(archive->GetNumberOfItems(&numItems)) | 923 | RINOK(archive->GetNumberOfItems(&numItems)) |
| 629 | if (numItems > k_NumFiles_Max) | 924 | if (numItems > k_NumFiles_Max) |
| 630 | return E_OUTOFMEMORY; | 925 | return E_OUTOFMEMORY; |
| 631 | if (progress) | 926 | if (progress) |
| 632 | RINOK(progress->SetTotal(numItems)) | 927 | RINOK(progress->SetTotal(numItems)) |
| 633 | UString fileName; | 928 | Dirs.AddNew(); // Dirs[0] - root dir |
| 634 | 929 | Dirs.AddNew() // Dirs[1] - for alt streams of root dir | |
| 635 | 930 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | |
| 636 | { | 931 | .PathPrefix.Add_Colon() // = ':'; |
| 637 | // Dirs[0] - root dir | 932 | #endif |
| 638 | /* CProxyDir2 &dir = */ Dirs.AddNew(); | 933 | ; |
| 639 | } | ||
| 640 | |||
| 641 | { | ||
| 642 | // Dirs[1] - for alt streams of root dir | ||
| 643 | CProxyDir2 &dir = Dirs.AddNew(); | ||
| 644 | dir.PathPrefix = ':'; | ||
| 645 | } | ||
| 646 | 934 | ||
| 935 | MemUsage = (UInt64)numItems * sizeof(*Files); | ||
| 936 | CHECK_MEM_USAGE | ||
| 647 | Z7_ARRAY_NEW(Files, CProxyFile2, numItems) | 937 | Z7_ARRAY_NEW(Files, CProxyFile2, numItems) |
| 648 | memset(Files, 0, (size_t)numItems * sizeof(*Files)); | 938 | memset(Files, 0, (size_t)numItems * sizeof(*Files)); |
| 649 | NumFiles = numItems; | 939 | NumFiles = numItems; |
| 650 | 940 | ||
| 941 | UString fileName; | ||
| 651 | UString tempUString; | 942 | UString tempUString; |
| 652 | AString tempAString; | 943 | AString tempAString; |
| 653 | 944 | ||
| 654 | UInt32 i; | 945 | UInt32 i; |
| 655 | for (i = 0; i < numItems; i++) | 946 | for (i = 0; i < numItems; i++) |
| 656 | { | 947 | { |
| 948 | CHECK_MEM_USAGE | ||
| 657 | if (progress && (i & 0xFFFFF) == 0) | 949 | if (progress && (i & 0xFFFFF) == 0) |
| 658 | { | 950 | { |
| 659 | const UInt64 currentItemIndex = i; | 951 | const UInt64 currentItemIndex = i; |
| 660 | RINOK(progress->SetCompleted(¤tItemIndex)) | 952 | RINOK(progress->SetCompleted(¤tItemIndex)) |
| 661 | } | 953 | } |
| 662 | |||
| 663 | CProxyFile2 &file = Files[i]; | 954 | CProxyFile2 &file = Files[i]; |
| 664 | file.Construct(); | 955 | file.Construct(); |
| 665 | 956 | ||
| @@ -668,7 +959,7 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) | |||
| 668 | UInt32 propType; | 959 | UInt32 propType; |
| 669 | RINOK(arc.GetRawProps->GetRawProp(i, kpidName, &p, &size, &propType)) | 960 | RINOK(arc.GetRawProps->GetRawProp(i, kpidName, &p, &size, &propType)) |
| 670 | 961 | ||
| 671 | #ifdef MY_CPU_LE | 962 | #ifdef MY_CPU_LE_ |
| 672 | if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) | 963 | if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) |
| 673 | { | 964 | { |
| 674 | file.Name = (const wchar_t *)p; | 965 | file.Name = (const wchar_t *)p; |
| @@ -677,58 +968,59 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) | |||
| 677 | file.NameLen = size / (unsigned)sizeof(wchar_t) - 1; | 968 | file.NameLen = size / (unsigned)sizeof(wchar_t) - 1; |
| 678 | } | 969 | } |
| 679 | else | 970 | else |
| 680 | #endif | 971 | #endif |
| 681 | if (p && propType == NPropDataType::kUtf8z) | ||
| 682 | { | ||
| 683 | tempAString = (const char *)p; | ||
| 684 | ConvertUTF8ToUnicode(tempAString, tempUString); | ||
| 685 | file.NameLen = tempUString.Len(); | ||
| 686 | file.Name = AllocStringAndCopy(tempUString); | ||
| 687 | file.NeedDeleteName = true; | ||
| 688 | } | ||
| 689 | else | ||
| 690 | { | 972 | { |
| 691 | NCOM::CPropVariant prop; | ||
| 692 | RINOK(arc.Archive->GetProperty(i, kpidName, &prop)) | ||
| 693 | const wchar_t *s; | 973 | const wchar_t *s; |
| 694 | if (prop.vt == VT_BSTR) | 974 | unsigned len; |
| 695 | s = prop.bstrVal; | 975 | if (p && propType == NPropDataType::kUtf8z) |
| 696 | else if (prop.vt == VT_EMPTY) | 976 | { |
| 697 | s = L"[Content]"; | 977 | tempAString = (const char *)p; |
| 978 | ConvertUTF8ToUnicode(tempAString, tempUString); | ||
| 979 | s = tempUString.Ptr(); | ||
| 980 | len = tempUString.Len(); | ||
| 981 | } | ||
| 698 | else | 982 | else |
| 699 | return E_FAIL; | 983 | { |
| 700 | file.NameLen = MyStringLen(s); | 984 | NCOM::CPropVariant prop; |
| 701 | file.Name = AllocStringAndCopy(s, file.NameLen); | 985 | RINOK(arc.Archive->GetProperty(i, kpidName, &prop)) |
| 986 | if (prop.vt == VT_BSTR) | ||
| 987 | s = prop.bstrVal; | ||
| 988 | else if (prop.vt == VT_EMPTY) | ||
| 989 | s = L"[Content]"; | ||
| 990 | else | ||
| 991 | return E_FAIL; | ||
| 992 | len = MyStringLen(s); | ||
| 993 | } | ||
| 994 | file.NameLen = len; | ||
| 995 | file.Name = AllocStringAndCopy(s, len); | ||
| 996 | UpdateMemUsage_with_StringLen(len); | ||
| 702 | file.NeedDeleteName = true; | 997 | file.NeedDeleteName = true; |
| 703 | } | 998 | } |
| 704 | 999 | ||
| 705 | UInt32 parent = (UInt32)(Int32)-1; | 1000 | UInt32 parent = (UInt32)(Int32)-1; |
| 706 | UInt32 parentType = 0; | 1001 | UInt32 parentType = 0; |
| 707 | RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType)) | 1002 | RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType)) |
| 1003 | if (parent >= numItems && parent != (UInt32)(Int32)-1) | ||
| 1004 | return E_FAIL; | ||
| 708 | file.Parent = (Int32)parent; | 1005 | file.Parent = (Int32)parent; |
| 709 | 1006 | /* | |
| 710 | if (arc.Ask_Deleted) | 1007 | if (arc.Ask_Deleted) |
| 711 | { | 1008 | { |
| 712 | bool isDeleted = false; | 1009 | bool isDeleted = false; |
| 713 | RINOK(Archive_IsItem_Deleted(archive, i, isDeleted)) | 1010 | RINOK(Archive_IsItem_Deleted(archive, i, isDeleted)) |
| 714 | if (isDeleted) | 1011 | if (isDeleted) {} |
| 715 | { | ||
| 716 | // continue; | ||
| 717 | // curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]"); | ||
| 718 | } | ||
| 719 | } | 1012 | } |
| 720 | 1013 | */ | |
| 721 | bool isDir; | 1014 | bool isDir; |
| 722 | RINOK(Archive_IsItem_Dir(archive, i, isDir)) | 1015 | RINOK(Archive_IsItem_Dir(archive, i, isDir)) |
| 723 | |||
| 724 | if (isDir) | 1016 | if (isDir) |
| 725 | { | 1017 | { |
| 726 | file.DirIndex = (int)Dirs.Size(); | 1018 | file.DirIndex = (int)Dirs.Size(); |
| 727 | CProxyDir2 &dir = Dirs.AddNew(); | 1019 | AddDir((int)i); // arcIndex |
| 728 | dir.ArcIndex = (int)i; | ||
| 729 | } | 1020 | } |
| 730 | if (arc.Ask_AltStream) | 1021 | if (arc.Ask_AltStream) |
| 731 | RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream)) | 1022 | RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream)) |
| 1023 | // if (file.IsAltStream) file.Parent = -1; // for debug | ||
| 732 | } | 1024 | } |
| 733 | 1025 | ||
| 734 | for (i = 0; i < numItems; i++) | 1026 | for (i = 0; i < numItems; i++) |
| @@ -746,8 +1038,7 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) | |||
| 746 | if (folderIndex2 == -1) | 1038 | if (folderIndex2 == -1) |
| 747 | { | 1039 | { |
| 748 | folderIndex2 = (int)Dirs.Size(); | 1040 | folderIndex2 = (int)Dirs.Size(); |
| 749 | CProxyDir2 &dir = Dirs.AddNew(); | 1041 | AddDir(file.Parent); // arcIndex |
| 750 | dir.ArcIndex = file.Parent; | ||
| 751 | } | 1042 | } |
| 752 | dirIndex = folderIndex2; | 1043 | dirIndex = folderIndex2; |
| 753 | } | 1044 | } |
| @@ -764,27 +1055,38 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) | |||
| 764 | } | 1055 | } |
| 765 | } | 1056 | } |
| 766 | 1057 | ||
| 1058 | MemUsage += Dirs[dirIndex].Items.IsEmpty() ? 16u : 4u + 1; | ||
| 1059 | CHECK_MEM_USAGE | ||
| 767 | Dirs[dirIndex].Items.Add(i); | 1060 | Dirs[dirIndex].Items.Add(i); |
| 768 | } | 1061 | } |
| 769 | 1062 | ||
| 1063 | unsigned progressCounter = 0; | ||
| 770 | for (i = 0; i < k_Proxy2_NumRootDirs; i++) | 1064 | for (i = 0; i < k_Proxy2_NumRootDirs; i++) |
| 771 | CalculateSizes(i, archive); | 1065 | { |
| 1066 | const UInt64 numItems64 = numItems; | ||
| 1067 | RINOK(CalculateSizes(i, archive, progress, &numItems64, progressCounter)) | ||
| 1068 | } | ||
| 1069 | // OutputDebugStringA("finished"); | ||
| 772 | 1070 | ||
| 773 | // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s); | 1071 | // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s); |
| 774 | |||
| 775 | return S_OK; | 1072 | return S_OK; |
| 776 | } | 1073 | } |
| 777 | 1074 | ||
| 778 | int CProxyArc2::FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const | 1075 | int CProxyArc2::FindItem(const unsigned dirIndex, const wchar_t *name, bool foldersOnly) const |
| 779 | { | 1076 | { |
| 780 | const CProxyDir2 &dir = Dirs[dirIndex]; | 1077 | int index = -1; |
| 781 | FOR_VECTOR (i, dir.Items) | 1078 | const CUIntVector &subFiles = Dirs[dirIndex].Items; |
| 1079 | FOR_VECTOR (i, subFiles) | ||
| 782 | { | 1080 | { |
| 783 | const CProxyFile2 &file = Files[dir.Items[i]]; | 1081 | const CProxyFile2 &file = Files[subFiles[i]]; |
| 784 | if (foldersOnly && file.DirIndex == -1) | 1082 | if (foldersOnly && file.DirIndex == -1) |
| 785 | continue; | 1083 | continue; |
| 786 | if (CompareFileNames(file.Name, name) == 0) | 1084 | if (CompareFileNames(file.Name, name) != 0) |
| 1085 | continue; | ||
| 1086 | if (MyStringCompare(file.Name, name) == 0) | ||
| 787 | return (int)i; | 1087 | return (int)i; |
| 1088 | if (index == -1) | ||
| 1089 | index = (int)i; | ||
| 788 | } | 1090 | } |
| 789 | return -1; | 1091 | return index; |
| 790 | } | 1092 | } |
diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h index c6736a8..e486cb6 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.h +++ b/CPP/7zip/UI/Agent/AgentProxy.h | |||
| @@ -27,9 +27,10 @@ struct CProxyDir | |||
| 27 | unsigned NameLen; | 27 | unsigned NameLen; |
| 28 | 28 | ||
| 29 | int ArcIndex; // index in proxy->Files[] ; -1 if there is no item for that folder | 29 | int ArcIndex; // index in proxy->Files[] ; -1 if there is no item for that folder |
| 30 | int ParentDir; // index in proxy->Dirs[] ; -1 for root folder; ; | 30 | int ParentDir; // index in proxy->Dirs[] ; -1 for root folder |
| 31 | CRecordVector<unsigned> SubDirs; | 31 | CUIntVector SubDirs; |
| 32 | CRecordVector<unsigned> SubFiles; | 32 | CUIntVector SubDirs2; |
| 33 | CUIntVector SubFiles; | ||
| 33 | 34 | ||
| 34 | UInt64 Size; | 35 | UInt64 Size; |
| 35 | UInt64 PackSize; | 36 | UInt64 PackSize; |
| @@ -37,47 +38,56 @@ struct CProxyDir | |||
| 37 | UInt32 NumSubDirs; | 38 | UInt32 NumSubDirs; |
| 38 | UInt32 NumSubFiles; | 39 | UInt32 NumSubFiles; |
| 39 | bool CrcIsDefined; | 40 | bool CrcIsDefined; |
| 41 | bool Is_Changed_LongPath; | ||
| 40 | 42 | ||
| 41 | CProxyDir(): Name(NULL), NameLen(0), ParentDir(-1) {} | 43 | CProxyDir(): Name(NULL), NameLen(0), ParentDir(-1), Is_Changed_LongPath(false) {} |
| 42 | ~CProxyDir() { delete [](wchar_t *)(void *)Name; } | 44 | ~CProxyDir() { delete [](wchar_t *)(void *)Name; } |
| 43 | 45 | ||
| 44 | void Clear(); | ||
| 45 | bool IsLeaf() const { return ArcIndex != -1; } | 46 | bool IsLeaf() const { return ArcIndex != -1; } |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 48 | class CProxyArc | 49 | class CProxyArc |
| 49 | { | 50 | { |
| 50 | int FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const; | 51 | int FindSubDir(const unsigned *items, unsigned right, |
| 52 | const wchar_t *name, unsigned &insertPos) const; | ||
| 51 | 53 | ||
| 52 | void CalculateSizes(unsigned dirIndex, IInArchive *archive); | 54 | void CalculateSizes(IInArchive *archive); |
| 55 | void MergeSubDirs(CProxyDir &baseDir); | ||
| 53 | unsigned AddDir(unsigned dirIndex, int arcIndex, const UString &name); | 56 | unsigned AddDir(unsigned dirIndex, int arcIndex, const UString &name); |
| 54 | void FreeFiles(); | 57 | void FreeFiles(); |
| 55 | public: | 58 | public: |
| 56 | CObjectVector<CProxyDir> Dirs; // Dirs[0] - root | 59 | CObjectVector<CProxyDir> Dirs; // Dirs[0] - root |
| 57 | CProxyFile *Files; // all items from archive in same order | 60 | CProxyFile *Files; // all items from archive in same order |
| 58 | unsigned NumFiles; | 61 | unsigned NumFiles; |
| 62 | bool Are_Changed_LongPaths; | ||
| 63 | UInt64 MemUsage; | ||
| 64 | UInt64 MemUsage_Limit; | ||
| 59 | 65 | ||
| 60 | CProxyArc(): Files(NULL), NumFiles(0) {} | 66 | CProxyArc(): Files(NULL), NumFiles(0), Are_Changed_LongPaths(false), MemUsage_Limit((UInt64)(Int64)-1) {} |
| 61 | ~CProxyArc() { FreeFiles(); } | 67 | ~CProxyArc() { FreeFiles(); } |
| 62 | 68 | ||
| 63 | // returns index in Dirs[], or -1, | 69 | // returns index in Dirs[], or -1, |
| 64 | int FindSubDir(unsigned dirIndex, const wchar_t *name) const; | 70 | int FindSubDir(unsigned dirIndex, const wchar_t *name) const; |
| 65 | 71 | ||
| 66 | void GetDirPathParts(unsigned dirIndex, UStringVector &pathParts) const; | 72 | void GetDirPathParts_isChanged(unsigned dirIndex, |
| 73 | UStringVector &pathPartsm, bool &isChangedPath) const; | ||
| 67 | // returns full path of Dirs[dirIndex], including back slash | 74 | // returns full path of Dirs[dirIndex], including back slash |
| 68 | UString GetDirPath_as_Prefix(unsigned dirIndex) const; | 75 | UString GetDirPath_as_Prefix(unsigned dirIndex) const; |
| 76 | void GetDirPath_as_Prefix_from_Base(unsigned dirIndex, UString &prefix, unsigned baseDirIndex) const; | ||
| 69 | 77 | ||
| 70 | // AddRealIndices DOES ADD also item represented by dirIndex (if it's Leaf) | 78 | // AddRealIndices DOES ADD also item represented by dirIndex (if it's Leaf) |
| 71 | void AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const; | 79 | void AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const; |
| 72 | int GetRealIndex(unsigned dirIndex, unsigned index) const; | 80 | int GetRealIndex(unsigned dirIndex, unsigned index) const; |
| 73 | void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const; | 81 | void GetRealIndices_Unsorted(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const; |
| 74 | 82 | ||
| 75 | HRESULT Load(const CArc &arc, IProgress *progress); | 83 | HRESULT Load(const CArc &arc, IArchiveOpenCallback *progress); |
| 76 | }; | 84 | }; |
| 77 | 85 | ||
| 78 | 86 | ||
| 79 | // ---------- for Tree-mode archive ---------- | 87 | // ---------- for Tree-mode archive ---------- |
| 80 | 88 | ||
| 89 | // #define Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | ||
| 90 | |||
| 81 | struct CProxyFile2 | 91 | struct CProxyFile2 |
| 82 | { | 92 | { |
| 83 | int DirIndex; // >= 0 for dir. (index in ProxyArchive2->Dirs) | 93 | int DirIndex; // >= 0 for dir. (index in ProxyArchive2->Dirs) |
| @@ -86,7 +96,7 @@ struct CProxyFile2 | |||
| 86 | const wchar_t *Name; | 96 | const wchar_t *Name; |
| 87 | unsigned NameLen; | 97 | unsigned NameLen; |
| 88 | bool NeedDeleteName; | 98 | bool NeedDeleteName; |
| 89 | bool Ignore; | 99 | bool Ignore; // = false always |
| 90 | bool IsAltStream; | 100 | bool IsAltStream; |
| 91 | 101 | ||
| 92 | int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; } | 102 | int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; } |
| @@ -108,17 +118,23 @@ struct CProxyFile2 | |||
| 108 | 118 | ||
| 109 | struct CProxyDir2 | 119 | struct CProxyDir2 |
| 110 | { | 120 | { |
| 111 | int ArcIndex; // = -1 for root folders, index in proxy->Files[] | 121 | int ArcIndex; // = -1 for root folders, index in CProxyArc2::Files[] |
| 112 | CRecordVector<unsigned> Items; | 122 | unsigned PrefixLen; |
| 123 | CUIntVector Items; // indexes in archive and in CProxyArc2::Files[] | ||
| 124 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | ||
| 113 | UString PathPrefix; | 125 | UString PathPrefix; |
| 126 | #endif | ||
| 114 | UInt64 Size; | 127 | UInt64 Size; |
| 115 | UInt64 PackSize; | 128 | UInt64 PackSize; |
| 129 | #ifdef Z7_AGENT_PROXY2_USE_DIR_PATH_PREFIX | ||
| 130 | bool IsLongPath; | ||
| 131 | #endif | ||
| 116 | bool CrcIsDefined; | 132 | bool CrcIsDefined; |
| 117 | UInt32 Crc; | 133 | UInt32 Crc; |
| 118 | UInt32 NumSubDirs; | 134 | UInt32 NumSubDirs; |
| 119 | UInt32 NumSubFiles; | 135 | UInt32 NumSubFiles; |
| 120 | 136 | ||
| 121 | CProxyDir2(): ArcIndex(-1) {} | 137 | CProxyDir2(); |
| 122 | }; | 138 | }; |
| 123 | 139 | ||
| 124 | const unsigned k_Proxy2_RootDirIndex = k_Proxy_RootDirIndex; | 140 | const unsigned k_Proxy2_RootDirIndex = k_Proxy_RootDirIndex; |
| @@ -127,48 +143,54 @@ const unsigned k_Proxy2_NumRootDirs = 2; | |||
| 127 | 143 | ||
| 128 | class CProxyArc2 | 144 | class CProxyArc2 |
| 129 | { | 145 | { |
| 130 | void CalculateSizes(unsigned dirIndex, IInArchive *archive); | 146 | HRESULT CalculateSizes(unsigned dirIndex, IInArchive *archive |
| 147 | , IProgress *progress, const UInt64 *completed, unsigned &progressCounter); | ||
| 131 | // AddRealIndices_of_Dir DOES NOT ADD item itself represented by dirIndex | 148 | // AddRealIndices_of_Dir DOES NOT ADD item itself represented by dirIndex |
| 132 | void AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const; | 149 | void AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const; |
| 133 | void FreeFiles(); | 150 | void FreeFiles(); |
| 151 | void UpdateMemUsage_with_StringLen(unsigned len) | ||
| 152 | { | ||
| 153 | MemUsage += (size_t)len * sizeof(Files->Name[0]) + 16; | ||
| 154 | } | ||
| 134 | public: | 155 | public: |
| 135 | CObjectVector<CProxyDir2> Dirs; // Dirs[0] - root folder | 156 | CObjectVector<CProxyDir2> Dirs; // Dirs[0] - root folder |
| 136 | // Dirs[1] - for alt streams of root dir | 157 | // Dirs[1] - for alt streams of root dir |
| 137 | CProxyFile2 *Files; // all items from archive in same order | 158 | CProxyFile2 *Files; // all items from archive in same order |
| 138 | unsigned NumFiles; | 159 | unsigned NumFiles; |
| 160 | UInt64 MemUsage; | ||
| 161 | UInt64 MemUsage_Limit; | ||
| 139 | 162 | ||
| 140 | CProxyArc2(): Files(NULL), NumFiles(0) {} | 163 | CProxyArc2(): Files(NULL), NumFiles(0), MemUsage_Limit((UInt64)(Int64)-1) {} |
| 141 | ~CProxyArc2() { FreeFiles(); } | 164 | ~CProxyArc2() { FreeFiles(); } |
| 142 | 165 | ||
| 143 | bool IsThere_SubDir(unsigned dirIndex, const UString &name) const; | ||
| 144 | |||
| 145 | void GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const; | 166 | void GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const; |
| 146 | UString GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const; | 167 | void GetDirPath_as_Prefix_from_Base(unsigned dirIndex, UString &prefix, unsigned baseDirIndex, unsigned lenLimit) const; |
| 168 | UString GetDirPath_as_Prefix(unsigned dirIndex, bool canReducePath = false) const; | ||
| 147 | bool IsAltDir(unsigned dirIndex) const; | 169 | bool IsAltDir(unsigned dirIndex) const; |
| 148 | 170 | ||
| 149 | // AddRealIndices_of_ArcItem DOES ADD item and subItems | 171 | // AddRealIndices_of_ArcItem DOES ADD item and subItems |
| 150 | void AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const; | 172 | void AddRealIndices_of_ArcItem(unsigned arcIndex, |
| 151 | unsigned GetRealIndex(unsigned dirIndex, unsigned index) const; | 173 | bool includeAltStreams, bool includeDirSubItems, |
| 152 | void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const; | 174 | CUIntVector &realIndices) const; |
| 175 | unsigned GetRealIndex(const unsigned dirIndex, const unsigned index) const | ||
| 176 | { | ||
| 177 | return Dirs[dirIndex].Items[index]; | ||
| 178 | } | ||
| 179 | void GetRealIndices_Unsorted(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, | ||
| 180 | bool includeAltStreams, CUIntVector &realIndices) const; | ||
| 153 | 181 | ||
| 154 | HRESULT Load(const CArc &arc, IProgress *progress); | 182 | HRESULT Load(const CArc &arc, IProgress *progress); |
| 155 | 183 | ||
| 156 | int GetParentDirOfFile(UInt32 arcIndex) const | 184 | int FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const; |
| 185 | bool IsThere_SubDir(unsigned dirIndex, const wchar_t *name) const | ||
| 157 | { | 186 | { |
| 158 | const CProxyFile2 &file = Files[arcIndex]; | 187 | return FindItem(dirIndex, name, true) != -1; // foldersOnly |
| 159 | |||
| 160 | if (file.Parent == -1) | ||
| 161 | return file.IsAltStream ? | ||
| 162 | k_Proxy2_AltRootDirIndex : | ||
| 163 | k_Proxy2_RootDirIndex; | ||
| 164 | |||
| 165 | const CProxyFile2 &parentFile = Files[file.Parent]; | ||
| 166 | return file.IsAltStream ? | ||
| 167 | parentFile.AltDirIndex : | ||
| 168 | parentFile.DirIndex; | ||
| 169 | } | 188 | } |
| 170 | 189 | ||
| 171 | int FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const; | 190 | void AddDir(int arcIndex); |
| 172 | }; | 191 | }; |
| 173 | 192 | ||
| 193 | void SetDirPrefix_as_LONG_PATH(UString &s, unsigned fileIndex, | ||
| 194 | bool asAltDirPrefix, bool isDir); | ||
| 195 | |||
| 174 | #endif | 196 | #endif |
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp index 3fa027d..6430503 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp | |||
| @@ -114,7 +114,19 @@ Z7_COM7F_IMF(CArchiveFolderManager::OpenFolderFile(IInStream *inStream, | |||
| 114 | return res; | 114 | return res; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | RINOK(archive->BindToRootFolder(resultFolder)) | 117 | agent->_progress_for_Open = progress; |
| 118 | agent->_progress_ArchiveOpenCallback_for_Open = openArchiveCallback; | ||
| 119 | { | ||
| 120 | HRESULT hres = E_OUTOFMEMORY; | ||
| 121 | // IInFolderArchive::BindToRootFolder() doesn't raise exceptions. | ||
| 122 | // so try/catch is optional | ||
| 123 | try { | ||
| 124 | hres = archive->BindToRootFolder(resultFolder); | ||
| 125 | } catch (...) {} | ||
| 126 | agent->_progress_for_Open = NULL; | ||
| 127 | agent->_progress_ArchiveOpenCallback_for_Open = NULL; | ||
| 128 | RINOK(hres) | ||
| 129 | } | ||
| 118 | return res; | 130 | return res; |
| 119 | } | 131 | } |
| 120 | 132 | ||
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp index 1da6601..44e9d91 100644 --- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp +++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp | |||
| @@ -21,10 +21,11 @@ using namespace NDir; | |||
| 21 | 21 | ||
| 22 | void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder) | 22 | void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder) |
| 23 | { | 23 | { |
| 24 | bool isChangedPath = false; | ||
| 24 | if (_proxy2) | 25 | if (_proxy2) |
| 25 | _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder); | 26 | _proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder); |
| 26 | else | 27 | else |
| 27 | _proxy->GetDirPathParts(_proxyDirIndex, pathParts); | 28 | _proxy->GetDirPathParts_isChanged(_proxyDirIndex, pathParts, isChangedPath); |
| 28 | } | 29 | } |
| 29 | 30 | ||
| 30 | static bool Delete_EmptyFolder_And_EmptySubFolders(const FString &path) | 31 | static bool Delete_EmptyFolder_And_EmptySubFolders(const FString &path) |
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 7f6da0c..a86dd20 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | |||
| @@ -161,7 +161,9 @@ static const char * const k_ZoneId_StreamName_With_Colon_Prefix = ":Zone.Identif | |||
| 161 | 161 | ||
| 162 | bool Is_ZoneId_StreamName(const wchar_t *s) | 162 | bool Is_ZoneId_StreamName(const wchar_t *s) |
| 163 | { | 163 | { |
| 164 | return StringsAreEqualNoCase_Ascii(s, k_ZoneId_StreamName_With_Colon_Prefix + 1); | 164 | UString s2 = s; |
| 165 | Correct_AltStream_Name(s2); | ||
| 166 | return StringsAreEqualNoCase_Ascii(s2, k_ZoneId_StreamName_With_Colon_Prefix + 1); | ||
| 165 | } | 167 | } |
| 166 | 168 | ||
| 167 | void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf) | 169 | void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf) |
| @@ -358,20 +360,19 @@ void CArchiveExtractCallback::Init( | |||
| 358 | _folderArchiveExtractCallback2.Release(); | 360 | _folderArchiveExtractCallback2.Release(); |
| 359 | _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); | 361 | _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); |
| 360 | 362 | ||
| 361 | #ifndef Z7_SFX | 363 | #ifndef Z7_SFX |
| 362 | 364 | _baseParentFolder = (UInt32)(Int32)-1; | |
| 365 | _use_baseParentFolder_mode = false; | ||
| 363 | ExtractToStreamCallback.Release(); | 366 | ExtractToStreamCallback.Release(); |
| 364 | _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback); | 367 | _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback); |
| 365 | if (ExtractToStreamCallback) | 368 | if (ExtractToStreamCallback) |
| 366 | { | 369 | { |
| 367 | Int32 useStreams = 0; | 370 | Int32 useStreams = 0; |
| 368 | if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK) | 371 | if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK |
| 369 | useStreams = 0; | 372 | || useStreams == 0) |
| 370 | if (useStreams == 0) | ||
| 371 | ExtractToStreamCallback.Release(); | 373 | ExtractToStreamCallback.Release(); |
| 372 | } | 374 | } |
| 373 | 375 | #endif | |
| 374 | #endif | ||
| 375 | 376 | ||
| 376 | LocalProgressSpec->Init(extractCallback2, true); | 377 | LocalProgressSpec->Init(extractCallback2, true); |
| 377 | LocalProgressSpec->SendProgress = false; | 378 | LocalProgressSpec->SendProgress = false; |
| @@ -379,11 +380,6 @@ void CArchiveExtractCallback::Init( | |||
| 379 | _removePathParts = removePathParts; | 380 | _removePathParts = removePathParts; |
| 380 | _removePartsForAltStreams = removePartsForAltStreams; | 381 | _removePartsForAltStreams = removePartsForAltStreams; |
| 381 | 382 | ||
| 382 | #ifndef Z7_SFX | ||
| 383 | _baseParentFolder = (UInt32)(Int32)-1; | ||
| 384 | _use_baseParentFolder_mode = false; | ||
| 385 | #endif | ||
| 386 | |||
| 387 | _arc = arc; | 383 | _arc = arc; |
| 388 | _dirPathPrefix = directoryPath; | 384 | _dirPathPrefix = directoryPath; |
| 389 | _dirPathPrefix_Full = directoryPath; | 385 | _dirPathPrefix_Full = directoryPath; |
| @@ -464,21 +460,16 @@ void CArchiveExtractCallback::CreateComplexDirectory( | |||
| 464 | const UStringVector &dirPathParts, bool isFinal, FString &fullPath) | 460 | const UStringVector &dirPathParts, bool isFinal, FString &fullPath) |
| 465 | { | 461 | { |
| 466 | // we use (_item.IsDir) in this function | 462 | // we use (_item.IsDir) in this function |
| 467 | |||
| 468 | bool isAbsPath = false; | 463 | bool isAbsPath = false; |
| 469 | |||
| 470 | if (!dirPathParts.IsEmpty()) | 464 | if (!dirPathParts.IsEmpty()) |
| 471 | { | 465 | { |
| 472 | const UString &s = dirPathParts[0]; | 466 | const UString &s = dirPathParts[0]; |
| 473 | if (s.IsEmpty()) | 467 | if (s.IsEmpty()) |
| 474 | isAbsPath = true; | 468 | isAbsPath = true; |
| 475 | #if defined(_WIN32) && !defined(UNDER_CE) | 469 | #if defined(_WIN32) && !defined(UNDER_CE) |
| 476 | else | 470 | else if (NName::IsDrivePath2(s)) |
| 477 | { | 471 | isAbsPath = true; |
| 478 | if (NName::IsDrivePath2(s)) | 472 | #endif |
| 479 | isAbsPath = true; | ||
| 480 | } | ||
| 481 | #endif | ||
| 482 | } | 473 | } |
| 483 | 474 | ||
| 484 | if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath) | 475 | if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath) |
| @@ -495,37 +486,73 @@ void CArchiveExtractCallback::CreateComplexDirectory( | |||
| 495 | 486 | ||
| 496 | const bool isFinalDir = (i == dirPathParts.Size() - 1 && isFinal && _item.IsDir); | 487 | const bool isFinalDir = (i == dirPathParts.Size() - 1 && isFinal && _item.IsDir); |
| 497 | 488 | ||
| 498 | if (fullPath.IsEmpty()) | 489 | if (fullPath.IsEmpty() |
| 490 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
| 491 | || (_pathMode == NExtract::NPathMode::kAbsPaths | ||
| 492 | && i == 0 && s.Len() == 2 && NName::IsDrivePath2(s)) | ||
| 493 | #endif | ||
| 494 | ) | ||
| 499 | { | 495 | { |
| 500 | if (isFinalDir) | 496 | if (isFinalDir) |
| 501 | _itemFailure = true; | 497 | _itemFailure = true; // we don't want to set attributes for root (or root drive) path |
| 502 | continue; | 498 | continue; |
| 503 | } | 499 | } |
| 504 | 500 | ||
| 505 | #if defined(_WIN32) && !defined(UNDER_CE) | 501 | // bool need_SetAttrib = isFinalDir; |
| 506 | if (_pathMode == NExtract::NPathMode::kAbsPaths) | 502 | if (!isFinalDir || !NFile::NFind::DoesDirExist(fullPath)) |
| 507 | if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s)) | 503 | { |
| 504 | HRESULT hres = S_OK; | ||
| 505 | #ifdef _WIN32 | ||
| 506 | if (!CreateDir(fullPath)) | ||
| 507 | hres = GetLastError_noZero_HRESULT(); | ||
| 508 | #else | ||
| 509 | mode_t mode = g_umask.mask; | ||
| 510 | if (isFinalDir && _fi.Attrib_Defined) | ||
| 508 | { | 511 | { |
| 509 | if (isFinalDir) | 512 | const UInt32 attrib = _fi.Attrib; |
| 513 | if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) | ||
| 510 | { | 514 | { |
| 511 | // we don't want to call SetAttrib() for root drive path | 515 | mode = attrib >> 16; |
| 512 | _itemFailure = true; | 516 | if (S_ISDIR(mode)) |
| 517 | mode |= (S_IRUSR | S_IWUSR | S_IXUSR); // user/7z must be able to create files in this directory | ||
| 518 | else | ||
| 519 | { | ||
| 520 | // we do not want to use attributes, if it's not directory type. | ||
| 521 | // SendMessageError("is not directory type in metadata", fullPath); | ||
| 522 | mode = g_umask.mask; | ||
| 523 | } | ||
| 524 | mode &= g_umask.mask; | ||
| 513 | } | 525 | } |
| 514 | continue; | ||
| 515 | } | 526 | } |
| 516 | #endif | 527 | // printf("\n mkdir mode = %o\n", (unsigned)mode); |
| 528 | if (mkdir(fullPath, mode) == 0) | ||
| 529 | { | ||
| 530 | if (isFinalDir) | ||
| 531 | _dirAttrib_wasSet = true; | ||
| 532 | // printf("\n mkdir OK\n"); | ||
| 533 | // need_SetAttrib = false; | ||
| 534 | } | ||
| 535 | else | ||
| 536 | hres = GetLastError_noZero_HRESULT(); | ||
| 537 | #endif | ||
| 517 | 538 | ||
| 518 | HRESULT hres = S_OK; | 539 | if (isFinalDir && !NFile::NFind::DoesDirExist(fullPath)) |
| 519 | if (!CreateDir(fullPath)) | ||
| 520 | hres = GetLastError_noZero_HRESULT(); | ||
| 521 | if (isFinalDir) | ||
| 522 | { | ||
| 523 | if (!NFile::NFind::DoesDirExist(fullPath)) | ||
| 524 | { | 540 | { |
| 525 | _itemFailure = true; | 541 | _itemFailure = true; |
| 526 | SendMessageError_with_Error(hres, "Cannot create folder", fullPath); | 542 | SendMessageError_with_Error(hres, "Cannot create folder", fullPath); |
| 543 | // need_SetAttrib = false; | ||
| 527 | } | 544 | } |
| 528 | } | 545 | } |
| 546 | /* | ||
| 547 | // this code doesn't process item excluded by "Eliminate duplication of root folder" | ||
| 548 | // so we will set attributes later | ||
| 549 | if (need_SetAttrib) | ||
| 550 | { | ||
| 551 | // printf("\n SetAttrib \n"); | ||
| 552 | SetAttrib(fullPath); | ||
| 553 | _dirAttrib_wasSet = true; | ||
| 554 | } | ||
| 555 | */ | ||
| 529 | } | 556 | } |
| 530 | } | 557 | } |
| 531 | 558 | ||
| @@ -926,7 +953,38 @@ HRESULT CArchiveExtractCallback::ReadLink() | |||
| 926 | #endif // SUPPORT_LINKS | 953 | #endif // SUPPORT_LINKS |
| 927 | 954 | ||
| 928 | 955 | ||
| 929 | #ifndef _WIN32 | 956 | #ifdef _WIN32 |
| 957 | |||
| 958 | #define SET_OWNER | ||
| 959 | #define SET_NEED_SET_OWNER | ||
| 960 | |||
| 961 | #else | ||
| 962 | |||
| 963 | #define SET_OWNER { SetOwner(); } | ||
| 964 | #define SET_NEED_SET_OWNER { _needSetOwner = true; } | ||
| 965 | |||
| 966 | void CArchiveExtractCallback::SetOwner() | ||
| 967 | { | ||
| 968 | if (!_needSetOwner) | ||
| 969 | return; | ||
| 970 | _needSetOwner = false; | ||
| 971 | // we want to call chown() only for file itself. | ||
| 972 | // we don't want to follow link. | ||
| 973 | // if (_isSymLinkCreated) return; | ||
| 974 | const FString &path = _diskFilePath; | ||
| 975 | if (_itemFailure | ||
| 976 | || path.IsEmpty() | ||
| 977 | || _stdOutMode | ||
| 978 | || !_extractMode) | ||
| 979 | return; | ||
| 980 | if (_fi.Owner.Id_Defined && | ||
| 981 | _fi.Group.Id_Defined) | ||
| 982 | { | ||
| 983 | // printf("\n SetOwner() %s\n", path.Ptr()); | ||
| 984 | if (my_chown(path, _fi.Owner.Id, _fi.Group.Id) != 0) | ||
| 985 | SendMessageError_with_LastError("Cannot set owner", path); | ||
| 986 | } | ||
| 987 | } | ||
| 930 | 988 | ||
| 931 | static HRESULT GetOwner(IInArchive *archive, | 989 | static HRESULT GetOwner(IInArchive *archive, |
| 932 | UInt32 index, UInt32 pidName, UInt32 pidId, CProcessedFileInfo::COwnerInfo &res) | 990 | UInt32 index, UInt32 pidName, UInt32 pidId, CProcessedFileInfo::COwnerInfo &res) |
| @@ -1009,7 +1067,7 @@ HRESULT CArchiveExtractCallback::Read_fi_Props() | |||
| 1009 | #ifndef _WIN32 | 1067 | #ifndef _WIN32 |
| 1010 | if (_ntOptions.ExtractOwner) | 1068 | if (_ntOptions.ExtractOwner) |
| 1011 | { | 1069 | { |
| 1012 | // SendMessageError_with_LastError("_ntOptions.ExtractOwner", _diskFilePath); | 1070 | // SendMessageError("_ntOptions.ExtractOwner", _diskFilePath); |
| 1013 | GetOwner(archive, index, kpidUser, kpidUserId, _fi.Owner); | 1071 | GetOwner(archive, index, kpidUser, kpidUserId, _fi.Owner); |
| 1014 | GetOwner(archive, index, kpidGroup, kpidGroupId, _fi.Group); | 1072 | GetOwner(archive, index, kpidGroup, kpidGroupId, _fi.Group); |
| 1015 | } | 1073 | } |
| @@ -1043,7 +1101,11 @@ void CArchiveExtractCallback::CorrectPathParts() | |||
| 1043 | { | 1101 | { |
| 1044 | pathParts.AddNew(); | 1102 | pathParts.AddNew(); |
| 1045 | if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt) | 1103 | if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt) |
| 1104 | { | ||
| 1105 | const UString s2 = Get_Correct_FsFile_Name(s); | ||
| 1106 | s = s2; | ||
| 1046 | needColon = false; | 1107 | needColon = false; |
| 1108 | } | ||
| 1047 | } | 1109 | } |
| 1048 | #ifdef _WIN32 | 1110 | #ifdef _WIN32 |
| 1049 | else if (_pathMode == NExtract::NPathMode::kAbsPaths && | 1111 | else if (_pathMode == NExtract::NPathMode::kAbsPaths && |
| @@ -1371,8 +1433,15 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
| 1371 | if (_link.LinkPath.IsEmpty()) | 1433 | if (_link.LinkPath.IsEmpty()) |
| 1372 | #endif | 1434 | #endif |
| 1373 | { | 1435 | { |
| 1436 | /* here we can set directory attributes for usual any items and for | ||
| 1437 | root directory excluded from processing by "Eliminate duplication of root folder" feature. */ | ||
| 1374 | if (!isAnti) | 1438 | if (!isAnti) |
| 1375 | SetAttrib(); | 1439 | { |
| 1440 | if (!_dirAttrib_wasSet) | ||
| 1441 | SetAttrib(_diskFilePath); | ||
| 1442 | SET_NEED_SET_OWNER | ||
| 1443 | SET_OWNER | ||
| 1444 | } | ||
| 1376 | return S_OK; | 1445 | return S_OK; |
| 1377 | } | 1446 | } |
| 1378 | } | 1447 | } |
| @@ -1443,7 +1512,9 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
| 1443 | return S_OK; | 1512 | return S_OK; |
| 1444 | // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath)); | 1513 | // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath)); |
| 1445 | // _needSetAttrib = true; // do we need to set attribute ? | 1514 | // _needSetAttrib = true; // do we need to set attribute ? |
| 1446 | SetAttrib(); | 1515 | SetAttrib(_diskFilePath); |
| 1516 | SET_NEED_SET_OWNER | ||
| 1517 | SET_OWNER | ||
| 1447 | /* if we set (needExit = false) here, _hashStreamSpec will be used, | 1518 | /* if we set (needExit = false) here, _hashStreamSpec will be used, |
| 1448 | and hash will be calulated for all hard links files (it's slower). | 1519 | and hash will be calulated for all hard links files (it's slower). |
| 1449 | But "Test" operation also calculates hashes. | 1520 | But "Test" operation also calculates hashes. |
| @@ -1462,7 +1533,46 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
| 1462 | 1533 | ||
| 1463 | _outFileStreamSpec = new COutFileStream; | 1534 | _outFileStreamSpec = new COutFileStream; |
| 1464 | CMyComPtr<IOutStream> outFileStream_Loc(_outFileStreamSpec); | 1535 | CMyComPtr<IOutStream> outFileStream_Loc(_outFileStreamSpec); |
| 1536 | |||
| 1537 | bool needSetAttrib = true; | ||
| 1538 | #ifndef _WIN32 | ||
| 1539 | if (_fi.Attrib_Defined) | ||
| 1540 | { | ||
| 1541 | /* | ||
| 1542 | system open() function uses system umask. | ||
| 1543 | our (g_umask.mask) is more restricted mask. | ||
| 1544 | So we use (mode) parameter in open(,, mode), because our mask for (mode) | ||
| 1545 | is more restricted than system umask. | ||
| 1546 | If we want to set unrestricted (mode) bits for file, then we must | ||
| 1547 | call additional fchmod() function later. | ||
| 1548 | */ | ||
| 1549 | mode_t mode = NWindows::NFile::NIO::k_OutFile_mode_default; // 0666 | ||
| 1550 | const UInt32 attrib = _fi.Attrib; | ||
| 1551 | if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) | ||
| 1552 | { | ||
| 1553 | mode = (attrib >> 16); | ||
| 1554 | // mode &= 07777; // for debug | ||
| 1555 | if (!S_ISREG(mode)) | ||
| 1556 | { | ||
| 1557 | // printf("\n !S_ISREG(mode) = %o\n", (unsigned)mode); | ||
| 1558 | needSetAttrib = false; | ||
| 1559 | } | ||
| 1560 | } | ||
| 1561 | else if (attrib & FILE_ATTRIBUTE_READONLY) | ||
| 1562 | mode &= (mode_t)~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions | ||
| 1563 | if (needSetAttrib) | ||
| 1564 | { | ||
| 1565 | // printf("\n File.mode_for_Create = %o\n", (unsigned)mode); | ||
| 1566 | mode &= g_umask.mask; | ||
| 1567 | // mode = 0777; // for debug | ||
| 1568 | // mode |= S_ISUID | S_ISGID | S_ISVTX; // for debug | ||
| 1569 | _outFileStreamSpec->File.mode_for_Create = mode; | ||
| 1570 | } | ||
| 1571 | needSetAttrib = false; | ||
| 1572 | } | ||
| 1573 | #endif | ||
| 1465 | 1574 | ||
| 1575 | // printf("\n GetExtractStream Create_ALWAYS_or_Open_ALWAYS : %s\n", fullProcessedPath.Ptr()); | ||
| 1466 | if (!_outFileStreamSpec->Create_ALWAYS_or_Open_ALWAYS(fullProcessedPath, !_isSplit)) | 1576 | if (!_outFileStreamSpec->Create_ALWAYS_or_Open_ALWAYS(fullProcessedPath, !_isSplit)) |
| 1467 | { | 1577 | { |
| 1468 | // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) | 1578 | // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) |
| @@ -1472,7 +1582,8 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
| 1472 | } | 1582 | } |
| 1473 | } | 1583 | } |
| 1474 | 1584 | ||
| 1475 | _needSetAttrib = true; | 1585 | SET_NEED_SET_OWNER |
| 1586 | _needSetAttrib = needSetAttrib; | ||
| 1476 | 1587 | ||
| 1477 | bool is_SymLink_in_Data = false; | 1588 | bool is_SymLink_in_Data = false; |
| 1478 | 1589 | ||
| @@ -1608,7 +1719,11 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
| 1608 | _extractMode = false; | 1719 | _extractMode = false; |
| 1609 | _is_SymLink_in_Data_Linux = false; | 1720 | _is_SymLink_in_Data_Linux = false; |
| 1610 | _needSetAttrib = false; | 1721 | _needSetAttrib = false; |
| 1611 | _isSymLinkCreated = false; | 1722 | _dirAttrib_wasSet = false; |
| 1723 | #ifndef _WIN32 | ||
| 1724 | _needSetOwner = false; | ||
| 1725 | #endif | ||
| 1726 | // _isSymLinkCreated = false; | ||
| 1612 | _itemFailure = false; | 1727 | _itemFailure = false; |
| 1613 | _some_pathParts_wereRemoved = false; | 1728 | _some_pathParts_wereRemoved = false; |
| 1614 | // _op_WasReported = false; | 1729 | // _op_WasReported = false; |
| @@ -1979,13 +2094,48 @@ HRESULT CArchiveExtractCallback::CloseFile() | |||
| 1979 | CFiTimesCAM t; | 2094 | CFiTimesCAM t; |
| 1980 | GetFiTimesCAM(_fi, t, *_arc); | 2095 | GetFiTimesCAM(_fi, t, *_arc); |
| 1981 | 2096 | ||
| 1982 | // #ifdef _WIN32 | 2097 | const bool needSetAttrib = (_needSetAttrib && _fi.Attrib_Defined); |
| 1983 | if (t.IsSomeTimeDefined()) | 2098 | if (t.IsSomeTimeDefined() || needSetAttrib) |
| 1984 | _outFileStreamSpec->SetTime( | 2099 | { |
| 2100 | bool needSetTime = true; | ||
| 2101 | if (needSetAttrib) | ||
| 2102 | { | ||
| 2103 | /* | ||
| 2104 | in Linux: { this code branch is not used, | ||
| 2105 | because (mode) was set in open() function in COutFile open function. | ||
| 2106 | If we call Set_Time_and_WinAttrib(), then later COutFile::Close() will call fchmod(). | ||
| 2107 | So we need Set_Time_and_WinAttrib() in linux only if we need insecure nonrestricted (mode) bits with fchmod(). | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | win10: if (attrib & FILE_ATTRIBUTE_DIRECTORY) | ||
| 2111 | { | ||
| 2112 | NtSetInformationFile() returns (STATUS_INVALID_PARAMETER) | ||
| 2113 | SetFileAttributes() just ignores FILE_ATTRIBUTE_DIRECTORY() | ||
| 2114 | } | ||
| 2115 | */ | ||
| 2116 | // _fi.Attrib |= 0xfffffff; // FOR DEBUG | ||
| 2117 | if (_outFileStreamSpec->File.Set_Time_and_WinAttrib( | ||
| 2118 | t.CTime_Defined ? &t.CTime : NULL, | ||
| 2119 | t.ATime_Defined ? &t.ATime : NULL, | ||
| 2120 | t.MTime_Defined ? &t.MTime : NULL, | ||
| 2121 | (DWORD)_fi.Attrib & ~(DWORD)FILE_ATTRIBUTE_DIRECTORY)) | ||
| 2122 | { | ||
| 2123 | needSetTime = false; | ||
| 2124 | _needSetAttrib = false; | ||
| 2125 | } | ||
| 2126 | else | ||
| 2127 | { | ||
| 2128 | // it's unexpected case. | ||
| 2129 | // we will set timestamp/attributes with another code later | ||
| 2130 | // SendMessageError_with_LastError("Cannot set timestamp and file attribute", _diskFilePath); | ||
| 2131 | } | ||
| 2132 | } | ||
| 2133 | if (needSetTime) | ||
| 2134 | _outFileStreamSpec->SetTime( | ||
| 1985 | t.CTime_Defined ? &t.CTime : NULL, | 2135 | t.CTime_Defined ? &t.CTime : NULL, |
| 1986 | t.ATime_Defined ? &t.ATime : NULL, | 2136 | t.ATime_Defined ? &t.ATime : NULL, |
| 1987 | t.MTime_Defined ? &t.MTime : NULL); | 2137 | t.MTime_Defined ? &t.MTime : NULL); |
| 1988 | // #endif | 2138 | } |
| 1989 | 2139 | ||
| 1990 | RINOK(_outFileStreamSpec->Close()) | 2140 | RINOK(_outFileStreamSpec->Close()) |
| 1991 | _outFileStream.Release(); | 2141 | _outFileStream.Release(); |
| @@ -2096,7 +2246,7 @@ HRESULT CArchiveExtractCallback::SetLink( | |||
| 2096 | return SendMessageError("Cannot create temporary link file", fullProcessedPath_from); | 2246 | return SendMessageError("Cannot create temporary link file", fullProcessedPath_from); |
| 2097 | #if 0 // 1 for debug | 2247 | #if 0 // 1 for debug |
| 2098 | // here we can write link path to temporary link file placeholder, | 2248 | // here we can write link path to temporary link file placeholder, |
| 2099 | // but empty placeholder is better, because we don't want to get any non-eampty data instead of link file. | 2249 | // but empty placeholder is better, because we don't want to get any non-empty data instead of link file. |
| 2100 | AString s; | 2250 | AString s; |
| 2101 | ConvertUnicodeToUTF8(link.LinkPath, s); | 2251 | ConvertUnicodeToUTF8(link.LinkPath, s); |
| 2102 | outFile.WriteFull(s, s.Len()); | 2252 | outFile.WriteFull(s, s.Len()); |
| @@ -2543,13 +2693,13 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
| 2543 | link.Parse_from_LinuxData(_outMemBuf, reparseSize) : | 2693 | link.Parse_from_LinuxData(_outMemBuf, reparseSize) : |
| 2544 | link.Parse_from_WindowsReparseData(_outMemBuf, reparseSize); | 2694 | link.Parse_from_WindowsReparseData(_outMemBuf, reparseSize); |
| 2545 | if (!needSetReparse) | 2695 | if (!needSetReparse) |
| 2546 | res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path)); | 2696 | res = SendMessageError("Incorrect reparse stream", us2fs(_item.Path)); |
| 2547 | // (link.LinkPath) uses system path separator. | 2697 | // (link.LinkPath) uses system path separator. |
| 2548 | // windows: (link.LinkPath) doesn't contain linux separator (slash). | 2698 | // windows: (link.LinkPath) doesn't contain linux separator (slash). |
| 2549 | } | 2699 | } |
| 2550 | else | 2700 | else |
| 2551 | { | 2701 | { |
| 2552 | res = SendMessageError_with_LastError("Unknown reparse stream", us2fs(_item.Path)); | 2702 | res = SendMessageError("Unknown reparse stream", us2fs(_item.Path)); |
| 2553 | } | 2703 | } |
| 2554 | if (!needSetReparse && _outFileStream) | 2704 | if (!needSetReparse && _outFileStream) |
| 2555 | { | 2705 | { |
| @@ -2587,8 +2737,14 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
| 2587 | // link.isJunction = true; // for debug | 2737 | // link.isJunction = true; // for debug |
| 2588 | link.Normalize_to_RelativeSafe(_removePathParts); | 2738 | link.Normalize_to_RelativeSafe(_removePathParts); |
| 2589 | RINOK(SetLink(_diskFilePath, link, linkWasSet)) | 2739 | RINOK(SetLink(_diskFilePath, link, linkWasSet)) |
| 2740 | /* DOCs: | ||
| 2741 | posix: permissions are ignored for access via link. | ||
| 2742 | Linux: the permissions of an ordinary symbolic link are not | ||
| 2743 | used in any operations; the permissions are always 0777 (read, | ||
| 2744 | write, and execute for all user categories), and can't be changed. | ||
| 2745 | So we don't set attributes for placeholder. | ||
| 2746 | */ | ||
| 2590 | /* | 2747 | /* |
| 2591 | // we don't set attributes for placeholder. | ||
| 2592 | if (linkWasSet) | 2748 | if (linkWasSet) |
| 2593 | _isSymLinkCreated = true; // link.IsSymLink(); | 2749 | _isSymLinkCreated = true; // link.IsSymLink(); |
| 2594 | else | 2750 | else |
| @@ -2605,15 +2761,6 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
| 2605 | static void SetAttrib_Base(const FString &path, const CProcessedFileInfo &fi, | 2761 | static void SetAttrib_Base(const FString &path, const CProcessedFileInfo &fi, |
| 2606 | const CArchiveExtractCallback &callback) | 2762 | const CArchiveExtractCallback &callback) |
| 2607 | { | 2763 | { |
| 2608 | #ifndef _WIN32 | ||
| 2609 | if (fi.Owner.Id_Defined && | ||
| 2610 | fi.Group.Id_Defined) | ||
| 2611 | { | ||
| 2612 | if (my_chown(path, fi.Owner.Id, fi.Group.Id) != 0) | ||
| 2613 | callback.SendMessageError_with_LastError("Cannot set owner", path); | ||
| 2614 | } | ||
| 2615 | #endif | ||
| 2616 | |||
| 2617 | if (fi.Attrib_Defined) | 2764 | if (fi.Attrib_Defined) |
| 2618 | { | 2765 | { |
| 2619 | // const AString s = GetAnsiString(_diskFilePath); | 2766 | // const AString s = GetAnsiString(_diskFilePath); |
| @@ -2626,21 +2773,21 @@ static void SetAttrib_Base(const FString &path, const CProcessedFileInfo &fi, | |||
| 2626 | } | 2773 | } |
| 2627 | } | 2774 | } |
| 2628 | 2775 | ||
| 2629 | void CArchiveExtractCallback::SetAttrib() const | 2776 | void CArchiveExtractCallback::SetAttrib(const FString &path) const |
| 2630 | { | 2777 | { |
| 2631 | #ifndef _WIN32 | 2778 | #ifndef _WIN32 |
| 2632 | // Linux now doesn't support permissions for symlinks | 2779 | // Linux now doesn't support permissions for symlinks |
| 2633 | if (_isSymLinkCreated) | 2780 | // if (_isSymLinkCreated) return; |
| 2634 | return; | ||
| 2635 | #endif | 2781 | #endif |
| 2782 | // printf("\n SetAttrib %s, \n", path.Ptr()); | ||
| 2636 | 2783 | ||
| 2637 | if (_itemFailure | 2784 | if (_itemFailure |
| 2638 | || _diskFilePath.IsEmpty() | 2785 | || path.IsEmpty() |
| 2639 | || _stdOutMode | 2786 | || _stdOutMode |
| 2640 | || !_extractMode) | 2787 | || !_extractMode) |
| 2641 | return; | 2788 | return; |
| 2642 | 2789 | ||
| 2643 | SetAttrib_Base(_diskFilePath, _fi, *this); | 2790 | SetAttrib_Base(path, _fi, *this); |
| 2644 | } | 2791 | } |
| 2645 | 2792 | ||
| 2646 | 2793 | ||
| @@ -2688,9 +2835,6 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) | |||
| 2688 | GetUnpackSize(); | 2835 | GetUnpackSize(); |
| 2689 | return ExtractToStreamCallback->SetOperationResult8(opRes, BoolToInt(_encrypted), _curSize); | 2836 | return ExtractToStreamCallback->SetOperationResult8(opRes, BoolToInt(_encrypted), _curSize); |
| 2690 | } | 2837 | } |
| 2691 | #endif | ||
| 2692 | |||
| 2693 | #ifndef Z7_SFX | ||
| 2694 | 2838 | ||
| 2695 | if (_hashStreamWasUsed) | 2839 | if (_hashStreamWasUsed) |
| 2696 | { | 2840 | { |
| @@ -2738,11 +2882,11 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) | |||
| 2738 | NumFiles++; | 2882 | NumFiles++; |
| 2739 | 2883 | ||
| 2740 | if (_needSetAttrib) | 2884 | if (_needSetAttrib) |
| 2741 | SetAttrib(); | 2885 | SetAttrib(_diskFilePath); |
| 2742 | 2886 | ||
| 2743 | RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))) | 2887 | SET_OWNER |
| 2744 | 2888 | ||
| 2745 | return S_OK; | 2889 | return _extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)); |
| 2746 | 2890 | ||
| 2747 | COM_TRY_END | 2891 | COM_TRY_END |
| 2748 | } | 2892 | } |
| @@ -2987,15 +3131,30 @@ HRESULT CArchiveExtractCallback::SetPostLinks() const | |||
| 2987 | RINOK(SetLink2(*this, link, linkWasSet)) | 3131 | RINOK(SetLink2(*this, link, linkWasSet)) |
| 2988 | if (linkWasSet) | 3132 | if (linkWasSet) |
| 2989 | { | 3133 | { |
| 2990 | #ifdef _WIN32 | 3134 | // we set timestamps before SetAttrib(), |
| 2991 | // Linux now doesn't support permissions for symlinks | 3135 | // because windows doesn't set timestamps, if file has read-only attribute |
| 2992 | SetAttrib_Base(link.fullProcessedPath_from, link.item_FileInfo, *this); | ||
| 2993 | #endif | ||
| 2994 | |||
| 2995 | CFiTimesCAM pt; | 3136 | CFiTimesCAM pt; |
| 2996 | GetFiTimesCAM(link.item_FileInfo, pt, *_arc); | 3137 | GetFiTimesCAM(link.item_FileInfo, pt, *_arc); |
| 2997 | if (pt.IsSomeTimeDefined()) | 3138 | if (pt.IsSomeTimeDefined()) |
| 2998 | pt.SetLinkFileTime_to_FS(link.fullProcessedPath_from); | 3139 | if (!pt.SetLinkFileTime_to_FS(link.fullProcessedPath_from)) |
| 3140 | { | ||
| 3141 | // SendMessageError_with_LastError("cannot set timestamp", link.fullProcessedPath_from); | ||
| 3142 | } | ||
| 3143 | |||
| 3144 | #ifdef _WIN32 | ||
| 3145 | SetAttrib_Base(link.fullProcessedPath_from, link.item_FileInfo, *this); | ||
| 3146 | #else | ||
| 3147 | // Linux now doesn't support permissions for symlinks. | ||
| 3148 | // We set only owner | ||
| 3149 | { | ||
| 3150 | const CProcessedFileInfo &fi = link.item_FileInfo; | ||
| 3151 | if (fi.Owner.Id_Defined && fi.Group.Id_Defined) | ||
| 3152 | { | ||
| 3153 | if (my_chown_Link(link.fullProcessedPath_from, fi.Owner.Id, fi.Group.Id) != 0) | ||
| 3154 | SendMessageError_with_LastError("Cannot set owner", link.fullProcessedPath_from); | ||
| 3155 | } | ||
| 3156 | } | ||
| 3157 | #endif | ||
| 2999 | 3158 | ||
| 3000 | #ifdef Z7_USE_SECURITY_CODE | 3159 | #ifdef Z7_USE_SECURITY_CODE |
| 3001 | // we set security information after timestamps setting | 3160 | // we set security information after timestamps setting |
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 3c62763..e1822c7 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h | |||
| @@ -260,14 +260,6 @@ struct COwnerInfo | |||
| 260 | COwnerInfo Group; | 260 | COwnerInfo Group; |
| 261 | #endif | 261 | #endif |
| 262 | 262 | ||
| 263 | void Clear() | ||
| 264 | { | ||
| 265 | #ifndef _WIN32 | ||
| 266 | Attrib_Defined = false; | ||
| 267 | Owner.Clear(); | ||
| 268 | #endif | ||
| 269 | } | ||
| 270 | |||
| 271 | bool IsReparse() const | 263 | bool IsReparse() const |
| 272 | { | 264 | { |
| 273 | return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); | 265 | return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); |
| @@ -386,7 +378,8 @@ private: | |||
| 386 | bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX. | 378 | bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX. |
| 387 | // _is_SymLink_in_Data_Linux is detected from Windows/Linux part of attributes of file. | 379 | // _is_SymLink_in_Data_Linux is detected from Windows/Linux part of attributes of file. |
| 388 | bool _needSetAttrib; | 380 | bool _needSetAttrib; |
| 389 | bool _isSymLinkCreated; | 381 | bool _dirAttrib_wasSet; |
| 382 | // bool _isSymLinkCreated; | ||
| 390 | bool _itemFailure; | 383 | bool _itemFailure; |
| 391 | bool _some_pathParts_wereRemoved; | 384 | bool _some_pathParts_wereRemoved; |
| 392 | 385 | ||
| @@ -395,6 +388,9 @@ private: | |||
| 395 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) | 388 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) |
| 396 | bool _saclEnabled; | 389 | bool _saclEnabled; |
| 397 | #endif | 390 | #endif |
| 391 | #ifndef _WIN32 | ||
| 392 | bool _needSetOwner; | ||
| 393 | #endif | ||
| 398 | 394 | ||
| 399 | NExtract::NPathMode::EEnum _pathMode; | 395 | NExtract::NPathMode::EEnum _pathMode; |
| 400 | NExtract::NOverwriteMode::EEnum _overwriteMode; | 396 | NExtract::NOverwriteMode::EEnum _overwriteMode; |
| @@ -470,8 +466,11 @@ private: | |||
| 470 | 466 | ||
| 471 | FString Hash_GetFullFilePath(); | 467 | FString Hash_GetFullFilePath(); |
| 472 | 468 | ||
| 473 | void SetAttrib() const; | 469 | void SetAttrib(const FString &path) const; |
| 474 | 470 | #ifndef _WIN32 | |
| 471 | void SetOwner(); | ||
| 472 | #endif | ||
| 473 | |||
| 475 | public: | 474 | public: |
| 476 | HRESULT SendMessageError(const char *message, const FString &path) const; | 475 | HRESULT SendMessageError(const char *message, const FString &path) const; |
| 477 | HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const; | 476 | HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const; |
diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index 8a72936..bf11d12 100644 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp | |||
| @@ -394,5 +394,10 @@ Z7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 /* total */)) | |||
| 394 | 394 | ||
| 395 | Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 * /* completed */)) | 395 | Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 * /* completed */)) |
| 396 | { | 396 | { |
| 397 | return S_OK; | 397 | // this call can be used for additional structure parsing after archive openning. |
| 398 | // so we ignore completed | ||
| 399 | // we just want to process open break | ||
| 400 | if (!Callback) | ||
| 401 | return S_OK; | ||
| 402 | return Callback->Open_CheckBreak(); | ||
| 398 | } | 403 | } |
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index 30fc1e6..6e083ea 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp | |||
| @@ -2866,6 +2866,8 @@ static void PrintPercents(IBenchPrintCallback &f, UInt64 val, UInt64 divider, un | |||
| 2866 | static void PrintChars(IBenchPrintCallback &f, char c, unsigned size) | 2866 | static void PrintChars(IBenchPrintCallback &f, char c, unsigned size) |
| 2867 | { | 2867 | { |
| 2868 | char s[256]; | 2868 | char s[256]; |
| 2869 | if (size >= sizeof(s)) | ||
| 2870 | size = sizeof(s) - 1; | ||
| 2869 | memset(s, (Byte)c, size); | 2871 | memset(s, (Byte)c, size); |
| 2870 | s[size] = 0; | 2872 | s[size] = 0; |
| 2871 | f.Print(s); | 2873 | f.Print(s); |
| @@ -4070,7 +4072,8 @@ HRESULT Bench( | |||
| 4070 | )); | 4072 | )); |
| 4071 | if (start >= freq * 16) | 4073 | if (start >= freq * 16) |
| 4072 | { | 4074 | { |
| 4073 | printCallback->Print(" (Cmplx)"); | 4075 | if (printCallback) |
| 4076 | printCallback->Print(" (Cmplx)"); | ||
| 4074 | if (!freqCallback) // we don't want complexity change for old gui lzma benchmark | 4077 | if (!freqCallback) // we don't want complexity change for old gui lzma benchmark |
| 4075 | { | 4078 | { |
| 4076 | needSetComplexity = true; | 4079 | needSetComplexity = true; |
| @@ -4658,6 +4661,8 @@ HRESULT Bench( | |||
| 4658 | } | 4661 | } |
| 4659 | } | 4662 | } |
| 4660 | 4663 | ||
| 4664 | if (!printCallback) | ||
| 4665 | return E_NOTIMPL; | ||
| 4661 | IBenchPrintCallback &f = *printCallback; | 4666 | IBenchPrintCallback &f = *printCallback; |
| 4662 | 4667 | ||
| 4663 | if (threadsPassIndex > 0) | 4668 | if (threadsPassIndex > 0) |
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index e234670..7ca6680 100644 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp | |||
| @@ -99,10 +99,13 @@ void Correct_AltStream_Name(UString &s) | |||
| 99 | const unsigned kPostfixSize = 6; | 99 | const unsigned kPostfixSize = 6; |
| 100 | if (s.Len() >= kPostfixSize | 100 | if (s.Len() >= kPostfixSize |
| 101 | && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA")) | 101 | && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA")) |
| 102 | { | ||
| 102 | len -= kPostfixSize; | 103 | len -= kPostfixSize; |
| 104 | s.DeleteFrom(len); | ||
| 105 | } | ||
| 103 | for (unsigned i = 0; i < len; i++) | 106 | for (unsigned i = 0; i < len; i++) |
| 104 | { | 107 | { |
| 105 | wchar_t c = s[i]; | 108 | const wchar_t c = s[i]; |
| 106 | if (c == ':' || c == '\\' || c == '/' | 109 | if (c == ':' || c == '\\' || c == '/' |
| 107 | || c == 0x202E // RLO | 110 | || c == 0x202E // RLO |
| 108 | ) | 111 | ) |
diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index c26d4c0..f9e4fae 100644 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp | |||
| @@ -524,32 +524,55 @@ static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &res | |||
| 524 | 524 | ||
| 525 | #ifndef Z7_SFX | 525 | #ifndef Z7_SFX |
| 526 | 526 | ||
| 527 | HRESULT CArc::GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const | 527 | HRESULT CArc::GetItem_PathToParent(UInt32 index, const UInt32 parent, UStringVector &parts) const |
| 528 | { | 528 | { |
| 529 | if (!GetRawProps) | 529 | if (!GetRawProps) |
| 530 | return E_FAIL; | 530 | return E_FAIL; |
| 531 | if (index == parent) | 531 | if (index == parent) |
| 532 | return S_OK; | 532 | return S_OK; |
| 533 | UInt32 curIndex = index; | ||
| 534 | 533 | ||
| 534 | CRecordVector<UInt32> vec; | ||
| 535 | UString s; | 535 | UString s; |
| 536 | 536 | bool isAltStream = false; | |
| 537 | bool prevWasAltStream = false; | 537 | |
| 538 | |||
| 539 | for (;;) | 538 | for (;;) |
| 540 | { | 539 | { |
| 541 | #ifdef MY_CPU_LE | 540 | vec.Add(index); |
| 541 | UInt32 curParent = (UInt32)(Int32)-1; | ||
| 542 | UInt32 parentType = 0; | ||
| 543 | RINOK(GetRawProps->GetParent(index, &curParent, &parentType)) | ||
| 544 | |||
| 545 | if (parentType == NParentType::kAltStream) | ||
| 546 | { | ||
| 547 | // that case is not expected because | ||
| 548 | // we don't call GetItem_PathToParent() function for alt stream items | ||
| 549 | if (vec.Size() != 1) | ||
| 550 | return E_FAIL; | ||
| 551 | isAltStream = true; | ||
| 552 | } | ||
| 553 | if (parent == curParent) | ||
| 554 | break; | ||
| 555 | if (curParent == (UInt32)(Int32)-1) | ||
| 556 | return E_FAIL; | ||
| 557 | index = curParent; | ||
| 558 | } | ||
| 559 | |||
| 560 | unsigned k = vec.Size(); | ||
| 561 | do | ||
| 562 | { | ||
| 563 | index = vec[--k]; | ||
| 564 | #ifdef MY_CPU_LE | ||
| 542 | const void *p; | 565 | const void *p; |
| 543 | UInt32 size; | 566 | UInt32 size; |
| 544 | UInt32 propType; | 567 | UInt32 propType; |
| 545 | RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType)) | 568 | RINOK(GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType)) |
| 546 | if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) | 569 | if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) |
| 547 | s = (const wchar_t *)p; | 570 | s = (const wchar_t *)p; |
| 548 | else | 571 | else |
| 549 | #endif | 572 | #endif |
| 550 | { | 573 | { |
| 551 | NCOM::CPropVariant prop; | 574 | NCOM::CPropVariant prop; |
| 552 | RINOK(Archive->GetProperty(curIndex, kpidName, &prop)) | 575 | RINOK(Archive->GetProperty(index, kpidName, &prop)) |
| 553 | if (prop.vt == VT_BSTR && prop.bstrVal) | 576 | if (prop.vt == VT_BSTR && prop.bstrVal) |
| 554 | s.SetFromBstr(prop.bstrVal); | 577 | s.SetFromBstr(prop.bstrVal); |
| 555 | else if (prop.vt == VT_EMPTY) | 578 | else if (prop.vt == VT_EMPTY) |
| @@ -557,51 +580,17 @@ HRESULT CArc::GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &p | |||
| 557 | else | 580 | else |
| 558 | return E_FAIL; | 581 | return E_FAIL; |
| 559 | } | 582 | } |
| 560 | 583 | if (isAltStream && k == 0 && !parts.IsEmpty()) | |
| 561 | UInt32 curParent = (UInt32)(Int32)-1; | ||
| 562 | UInt32 parentType = 0; | ||
| 563 | RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType)) | ||
| 564 | |||
| 565 | // 18.06: fixed : we don't want to split name to parts | ||
| 566 | /* | ||
| 567 | if (parentType != NParentType::kAltStream) | ||
| 568 | { | ||
| 569 | for (;;) | ||
| 570 | { | ||
| 571 | int pos = s.ReverseFind_PathSepar(); | ||
| 572 | if (pos < 0) | ||
| 573 | { | ||
| 574 | break; | ||
| 575 | } | ||
| 576 | parts.Insert(0, s.Ptr(pos + 1)); | ||
| 577 | s.DeleteFrom(pos); | ||
| 578 | } | ||
| 579 | } | ||
| 580 | */ | ||
| 581 | |||
| 582 | parts.Insert(0, s); | ||
| 583 | |||
| 584 | if (prevWasAltStream) | ||
| 585 | { | 584 | { |
| 586 | { | 585 | UString &s2 = parts.Back(); |
| 587 | UString &s2 = parts[parts.Size() - 2]; | 586 | s2.Add_Colon(); |
| 588 | s2.Add_Colon(); | 587 | s2 += s; |
| 589 | s2 += parts.Back(); | ||
| 590 | } | ||
| 591 | parts.DeleteBack(); | ||
| 592 | } | 588 | } |
| 593 | 589 | else | |
| 594 | if (parent == curParent) | 590 | parts.Add(s); |
| 595 | return S_OK; | ||
| 596 | |||
| 597 | prevWasAltStream = false; | ||
| 598 | if (parentType == NParentType::kAltStream) | ||
| 599 | prevWasAltStream = true; | ||
| 600 | |||
| 601 | if (curParent == (UInt32)(Int32)-1) | ||
| 602 | return E_FAIL; | ||
| 603 | curIndex = curParent; | ||
| 604 | } | 591 | } |
| 592 | while (k); | ||
| 593 | return S_OK; | ||
| 605 | } | 594 | } |
| 606 | 595 | ||
| 607 | #endif | 596 | #endif |
| @@ -888,7 +877,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const | |||
| 888 | { | 877 | { |
| 889 | /* Good handler must support GetRawProps::GetParent for alt streams. | 878 | /* Good handler must support GetRawProps::GetParent for alt streams. |
| 890 | So the following code currently is not used */ | 879 | So the following code currently is not used */ |
| 891 | int colon = FindAltStreamColon_in_Path(item.Path); | 880 | const int colon = FindAltStreamColon_in_Path(item.Path); |
| 892 | if (colon >= 0) | 881 | if (colon >= 0) |
| 893 | { | 882 | { |
| 894 | item.MainPath.DeleteFrom((unsigned)colon); | 883 | item.MainPath.DeleteFrom((unsigned)colon); |
| @@ -3397,8 +3386,7 @@ HRESULT CArchiveLink::Open(COpenOptions &op) | |||
| 3397 | HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) | 3386 | HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) |
| 3398 | { | 3387 | { |
| 3399 | VolumesSize = 0; | 3388 | VolumesSize = 0; |
| 3400 | COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; | 3389 | CMyComPtr2_Create<IArchiveOpenCallback, COpenCallbackImp> openCallbackSpec; |
| 3401 | CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec; | ||
| 3402 | openCallbackSpec->Callback = callbackUI; | 3390 | openCallbackSpec->Callback = callbackUI; |
| 3403 | 3391 | ||
| 3404 | FString prefix, name; | 3392 | FString prefix, name; |
| @@ -3413,8 +3401,8 @@ HRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI) | |||
| 3413 | openCallbackSpec->SetSubArchiveName(op.filePath); | 3401 | openCallbackSpec->SetSubArchiveName(op.filePath); |
| 3414 | } | 3402 | } |
| 3415 | 3403 | ||
| 3416 | op.callback = callback; | 3404 | op.callback = openCallbackSpec; |
| 3417 | op.callbackSpec = openCallbackSpec; | 3405 | op.callbackSpec = openCallbackSpec.ClsPtr(); |
| 3418 | 3406 | ||
| 3419 | HRESULT res = Open(op); | 3407 | HRESULT res = Open(op); |
| 3420 | 3408 | ||
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp index d73680b..85f3fa8 100644 --- a/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp | |||
| @@ -55,27 +55,28 @@ FILE_ATTRIBUTE_ | |||
| 55 | 55 | ||
| 56 | 56 | ||
| 57 | static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' }; | 57 | static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' }; |
| 58 | #define MY_ATTR_CHAR(a, n, c) (((a) & (1 << (n))) ? c : '-') | 58 | #define MY_POSIX_MODE_CHAR(a, mask, c) (((a) & (mask)) ? (c) : '-') |
| 59 | 59 | ||
| 60 | static void ConvertPosixAttribToString(char *s, UInt32 a) throw() | 60 | static void ConvertPosixAttribToString(char *s, UInt32 a) throw() |
| 61 | { | 61 | { |
| 62 | s[0] = kPosixTypes[(a >> 12) & 0xF]; | 62 | *s++ = kPosixTypes[(a >> 12) & 0xF]; |
| 63 | for (int i = 6; i >= 0; i -= 3) | 63 | for (unsigned mask = 1 << 8; mask;) |
| 64 | { | 64 | { |
| 65 | s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r'); | 65 | s[0] = MY_POSIX_MODE_CHAR(a, mask, 'r'); mask >>= 1; |
| 66 | s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w'); | 66 | s[1] = MY_POSIX_MODE_CHAR(a, mask, 'w'); mask >>= 1; |
| 67 | s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x'); | 67 | s[2] = MY_POSIX_MODE_CHAR(a, mask, 'x'); mask >>= 1; |
| 68 | s += 3; | ||
| 68 | } | 69 | } |
| 69 | if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); // S_ISUID | 70 | if (a & 0x800) s[-7] = ((a & (1 << 6)) ? 's' : 'S'); // S_ISUID |
| 70 | if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); // S_ISGID | 71 | if (a & 0x400) s[-4] = ((a & (1 << 3)) ? 's' : 'S'); // S_ISGID |
| 71 | if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); // S_ISVTX | 72 | if (a & 0x200) s[-1] = ((a & (1 << 0)) ? 't' : 'T'); // S_ISVTX |
| 72 | s[10] = 0; | 73 | *s = 0; |
| 73 | 74 | ||
| 74 | a &= ~(UInt32)0xFFFF; | 75 | a &= ~(UInt32)0xFFFF; |
| 75 | if (a != 0) | 76 | if (a) |
| 76 | { | 77 | { |
| 77 | s[10] = ' '; | 78 | *s++ = ' '; |
| 78 | ConvertUInt32ToHex8Digits(a, s + 11); | 79 | ConvertUInt32ToHex8Digits(a, s); |
| 79 | } | 80 | } |
| 80 | } | 81 | } |
| 81 | 82 | ||
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index e2f1866..bea31ce 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp | |||
| @@ -840,13 +840,18 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in | |||
| 840 | { | 840 | { |
| 841 | if (index != (UInt32)(Int32)-1) | 841 | if (index != (UInt32)(Int32)-1) |
| 842 | { | 842 | { |
| 843 | // v26.03: we have no way to convert index_in_server to index_in_ArcItems | ||
| 844 | // so the code was commented: | ||
| 845 | /* | ||
| 843 | if (ArcItems) | 846 | if (ArcItems) |
| 844 | { | 847 | { |
| 845 | const CArcItem &ai = (*ArcItems)[index]; | 848 | const CArcItem &ai = (*ArcItems)[index]; |
| 846 | s = ai.Name; | 849 | s = ai.Name; |
| 847 | isDir = ai.IsDir; | 850 | isDir = ai.IsDir; |
| 848 | } | 851 | } |
| 849 | else if (Arc) | 852 | else |
| 853 | */ | ||
| 854 | if (Arc) | ||
| 850 | { | 855 | { |
| 851 | RINOK(Arc->GetItem_Path(index, s2)) | 856 | RINOK(Arc->GetItem_Path(index, s2)) |
| 852 | s = s2; | 857 | s = s2; |
| @@ -899,9 +904,13 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt3 | |||
| 899 | { | 904 | { |
| 900 | if (index != (UInt32)(Int32)-1) | 905 | if (index != (UInt32)(Int32)-1) |
| 901 | { | 906 | { |
| 907 | // v26.03: we have no way to convert index_in_server to index_in_ArcItems | ||
| 908 | /* | ||
| 902 | if (ArcItems) | 909 | if (ArcItems) |
| 903 | s = (*ArcItems)[index].Name; | 910 | s = (*ArcItems)[index].Name; |
| 904 | else if (Arc) | 911 | else |
| 912 | */ | ||
| 913 | if (Arc) | ||
| 905 | { | 914 | { |
| 906 | RINOK(Arc->GetItem_Path(index, s2)) | 915 | RINOK(Arc->GetItem_Path(index, s2)) |
| 907 | s = s2; | 916 | s = s2; |
diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp index 685ac70..3ba811c 100644 --- a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp +++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp | |||
| @@ -2,27 +2,6 @@ | |||
| 2 | 2 | ||
| 3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
| 4 | 4 | ||
| 5 | #ifdef __MINGW32_VERSION | ||
| 6 | // #if !defined(_MSC_VER) && (__GNUC__) && (__GNUC__ < 10) | ||
| 7 | // for old mingw | ||
| 8 | #include <ddk/ntddk.h> | ||
| 9 | #else | ||
| 10 | #ifndef Z7_OLD_WIN_SDK | ||
| 11 | #if !defined(_M_IA64) | ||
| 12 | #include <winternl.h> | ||
| 13 | #endif | ||
| 14 | #else | ||
| 15 | typedef LONG NTSTATUS; | ||
| 16 | typedef struct _IO_STATUS_BLOCK { | ||
| 17 | union { | ||
| 18 | NTSTATUS Status; | ||
| 19 | PVOID Pointer; | ||
| 20 | }; | ||
| 21 | ULONG_PTR Information; | ||
| 22 | } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; | ||
| 23 | #endif | ||
| 24 | #endif | ||
| 25 | |||
| 26 | #include "../../../Common/ComTry.h" | 5 | #include "../../../Common/ComTry.h" |
| 27 | #include "../../../Common/StringConvert.h" | 6 | #include "../../../Common/StringConvert.h" |
| 28 | #include "../../../Common/Wildcard.h" | 7 | #include "../../../Common/Wildcard.h" |
| @@ -511,13 +490,6 @@ static HRESULT UpdateFile(NFsFolder::CCopyStateIO &state, CFSTR inPath, CFSTR ou | |||
| 511 | 490 | ||
| 512 | EXTERN_C_BEGIN | 491 | EXTERN_C_BEGIN |
| 513 | 492 | ||
| 514 | typedef enum | ||
| 515 | { | ||
| 516 | Z7_WIN_FileRenameInformation = 10 | ||
| 517 | } | ||
| 518 | Z7_WIN_FILE_INFORMATION_CLASS; | ||
| 519 | |||
| 520 | |||
| 521 | typedef struct | 493 | typedef struct |
| 522 | { | 494 | { |
| 523 | // #if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS1) | 495 | // #if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS1) |
| @@ -534,34 +506,6 @@ typedef struct | |||
| 534 | WCHAR FileName[1]; | 506 | WCHAR FileName[1]; |
| 535 | } Z7_WIN_FILE_RENAME_INFORMATION; | 507 | } Z7_WIN_FILE_RENAME_INFORMATION; |
| 536 | 508 | ||
| 537 | #if (_WIN32_WINNT >= 0x0500) && !defined(_M_IA64) | ||
| 538 | #define Z7_WIN_NTSTATUS NTSTATUS | ||
| 539 | #define Z7_WIN_IO_STATUS_BLOCK IO_STATUS_BLOCK | ||
| 540 | #else | ||
| 541 | typedef LONG Z7_WIN_NTSTATUS; | ||
| 542 | typedef struct | ||
| 543 | { | ||
| 544 | union | ||
| 545 | { | ||
| 546 | Z7_WIN_NTSTATUS Status; | ||
| 547 | PVOID Pointer; | ||
| 548 | } DUMMYUNIONNAME; | ||
| 549 | ULONG_PTR Information; | ||
| 550 | } Z7_WIN_IO_STATUS_BLOCK; | ||
| 551 | #endif | ||
| 552 | |||
| 553 | typedef Z7_WIN_NTSTATUS (WINAPI *Func_NtSetInformationFile)( | ||
| 554 | HANDLE FileHandle, | ||
| 555 | Z7_WIN_IO_STATUS_BLOCK *IoStatusBlock, | ||
| 556 | PVOID FileInformation, | ||
| 557 | ULONG Length, | ||
| 558 | Z7_WIN_FILE_INFORMATION_CLASS FileInformationClass); | ||
| 559 | |||
| 560 | // NTAPI | ||
| 561 | typedef ULONG (WINAPI *Func_RtlNtStatusToDosError)(Z7_WIN_NTSTATUS Status); | ||
| 562 | |||
| 563 | #define MY_STATUS_SUCCESS 0 | ||
| 564 | |||
| 565 | EXTERN_C_END | 509 | EXTERN_C_END |
| 566 | 510 | ||
| 567 | // static Func_NtSetInformationFile f_NtSetInformationFile; | 511 | // static Func_NtSetInformationFile f_NtSetInformationFile; |
| @@ -572,16 +516,6 @@ Z7_COM7F_IMF(CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IPr | |||
| 572 | { | 516 | { |
| 573 | const CAltStream &ss = Streams[index]; | 517 | const CAltStream &ss = Streams[index]; |
| 574 | const FString srcPath = _pathPrefix + us2fs(ss.Name); | 518 | const FString srcPath = _pathPrefix + us2fs(ss.Name); |
| 575 | |||
| 576 | const HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); | ||
| 577 | // if (!g_NtSetInformationFile_WasRequested) { | ||
| 578 | // g_NtSetInformationFile_WasRequested = true; | ||
| 579 | const | ||
| 580 | Func_NtSetInformationFile | ||
| 581 | f_NtSetInformationFile = Z7_GET_PROC_ADDRESS( | ||
| 582 | Func_NtSetInformationFile, ntdll, | ||
| 583 | "NtSetInformationFile"); | ||
| 584 | if (f_NtSetInformationFile) | ||
| 585 | { | 519 | { |
| 586 | NIO::CInFile inFile; | 520 | NIO::CInFile inFile; |
| 587 | if (inFile.Open_for_FileRenameInformation(srcPath)) | 521 | if (inFile.Open_for_FileRenameInformation(srcPath)) |
| @@ -599,24 +533,9 @@ Z7_COM7F_IMF(CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IPr | |||
| 599 | fri->RootDirectory = NULL; | 533 | fri->RootDirectory = NULL; |
| 600 | fri->FileNameLength = len; | 534 | fri->FileNameLength = len; |
| 601 | memcpy(fri->FileName, destPath.Ptr(), len); | 535 | memcpy(fri->FileName, destPath.Ptr(), len); |
| 602 | Z7_WIN_IO_STATUS_BLOCK iosb; | 536 | const DWORD res = inFile.Call_NtSetInformationFile_return_WinError( |
| 603 | const Z7_WIN_NTSTATUS status = f_NtSetInformationFile (inFile.GetHandle(), | 537 | fri, (ULONG)buffer.Size(), Z7_WIN_FileRenameInformation); |
| 604 | &iosb, fri, (ULONG)buffer.Size(), Z7_WIN_FileRenameInformation); | 538 | return HRESULT_FROM_WIN32(res); |
| 605 | if (status != MY_STATUS_SUCCESS) | ||
| 606 | { | ||
| 607 | const | ||
| 608 | Func_RtlNtStatusToDosError | ||
| 609 | f_RtlNtStatusToDosError = Z7_GET_PROC_ADDRESS( | ||
| 610 | Func_RtlNtStatusToDosError, ntdll, | ||
| 611 | "RtlNtStatusToDosError"); | ||
| 612 | if (f_RtlNtStatusToDosError) | ||
| 613 | { | ||
| 614 | const ULONG res = f_RtlNtStatusToDosError(status); | ||
| 615 | if (res != ERROR_MR_MID_NOT_FOUND) | ||
| 616 | return HRESULT_FROM_WIN32(res); | ||
| 617 | } | ||
| 618 | } | ||
| 619 | return status; | ||
| 620 | } | 539 | } |
| 621 | } | 540 | } |
| 622 | 541 | ||
diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp index fc2fd6c..9351993 100644 --- a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp +++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp | |||
| @@ -32,6 +32,8 @@ static void DeepCopyFormatEtc(FORMATETC *dest, const FORMATETC *src) | |||
| 32 | if (src->ptd) | 32 | if (src->ptd) |
| 33 | { | 33 | { |
| 34 | dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE)); | 34 | dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE)); |
| 35 | if (!dest->ptd) | ||
| 36 | throw 2026; // CNewException() | ||
| 35 | *(dest->ptd) = *(src->ptd); | 37 | *(dest->ptd) = *(src->ptd); |
| 36 | } | 38 | } |
| 37 | } | 39 | } |
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index 51dfaa9..00c9353 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp | |||
| @@ -45,6 +45,26 @@ typedef struct _IO_STATUS_BLOCK { | |||
| 45 | 45 | ||
| 46 | #include "SysIconUtils.h" | 46 | #include "SysIconUtils.h" |
| 47 | 47 | ||
| 48 | EXTERN_C_BEGIN | ||
| 49 | |||
| 50 | #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500) && !defined(_M_IA64) | ||
| 51 | #define Z7_WIN_NTSTATUS NTSTATUS | ||
| 52 | #define Z7_WIN_IO_STATUS_BLOCK IO_STATUS_BLOCK | ||
| 53 | #else | ||
| 54 | typedef LONG Z7_WIN_NTSTATUS; | ||
| 55 | typedef struct | ||
| 56 | { | ||
| 57 | union | ||
| 58 | { | ||
| 59 | Z7_WIN_NTSTATUS Status; | ||
| 60 | PVOID Pointer; | ||
| 61 | } DUMMYUNIONNAME; | ||
| 62 | ULONG_PTR Information; | ||
| 63 | } Z7_WIN_IO_STATUS_BLOCK; | ||
| 64 | #endif | ||
| 65 | |||
| 66 | EXTERN_C_END | ||
| 67 | |||
| 48 | #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0501 | 68 | #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0501 |
| 49 | #ifdef _APISETFILE_ | 69 | #ifdef _APISETFILE_ |
| 50 | // Windows SDK 8.1 defines in fileapi.h the function GetCompressedFileSizeW only if _WIN32_WINNT >= 0x0501 | 70 | // Windows SDK 8.1 defines in fileapi.h the function GetCompressedFileSizeW only if _WIN32_WINNT >= 0x0501 |
| @@ -445,46 +465,6 @@ bool CFSFolder::ReadFileInfo(CDirItem &di) | |||
| 445 | 465 | ||
| 446 | 466 | ||
| 447 | EXTERN_C_BEGIN | 467 | EXTERN_C_BEGIN |
| 448 | |||
| 449 | typedef struct | ||
| 450 | { | ||
| 451 | LARGE_INTEGER CreationTime; | ||
| 452 | LARGE_INTEGER LastAccessTime; | ||
| 453 | LARGE_INTEGER LastWriteTime; | ||
| 454 | LARGE_INTEGER ChangeTime; | ||
| 455 | ULONG FileAttributes; | ||
| 456 | UInt32 Reserved; // it's expected for alignment | ||
| 457 | } | ||
| 458 | Z7_WIN_FILE_BASIC_INFORMATION; | ||
| 459 | |||
| 460 | |||
| 461 | typedef enum | ||
| 462 | { | ||
| 463 | Z7_WIN_FileDirectoryInformation = 1, | ||
| 464 | Z7_WIN_FileFullDirectoryInformation, | ||
| 465 | Z7_WIN_FileBothDirectoryInformation, | ||
| 466 | Z7_WIN_FileBasicInformation | ||
| 467 | } | ||
| 468 | Z7_WIN_FILE_INFORMATION_CLASS; | ||
| 469 | |||
| 470 | |||
| 471 | #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500) && !defined(_M_IA64) | ||
| 472 | #define Z7_WIN_NTSTATUS NTSTATUS | ||
| 473 | #define Z7_WIN_IO_STATUS_BLOCK IO_STATUS_BLOCK | ||
| 474 | #else | ||
| 475 | typedef LONG Z7_WIN_NTSTATUS; | ||
| 476 | typedef struct | ||
| 477 | { | ||
| 478 | union | ||
| 479 | { | ||
| 480 | Z7_WIN_NTSTATUS Status; | ||
| 481 | PVOID Pointer; | ||
| 482 | } DUMMYUNIONNAME; | ||
| 483 | ULONG_PTR Information; | ||
| 484 | } Z7_WIN_IO_STATUS_BLOCK; | ||
| 485 | #endif | ||
| 486 | |||
| 487 | |||
| 488 | typedef Z7_WIN_NTSTATUS (WINAPI * Func_NtQueryInformationFile)( | 468 | typedef Z7_WIN_NTSTATUS (WINAPI * Func_NtQueryInformationFile)( |
| 489 | HANDLE handle, Z7_WIN_IO_STATUS_BLOCK *io, | 469 | HANDLE handle, Z7_WIN_IO_STATUS_BLOCK *io, |
| 490 | void *ptr, LONG len, Z7_WIN_FILE_INFORMATION_CLASS cls); | 470 | void *ptr, LONG len, Z7_WIN_FILE_INFORMATION_CLASS cls); |
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index 9d78368..8a902ef 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp | |||
| @@ -871,27 +871,50 @@ bool CPanel::IsVirus_Message(const UString &name) | |||
| 871 | const wchar_t cRLO = (wchar_t)0x202E; | 871 | const wchar_t cRLO = (wchar_t)0x202E; |
| 872 | bool isVirus = false; | 872 | bool isVirus = false; |
| 873 | bool isSpaceError = false; | 873 | bool isSpaceError = false; |
| 874 | name2 = name; | 874 | { |
| 875 | 875 | unsigned numSpaces = 0; | |
| 876 | for (unsigned i = 0; i < name.Len(); i++) | ||
| 877 | { | ||
| 878 | const wchar_t c = name[i]; | ||
| 879 | switch (c) | ||
| 880 | { | ||
| 881 | case ' ': | ||
| 882 | case '\t': | ||
| 883 | case 0x00A0: // Non-Breaking Space | ||
| 884 | case 0x2002: // En Space | ||
| 885 | case 0x2003: // Em Space | ||
| 886 | case 0x2004: // Three-Per-Em Space | ||
| 887 | case 0x2005: // Four-Per-Em Space | ||
| 888 | case 0x2006: // Six-Per-Em Space | ||
| 889 | case 0x2007: // Figure Space | ||
| 890 | case 0x2008: // Punctuation Space | ||
| 891 | case 0x2009: // Thin Space | ||
| 892 | case 0x200A: // Hair Space | ||
| 893 | case 0x200B: // Zero Width Space | ||
| 894 | case 0x202F: // Narrow Non-Breaking Space | ||
| 895 | case 0x205F: // Medium Mathematical Space | ||
| 896 | case 0x3000: // Ideographic Space | ||
| 897 | numSpaces++; | ||
| 898 | break; | ||
| 899 | default: | ||
| 900 | numSpaces = 0; | ||
| 901 | break; | ||
| 902 | } | ||
| 903 | if (numSpaces <= 1) | ||
| 904 | name2 += c; | ||
| 905 | if (numSpaces >= 5) | ||
| 906 | { | ||
| 907 | isVirus = true; | ||
| 908 | isSpaceError = true; | ||
| 909 | } | ||
| 910 | } | ||
| 911 | } | ||
| 876 | if (name2.Find(cRLO) >= 0) | 912 | if (name2.Find(cRLO) >= 0) |
| 877 | { | 913 | { |
| 878 | const UString badString(cRLO); | 914 | const UString badString(cRLO); |
| 879 | name2.Replace(badString, L"[RLO]"); | 915 | name2.Replace(badString, L"[RLO]"); |
| 880 | isVirus = true; | 916 | isVirus = true; |
| 881 | } | 917 | } |
| 882 | { | ||
| 883 | const wchar_t * const kVirusSpaces = L" "; | ||
| 884 | // const unsigned kNumSpaces = strlen(kVirusSpaces); | ||
| 885 | for (;;) | ||
| 886 | { | ||
| 887 | int pos = name2.Find(kVirusSpaces); | ||
| 888 | if (pos < 0) | ||
| 889 | break; | ||
| 890 | isVirus = true; | ||
| 891 | isSpaceError = true; | ||
| 892 | name2.Replace(kVirusSpaces, L" "); | ||
| 893 | } | ||
| 894 | } | ||
| 895 | 918 | ||
| 896 | #ifdef _WIN32 | 919 | #ifdef _WIN32 |
| 897 | { | 920 | { |
diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp index 868ad22..1bc8174 100644 --- a/CPP/7zip/UI/FileManager/PanelItems.cpp +++ b/CPP/7zip/UI/FileManager/PanelItems.cpp | |||
| @@ -648,9 +648,28 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) | |||
| 648 | 648 | ||
| 649 | // OutputDebugStringA("S1\n"); | 649 | // OutputDebugStringA("S1\n"); |
| 650 | 650 | ||
| 651 | UString correctedName; | 651 | UString correctedName, itemName, relPath, focusedNamePure, selectedName; |
| 652 | UString itemName; | 652 | bool needCheckSlash = false; |
| 653 | UString relPath; | 653 | if (state.FocusedName_Defined) |
| 654 | { | ||
| 655 | focusedNamePure = state.FocusedName; | ||
| 656 | const int pos = focusedNamePure.ReverseFind_PathSepar(); | ||
| 657 | if (pos >= 0) | ||
| 658 | { | ||
| 659 | focusedNamePure.DeleteFrontal((unsigned)pos + 1); | ||
| 660 | needCheckSlash = true; | ||
| 661 | } | ||
| 662 | } | ||
| 663 | if (state.SelectedNames.Size() == 1) | ||
| 664 | { | ||
| 665 | selectedName = state.SelectedNames[0]; | ||
| 666 | const int pos = selectedName.ReverseFind_PathSepar(); | ||
| 667 | if (pos >= 0) | ||
| 668 | { | ||
| 669 | selectedName.DeleteFrontal((unsigned)pos + 1); | ||
| 670 | needCheckSlash = true; | ||
| 671 | } | ||
| 672 | } | ||
| 654 | 673 | ||
| 655 | for (UInt32 i = 0; i < numItems; i++) | 674 | for (UInt32 i = 0; i < numItems; i++) |
| 656 | { | 675 | { |
| @@ -667,8 +686,11 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) | |||
| 667 | } | 686 | } |
| 668 | 687 | ||
| 669 | bool selected = false; | 688 | bool selected = false; |
| 670 | 689 | ||
| 671 | if (state.FocusedName_Defined || !state.SelectedNames.IsEmpty()) | 690 | if (state.SelectedNames.Size() > 1 |
| 691 | || (state.SelectedNames.Size() == 1 && selectedName == name) | ||
| 692 | || (state.FocusedName_Defined && focusedNamePure == name) | ||
| 693 | || (needCheckSlash && NWindows::NFile::NName::FindSepar(name) >= 0)) | ||
| 672 | { | 694 | { |
| 673 | relPath.Empty(); | 695 | relPath.Empty(); |
| 674 | // relPath += GetItemPrefix(i); | 696 | // relPath += GetItemPrefix(i); |
| @@ -875,10 +897,10 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state) | |||
| 875 | SetFocusedSelectedItem(cursorIndex, state.SelectFocused); | 897 | SetFocusedSelectedItem(cursorIndex, state.SelectFocused); |
| 876 | 898 | ||
| 877 | Print_OnNotify("after SetFocusedSelectedItem"); | 899 | Print_OnNotify("after SetFocusedSelectedItem"); |
| 878 | 900 | // OutputDebugStringA("Sort before"); | |
| 879 | SetSortRawStatus(); | 901 | SetSortRawStatus(); |
| 880 | _listView.SortItems(CompareItems, (LPARAM)this); | 902 | _listView.SortItems(CompareItems, (LPARAM)this); |
| 881 | 903 | // OutputDebugStringA("=== Sort after"); | |
| 882 | Print_OnNotify("after Sort"); | 904 | Print_OnNotify("after Sort"); |
| 883 | 905 | ||
| 884 | if (cursorIndex < 0 && _listView.GetItemCount() > 0) | 906 | if (cursorIndex < 0 && _listView.GetItemCount() > 0) |
| @@ -1089,19 +1111,19 @@ void CPanel::OpenSelectedItems(bool tryInternal) | |||
| 1089 | indices.Insert(0, realIndex); | 1111 | indices.Insert(0, realIndex); |
| 1090 | } | 1112 | } |
| 1091 | 1113 | ||
| 1092 | bool dirIsStarted = false; | 1114 | // bool dirIsStarted = false; |
| 1093 | FOR_VECTOR (i, indices) | 1115 | FOR_VECTOR (i, indices) |
| 1094 | { | 1116 | { |
| 1095 | UInt32 index = indices[i]; | 1117 | UInt32 index = indices[i]; |
| 1096 | // CFileInfo &aFile = m_Files[index]; | 1118 | // CFileInfo &aFile = m_Files[index]; |
| 1097 | if (IsItem_Folder(index)) | 1119 | if (IsItem_Folder(index)) |
| 1098 | { | 1120 | { |
| 1099 | if (!dirIsStarted) | 1121 | // if (!dirIsStarted) |
| 1100 | { | 1122 | { |
| 1101 | if (tryInternal) | 1123 | if (tryInternal) |
| 1102 | { | 1124 | { |
| 1103 | OpenFolder(index); | 1125 | OpenFolder(index); |
| 1104 | dirIsStarted = true; | 1126 | // dirIsStarted = true; |
| 1105 | break; | 1127 | break; |
| 1106 | } | 1128 | } |
| 1107 | else | 1129 | else |
| @@ -1162,14 +1184,15 @@ void CPanel::GetItemName(unsigned itemIndex, UString &s) const | |||
| 1162 | 1184 | ||
| 1163 | UString CPanel::GetItemPrefix(unsigned itemIndex) const | 1185 | UString CPanel::GetItemPrefix(unsigned itemIndex) const |
| 1164 | { | 1186 | { |
| 1165 | if (itemIndex == kParentIndex) | ||
| 1166 | return UString(); | ||
| 1167 | NCOM::CPropVariant prop; | ||
| 1168 | if (_folder->GetProperty(itemIndex, kpidPrefix, &prop) != S_OK) | ||
| 1169 | throw 2723400; | ||
| 1170 | UString prefix; | 1187 | UString prefix; |
| 1171 | if (prop.vt == VT_BSTR) | 1188 | if (itemIndex != kParentIndex) |
| 1172 | prefix.SetFromBstr(prop.bstrVal); | 1189 | { |
| 1190 | NCOM::CPropVariant prop; | ||
| 1191 | if (_folder->GetProperty(itemIndex, kpidPrefix, &prop) != S_OK) | ||
| 1192 | throw 2723400; | ||
| 1193 | if (prop.vt == VT_BSTR) | ||
| 1194 | prefix.SetFromBstr(prop.bstrVal); | ||
| 1195 | } | ||
| 1173 | return prefix; | 1196 | return prefix; |
| 1174 | } | 1197 | } |
| 1175 | 1198 | ||
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index e655843..231a68f 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp | |||
| @@ -493,9 +493,11 @@ HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, | |||
| 493 | HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, | 493 | HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, |
| 494 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl) | 494 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl) |
| 495 | { | 495 | { |
| 496 | ULONG eaten = 0; | 496 | // ULONG eaten = 0; |
| 497 | return shellFolder->ParseDisplayName(hwnd, NULL, | 497 | return shellFolder->ParseDisplayName(hwnd, NULL, |
| 498 | path.Ptr_non_const(), &eaten, ppidl, NULL); | 498 | path.Ptr_non_const(), |
| 499 | NULL, // &eaten | ||
| 500 | ppidl, NULL); | ||
| 499 | } | 501 | } |
| 500 | 502 | ||
| 501 | 503 | ||
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp index 72fe5e7..d342181 100644 --- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp | |||
| @@ -25,7 +25,7 @@ CExtToIconMap g_Ext_to_Icon_Map; | |||
| 25 | int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl) | 25 | int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl) |
| 26 | { | 26 | { |
| 27 | LPITEMIDLIST pidl = NULL; | 27 | LPITEMIDLIST pidl = NULL; |
| 28 | SHGetSpecialFolderLocation(NULL, csidl, &pidl); | 28 | if (SHGetSpecialFolderLocation(NULL, csidl, &pidl) == S_OK) |
| 29 | if (pidl) | 29 | if (pidl) |
| 30 | { | 30 | { |
| 31 | SHFILEINFO shFileInfo; | 31 | SHFILEINFO shFileInfo; |
| @@ -333,6 +333,7 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin | |||
| 333 | HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons) | 333 | HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons) |
| 334 | { | 334 | { |
| 335 | SHFILEINFO shFileInfo; | 335 | SHFILEINFO shFileInfo; |
| 336 | Z7_memset_0_VAR(shFileInfo); // optional | ||
| 336 | // shFileInfo.hIcon = NULL; // optional | 337 | // shFileInfo.hIcon = NULL; // optional |
| 337 | const DWORD_PTR res = SHGetFileInfo(TEXT(""), | 338 | const DWORD_PTR res = SHGetFileInfo(TEXT(""), |
| 338 | /* FILE_ATTRIBUTE_ARCHIVE | */ | 339 | /* FILE_ATTRIBUTE_ARCHIVE | */ |
diff --git a/CPP/Build.mak b/CPP/Build.mak index d9fcfb5..355063b 100644 --- a/CPP/Build.mak +++ b/CPP/Build.mak | |||
| @@ -63,23 +63,24 @@ COMPL_ASM = $(MY_ML) $** $O/$(*B).obj | |||
| 63 | COMPL_ASM = $(MY_ML) -c -Fo$O/ $** | 63 | COMPL_ASM = $(MY_ML) -c -Fo$O/ $** |
| 64 | !ENDIF | 64 | !ENDIF |
| 65 | 65 | ||
| 66 | CFLAGS_c_switch = -c -Fo$O/ | ||
| 67 | |||
| 66 | !IFDEF OLD_COMPILER | 68 | !IFDEF OLD_COMPILER |
| 67 | CFLAGS_WARN_LEVEL = -W4 | 69 | CFLAGS_WARN_LEVEL = -W4 |
| 68 | !ELSE | 70 | !ELSE |
| 71 | !IF "$(CC)" != "clang-cl" | ||
| 72 | CFLAGS_WARN_LEVEL = -Wall -analyze | ||
| 73 | !ELSE | ||
| 74 | CFLAGS_WARN_LEVEL = -Wall --analyze -Xclang -analyzer-output=text | ||
| 75 | # CFLAGS_c_switch = | ||
| 76 | !ENDIF | ||
| 69 | CFLAGS_WARN_LEVEL = -Wall | 77 | CFLAGS_WARN_LEVEL = -Wall |
| 70 | !ENDIF | 78 | !ENDIF |
| 71 | 79 | ||
| 72 | CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ $(CFLAGS_WARN_LEVEL) -WX -EHsc -Gy -GR- -GF | 80 | CFLAGS = $(CFLAGS) -nologo $(CFLAGS_c_switch) $(CFLAGS_WARN_LEVEL) -WX -EHsc -Gy -GR- -GF |
| 73 | 81 | ||
| 74 | !IF "$(CC)" == "clang-cl" | 82 | !IF "$(CC)" == "clang-cl" |
| 75 | 83 | CFLAGS = $(CFLAGS) -Werror -Wall -Wextra -Weverything -Wfatal-errors | |
| 76 | CFLAGS = $(CFLAGS) \ | ||
| 77 | -Werror \ | ||
| 78 | -Wall \ | ||
| 79 | -Wextra \ | ||
| 80 | -Weverything \ | ||
| 81 | -Wfatal-errors \ | ||
| 82 | |||
| 83 | !ENDIF | 84 | !ENDIF |
| 84 | 85 | ||
| 85 | # !IFDEF MY_DYNAMIC_LINK | 86 | # !IFDEF MY_DYNAMIC_LINK |
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h index 7dc21ba..b45530a 100644 --- a/CPP/Common/MyCom.h +++ b/CPP/Common/MyCom.h | |||
| @@ -688,6 +688,6 @@ EXTERN_C_END | |||
| 688 | Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \ | 688 | Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \ |
| 689 | 689 | ||
| 690 | 690 | ||
| 691 | #define k_My_HRESULT_WritingWasCut 0x20000010 | 691 | #define k_My_HRESULT_WritingWasCut ((HRESULT)0x20000010) |
| 692 | 692 | ||
| 693 | #endif | 693 | #endif |
diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h index a772785..c806767 100644 --- a/CPP/Common/MyVector.h +++ b/CPP/Common/MyVector.h | |||
| @@ -92,6 +92,21 @@ public: | |||
| 92 | _size = newSize; | 92 | _size = newSize; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | void ChangeSize_KeepData_plus_AdditionalReserve(const unsigned newSize) | ||
| 96 | { | ||
| 97 | if (newSize > _capacity) | ||
| 98 | { | ||
| 99 | if (newSize > k_VectorSizeMax) | ||
| 100 | throw 2021; | ||
| 101 | const unsigned rem = k_VectorSizeMax - newSize; | ||
| 102 | unsigned add = newSize >> 2; | ||
| 103 | if (add > rem) | ||
| 104 | add = rem; | ||
| 105 | ReAllocForNewCapacity(newSize + add); | ||
| 106 | } | ||
| 107 | _size = newSize; | ||
| 108 | } | ||
| 109 | |||
| 95 | void ClearAndReserve(unsigned newCapacity) | 110 | void ClearAndReserve(unsigned newCapacity) |
| 96 | { | 111 | { |
| 97 | Clear(); | 112 | Clear(); |
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index ad0d8c9..bf77c15 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp | |||
| @@ -34,7 +34,9 @@ using namespace NName; | |||
| 34 | 34 | ||
| 35 | #ifndef _WIN32 | 35 | #ifndef _WIN32 |
| 36 | 36 | ||
| 37 | static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts) | 37 | extern |
| 38 | bool FiTime_To_timespec(const CFiTime *ft, timespec &ts); | ||
| 39 | bool FiTime_To_timespec(const CFiTime *ft, timespec &ts) | ||
| 38 | { | 40 | { |
| 39 | if (ft) | 41 | if (ft) |
| 40 | { | 42 | { |
| @@ -51,7 +53,7 @@ static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts) | |||
| 51 | ts.tv_sec = 0; | 53 | ts.tv_sec = 0; |
| 52 | ts.tv_nsec = | 54 | ts.tv_nsec = |
| 53 | #ifdef UTIME_OMIT | 55 | #ifdef UTIME_OMIT |
| 54 | UTIME_OMIT; // -2 keep old timesptamp | 56 | UTIME_OMIT; // -2 keep old timestamp |
| 55 | #else | 57 | #else |
| 56 | // UTIME_NOW; -1 // set to the current time | 58 | // UTIME_NOW; -1 // set to the current time |
| 57 | 0; | 59 | 0; |
| @@ -170,6 +172,10 @@ bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, con | |||
| 170 | 172 | ||
| 171 | bool SetFileAttrib(CFSTR path, DWORD attrib) | 173 | bool SetFileAttrib(CFSTR path, DWORD attrib) |
| 172 | { | 174 | { |
| 175 | /* win10: | ||
| 176 | if (attrib == 0), it sets (FILE_ATTRIBUTE_NORMAL) attribute | ||
| 177 | (FILE_ATTRIBUTE_DIRECTORY and some another attributes are ignored for files). | ||
| 178 | */ | ||
| 173 | #ifndef _UNICODE | 179 | #ifndef _UNICODE |
| 174 | if (!g_IsNT) | 180 | if (!g_IsNT) |
| 175 | { | 181 | { |
| @@ -1078,7 +1084,7 @@ static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progres | |||
| 1078 | } | 1084 | } |
| 1079 | // There is file IO error or process was interrupted by user. | 1085 | // There is file IO error or process was interrupted by user. |
| 1080 | // We close output file and delete it. | 1086 | // We close output file and delete it. |
| 1081 | // DeleteFileAlways doesn't change errno (if successed), but we restore errno. | 1087 | // DeleteFileAlways doesn't change errno (if succeed), but we restore errno. |
| 1082 | const int errno_save = errno; | 1088 | const int errno_save = errno; |
| 1083 | DeleteFileAlways(newFile); | 1089 | DeleteFileAlways(newFile); |
| 1084 | errno = errno_save; | 1090 | errno = errno_save; |
| @@ -1240,26 +1246,34 @@ bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, con | |||
| 1240 | } | 1246 | } |
| 1241 | 1247 | ||
| 1242 | 1248 | ||
| 1243 | struct C_umask | 1249 | C_umask::C_umask() |
| 1244 | { | 1250 | { |
| 1245 | mode_t mask; | 1251 | /* |
| 1246 | 1252 | For security purposes, we restrict the file (mode) attributes | |
| 1247 | C_umask() | 1253 | using the process's file mode creation mask (umask). |
| 1248 | { | 1254 | System's umask is used by open(), mkdir(), and other system calls |
| 1249 | /* by security reasons we restrict attributes according | 1255 | that create files to modify the permissions placed on newly |
| 1250 | with process's file mode creation mask (umask) */ | 1256 | created files or directories. |
| 1251 | const mode_t um = umask(0); // octal :0022 is expected | 1257 | We use (g_umask.mask) for any function that changes the file's access |
| 1252 | mask = 0777 & (~um); // octal: 0755 is expected | 1258 | mode but is not affected by the system's umask. |
| 1253 | umask(um); // restore the umask | 1259 | We use additional mask restiction 0777 for security purposes. |
| 1254 | // printf("\n umask = 0%03o mask = 0%03o\n", um, mask); | 1260 | So we don't create the following mode bits for files and directories: |
| 1255 | 1261 | S_ISUID 04000 set-user-ID bit | |
| 1256 | // mask = 0777; // debug we can disable the restriction: | 1262 | S_ISGID 02000 set-group-ID bit |
| 1257 | } | 1263 | S_ISVTX 01000 sticky bit |
| 1258 | }; | 1264 | system's open(), mkdir() also can have similar 0777 restiction for some cases. |
| 1265 | */ | ||
| 1266 | const mode_t um = umask(0); // um = 0022 (octal) is expected | ||
| 1267 | mask = ~um | ||
| 1268 | & 0777; // 0777 is our additional mode restruction : is secure | ||
| 1269 | // & 07777; // for debug : 07777 to support all mode bits : is not secure | ||
| 1270 | // mask = 07777; // for debug : to restore all mode bits | ||
| 1271 | umask(um); // restore original umask that was changed by umask(0) in code above | ||
| 1272 | } | ||
| 1259 | 1273 | ||
| 1260 | static C_umask g_umask; | 1274 | C_umask g_umask; |
| 1261 | 1275 | ||
| 1262 | // #define PRF(x) x; | 1276 | // #define PRF(x) x |
| 1263 | #define PRF(x) | 1277 | #define PRF(x) |
| 1264 | 1278 | ||
| 1265 | #define TRACE_SetFileAttrib(msg) \ | 1279 | #define TRACE_SetFileAttrib(msg) \ |
| @@ -1273,12 +1287,17 @@ int my_chown(CFSTR path, uid_t owner, gid_t group) | |||
| 1273 | return chown(path, owner, group); | 1287 | return chown(path, owner, group); |
| 1274 | } | 1288 | } |
| 1275 | 1289 | ||
| 1290 | int my_chown_Link(CFSTR path, uid_t owner, gid_t group) | ||
| 1291 | { | ||
| 1292 | return lchown(path, owner, group); | ||
| 1293 | // return fchownat(AT_FDCWD, path, owner, group, AT_SYMLINK_NOFOLLOW); | ||
| 1294 | } | ||
| 1295 | |||
| 1276 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) | 1296 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) |
| 1277 | { | 1297 | { |
| 1278 | TRACE_SetFileAttrib("") | 1298 | TRACE_SetFileAttrib("") |
| 1279 | 1299 | mode_t mode; | |
| 1280 | struct stat st; | 1300 | struct stat st; |
| 1281 | |||
| 1282 | bool use_lstat = true; | 1301 | bool use_lstat = true; |
| 1283 | if (use_lstat) | 1302 | if (use_lstat) |
| 1284 | { | 1303 | { |
| @@ -1297,20 +1316,26 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) | |||
| 1297 | return false; | 1316 | return false; |
| 1298 | } | 1317 | } |
| 1299 | } | 1318 | } |
| 1300 | 1319 | mode = st.st_mode; | |
| 1320 | |||
| 1301 | if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) | 1321 | if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) |
| 1302 | { | 1322 | { |
| 1303 | TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION") | 1323 | TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION") |
| 1304 | st.st_mode = attrib >> 16; | 1324 | mode = attrib >> 16; |
| 1305 | if (S_ISDIR(st.st_mode)) | 1325 | if (S_ISDIR(mode)) |
| 1306 | { | 1326 | { |
| 1327 | if (!S_ISDIR(st.st_mode)) | ||
| 1328 | return true; | ||
| 1307 | // user/7z must be able to create files in this directory | 1329 | // user/7z must be able to create files in this directory |
| 1308 | st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR); | 1330 | mode |= (S_IRUSR | S_IWUSR | S_IXUSR); |
| 1331 | } | ||
| 1332 | else | ||
| 1333 | { | ||
| 1334 | if (!S_ISREG(mode) || !S_ISREG(st.st_mode)) | ||
| 1335 | return true; | ||
| 1309 | } | 1336 | } |
| 1310 | else if (!S_ISREG(st.st_mode)) | ||
| 1311 | return true; | ||
| 1312 | } | 1337 | } |
| 1313 | else if (S_ISLNK(st.st_mode)) | 1338 | else if (S_ISLNK(mode)) |
| 1314 | { | 1339 | { |
| 1315 | /* for most systems: permissions for symlinks are fixed to rwxrwxrwx. | 1340 | /* for most systems: permissions for symlinks are fixed to rwxrwxrwx. |
| 1316 | so we don't need chmod() for symlinks. */ | 1341 | so we don't need chmod() for symlinks. */ |
| @@ -1322,27 +1347,28 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) | |||
| 1322 | { | 1347 | { |
| 1323 | TRACE_SetFileAttrib("Only Windows Attributes") | 1348 | TRACE_SetFileAttrib("Only Windows Attributes") |
| 1324 | // Only Windows Attributes | 1349 | // Only Windows Attributes |
| 1325 | if (S_ISDIR(st.st_mode) | 1350 | if (S_ISDIR(mode) |
| 1326 | || (attrib & FILE_ATTRIBUTE_READONLY) == 0) | 1351 | || (attrib & FILE_ATTRIBUTE_READONLY) == 0) |
| 1327 | return true; | 1352 | return true; |
| 1328 | st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions | 1353 | mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions |
| 1329 | } | 1354 | } |
| 1330 | 1355 | ||
| 1331 | int res; | 1356 | int res; |
| 1357 | mode &= g_umask.mask; | ||
| 1332 | /* | 1358 | /* |
| 1333 | if (S_ISLNK(st.st_mode)) | 1359 | if (S_ISLNK(mode)) |
| 1334 | { | 1360 | { |
| 1335 | printf("\nfchmodat()\n"); | 1361 | printf("\nfchmodat()\n"); |
| 1336 | TRACE_chmod(path, (st.st_mode) & g_umask.mask) | 1362 | TRACE_chmod(path, (mode)) |
| 1337 | // AT_SYMLINK_NOFOLLOW is not implemted still in Linux. | 1363 | // AT_SYMLINK_NOFOLLOW is not implemented still in Linux. |
| 1338 | res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask, | 1364 | res = fchmodat(AT_FDCWD, path, (mode), |
| 1339 | S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0); | 1365 | S_ISLNK(mode) ? AT_SYMLINK_NOFOLLOW : 0); |
| 1340 | } | 1366 | } |
| 1341 | else | 1367 | else |
| 1342 | */ | 1368 | */ |
| 1343 | { | 1369 | { |
| 1344 | TRACE_chmod(path, (st.st_mode) & g_umask.mask) | 1370 | TRACE_chmod(path, mode) |
| 1345 | res = chmod(path, (st.st_mode) & g_umask.mask); | 1371 | res = chmod(path, mode); |
| 1346 | } | 1372 | } |
| 1347 | // TRACE_SetFileAttrib("End") | 1373 | // TRACE_SetFileAttrib("End") |
| 1348 | return (res == 0); | 1374 | return (res == 0); |
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h index 9ba98fc..e8d9d31 100644 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h | |||
| @@ -46,6 +46,7 @@ bool SetFileAttrib(CFSTR path, DWORD attrib); | |||
| 46 | #else | 46 | #else |
| 47 | 47 | ||
| 48 | int my_chown(CFSTR path, uid_t owner, gid_t group); | 48 | int my_chown(CFSTR path, uid_t owner, gid_t group); |
| 49 | int my_chown_Link(CFSTR path, uid_t owner, gid_t group); | ||
| 49 | 50 | ||
| 50 | #endif | 51 | #endif |
| 51 | 52 | ||
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp index dc4de14..8be06fc 100644 --- a/CPP/Windows/FileIO.cpp +++ b/CPP/Windows/FileIO.cpp | |||
| @@ -6,6 +6,29 @@ | |||
| 6 | #include "../../C/Alloc.h" | 6 | #include "../../C/Alloc.h" |
| 7 | #endif | 7 | #endif |
| 8 | 8 | ||
| 9 | #ifdef _WIN32 | ||
| 10 | #ifdef __MINGW32_VERSION | ||
| 11 | // #if !defined(_MSC_VER) && (__GNUC__) && (__GNUC__ < 10) | ||
| 12 | // for old mingw | ||
| 13 | #include <ddk/ntddk.h> | ||
| 14 | #else | ||
| 15 | #ifndef Z7_OLD_WIN_SDK | ||
| 16 | #if !defined(_M_IA64) | ||
| 17 | #include <winternl.h> | ||
| 18 | #endif | ||
| 19 | #else | ||
| 20 | typedef LONG NTSTATUS; | ||
| 21 | typedef struct _IO_STATUS_BLOCK { | ||
| 22 | union { | ||
| 23 | NTSTATUS Status; | ||
| 24 | PVOID Pointer; | ||
| 25 | }; | ||
| 26 | ULONG_PTR Information; | ||
| 27 | } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; | ||
| 28 | #endif | ||
| 29 | #endif | ||
| 30 | #endif // _WIN32 | ||
| 31 | |||
| 9 | // #include <stdio.h> | 32 | // #include <stdio.h> |
| 10 | 33 | ||
| 11 | /* | 34 | /* |
| @@ -33,6 +56,48 @@ HRESULT GetLastError_noZero_HRESULT() | |||
| 33 | extern bool g_IsNT; | 56 | extern bool g_IsNT; |
| 34 | #endif | 57 | #endif |
| 35 | 58 | ||
| 59 | #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500) && !defined(_M_IA64) | ||
| 60 | #define Z7_WIN_NTSTATUS NTSTATUS | ||
| 61 | #define Z7_WIN_IO_STATUS_BLOCK IO_STATUS_BLOCK | ||
| 62 | #else | ||
| 63 | typedef LONG Z7_WIN_NTSTATUS; | ||
| 64 | typedef struct | ||
| 65 | { | ||
| 66 | union | ||
| 67 | { | ||
| 68 | Z7_WIN_NTSTATUS Status; | ||
| 69 | PVOID Pointer; | ||
| 70 | } DUMMYUNIONNAME; | ||
| 71 | ULONG_PTR Information; | ||
| 72 | } Z7_WIN_IO_STATUS_BLOCK; | ||
| 73 | #endif | ||
| 74 | |||
| 75 | typedef Z7_WIN_NTSTATUS (WINAPI *Func_NtSetInformationFile)( | ||
| 76 | HANDLE FileHandle, | ||
| 77 | Z7_WIN_IO_STATUS_BLOCK *IoStatusBlock, | ||
| 78 | PVOID FileInformation, | ||
| 79 | ULONG Length, | ||
| 80 | Z7_WIN_FILE_INFORMATION_CLASS FileInformationClass); | ||
| 81 | // NTAPI | ||
| 82 | typedef ULONG (WINAPI *Func_RtlNtStatusToDosError)(Z7_WIN_NTSTATUS Status); | ||
| 83 | |||
| 84 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | ||
| 85 | static Func_NtSetInformationFile g_NtSetInformationFile; | ||
| 86 | static Func_RtlNtStatusToDosError g_RtlNtStatusToDosError; | ||
| 87 | static struct C_Init_NtSetInformationFile | ||
| 88 | { | ||
| 89 | C_Init_NtSetInformationFile() | ||
| 90 | { | ||
| 91 | const HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); | ||
| 92 | g_NtSetInformationFile = Z7_GET_PROC_ADDRESS( | ||
| 93 | Func_NtSetInformationFile, ntdll, | ||
| 94 | "NtSetInformationFile"); | ||
| 95 | g_RtlNtStatusToDosError = Z7_GET_PROC_ADDRESS( | ||
| 96 | Func_RtlNtStatusToDosError, ntdll, | ||
| 97 | "RtlNtStatusToDosError"); | ||
| 98 | } | ||
| 99 | } g_C_Init_NtSetInformationFile; | ||
| 100 | |||
| 36 | using namespace NWindows; | 101 | using namespace NWindows; |
| 37 | using namespace NFile; | 102 | using namespace NFile; |
| 38 | using namespace NName; | 103 | using namespace NName; |
| @@ -353,7 +418,7 @@ void CInFile::CalcDeviceSize(CFSTR s) | |||
| 353 | WinXP 64-bit: | 418 | WinXP 64-bit: |
| 354 | 419 | ||
| 355 | HDD \\.\PhysicalDrive0 (MBR): | 420 | HDD \\.\PhysicalDrive0 (MBR): |
| 356 | GetPartitionInfo == GeometryEx : corrrect size? (includes tail) | 421 | GetPartitionInfo == GeometryEx : correct size? (includes tail) |
| 357 | Geometry : smaller than GeometryEx (no tail, maybe correct too?) | 422 | Geometry : smaller than GeometryEx (no tail, maybe correct too?) |
| 358 | MyGetDiskFreeSpace : FAIL | 423 | MyGetDiskFreeSpace : FAIL |
| 359 | Size correction is slow and block size (kClusterSize) must be small? | 424 | Size correction is slow and block size (kClusterSize) must be small? |
| @@ -365,8 +430,8 @@ void CInFile::CalcDeviceSize(CFSTR s) | |||
| 365 | 430 | ||
| 366 | CD-ROM drive (ISO): | 431 | CD-ROM drive (ISO): |
| 367 | MyGetDiskFreeSpace : correct size. Same size can be calculated after correction | 432 | MyGetDiskFreeSpace : correct size. Same size can be calculated after correction |
| 368 | Geometry == CdRomGeometry : smaller than corrrect size | 433 | Geometry == CdRomGeometry : smaller than correct size |
| 369 | GetPartitionInfo == GeometryEx : larger than corrrect size | 434 | GetPartitionInfo == GeometryEx : larger than correct size |
| 370 | 435 | ||
| 371 | Floppy \\.\a: (FAT): | 436 | Floppy \\.\a: (FAT): |
| 372 | Geometry : correct size. | 437 | Geometry : correct size. |
| @@ -539,6 +604,70 @@ bool COutFile::Open_Disposition(CFSTR fileName, DWORD creationDisposition) | |||
| 539 | bool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes) | 604 | bool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes) |
| 540 | { return Open(fileName, FILE_SHARE_READ, CREATE_ALWAYS, flagsAndAttributes); } | 605 | { return Open(fileName, FILE_SHARE_READ, CREATE_ALWAYS, flagsAndAttributes); } |
| 541 | 606 | ||
| 607 | DWORD CFileBase::Call_NtSetInformationFile_return_WinError( | ||
| 608 | void *data, ULONG len, Z7_WIN_FILE_INFORMATION_CLASS fileInformationClass) const | ||
| 609 | { | ||
| 610 | if (!g_NtSetInformationFile) | ||
| 611 | return ERROR_PROC_NOT_FOUND; | ||
| 612 | Z7_WIN_IO_STATUS_BLOCK ioStatus; | ||
| 613 | Z7_memset_0_VAR(ioStatus); // optional | ||
| 614 | const Z7_WIN_NTSTATUS status = g_NtSetInformationFile(_handle, | ||
| 615 | &ioStatus, data, len, fileInformationClass); | ||
| 616 | if (status == 0) // MY_STATUS_SUCCESS | ||
| 617 | return 0; | ||
| 618 | if (g_RtlNtStatusToDosError) | ||
| 619 | { | ||
| 620 | const ULONG res = g_RtlNtStatusToDosError(status); | ||
| 621 | if (res != ERROR_MR_MID_NOT_FOUND) | ||
| 622 | return res; | ||
| 623 | } | ||
| 624 | return 1; | ||
| 625 | } | ||
| 626 | |||
| 627 | |||
| 628 | #define SET_TIME_FIELD_IF_DEFINED(dest, src) \ | ||
| 629 | { if (src) { \ | ||
| 630 | dest.LowPart = (src)->dwLowDateTime; \ | ||
| 631 | dest.HighPart = (LONG)(src)->dwHighDateTime; \ | ||
| 632 | } \ | ||
| 633 | } | ||
| 634 | |||
| 635 | bool COutFile::Set_Time_and_WinAttrib(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime, DWORD attrib) throw() | ||
| 636 | { | ||
| 637 | #ifdef _WIN32 | ||
| 638 | // similar to GetAttrib_PosixHighDetect(attrib) | ||
| 639 | if (attrib & 0xF0000000) | ||
| 640 | attrib &= 0x3FFF; | ||
| 641 | #endif | ||
| 642 | |||
| 643 | Z7_WIN_FILE_BASIC_INFORMATION fbi; | ||
| 644 | Z7_memset_0_VAR(fbi); | ||
| 645 | SET_TIME_FIELD_IF_DEFINED (fbi.CreationTime, cTime) | ||
| 646 | SET_TIME_FIELD_IF_DEFINED (fbi.LastAccessTime, aTime) | ||
| 647 | SET_TIME_FIELD_IF_DEFINED (fbi.LastWriteTime, mTime) | ||
| 648 | // fbi.ChangeTime.QuadPart = 0; | ||
| 649 | /* | ||
| 650 | if (attrib == 0) | ||
| 651 | { win10: NtSetInformationFile() doesn't change file attribute | ||
| 652 | if (attrib & FILE_ATTRIBUTE_DIRECTORY) | ||
| 653 | { win10: NtSetInformationFile() returns (STATUS_INVALID_PARAMETER) } | ||
| 654 | we provide similar attribute processing as | ||
| 655 | SetFileAttributes(): | ||
| 656 | - we ignore (FILE_ATTRIBUTE_DIRECTORY) | ||
| 657 | - we write (FILE_ATTRIBUTE_NORMAL) instead of (0) | ||
| 658 | */ | ||
| 659 | attrib &= ~(DWORD)FILE_ATTRIBUTE_DIRECTORY; | ||
| 660 | if (attrib == 0) | ||
| 661 | attrib = FILE_ATTRIBUTE_NORMAL; | ||
| 662 | fbi.FileAttributes = attrib; | ||
| 663 | const DWORD wres = Call_NtSetInformationFile_return_WinError( | ||
| 664 | &fbi, sizeof(fbi), Z7_WIN_FileBasicInformation); | ||
| 665 | if (wres == 0) | ||
| 666 | return true; | ||
| 667 | SetLastError(wres); | ||
| 668 | return false; | ||
| 669 | } | ||
| 670 | |||
| 542 | bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() | 671 | bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() |
| 543 | { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } | 672 | { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } |
| 544 | 673 | ||
| @@ -628,10 +757,16 @@ bool COutFile::SetLength_KeepPosition(UInt64 length) throw() | |||
| 628 | #include <fcntl.h> | 757 | #include <fcntl.h> |
| 629 | #include <unistd.h> | 758 | #include <unistd.h> |
| 630 | 759 | ||
| 760 | extern | ||
| 761 | bool FiTime_To_timespec(const CFiTime *ft, timespec &ts); | ||
| 762 | |||
| 631 | namespace NWindows { | 763 | namespace NWindows { |
| 632 | namespace NFile { | 764 | namespace NFile { |
| 633 | 765 | ||
| 634 | namespace NDir { | 766 | namespace NDir { |
| 767 | |||
| 768 | extern C_umask g_umask; | ||
| 769 | |||
| 635 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); | 770 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); |
| 636 | } | 771 | } |
| 637 | 772 | ||
| @@ -644,6 +779,34 @@ bool CFileBase::OpenBinary(const char *name, int flags, mode_t mode) | |||
| 644 | #endif | 779 | #endif |
| 645 | 780 | ||
| 646 | Close(); | 781 | Close(); |
| 782 | /* | ||
| 783 | The mode argument specifies the file mode bits to be | ||
| 784 | applied when a new file is created. If neither O_CREAT nor | ||
| 785 | O_TMPFILE is specified in flags, then mode is ignored (and | ||
| 786 | can thus be specified as 0, or simply omitted). | ||
| 787 | |||
| 788 | The effective mode is modified by the process's umask in | ||
| 789 | the usual way: in the absence of a default ACL, the mode of | ||
| 790 | the created file is (mode & ~umask). | ||
| 791 | |||
| 792 | Note that mode applies only to future accesses of the newly | ||
| 793 | created file; the open() call that creates a read-only file | ||
| 794 | may well return a read/write file descriptor. | ||
| 795 | |||
| 796 | POSIX: if other bits (~0777) are set in mode : the effect is unspecified | ||
| 797 | Linux: | ||
| 798 | S_ISUID 04000 set-user-ID bit | ||
| 799 | S_ISGID 02000 set-group-ID bit | ||
| 800 | S_ISVTX 01000 sticky bit | ||
| 801 | |||
| 802 | S_ISVTX can be set, but it's useless for file in modern linux. | ||
| 803 | by security reasons: | ||
| 804 | open() ignores S_ISUID | ||
| 805 | open() ignores S_ISGID, if S_IXGRP is set. | ||
| 806 | */ | ||
| 807 | // mode |= S_ISUID | S_ISGID | S_ISVTX; // for debug | ||
| 808 | // printf("\n open() mode=%o\n", (unsigned)(mode)); | ||
| 809 | |||
| 647 | _handle = ::open(name, flags, mode); | 810 | _handle = ::open(name, flags, mode); |
| 648 | return _handle != -1; | 811 | return _handle != -1; |
| 649 | 812 | ||
| @@ -740,7 +903,7 @@ bool CFileBase::SeekToBegin() const throw() | |||
| 740 | 903 | ||
| 741 | bool CInFile::Open(const char *name) | 904 | bool CInFile::Open(const char *name) |
| 742 | { | 905 | { |
| 743 | return CFileBase::OpenBinary(name, O_RDONLY); | 906 | return CFileBase::OpenBinary(name, O_RDONLY, k_OutFile_mode_default); |
| 744 | } | 907 | } |
| 745 | 908 | ||
| 746 | bool CInFile::OpenShared(const char *name, bool) | 909 | bool CInFile::OpenShared(const char *name, bool) |
| @@ -903,11 +1066,64 @@ bool COutFile::SetLength(UInt64 length) throw() | |||
| 903 | return (iret == 0); | 1066 | return (iret == 0); |
| 904 | } | 1067 | } |
| 905 | 1068 | ||
| 1069 | // #define PRF(x) x | ||
| 1070 | #define PRF(x) | ||
| 1071 | |||
| 906 | bool COutFile::Close() | 1072 | bool COutFile::Close() |
| 907 | { | 1073 | { |
| 908 | const bool res = CFileBase::Close(); | 1074 | bool res = true; |
| 909 | if (!res) | 1075 | if (_handle == -1) |
| 910 | return res; | 1076 | return true; |
| 1077 | { | ||
| 1078 | // bool res2 = true; | ||
| 1079 | if (mode_for_Close_defined) | ||
| 1080 | { | ||
| 1081 | PRF(printf("\n COutFile::Close() mode=%o\n", (unsigned)(mode_for_Close));) | ||
| 1082 | // fchmod() function ignores the file creation mask set by umask() | ||
| 1083 | // so we can restore any of (07777) mode bits | ||
| 1084 | // mode_for_Close |= (0xffff << 12); // for debug | ||
| 1085 | if (fchmod(_handle, mode_for_Close) == 0) | ||
| 1086 | { | ||
| 1087 | mode_for_Close_defined = false; | ||
| 1088 | PRF(printf("\n COutFile::Close() fchmod() == 0\n");) | ||
| 1089 | } | ||
| 1090 | // else res2 = false; | ||
| 1091 | } | ||
| 1092 | { | ||
| 1093 | if (MTime_defined || ATime_defined) | ||
| 1094 | { | ||
| 1095 | struct timespec times[2]; | ||
| 1096 | FiTime_To_timespec(ATime_defined ? &ATime : NULL, times[0]); | ||
| 1097 | FiTime_To_timespec(MTime_defined ? &MTime : NULL, times[1]); | ||
| 1098 | // futimens : POSIX.1-2008 | ||
| 1099 | if (futimens(_handle, times) == 0) | ||
| 1100 | { | ||
| 1101 | PRF(printf("\n futimens() OK \n");) | ||
| 1102 | ATime_defined = false; | ||
| 1103 | MTime_defined = false; | ||
| 1104 | } | ||
| 1105 | else | ||
| 1106 | { | ||
| 1107 | PRF(printf("\n futimens() ERROR: %d=%s\n", errno, strerror(errno));) | ||
| 1108 | } | ||
| 1109 | } | ||
| 1110 | } | ||
| 1111 | res = CFileBase::Close(); | ||
| 1112 | if (!res) | ||
| 1113 | return res; | ||
| 1114 | // res = res2; | ||
| 1115 | } | ||
| 1116 | if (mode_for_Close_defined) | ||
| 1117 | { | ||
| 1118 | // chmod() ignores the file creation mask set by umask() | ||
| 1119 | // so we can restore any of (07777) mode bits | ||
| 1120 | // const int res_chmod = | ||
| 1121 | chmod(Path, mode_for_Close); | ||
| 1122 | mode_for_Close_defined = false; | ||
| 1123 | // if (res_chmod != 0 && res == true) res = false; | ||
| 1124 | // PRF(printf("\n COutFile::Close() chmod res=%d\n", (int)res_chmod);) | ||
| 1125 | } | ||
| 1126 | |||
| 911 | if (CTime_defined || ATime_defined || MTime_defined) | 1127 | if (CTime_defined || ATime_defined || MTime_defined) |
| 912 | { | 1128 | { |
| 913 | /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path, | 1129 | /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path, |
| @@ -942,6 +1158,24 @@ bool COutFile::SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime | |||
| 942 | */ | 1158 | */ |
| 943 | } | 1159 | } |
| 944 | 1160 | ||
| 1161 | bool COutFile::Set_Time_and_WinAttrib( | ||
| 1162 | const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD attrib) throw() | ||
| 1163 | { | ||
| 1164 | PRF(printf("\n Set_Time_and_WinAttrib() mode=%o\n", (unsigned)(attrib >> 16));) | ||
| 1165 | SetTime(cTime, aTime, mTime); | ||
| 1166 | // we will use fchmod() or chmod() later in Close() fucntion. | ||
| 1167 | // fchmod() or chmod() are not limited by system umask. | ||
| 1168 | // but for security reasons we use the system mask (g_umask.mask) derived from umask(). | ||
| 1169 | mode_t mode = k_OutFile_mode_default; // 0666 | ||
| 1170 | if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) | ||
| 1171 | mode = (attrib >> 16); | ||
| 1172 | else if (attrib & FILE_ATTRIBUTE_READONLY) | ||
| 1173 | mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions | ||
| 1174 | mode_for_Close = mode & NDir::g_umask.mask; | ||
| 1175 | mode_for_Close_defined = true; | ||
| 1176 | return true; | ||
| 1177 | } | ||
| 1178 | |||
| 945 | bool COutFile::SetMTime(const CFiTime *mTime) throw() | 1179 | bool COutFile::SetMTime(const CFiTime *mTime) throw() |
| 946 | { | 1180 | { |
| 947 | if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; | 1181 | if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; |
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h index a202df5..9c32137 100644 --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h | |||
| @@ -19,6 +19,27 @@ | |||
| 19 | #include <winioctl.h> | 19 | #include <winioctl.h> |
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | typedef enum | ||
| 23 | { | ||
| 24 | Z7_WIN_FileDirectoryInformation = 1, | ||
| 25 | Z7_WIN_FileFullDirectoryInformation, | ||
| 26 | Z7_WIN_FileBothDirectoryInformation, | ||
| 27 | Z7_WIN_FileBasicInformation, | ||
| 28 | Z7_WIN_FileRenameInformation = 10 | ||
| 29 | } Z7_WIN_FILE_INFORMATION_CLASS; | ||
| 30 | |||
| 31 | // FILE_BASIC_INFORMATION / FILE_BASIC_INFO | ||
| 32 | typedef struct | ||
| 33 | { | ||
| 34 | LARGE_INTEGER CreationTime; | ||
| 35 | LARGE_INTEGER LastAccessTime; | ||
| 36 | LARGE_INTEGER LastWriteTime; | ||
| 37 | LARGE_INTEGER ChangeTime; | ||
| 38 | ULONG FileAttributes; | ||
| 39 | ULONG Reserved; // it's expected dummy variable for alignment : optional | ||
| 40 | } | ||
| 41 | Z7_WIN_FILE_BASIC_INFORMATION; | ||
| 42 | |||
| 22 | #else | 43 | #else |
| 23 | 44 | ||
| 24 | #include <sys/types.h> | 45 | #include <sys/types.h> |
| @@ -205,6 +226,9 @@ public: | |||
| 205 | return false; | 226 | return false; |
| 206 | return file.GetFileInformation(info); | 227 | return file.GetFileInformation(info); |
| 207 | } | 228 | } |
| 229 | |||
| 230 | DWORD Call_NtSetInformationFile_return_WinError(void *data, ULONG len, | ||
| 231 | Z7_WIN_FILE_INFORMATION_CLASS fileInformationClass) const; | ||
| 208 | }; | 232 | }; |
| 209 | 233 | ||
| 210 | #ifndef UNDER_CE | 234 | #ifndef UNDER_CE |
| @@ -323,6 +347,8 @@ public: | |||
| 323 | 347 | ||
| 324 | bool Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes); | 348 | bool Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes); |
| 325 | 349 | ||
| 350 | bool Set_Time_and_WinAttrib(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD attrib) throw(); | ||
| 351 | |||
| 326 | bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); | 352 | bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); |
| 327 | bool SetMTime(const CFiTime *mTime) throw(); | 353 | bool SetMTime(const CFiTime *mTime) throw(); |
| 328 | bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); | 354 | bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); |
| @@ -338,6 +364,15 @@ public: | |||
| 338 | 364 | ||
| 339 | #else // _WIN32 | 365 | #else // _WIN32 |
| 340 | 366 | ||
| 367 | namespace NDir { | ||
| 368 | struct C_umask | ||
| 369 | { | ||
| 370 | mode_t mask; | ||
| 371 | C_umask(); | ||
| 372 | }; | ||
| 373 | extern C_umask g_umask; | ||
| 374 | } | ||
| 375 | |||
| 341 | namespace NIO { | 376 | namespace NIO { |
| 342 | 377 | ||
| 343 | bool GetReparseData(CFSTR path, CByteBuffer &reparseData); | 378 | bool GetReparseData(CFSTR path, CByteBuffer &reparseData); |
| @@ -347,6 +382,7 @@ bool GetReparseData(CFSTR path, CByteBuffer &reparseData); | |||
| 347 | bool SetSymLink(CFSTR from, CFSTR to); | 382 | bool SetSymLink(CFSTR from, CFSTR to); |
| 348 | bool SetSymLink_UString(CFSTR from, const UString &to); | 383 | bool SetSymLink_UString(CFSTR from, const UString &to); |
| 349 | 384 | ||
| 385 | const mode_t k_OutFile_mode_default = 0666; | ||
| 350 | 386 | ||
| 351 | class CFileBase | 387 | class CFileBase |
| 352 | { | 388 | { |
| @@ -359,7 +395,7 @@ protected: | |||
| 359 | UInt64 Size; // it can be larger than real available size | 395 | UInt64 Size; // it can be larger than real available size |
| 360 | */ | 396 | */ |
| 361 | 397 | ||
| 362 | bool OpenBinary(const char *name, int flags, mode_t mode = 0666); | 398 | bool OpenBinary(const char *name, int flags, mode_t mode /* = k_OutFile_mode_default */); |
| 363 | public: | 399 | public: |
| 364 | bool PreserveATime; | 400 | bool PreserveATime; |
| 365 | #if 0 | 401 | #if 0 |
| @@ -411,9 +447,11 @@ class COutFile: public CFileBase | |||
| 411 | bool CTime_defined; | 447 | bool CTime_defined; |
| 412 | bool ATime_defined; | 448 | bool ATime_defined; |
| 413 | bool MTime_defined; | 449 | bool MTime_defined; |
| 450 | bool mode_for_Close_defined; | ||
| 414 | CFiTime CTime; | 451 | CFiTime CTime; |
| 415 | CFiTime ATime; | 452 | CFiTime ATime; |
| 416 | CFiTime MTime; | 453 | CFiTime MTime; |
| 454 | mode_t mode_for_Close; | ||
| 417 | 455 | ||
| 418 | AString Path; | 456 | AString Path; |
| 419 | ssize_t write_part(const void *data, size_t size) throw(); | 457 | ssize_t write_part(const void *data, size_t size) throw(); |
| @@ -425,9 +463,11 @@ public: | |||
| 425 | CTime_defined(false), | 463 | CTime_defined(false), |
| 426 | ATime_defined(false), | 464 | ATime_defined(false), |
| 427 | MTime_defined(false), | 465 | MTime_defined(false), |
| 428 | mode_for_Create(0666) | 466 | mode_for_Close_defined(false), |
| 467 | mode_for_Create(k_OutFile_mode_default) // 0666 | ||
| 429 | {} | 468 | {} |
| 430 | 469 | ||
| 470 | ~COutFile() { Close(); } | ||
| 431 | bool Close(); | 471 | bool Close(); |
| 432 | 472 | ||
| 433 | bool Open_EXISTING(CFSTR fileName); | 473 | bool Open_EXISTING(CFSTR fileName); |
| @@ -454,6 +494,7 @@ public: | |||
| 454 | return SetLength(length); | 494 | return SetLength(length); |
| 455 | } | 495 | } |
| 456 | bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); | 496 | bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); |
| 497 | bool Set_Time_and_WinAttrib(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD attrib) throw(); | ||
| 457 | bool SetMTime(const CFiTime *mTime) throw(); | 498 | bool SetMTime(const CFiTime *mTime) throw(); |
| 458 | }; | 499 | }; |
| 459 | 500 | ||
