3
#define RECVOL_BUFSIZE 0x800
5
RecVolumes::RecVolumes()
7
Buf.Alloc(RECVOL_BUFSIZE*256);
8
memset(SrcFile,0,sizeof(SrcFile));
12
RecVolumes::~RecVolumes()
14
for (int I=0;I<sizeof(SrcFile)/sizeof(SrcFile[0]);I++)
21
bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
22
const wchar *NameW,bool Silent)
27
strcpyw(ArcNameW,NameW);
28
char *Ext=GetExt(ArcName);
30
bool RevName=Ext!=NULL && stricomp(Ext,".rev")==0;
33
for (int DigitGroup=0;Ext>ArcName && DigitGroup<3;Ext--)
35
if (isdigit(*(Ext-1)) && (*Ext=='_' || DigitGroup<2))
43
while (isdigit(*Ext) && Ext>ArcName+1)
47
Find.SetMask(ArcName);
49
while (Find.Next(&FD))
52
if (Arc.WOpen(FD.Name,FD.NameW) && Arc.IsArchive(true))
54
strcpy(ArcName,FD.Name);
62
if (!Arc.WCheckOpen(ArcName,ArcNameW))
67
Log(ArcName,St(MNotVolume),ArcName);
71
bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING);
73
char *VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering);
75
strcpy(RecVolMask,ArcName);
76
int BaseNamePartLength=VolNumStart-ArcName;
77
strcpy(RecVolMask+BaseNamePartLength,"*.rev");
83
Find.SetMask(RecVolMask);
84
struct FindData RecData;
85
int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0;
87
while (Find.Next(&RecData))
89
char *Name=RecData.Name;
91
if (!RevName && !NewStyle)
94
char *Dot=GetExt(Name);
99
while (Dot>Name && *Dot!='.')
113
CurFile.Seek(0,SEEK_END);
114
Int64 Length=CurFile.Tell();
115
CurFile.Seek(Length-7,SEEK_SET);
116
for (int I=0;I<3;I++)
117
P[2-I]=CurFile.GetByte()+1;
119
for (int I=0;I<4;I++)
120
FileCRC|=CurFile.GetByte()<<(I*8);
121
if (FileCRC!=CalcFileCRC(&CurFile,Length-4))
124
mprintf(St(MCRCFailed),Name);
131
char *Dot=GetExt(Name);
134
bool WrongParam=false;
135
for (int I=0;I<sizeof(P)/sizeof(P[0]);I++)
140
} while (isdigit(*Dot) && Dot>=Name+BaseNamePartLength);
142
if (P[I]==0 || P[I]>255)
150
if (RecVolNumber!=0 && RecVolNumber!=P[1] || FileNumber!=0 && FileNumber!=P[2])
153
Log(NULL,St(MRecVolDiffSets),Name,PrevName);
159
strcpy(PrevName,Name);
160
File *NewFile=new File;
161
NewFile->TOpen(Name);
162
SrcFile[FileNumber+P[0]-1]=NewFile;
166
RecFileSize=NewFile->FileLength();
170
if (!Silent || FoundRecVolumes!=0)
172
mprintf(St(MRecVolFound),FoundRecVolumes);
175
if (FoundRecVolumes==0)
178
bool WriteFlags[256];
179
memset(WriteFlags,0,sizeof(WriteFlags));
181
char LastVolName[NM];
184
for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++)
186
Archive *NewFile=new Archive;
187
bool ValidVolume=FileExist(ArcName);
190
NewFile->TOpen(ArcName);
191
ValidVolume=NewFile->IsArchive(false);
194
bool EndFound=false,EndBlockRequired=false;
195
while (!EndFound && NewFile->ReadHeader()!=0)
197
if (NewFile->GetHeaderType()==FILE_HEAD)
199
if (NewFile->NewLhd.UnpVer>=29)
200
EndBlockRequired=true;
201
if (!EndBlockRequired && (NewFile->NewLhd.Flags & LHD_SPLIT_AFTER))
204
if (NewFile->GetHeaderType()==ENDARC_HEAD)
206
if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 &&
207
NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos))
211
mprintf(St(MCRCFailed),ArcName);
216
NewFile->SeekToNext();
225
strcpy(NewName,ArcName);
226
strcat(NewName,".bad");
228
mprintf(St(MBadArc),ArcName);
229
mprintf(St(MRenaming),ArcName,NewName);
231
rename(ArcName,NewName);
233
NewFile->Seek(0,SEEK_SET);
237
NewFile->TCreate(ArcName);
238
WriteFlags[CurArcNum]=true;
241
if (CurArcNum==FileNumber-1)
242
strcpy(LastVolName,ArcName);
245
mprintf(St(MAbsNextVol),ArcName);
248
SrcFile[CurArcNum]=(File*)NewFile;
249
NextVolumeName(ArcName,!NewNumbering);
253
mprintf(St(MRecVolMissing),MissingVolumes);
256
if (MissingVolumes==0)
259
mprintf(St(MRecVolAllExist));
264
if (MissingVolumes>FoundRecVolumes)
267
mprintf(St(MRecVolCannotFix));
272
mprintf(St(MReconstructing));
275
RSCoder RSC(RecVolNumber);
277
int TotalFiles=FileNumber+RecVolNumber;
278
int Erasures[256],EraSize=0;
280
for (int I=0;I<TotalFiles;I++)
281
if (WriteFlags[I] || SrcFile[I]==NULL)
282
Erasures[EraSize++]=I;
285
Int64 ProcessedSize=0;
295
if ((++RecCount & 15)==0)
298
for (int I=0;I<TotalFiles;I++)
299
if (WriteFlags[I] || SrcFile[I]==NULL)
300
memset(&Buf[I*RECVOL_BUFSIZE],0,RECVOL_BUFSIZE);
303
int ReadSize=SrcFile[I]->Read(&Buf[I*RECVOL_BUFSIZE],RECVOL_BUFSIZE);
304
if (ReadSize!=RECVOL_BUFSIZE)
305
memset(&Buf[I*RECVOL_BUFSIZE+ReadSize],0,RECVOL_BUFSIZE-ReadSize);
306
if (ReadSize>MaxRead)
312
int CurPercent=ToPercent(ProcessedSize,RecFileSize);
313
if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
315
mprintf("\b\b\b\b%3d%%",CurPercent);
316
LastPercent=CurPercent;
318
ProcessedSize+=MaxRead;
320
for (int BufPos=0;BufPos<MaxRead;BufPos++)
323
for (int I=0;I<TotalFiles;I++)
324
Data[I]=Buf[I*RECVOL_BUFSIZE+BufPos];
325
RSC.Decode(Data,TotalFiles,Erasures,EraSize);
326
for (int I=0;I<EraSize;I++)
327
Buf[Erasures[I]*RECVOL_BUFSIZE+BufPos]=Data[Erasures[I]];
329
for (int I=0;I<FileNumber;I++)
330
Buf[I*RECVOL_BUFSIZE+BufPos]=Data[I];
333
for (int I=0;I<FileNumber;I++)
335
SrcFile[I]->Write(&Buf[I*RECVOL_BUFSIZE],MaxRead);
337
for (int I=0;I<RecVolNumber+FileNumber;I++)
338
if (SrcFile[I]!=NULL)
340
File *CurFile=SrcFile[I];
341
if (NewStyle && WriteFlags[I])
343
Int64 Length=CurFile->Tell();
344
CurFile->Seek(Length-7,SEEK_SET);
345
for (int J=0;J<7;J++)
354
if (Arc.Open(LastVolName,NULL,false,true) && Arc.IsArchive(true) &&
355
Arc.SearchBlock(ENDARC_HEAD))
357
Arc.Seek(Arc.NextBlockPos,SEEK_SET);
359
int ReadSize=Arc.Read(Buf,sizeof(Buf));
361
while (ZeroCount<ReadSize && Buf[ZeroCount]==0)
363
if (ZeroCount==ReadSize)
365
Arc.Seek(Arc.NextBlockPos,SEEK_SET);
370
#if !defined(GUI) && !defined(SILENT)
371
if (!Cmd->DisablePercentage)
372
mprintf("\b\b\b\b100%%");