unrarsrc  6.1.7
About: unrar extracts, views and tests the contents of archives created with the RAR archiver.
  Fossies Dox: unrarsrc-6.1.7.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

volume.cpp
Go to the documentation of this file.
1#include "rar.hpp"
2
3#ifdef RARDLL
4static bool DllVolChange(RAROptions *Cmd,wchar *NextName,size_t NameSize);
5static bool DllVolNotify(RAROptions *Cmd,wchar *NextName);
6#endif
7
8
9
10bool 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))
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.
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 {
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
193bool 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
249bool 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
@ RARFMT50
Definition: archive.hpp:13
ErrorHandler ErrHandler
size_t ReadHeader()
Definition: arcread.cpp:3
bool Encrypted
Definition: archive.hpp:126
HEADER_TYPE GetHeaderType()
Definition: archive.hpp:85
FileHeader FileHead
Definition: archive.hpp:104
RARFORMAT Format
Definition: archive.hpp:117
RAROptions * GetRAROptions()
Definition: archive.hpp:86
int64 NextBlockPos
Definition: archive.hpp:115
void ConvertAttributes()
Definition: arcread.cpp:1305
FileHeader SubHead
Definition: archive.hpp:107
size_t SearchBlock(HEADER_TYPE HeaderType)
Definition: arcread.cpp:48
bool NewNumbering
Definition: archive.hpp:124
void CheckArc(bool EnableBroken)
Definition: archive.cpp:63
int64 LastArcSize
Definition: rdwrfn.hpp:93
int64 ProcessedArcSize
Definition: rdwrfn.hpp:90
int64 TotalArcSize
Definition: rdwrfn.hpp:95
void AdjustTotalArcSize(Archive *Arc)
Definition: rdwrfn.cpp:296
void SetPackedSizeToRead(int64 Size)
Definition: rdwrfn.hpp:66
bool UnpVolume
Definition: rdwrfn.hpp:83
int64 CurUnpRead
Definition: rdwrfn.hpp:85
DataHash PackedDataHash
Definition: rdwrfn.hpp:97
void Init(HASH_TYPE Type, uint MaxThreads)
Definition: hash.cpp:67
bool Cmp(HashValue *CmpValue, byte *Key)
Definition: hash.cpp:128
void Exit(RAR_EXIT ExitCode)
Definition: errhnd.cpp:236
virtual void Seek(int64 Offset, int Method)
Definition: file.cpp:514
virtual bool Open(const wchar *Name, uint Mode=FMF_READ)
Definition: file.cpp:48
virtual int64 Tell()
Definition: file.cpp:576
wchar FileName[NM]
Definition: file.hpp:88
virtual bool Close()
Definition: file.cpp:241
bool VolumePause
Definition: options.hpp:190
bool DisableNames
Definition: options.hpp:138
bool AllYes
Definition: options.hpp:152
bool DisablePercentage
Definition: options.hpp:135
bool OpenShared
Definition: options.hpp:164
uint Threads
Definition: options.hpp:206
void mprintf(const wchar *fmt,...)
Definition: consio.cpp:118
#define RAR_VOL_ASK
Definition: dll.hpp:31
#define RAR_VOL_NOTIFY
Definition: dll.hpp:32
@ UCM_CHANGEVOLUMEW
Definition: dll.hpp:159
@ UCM_CHANGEVOLUME
Definition: dll.hpp:159
#define ERAR_EOPEN
Definition: dll.hpp:12
@ RARX_FATAL
Definition: errhnd.hpp:8
@ FMF_OPENSHARED
Definition: file.hpp:34
bool IsRemovable(const wchar *Name)
Definition: filefn.cpp:131
HEADER_TYPE
Definition: headers.hpp:74
@ HEAD_FILE
Definition: headers.hpp:76
@ HEAD_SERVICE
Definition: headers.hpp:76
@ HEAD_ENDARC
Definition: headers.hpp:77
#define MExtrPoints
Definition: loclang.hpp:218
#define MExtrVol
Definition: loclang.hpp:171
#define MTestVol
Definition: loclang.hpp:170
void NextVolumeName(wchar *ArcName, uint MaxLength, bool OldNumbering)
Definition: pathfn.cpp:359
#define ASIZE(x)
Definition: rardefs.hpp:10
wchar_t wchar
Definition: rartypes.hpp:13
int64_t int64
Definition: rartypes.hpp:12
unsigned int uint
Definition: rartypes.hpp:8
bool RecVolumesRestore(RAROptions *Cmd, const wchar *Name, bool Silent)
Definition: recvol.cpp:8
const wchar * St(MSGID StringId)
Definition: resource.cpp:8
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
Definition: strfn.cpp:275
void strncpyz(char *dest, const char *src, size_t maxlen)
Definition: strfn.cpp:263
HashValue FileHash
Definition: headers.hpp:196
bool UseHashKey
Definition: headers.hpp:214
wchar FileName[NM]
Definition: headers.hpp:184
byte HashKey[SHA256_DIGEST_SIZE]
Definition: headers.hpp:218
int64 PackSize
Definition: headers.hpp:192
uint UnpVer
Definition: headers.hpp:178
bool SplitAfter
Definition: headers.hpp:201
HASH_TYPE Type
Definition: hash.hpp:12
uint CRC32
Definition: hash.hpp:15
bool uiAskNextVolume(wchar *VolName, size_t MaxSize)
Definition: uiconsole.cpp:433
void uiMsg(UIMESSAGE_CODE Code)
Definition: ui.hpp:148
@ UIERROR_MISSINGVOL
Definition: ui.hpp:33
@ UIERROR_BADARCHIVE
Definition: ui.hpp:29
@ UIERROR_CHECKSUMPACKED
Definition: ui.hpp:11
bool WideToChar(const wchar *Src, char *Dest, size_t DestSize)
Definition: unicode.cpp:20
bool CharToWide(const char *Src, wchar *Dest, size_t DestSize)
Definition: unicode.cpp:85
bool MergeArchive(Archive &Arc, ComprDataIO *DataIO, bool ShowFileName, wchar Command)
Definition: volume.cpp:10