~ubuntu-branches/ubuntu/utopic/unrar-nonfree/utopic-updates

« back to all changes in this revision

Viewing changes to recvol.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Chris Anderson
  • Date: 2004-07-02 01:53:47 UTC
  • Revision ID: james.westby@ubuntu.com-20040702015347-26ptn0errf3ew0u9
Tags: upstream-3.3.6
ImportĀ upstreamĀ versionĀ 3.3.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "rar.hpp"
 
2
 
 
3
#define RECVOL_BUFSIZE  0x800
 
4
 
 
5
RecVolumes::RecVolumes()
 
6
{
 
7
  Buf.Alloc(RECVOL_BUFSIZE*256);
 
8
  memset(SrcFile,0,sizeof(SrcFile));
 
9
}
 
10
 
 
11
 
 
12
RecVolumes::~RecVolumes()
 
13
{
 
14
  for (int I=0;I<sizeof(SrcFile)/sizeof(SrcFile[0]);I++)
 
15
    delete SrcFile[I];
 
16
}
 
17
 
 
18
 
 
19
 
 
20
 
 
21
bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
 
22
                         const wchar *NameW,bool Silent)
 
23
{
 
24
  char ArcName[NM];
 
25
  wchar ArcNameW[NM];
 
26
  strcpy(ArcName,Name);
 
27
  strcpyw(ArcNameW,NameW);
 
28
  char *Ext=GetExt(ArcName);
 
29
  bool NewStyle=false;
 
30
  bool RevName=Ext!=NULL && stricomp(Ext,".rev")==0;
 
31
  if (RevName)
 
32
  {
 
33
    for (int DigitGroup=0;Ext>ArcName && DigitGroup<3;Ext--)
 
34
      if (!isdigit(*Ext))
 
35
        if (isdigit(*(Ext-1)) && (*Ext=='_' || DigitGroup<2))
 
36
          DigitGroup++;
 
37
        else
 
38
          if (DigitGroup<2)
 
39
          {
 
40
            NewStyle=true;
 
41
            break;
 
42
          }
 
43
    while (isdigit(*Ext) && Ext>ArcName+1)
 
44
      Ext--;
 
45
    strcpy(Ext,"*.*");
 
46
    FindFile Find;
 
47
    Find.SetMask(ArcName);
 
48
    struct FindData FD;
 
49
    while (Find.Next(&FD))
 
50
    {
 
51
      Archive Arc(Cmd);
 
52
      if (Arc.WOpen(FD.Name,FD.NameW) && Arc.IsArchive(true))
 
53
      {
 
54
        strcpy(ArcName,FD.Name);
 
55
        *ArcNameW=0;
 
56
        break;
 
57
      }
 
58
    }
 
59
  }
 
60
 
 
61
  Archive Arc(Cmd);
 
62
  if (!Arc.WCheckOpen(ArcName,ArcNameW))
 
63
    return(false);
 
64
  if (!Arc.Volume)
 
65
  {
 
66
#ifndef SILENT
 
67
    Log(ArcName,St(MNotVolume),ArcName);
 
68
#endif
 
69
    return(false);
 
70
  }
 
71
  bool NewNumbering=(Arc.NewMhd.Flags & MHD_NEWNUMBERING);
 
72
  Arc.Close();
 
73
  char *VolNumStart=VolNameToFirstName(ArcName,ArcName,NewNumbering);
 
74
  char RecVolMask[NM];
 
75
  strcpy(RecVolMask,ArcName);
 
76
  int BaseNamePartLength=VolNumStart-ArcName;
 
77
  strcpy(RecVolMask+BaseNamePartLength,"*.rev");
 
78
 
 
79
#ifndef SILENT
 
80
  Int64 RecFileSize=0;
 
81
#endif
 
82
  FindFile Find;
 
83
  Find.SetMask(RecVolMask);
 
84
  struct FindData RecData;
 
85
  int FileNumber=0,RecVolNumber=0,FoundRecVolumes=0,MissingVolumes=0;
 
86
  char PrevName[NM];
 
87
  while (Find.Next(&RecData))
 
88
  {
 
89
    char *Name=RecData.Name;
 
90
    int P[3];
 
91
    if (!RevName && !NewStyle)
 
92
    {
 
93
      NewStyle=true;
 
94
      char *Dot=GetExt(Name);
 
95
      if (Dot!=NULL)
 
96
      {
 
97
        int LineCount=0;
 
98
        Dot--;
 
99
        while (Dot>Name && *Dot!='.')
 
100
        {
 
101
          if (*Dot=='_')
 
102
            LineCount++;
 
103
          Dot--;
 
104
        }
 
105
        if (LineCount==2)
 
106
          NewStyle=false;
 
107
      }
 
108
    }
 
109
    if (NewStyle)
 
110
    {
 
111
      File CurFile;
 
112
      CurFile.TOpen(Name);
 
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;
 
118
      uint FileCRC=0;
 
119
      for (int I=0;I<4;I++)
 
120
        FileCRC|=CurFile.GetByte()<<(I*8);
 
121
      if (FileCRC!=CalcFileCRC(&CurFile,Length-4))
 
122
      {
 
123
#ifndef SILENT
 
124
        mprintf(St(MCRCFailed),Name);
 
125
#endif
 
126
        continue;
 
127
      }
 
128
    }
 
129
    else
 
130
    {
 
131
      char *Dot=GetExt(Name);
 
132
      if (Dot==NULL)
 
133
        continue;
 
134
      bool WrongParam=false;
 
135
      for (int I=0;I<sizeof(P)/sizeof(P[0]);I++)
 
136
      {
 
137
        do
 
138
        {
 
139
          Dot--;
 
140
        } while (isdigit(*Dot) && Dot>=Name+BaseNamePartLength);
 
141
        P[I]=atoi(Dot+1);
 
142
        if (P[I]==0 || P[I]>255)
 
143
          WrongParam=true;
 
144
      }
 
145
      if (WrongParam)
 
146
        continue;
 
147
    }
 
148
    if (P[1]+P[2]>255)
 
149
      continue;
 
150
    if (RecVolNumber!=0 && RecVolNumber!=P[1] || FileNumber!=0 && FileNumber!=P[2])
 
151
    {
 
152
#ifndef SILENT
 
153
      Log(NULL,St(MRecVolDiffSets),Name,PrevName);
 
154
#endif
 
155
      return(false);
 
156
    }
 
157
    RecVolNumber=P[1];
 
158
    FileNumber=P[2];
 
159
    strcpy(PrevName,Name);
 
160
    File *NewFile=new File;
 
161
    NewFile->TOpen(Name);
 
162
    SrcFile[FileNumber+P[0]-1]=NewFile;
 
163
    FoundRecVolumes++;
 
164
#ifndef SILENT
 
165
    if (RecFileSize==0)
 
166
      RecFileSize=NewFile->FileLength();
 
167
#endif
 
168
  }
 
169
#ifndef SILENT
 
170
  if (!Silent || FoundRecVolumes!=0)
 
171
  {
 
172
    mprintf(St(MRecVolFound),FoundRecVolumes);
 
173
  }
 
174
#endif
 
175
  if (FoundRecVolumes==0)
 
176
    return(false);
 
177
 
 
178
  bool WriteFlags[256];
 
179
  memset(WriteFlags,0,sizeof(WriteFlags));
 
180
 
 
181
  char LastVolName[NM];
 
182
  *LastVolName=0;
 
183
 
 
184
  for (int CurArcNum=0;CurArcNum<FileNumber;CurArcNum++)
 
185
  {
 
186
    Archive *NewFile=new Archive;
 
187
    bool ValidVolume=FileExist(ArcName);
 
188
    if (ValidVolume)
 
189
    {
 
190
      NewFile->TOpen(ArcName);
 
191
      ValidVolume=NewFile->IsArchive(false);
 
192
      if (ValidVolume)
 
193
      {
 
194
        bool EndFound=false,EndBlockRequired=false;
 
195
        while (!EndFound && NewFile->ReadHeader()!=0)
 
196
        {
 
197
          if (NewFile->GetHeaderType()==FILE_HEAD)
 
198
          {
 
199
            if (NewFile->NewLhd.UnpVer>=29)
 
200
              EndBlockRequired=true;
 
201
            if (!EndBlockRequired && (NewFile->NewLhd.Flags & LHD_SPLIT_AFTER))
 
202
              EndFound=true;
 
203
          }
 
204
          if (NewFile->GetHeaderType()==ENDARC_HEAD)
 
205
          {
 
206
            if ((NewFile->EndArcHead.Flags&EARC_DATACRC)!=0 && 
 
207
                NewFile->EndArcHead.ArcDataCRC!=CalcFileCRC(NewFile,NewFile->CurBlockPos))
 
208
            {
 
209
              ValidVolume=false;
 
210
#ifndef SILENT
 
211
              mprintf(St(MCRCFailed),ArcName);
 
212
#endif
 
213
            }
 
214
            EndFound=true;
 
215
          }
 
216
          NewFile->SeekToNext();
 
217
        }
 
218
        if (!EndFound)
 
219
          ValidVolume=false;
 
220
      }
 
221
      if (!ValidVolume)
 
222
      {
 
223
        NewFile->Close();
 
224
        char NewName[NM];
 
225
        strcpy(NewName,ArcName);
 
226
        strcat(NewName,".bad");
 
227
#ifndef SILENT
 
228
        mprintf(St(MBadArc),ArcName);
 
229
        mprintf(St(MRenaming),ArcName,NewName);
 
230
#endif
 
231
        rename(ArcName,NewName);
 
232
      }
 
233
      NewFile->Seek(0,SEEK_SET);
 
234
    }
 
235
    if (!ValidVolume)
 
236
    {
 
237
      NewFile->TCreate(ArcName);
 
238
      WriteFlags[CurArcNum]=true;
 
239
      MissingVolumes++;
 
240
 
 
241
      if (CurArcNum==FileNumber-1)
 
242
        strcpy(LastVolName,ArcName);
 
243
 
 
244
#ifndef SILENT
 
245
      mprintf(St(MAbsNextVol),ArcName);
 
246
#endif
 
247
    }
 
248
    SrcFile[CurArcNum]=(File*)NewFile;
 
249
    NextVolumeName(ArcName,!NewNumbering);
 
250
  }
 
251
 
 
252
#ifndef SILENT
 
253
  mprintf(St(MRecVolMissing),MissingVolumes);
 
254
#endif
 
255
 
 
256
  if (MissingVolumes==0)
 
257
  {
 
258
#ifndef SILENT
 
259
    mprintf(St(MRecVolAllExist));
 
260
#endif
 
261
    return(false);
 
262
  }
 
263
 
 
264
  if (MissingVolumes>FoundRecVolumes)
 
265
  {
 
266
#ifndef SILENT
 
267
    mprintf(St(MRecVolCannotFix));
 
268
#endif
 
269
    return(false);
 
270
  }
 
271
#ifndef SILENT
 
272
  mprintf(St(MReconstructing));
 
273
#endif
 
274
 
 
275
  RSCoder RSC(RecVolNumber);
 
276
 
 
277
  int TotalFiles=FileNumber+RecVolNumber;
 
278
  int Erasures[256],EraSize=0;
 
279
 
 
280
  for (int I=0;I<TotalFiles;I++)
 
281
    if (WriteFlags[I] || SrcFile[I]==NULL)
 
282
      Erasures[EraSize++]=I;
 
283
 
 
284
#ifndef SILENT
 
285
  Int64 ProcessedSize=0;
 
286
#ifndef GUI
 
287
  int LastPercent=-1;
 
288
  mprintf("     ");
 
289
#endif
 
290
#endif
 
291
  int RecCount=0;
 
292
 
 
293
  while (true)
 
294
  {
 
295
    if ((++RecCount & 15)==0)
 
296
      Wait();
 
297
    int MaxRead=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);
 
301
      else
 
302
      {
 
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)
 
307
          MaxRead=ReadSize;
 
308
      }
 
309
    if (MaxRead==0)
 
310
      break;
 
311
#ifndef SILENT
 
312
    int CurPercent=ToPercent(ProcessedSize,RecFileSize);
 
313
    if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
 
314
    {
 
315
      mprintf("\b\b\b\b%3d%%",CurPercent);
 
316
      LastPercent=CurPercent;
 
317
    }
 
318
    ProcessedSize+=MaxRead;
 
319
#endif
 
320
    for (int BufPos=0;BufPos<MaxRead;BufPos++)
 
321
    {
 
322
      byte Data[256];
 
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]];
 
328
/*
 
329
      for (int I=0;I<FileNumber;I++)
 
330
        Buf[I*RECVOL_BUFSIZE+BufPos]=Data[I];
 
331
*/
 
332
    }
 
333
    for (int I=0;I<FileNumber;I++)
 
334
      if (WriteFlags[I])
 
335
        SrcFile[I]->Write(&Buf[I*RECVOL_BUFSIZE],MaxRead);
 
336
  }
 
337
  for (int I=0;I<RecVolNumber+FileNumber;I++)
 
338
    if (SrcFile[I]!=NULL)
 
339
    {
 
340
      File *CurFile=SrcFile[I];
 
341
      if (NewStyle && WriteFlags[I])
 
342
      {
 
343
        Int64 Length=CurFile->Tell();
 
344
        CurFile->Seek(Length-7,SEEK_SET);
 
345
        for (int J=0;J<7;J++)
 
346
          CurFile->PutByte(0);
 
347
      }
 
348
      CurFile->Close();
 
349
      SrcFile[I]=NULL;
 
350
    }
 
351
  if (*LastVolName)
 
352
  {
 
353
    Archive Arc(Cmd);
 
354
    if (Arc.Open(LastVolName,NULL,false,true) && Arc.IsArchive(true) &&
 
355
        Arc.SearchBlock(ENDARC_HEAD))
 
356
    {
 
357
      Arc.Seek(Arc.NextBlockPos,SEEK_SET);
 
358
      char Buf[8192];
 
359
      int ReadSize=Arc.Read(Buf,sizeof(Buf));
 
360
      int ZeroCount=0;
 
361
      while (ZeroCount<ReadSize && Buf[ZeroCount]==0)
 
362
        ZeroCount++;
 
363
      if (ZeroCount==ReadSize)
 
364
      {
 
365
        Arc.Seek(Arc.NextBlockPos,SEEK_SET);
 
366
        Arc.Truncate();
 
367
      }
 
368
    }
 
369
  }
 
370
#if !defined(GUI) && !defined(SILENT)
 
371
  if (!Cmd->DisablePercentage)
 
372
    mprintf("\b\b\b\b100%%");
 
373
  if (!Silent)
 
374
    mprintf(St(MDone));
 
375
#endif
 
376
  return(true);
 
377
}