"Fossies" - the Fresh Open Source Software Archive 
Member "unrar/volume.cpp" (4 May 2022, 7734 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 "volume.cpp" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
6.1.3_vs_6.1.4.
1 #include "rar.hpp"
2
3 #ifdef RARDLL
4 static bool DllVolChange(RAROptions *Cmd,wchar *NextName,size_t NameSize);
5 static bool DllVolNotify(RAROptions *Cmd,wchar *NextName);
6 #endif
7
8
9
10 bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Command)
11 {
12 RAROptions *Cmd=Arc.GetRAROptions();
13
14 HEADER_TYPE HeaderType=Arc.GetHeaderType();
15 FileHeader *hd=HeaderType==HEAD_SERVICE ? &Arc.SubHead:&Arc.FileHead;
16 bool SplitHeader=(HeaderType==HEAD_FILE || HeaderType==HEAD_SERVICE) &&
17 hd->SplitAfter;
18
19 if (DataIO!=NULL && SplitHeader)
20 {
21 bool PackedHashPresent=Arc.Format==RARFMT50 ||
22 hd->UnpVer>=20 && hd->FileHash.CRC32!=0xffffffff;
23 if (PackedHashPresent &&
24 !DataIO->PackedDataHash.Cmp(&hd->FileHash,hd->UseHashKey ? hd->HashKey:NULL))
25 uiMsg(UIERROR_CHECKSUMPACKED, Arc.FileName, hd->FileName);
26 }
27
28 bool PrevVolEncrypted=Arc.Encrypted;
29
30 int64 PosBeforeClose=Arc.Tell();
31
32 if (DataIO!=NULL)
33 DataIO->ProcessedArcSize+=DataIO->LastArcSize;
34
35
36 Arc.Close();
37
38 wchar NextName[NM];
39 wcsncpyz(NextName,Arc.FileName,ASIZE(NextName));
40 NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);
41
42 #if !defined(SFX_MODULE) && !defined(RARDLL)
43 bool RecoveryDone=false;
44 #endif
45 bool OldSchemeTested=false;
46
47 bool FailedOpen=false; // No more next volume open attempts if true.
48 #if !defined(SILENT)
49 // In -vp mode we force the pause before next volume even if it is present
50 // and even if we are on the hard disk. It is important when user does not
51 // want to process partially downloaded volumes preliminary.
52 // 2022.01.11: In WinRAR 6.10 beta versions we tried to ignore VolumePause
53 // if we could open the next volume with FMF_OPENEXCLUSIVE. But another
54 // developer asked us to return the previous behavior and always prompt
55 // for confirmation. They want to control when unrar continues, because
56 // the next file might not be fully decoded yet. They write chunks of data
57 // and then close the file again until the next chunk comes in.
58
59 if (Cmd->VolumePause && !uiAskNextVolume(NextName,ASIZE(NextName)))
60 FailedOpen=true;
61 #endif
62
63 uint OpenMode = Cmd->OpenShared ? FMF_OPENSHARED : 0;
64
65 if (!FailedOpen)
66 while (!Arc.Open(NextName,OpenMode))
67 {
68 // We need to open a new volume which size was not calculated
69 // in total size before, so we cannot calculate the total progress
70 // anymore. Let's reset the total size to zero and stop
71 // the total progress.
72 if (DataIO!=NULL)
73 DataIO->TotalArcSize=0;
74
75 if (!OldSchemeTested)
76 {
77 // Checking for new style volumes renamed by user to old style
78 // name format. Some users did it for unknown reason.
79 wchar AltNextName[NM];
80 wcsncpyz(AltNextName,Arc.FileName,ASIZE(AltNextName));
81 NextVolumeName(AltNextName,ASIZE(AltNextName),true);
82 OldSchemeTested=true;
83 if (Arc.Open(AltNextName,OpenMode))
84 {
85 wcsncpyz(NextName,AltNextName,ASIZE(NextName));
86 break;
87 }
88 }
89 #ifdef RARDLL
90 if (!DllVolChange(Cmd,NextName,ASIZE(NextName)))
91 {
92 FailedOpen=true;
93 break;
94 }
95 #else // !RARDLL
96
97 #ifndef SFX_MODULE
98 if (!RecoveryDone)
99 {
100 RecVolumesRestore(Cmd,Arc.FileName,true);
101 RecoveryDone=true;
102 continue;
103 }
104 #endif
105
106 if (!Cmd->VolumePause && !IsRemovable(NextName))
107 {
108 FailedOpen=true;
109 break;
110 }
111 #ifndef SILENT
112 if (Cmd->AllYes || !uiAskNextVolume(NextName,ASIZE(NextName)))
113 #endif
114 {
115 FailedOpen=true;
116 break;
117 }
118
119 #endif // RARDLL
120 }
121
122 if (FailedOpen)
123 {
124 uiMsg(UIERROR_MISSINGVOL,NextName);
125 Arc.Open(Arc.FileName,OpenMode);
126 Arc.Seek(PosBeforeClose,SEEK_SET);
127 return false;
128 }
129
130 if (Command=='T' || Command=='X' || Command=='E')
131 mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);
132
133
134 Arc.CheckArc(true);
135 #ifdef RARDLL
136 if (!DllVolNotify(Cmd,NextName))
137 return false;
138 #endif
139
140 if (Arc.Encrypted!=PrevVolEncrypted)
141 {
142 // There is no legitimate reason for encrypted header state to be
143 // changed in the middle of volume sequence. So we abort here to prevent
144 // replacing an encrypted header volume to unencrypted and adding
145 // unexpected files by third party to encrypted extraction.
146 uiMsg(UIERROR_BADARCHIVE,Arc.FileName);
147 ErrHandler.Exit(RARX_FATAL);
148 }
149
150 if (SplitHeader)
151 Arc.SearchBlock(HeaderType);
152 else
153 Arc.ReadHeader();
154 if (Arc.GetHeaderType()==HEAD_FILE)
155 {
156 Arc.ConvertAttributes();
157 Arc.Seek(Arc.NextBlockPos-Arc.FileHead.PackSize,SEEK_SET);
158 }
159 if (ShowFileName && !Cmd->DisableNames)
160 {
161 mprintf(St(MExtrPoints),Arc.FileHead.FileName);
162 if (!Cmd->DisablePercentage)
163 mprintf(L" ");
164 }
165 if (DataIO!=NULL)
166 {
167 if (HeaderType==HEAD_ENDARC)
168 DataIO->UnpVolume=false;
169 else
170 {
171 DataIO->UnpVolume=hd->SplitAfter;
172 DataIO->SetPackedSizeToRead(hd->PackSize);
173 }
174
175 DataIO->AdjustTotalArcSize(&Arc);
176
177 // Reset the size of packed data read from current volume. It is used
178 // to display the total progress and preceding volumes are already
179 // compensated with ProcessedArcSize, so we need to reset this variable.
180 DataIO->CurUnpRead=0;
181
182 DataIO->PackedDataHash.Init(hd->FileHash.Type,Cmd->Threads);
183 }
184 return true;
185 }
186
187
188
189
190
191
192 #ifdef RARDLL
193 bool DllVolChange(RAROptions *Cmd,wchar *NextName,size_t NameSize)
194 {
195 bool DllVolChanged=false,DllVolAborted=false;
196
197 if (Cmd->Callback!=NULL)
198 {
199 wchar OrgNextName[NM];
200 wcsncpyz(OrgNextName,NextName,ASIZE(OrgNextName));
201 if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)==-1)
202 DllVolAborted=true;
203 else
204 if (wcscmp(OrgNextName,NextName)!=0)
205 DllVolChanged=true;
206 else
207 {
208 char NextNameA[NM],OrgNextNameA[NM];
209 WideToChar(NextName,NextNameA,ASIZE(NextNameA));
210 strncpyz(OrgNextNameA,NextNameA,ASIZE(OrgNextNameA));
211 if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextNameA,RAR_VOL_ASK)==-1)
212 DllVolAborted=true;
213 else
214 if (strcmp(OrgNextNameA,NextNameA)!=0)
215 {
216 // We can damage some Unicode characters by U->A->U conversion,
217 // so set Unicode name only if we see that ANSI name is changed.
218 CharToWide(NextNameA,NextName,NameSize);
219 DllVolChanged=true;
220 }
221 }
222 }
223 if (!DllVolChanged && Cmd->ChangeVolProc!=NULL)
224 {
225 char NextNameA[NM];
226 WideToChar(NextName,NextNameA,ASIZE(NextNameA));
227 int RetCode=Cmd->ChangeVolProc(NextNameA,RAR_VOL_ASK);
228 if (RetCode==0)
229 DllVolAborted=true;
230 else
231 CharToWide(NextNameA,NextName,NameSize);
232 }
233
234 // We quit only on 'abort' condition, but not on 'name not changed'.
235 // It is legitimate for program to return the same name when waiting
236 // for currently non-existent volume.
237 // Also we quit to prevent an infinite loop if no callback is defined.
238 if (DllVolAborted || Cmd->Callback==NULL && Cmd->ChangeVolProc==NULL)
239 {
240 Cmd->DllError=ERAR_EOPEN;
241 return false;
242 }
243 return true;
244 }
245 #endif
246
247
248 #ifdef RARDLL
249 bool DllVolNotify(RAROptions *Cmd,wchar *NextName)
250 {
251 char NextNameA[NM];
252 WideToChar(NextName,NextNameA,ASIZE(NextNameA));
253 if (Cmd->Callback!=NULL)
254 {
255 if (Cmd->Callback(UCM_CHANGEVOLUMEW,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1)
256 return false;
257 if (Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextNameA,RAR_VOL_NOTIFY)==-1)
258 return false;
259 }
260 if (Cmd->ChangeVolProc!=NULL)
261 {
262 int RetCode=Cmd->ChangeVolProc(NextNameA,RAR_VOL_NOTIFY);
263 if (RetCode==0)
264 return false;
265 }
266 return true;
267 }
268 #endif