"Fossies" - the Fresh Open Source Software Archive 
Member "unrar/rdwrfn.cpp" (4 May 2022, 8233 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "rdwrfn.cpp" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
6.1.2_vs_6.1.3.
1 #include "rar.hpp"
2
3 ComprDataIO::ComprDataIO()
4 {
5 #ifndef RAR_NOCRYPT
6 Crypt=new CryptData;
7 Decrypt=new CryptData;
8 #endif
9
10 Init();
11 }
12
13
14 void ComprDataIO::Init()
15 {
16 UnpackFromMemory=false;
17 UnpackToMemory=false;
18 UnpPackedSize=0;
19 UnpPackedLeft=0;
20 ShowProgress=true;
21 TestMode=false;
22 SkipUnpCRC=false;
23 NoFileHeader=false;
24 PackVolume=false;
25 UnpVolume=false;
26 NextVolumeMissing=false;
27 SrcFile=NULL;
28 DestFile=NULL;
29 UnpWrAddr=NULL;
30 UnpWrSize=0;
31 Command=NULL;
32 Encryption=false;
33 Decryption=false;
34 CurPackRead=CurPackWrite=CurUnpRead=CurUnpWrite=0;
35 LastPercent=-1;
36 SubHead=NULL;
37 SubHeadPos=NULL;
38 CurrentCommand=0;
39 ProcessedArcSize=0;
40 LastArcSize=0;
41 TotalArcSize=0;
42 }
43
44
45 ComprDataIO::~ComprDataIO()
46 {
47 #ifndef RAR_NOCRYPT
48 delete Crypt;
49 delete Decrypt;
50 #endif
51 }
52
53
54
55
56 int ComprDataIO::UnpRead(byte *Addr,size_t Count)
57 {
58 #ifndef RAR_NOCRYPT
59 // In case of encryption we need to align read size to encryption
60 // block size. We can do it by simple masking, because unpack read code
61 // always reads more than CRYPT_BLOCK_SIZE, so we do not risk to make it 0.
62 if (Decryption)
63 Count &= ~CRYPT_BLOCK_MASK;
64 #endif
65
66 int ReadSize=0,TotalRead=0;
67 byte *ReadAddr;
68 ReadAddr=Addr;
69 while (Count > 0)
70 {
71 Archive *SrcArc=(Archive *)SrcFile;
72
73 if (UnpackFromMemory)
74 {
75 memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize);
76 ReadSize=(int)UnpackFromMemorySize;
77 UnpackFromMemorySize=0;
78 }
79 else
80 {
81 size_t SizeToRead=((int64)Count>UnpPackedLeft) ? (size_t)UnpPackedLeft:Count;
82 if (SizeToRead > 0)
83 {
84 if (UnpVolume && Decryption && (int64)Count>UnpPackedLeft)
85 {
86 // We need aligned blocks for decryption and we want "Keep broken
87 // files" to work efficiently with missing encrypted volumes.
88 // So for last data block in volume we adjust the size to read to
89 // next equal or smaller block producing aligned total block size.
90 // So we'll ask for next volume only when processing few unaligned
91 // bytes left in the end, when most of data is already extracted.
92 size_t NewTotalRead = TotalRead + SizeToRead;
93 size_t Adjust = NewTotalRead - (NewTotalRead & ~CRYPT_BLOCK_MASK);
94 size_t NewSizeToRead = SizeToRead - Adjust;
95 if ((int)NewSizeToRead > 0)
96 SizeToRead = NewSizeToRead;
97 }
98
99 if (!SrcFile->IsOpened())
100 return -1;
101 ReadSize=SrcFile->Read(ReadAddr,SizeToRead);
102 FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead;
103 if (!NoFileHeader && hd->SplitAfter)
104 PackedDataHash.Update(ReadAddr,ReadSize);
105 }
106 }
107 CurUnpRead+=ReadSize;
108 TotalRead+=ReadSize;
109 #ifndef NOVOLUME
110 // These variable are not used in NOVOLUME mode, so it is better
111 // to exclude commands below to avoid compiler warnings.
112 ReadAddr+=ReadSize;
113 Count-=ReadSize;
114 #endif
115 UnpPackedLeft-=ReadSize;
116
117 // Do not ask for next volume if we read something from current volume.
118 // If next volume is missing, we need to process all data from current
119 // volume before aborting. It helps to recover all possible data
120 // in "Keep broken files" mode. But if we process encrypted data,
121 // we ask for next volume also if we have non-aligned encryption block.
122 // Since we adjust data size for decryption earlier above,
123 // it does not hurt "Keep broken files" mode efficiency.
124 if (UnpVolume && UnpPackedLeft == 0 &&
125 (ReadSize==0 || Decryption && (TotalRead & CRYPT_BLOCK_MASK) != 0) )
126 {
127 #ifndef NOVOLUME
128 if (!MergeArchive(*SrcArc,this,true,CurrentCommand))
129 #endif
130 {
131 NextVolumeMissing=true;
132 return -1;
133 }
134 }
135 else
136 break;
137 }
138 Archive *SrcArc=(Archive *)SrcFile;
139 if (SrcArc!=NULL)
140 ShowUnpRead(SrcArc->NextBlockPos-UnpPackedSize+CurUnpRead,TotalArcSize);
141 if (ReadSize!=-1)
142 {
143 ReadSize=TotalRead;
144 #ifndef RAR_NOCRYPT
145 if (Decryption)
146 Decrypt->DecryptBlock(Addr,ReadSize);
147 #endif
148 }
149 Wait();
150 return ReadSize;
151 }
152
153
154 void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
155 {
156
157 #ifdef RARDLL
158 RAROptions *Cmd=((Archive *)SrcFile)->GetRAROptions();
159 if (Cmd->DllOpMode!=RAR_SKIP)
160 {
161 if (Cmd->Callback!=NULL &&
162 Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LPARAM)Addr,Count)==-1)
163 ErrHandler.Exit(RARX_USERBREAK);
164 if (Cmd->ProcessDataProc!=NULL)
165 {
166 int RetCode=Cmd->ProcessDataProc(Addr,(int)Count);
167 if (RetCode==0)
168 ErrHandler.Exit(RARX_USERBREAK);
169 }
170 }
171 #endif // RARDLL
172
173 UnpWrAddr=Addr;
174 UnpWrSize=Count;
175 if (UnpackToMemory)
176 {
177 if (Count <= UnpackToMemorySize)
178 {
179 memcpy(UnpackToMemoryAddr,Addr,Count);
180 UnpackToMemoryAddr+=Count;
181 UnpackToMemorySize-=Count;
182 }
183 }
184 else
185 if (!TestMode)
186 DestFile->Write(Addr,Count);
187 CurUnpWrite+=Count;
188 if (!SkipUnpCRC)
189 UnpHash.Update(Addr,Count);
190 ShowUnpWrite();
191 Wait();
192 }
193
194
195
196
197
198
199 void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
200 {
201 if (ShowProgress && SrcFile!=NULL)
202 {
203 // Important when processing several archives or multivolume archive.
204 ArcPos+=ProcessedArcSize;
205
206 Archive *SrcArc=(Archive *)SrcFile;
207 RAROptions *Cmd=SrcArc->GetRAROptions();
208
209 int CurPercent=ToPercent(ArcPos,ArcSize);
210 if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
211 {
212 uiExtractProgress(CurUnpWrite,SrcArc->FileHead.UnpSize,ArcPos,ArcSize);
213 LastPercent=CurPercent;
214 }
215 }
216 }
217
218
219 void ComprDataIO::ShowUnpWrite()
220 {
221 }
222
223
224
225
226
227
228
229
230
231
232 void ComprDataIO::SetFiles(File *SrcFile,File *DestFile)
233 {
234 if (SrcFile!=NULL)
235 ComprDataIO::SrcFile=SrcFile;
236 if (DestFile!=NULL)
237 ComprDataIO::DestFile=DestFile;
238 LastPercent=-1;
239 }
240
241
242 void ComprDataIO::GetUnpackedData(byte **Data,size_t *Size)
243 {
244 *Data=UnpWrAddr;
245 *Size=UnpWrSize;
246 }
247
248
249 void ComprDataIO::SetEncryption(bool Encrypt,CRYPT_METHOD Method,
250 SecPassword *Password,const byte *Salt,const byte *InitV,
251 uint Lg2Cnt,byte *HashKey,byte *PswCheck)
252 {
253 #ifndef RAR_NOCRYPT
254 if (Encrypt)
255 Encryption=Crypt->SetCryptKeys(true,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
256 else
257 Decryption=Decrypt->SetCryptKeys(false,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
258 #endif
259 }
260
261
262 #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
263 void ComprDataIO::SetAV15Encryption()
264 {
265 Decryption=true;
266 Decrypt->SetAV15Encryption();
267 }
268 #endif
269
270
271 #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
272 void ComprDataIO::SetCmt13Encryption()
273 {
274 Decryption=true;
275 Decrypt->SetCmt13Encryption();
276 }
277 #endif
278
279
280
281
282 void ComprDataIO::SetUnpackToMemory(byte *Addr,uint Size)
283 {
284 UnpackToMemory=true;
285 UnpackToMemoryAddr=Addr;
286 UnpackToMemorySize=Size;
287 }
288
289
290 // Extraction progress is based on the position in archive and we adjust
291 // the total archives size here, so trailing blocks do not prevent progress
292 // reaching 100% at the end of extraction. Alternatively we could print "100%"
293 // after completing the entire archive extraction, but then we would need
294 // to take into account possible messages like the checksum error after
295 // last file percent progress.
296 void ComprDataIO::AdjustTotalArcSize(Archive *Arc)
297 {
298 // If we know a position of QO or RR blocks, use them to adjust the total
299 // packed size to beginning of these blocks. Earlier we already calculated
300 // the total size based on entire archive sizes. We also set LastArcSize
301 // to start of first trailing block, to add it later to ProcessedArcSize.
302 int64 ArcLength=Arc->IsSeekable() ? Arc->FileLength() : 0;
303 if (Arc->MainHead.QOpenOffset!=0) // QO is always preceding RR record.
304 LastArcSize=Arc->MainHead.QOpenOffset;
305 else
306 if (Arc->MainHead.RROffset!=0)
307 LastArcSize=Arc->MainHead.RROffset;
308 else
309 {
310 // If neither QO nor RR are found, exclude the approximate size of
311 // end of archive block.
312 // We select EndBlock to be larger than typical 8 bytes HEAD_ENDARC,
313 // but to not exceed the smallest 22 bytes HEAD_FILE with 1 byte file
314 // name, so we do not have two files with 100% at the end of archive.
315 const uint EndBlock=23;
316
317 if (ArcLength>EndBlock)
318 LastArcSize=ArcLength-EndBlock;
319 }
320
321 TotalArcSize-=ArcLength-LastArcSize;
322 }