| 51 | |
| 52 | |
| 53 | int ComprDataIO::UnpRead(byte *Addr,size_t Count) |
| 54 | { |
| 55 | #ifndef RAR_NOCRYPT |
| 56 | // In case of encryption we need to align read size to encryption |
| 57 | // block size. We can do it by simple masking, because unpack read code |
| 58 | // always reads more than CRYPT_BLOCK_SIZE, so we do not risk to make it 0. |
| 59 | if (Decryption) |
| 60 | Count &= ~CRYPT_BLOCK_MASK; |
| 61 | #endif |
| 62 | |
| 63 | int ReadSize=0,TotalRead=0; |
| 64 | byte *ReadAddr; |
| 65 | ReadAddr=Addr; |
| 66 | while (Count > 0) |
| 67 | { |
| 68 | Archive *SrcArc=(Archive *)SrcFile; |
| 69 | |
| 70 | if (UnpackFromMemory) |
| 71 | { |
| 72 | memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize); |
| 73 | ReadSize=(int)UnpackFromMemorySize; |
| 74 | UnpackFromMemorySize=0; |
| 75 | } |
| 76 | else |
| 77 | { |
| 78 | size_t SizeToRead=((int64)Count>UnpPackedSize) ? (size_t)UnpPackedSize:Count; |
| 79 | if (SizeToRead > 0) |
| 80 | { |
| 81 | if (UnpVolume && Decryption && (int64)Count>UnpPackedSize) |
| 82 | { |
| 83 | // We need aligned blocks for decryption and we want "Keep broken |
| 84 | // files" to work efficiently with missing encrypted volumes. |
| 85 | // So for last data block in volume we adjust the size to read to |
| 86 | // next equal or smaller block producing aligned total block size. |
| 87 | // So we'll ask for next volume only when processing few unaligned |
| 88 | // bytes left in the end, when most of data is already extracted. |
| 89 | size_t NewTotalRead = TotalRead + SizeToRead; |
| 90 | size_t Adjust = NewTotalRead - (NewTotalRead & ~CRYPT_BLOCK_MASK); |
| 91 | size_t NewSizeToRead = SizeToRead - Adjust; |
| 92 | if ((int)NewSizeToRead > 0) |
| 93 | SizeToRead = NewSizeToRead; |
| 94 | } |
| 95 | |
| 96 | if (!SrcFile->IsOpened()) |
| 97 | return -1; |
| 98 | ReadSize=SrcFile->Read(ReadAddr,SizeToRead); |
| 99 | FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead; |
| 100 | if (!NoFileHeader && hd->SplitAfter) |
| 101 | PackedDataHash.Update(ReadAddr,ReadSize); |
| 102 | } |
| 103 | } |
| 104 | CurUnpRead+=ReadSize; |
| 105 | TotalRead+=ReadSize; |
| 106 | #ifndef NOVOLUME |
| 107 | // These variable are not used in NOVOLUME mode, so it is better |
| 108 | // to exclude commands below to avoid compiler warnings. |
| 109 | ReadAddr+=ReadSize; |
| 110 | Count-=ReadSize; |
no test coverage detected