int ComprDataIO::UnpRead(byte *Addr,size_t Count) { int RetCode=0,TotalRead=0; byte *ReadAddr; ReadAddr=Addr; while (Count > 0) { Archive *SrcArc=(Archive *)SrcFile; size_t ReadSize=((int64)Count>UnpPackedSize) ? (size_t)UnpPackedSize:Count; if (UnpackFromMemory) { memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize); RetCode=(int)UnpackFromMemorySize; UnpackFromMemorySize=0; } else { if (!SrcFile->IsOpened()) return(-1); RetCode=SrcFile->Read(ReadAddr,ReadSize); FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->NewLhd; if (hd->Flags & LHD_SPLIT_AFTER) PackedCRC=CRC(PackedCRC,ReadAddr,RetCode); } CurUnpRead+=RetCode; TotalRead+=RetCode; #ifndef NOVOLUME // These variable are not used in NOVOLUME mode, so it is better // to exclude commands below to avoid compiler warnings. ReadAddr+=RetCode; Count-=RetCode; #endif UnpPackedSize-=RetCode; if (UnpPackedSize == 0 && UnpVolume) { #ifndef NOVOLUME if (!MergeArchive(*SrcArc,this,true,CurrentCommand)) #endif { NextVolumeMissing=true; return(-1); } } else break; } Archive *SrcArc=(Archive *)SrcFile; if (SrcArc!=NULL) ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize); if (RetCode!=-1) { RetCode=TotalRead; #ifndef NOCRYPT if (Decryption) #ifndef SFX_MODULE if (Decryption<20) Decrypt.Crypt(Addr,RetCode,(Decryption==15) ? NEW_CRYPT : OLD_DECODE); else if (Decryption==20) for (int I=0;I<RetCode;I+=16) Decrypt.DecryptBlock20(&Addr[I]); else #endif { int CryptSize=(RetCode & 0xf)==0 ? RetCode:((RetCode & ~0xf)+16); Decrypt.DecryptBlock(Addr,CryptSize); } #endif } Wait(); return(RetCode); }
int ComprDataIO::UnpRead(byte *Addr,uint Count) { int RetCode=0,TotalRead=0; byte *ReadAddr; ReadAddr=Addr; while (Count > 0) { Archive *SrcArc=(Archive *)SrcFile; uint ReadSize=(Count>UnpPackedSize) ? int64to32(UnpPackedSize):Count; if (UnpackFromMemory) { memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize); RetCode=UnpackFromMemorySize; UnpackFromMemorySize=0; } else { bool bRead = true; if (!SrcFile->IsOpened()) { NextVolumeMissing = true; return(-1); } if (UnpackToMemory) if (hSeek->Wait(1)) // we are seeking { if (m_iSeekTo > CurUnpStart+SrcArc->NewLhd.FullPackSize) // need to seek outside this block { TotalRead += (int)(SrcArc->NextBlockPos-SrcFile->Tell()); CurUnpRead=CurUnpStart+SrcArc->NewLhd.FullPackSize; UnpPackedSize=0; RetCode = 0; bRead = false; } else { Int64 iStartOfFile = SrcArc->NextBlockPos-SrcArc->NewLhd.FullPackSize; m_iStartOfBuffer = CurUnpStart; Int64 iSeekTo=m_iSeekTo-CurUnpStart<MAXWINMEMSIZE/2?iStartOfFile:iStartOfFile+m_iSeekTo-CurUnpStart-MAXWINMEMSIZE/2; if (iSeekTo == iStartOfFile) // front { if (CurUnpStart+MAXWINMEMSIZE>SrcArc->NewLhd.FullUnpSize) { m_iSeekTo=iStartOfFile; UnpPackedSize = SrcArc->NewLhd.FullPackSize; } else { m_iSeekTo=MAXWINMEMSIZE-(m_iSeekTo-CurUnpStart); UnpPackedSize = SrcArc->NewLhd.FullPackSize - (m_iStartOfBuffer - CurUnpStart); } } else { m_iStartOfBuffer = m_iSeekTo-MAXWINMEMSIZE/2; // front if (m_iSeekTo+MAXWINMEMSIZE/2>SrcArc->NewLhd.FullUnpSize) { iSeekTo = iStartOfFile+SrcArc->NewLhd.FullPackSize-MAXWINMEMSIZE; m_iStartOfBuffer = CurUnpStart+SrcArc->NewLhd.FullPackSize-MAXWINMEMSIZE; m_iSeekTo = MAXWINMEMSIZE-(m_iSeekTo-m_iStartOfBuffer); UnpPackedSize = MAXWINMEMSIZE; } else { m_iSeekTo=MAXWINMEMSIZE/2; UnpPackedSize = SrcArc->NewLhd.FullPackSize - (m_iStartOfBuffer - CurUnpStart); } } SrcFile->Seek(iSeekTo,SEEK_SET); TotalRead = 0; CurUnpRead = CurUnpStart + iSeekTo - iStartOfFile; CurUnpWrite = SrcFile->Tell() - iStartOfFile + CurUnpStart; hSeek->Reset(); hSeekDone->Signal(); } } if (bRead) { ReadSize=(Count>UnpPackedSize) ? int64to32(UnpPackedSize):Count; RetCode=SrcFile->Read(ReadAddr,ReadSize); FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->NewLhd; if (hd->Flags & LHD_SPLIT_AFTER) { PackedCRC=CRC(PackedCRC,ReadAddr,ReadSize); } } } CurUnpRead+=RetCode; ReadAddr+=RetCode; TotalRead+=RetCode; Count-=RetCode; UnpPackedSize-=RetCode; if (UnpPackedSize == 0 && UnpVolume) { #ifndef NOVOLUME if (!MergeArchive(*SrcArc,this,true,CurrentCommand)) #endif { NextVolumeMissing=true; return(-1); } CurUnpStart = CurUnpRead; /*if (m_pDlgProgress) { CURL url(SrcArc->FileName); m_pDlgProgress->SetLine(0,url.GetWithoutUserDetails()); // update currently extracted rar file m_pDlgProgress->Progress(); }*/ } else break; } Archive *SrcArc=(Archive *)SrcFile; if (SrcArc!=NULL) ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize); if (RetCode!=-1) { RetCode=TotalRead; #ifndef NOCRYPT if (Decryption) { #ifndef SFX_MODULE if (Decryption<20) Decrypt.Crypt(Addr,RetCode,(Decryption==15) ? NEW_CRYPT : OLD_DECODE); else if (Decryption==20) for (int I=0;I<RetCode;I+=16) Decrypt.DecryptBlock20(&Addr[I]); else #endif { int CryptSize=(RetCode & 0xf)==0 ? RetCode:((RetCode & ~0xf)+16); Decrypt.DecryptBlock(Addr,CryptSize); } } #endif } Wait(); return(RetCode); }
int ComprDataIO::UnpRead(byte *Addr,size_t Count) { #ifndef RAR_NOCRYPT // In case of encryption we need to align read size to encryption // block size. We can do it by simple masking, because unpack read code // always reads more than CRYPT_BLOCK_SIZE, so we do not risk to make it 0. if (Decryption) Count &= ~CRYPT_BLOCK_MASK; #endif int ReadSize=0,TotalRead=0; byte *ReadAddr; ReadAddr=Addr; while (Count > 0) { Archive *SrcArc=(Archive *)SrcFile; if (UnpackFromMemory) { memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize); ReadSize=(int)UnpackFromMemorySize; UnpackFromMemorySize=0; } else { size_t SizeToRead=((int64)Count>UnpPackedSize) ? (size_t)UnpPackedSize:Count; if (SizeToRead > 0) { if (UnpVolume && Decryption && (int64)Count>UnpPackedSize) { // We need aligned blocks for decryption and we want "Keep broken // files" to work efficiently with missing encrypted volumes. // So for last data block in volume we adjust the size to read to // next equal or smaller block producing aligned total block size. // So we'll ask for next volume only when processing few unaligned // bytes left in the end, when most of data is already extracted. size_t NewTotalRead = TotalRead + SizeToRead; size_t Adjust = NewTotalRead - (NewTotalRead & ~CRYPT_BLOCK_MASK); size_t NewSizeToRead = SizeToRead - Adjust; if ((int)NewSizeToRead > 0) SizeToRead = NewSizeToRead; } if (!SrcFile->IsOpened()) return -1; ReadSize=SrcFile->Read(ReadAddr,SizeToRead); FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead; if (hd->SplitAfter) PackedDataHash.Update(ReadAddr,ReadSize); } } CurUnpRead+=ReadSize; TotalRead+=ReadSize; #ifndef NOVOLUME // These variable are not used in NOVOLUME mode, so it is better // to exclude commands below to avoid compiler warnings. ReadAddr+=ReadSize; Count-=ReadSize; #endif UnpPackedSize-=ReadSize; // Do not ask for next volume if we read something from current volume. // If next volume is missing, we need to process all data from current // volume before aborting. It helps to recover all possible data // in "Keep broken files" mode. But if we process encrypted data, // we ask for next volume also if we have non-aligned encryption block. // Since we adjust data size for decryption earlier above, // it does not hurt "Keep broken files" mode efficiency. if (UnpVolume && UnpPackedSize == 0 && (ReadSize==0 || Decryption && (TotalRead & CRYPT_BLOCK_MASK) != 0) ) { #ifndef NOVOLUME if (!MergeArchive(*SrcArc,this,true,CurrentCommand)) #endif { NextVolumeMissing=true; return -1; } } else break; } Archive *SrcArc=(Archive *)SrcFile; if (SrcArc!=NULL) ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize); if (ReadSize!=-1) { ReadSize=TotalRead; #ifndef RAR_NOCRYPT if (Decryption) Decrypt.DecryptBlock(Addr,ReadSize); #endif } Wait(); return ReadSize; }
int ComprDataIO::UnpRead(byte *Addr,size_t Count) { #ifndef RAR_NOCRYPT // In case of encryption we need to align read size to encryption // block size. We can do it by simple masking, because unpack read code // always reads more than CRYPT_BLOCK_SIZE, so we do not risk to make it 0. if (Decryption) Count&=~CRYPT_BLOCK_MASK; #endif int ReadSize=0,TotalRead=0; byte *ReadAddr; ReadAddr=Addr; while (Count > 0) { Archive *SrcArc=(Archive *)SrcFile; if (UnpackFromMemory) { memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize); ReadSize=(int)UnpackFromMemorySize; UnpackFromMemorySize=0; } else { size_t SizeToRead=((int64)Count>UnpPackedSize) ? (size_t)UnpPackedSize:Count; if (SizeToRead==0) return 0; if (!SrcFile->IsOpened()) return(-1); ReadSize=SrcFile->Read(ReadAddr,SizeToRead); FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead; if (hd->SplitAfter) PackedDataHash.Update(ReadAddr,ReadSize); } CurUnpRead+=ReadSize; TotalRead+=ReadSize; #ifndef NOVOLUME // These variable are not used in NOVOLUME mode, so it is better // to exclude commands below to avoid compiler warnings. ReadAddr+=ReadSize; Count-=ReadSize; #endif UnpPackedSize-=ReadSize; if (UnpPackedSize == 0 && UnpVolume) { #ifndef NOVOLUME if (!MergeArchive(*SrcArc,this,true,CurrentCommand)) #endif { NextVolumeMissing=true; return(-1); } } else break; } Archive *SrcArc=(Archive *)SrcFile; if (SrcArc!=NULL) ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize); if (ReadSize!=-1) { ReadSize=TotalRead; #ifndef RAR_NOCRYPT if (Decryption) Decrypt.DecryptBlock(Addr,ReadSize); #endif } Wait(); return ReadSize; }
int ComprDataIO::UnpRead(unsigned char *Addr,unsigned int Count) { int RetCode=0,TotalRead=0; unsigned char *ReadAddr; ReadAddr=Addr; while (Count > 0) { Archive *SrcArc=(Archive *)SrcFile; unsigned int ReadSize=(Count>UnpPackedSize) ? int64to32(UnpPackedSize):Count; if (UnpackFromMemory) { memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize); RetCode=UnpackFromMemorySize; UnpackFromMemorySize=0; } else { if (!SrcFile->IsOpened()) return(-1); RetCode=SrcFile->Read(ReadAddr,ReadSize); FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->NewLhd; if (hd->Flags & LHD_SPLIT_AFTER) PackedCRC=CRC(PackedCRC,ReadAddr,ReadSize); } CurUnpRead+=RetCode; ReadAddr+=RetCode; TotalRead+=RetCode; Count-=RetCode; UnpPackedSize-=RetCode; if (UnpPackedSize == 0 && UnpVolume) { #ifndef NOVOLUME if (!MergeArchive(*SrcArc,this,true,CurrentCommand)) #endif { NextVolumeMissing=true; return(-1); } } else break; } Archive *SrcArc=(Archive *)SrcFile; if (SrcArc!=NULL) ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize); if (RetCode!=-1) { RetCode=TotalRead; #ifndef NOCRYPT if (Decryption) #ifndef SFX_MODULE if (Decryption<20) Decrypt.Crypt(Addr,RetCode,(Decryption==15) ? NEW_CRYPT : OLD_DECODE); else if (Decryption==20) for (unsigned int I=0;I<RetCode;I+=16) Decrypt.DecryptBlock20(&Addr[I]); else #endif { int CryptSize=(RetCode & 0xf)==0 ? RetCode:((RetCode & ~0xf)+16); Decrypt.DecryptBlock(Addr,CryptSize); } #endif } Wait(); return(RetCode); }