libclamunrar/recvol.cpp
d39cb658
 #include "rar.hpp"
 
 #include "recvol3.cpp"
 #include "recvol5.cpp"
 
 
 
 bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent)
 {
   Archive Arc(Cmd);
   if (!Arc.Open(Name))
   {
     if (!Silent)
       ErrHandler.OpenErrorMsg(Name);
     return false;
   }
 
   RARFORMAT Fmt=RARFMT15;
   if (Arc.IsArchive(true))
     Fmt=Arc.Format;
   else
   {
     byte Sign[REV5_SIGN_SIZE];
     Arc.Seek(0,SEEK_SET);
     if (Arc.Read(Sign,REV5_SIGN_SIZE)==REV5_SIGN_SIZE && memcmp(Sign,REV5_SIGN,REV5_SIGN_SIZE)==0)
       Fmt=RARFMT50;
   }
   Arc.Close();
 
   // We define RecVol as local variable for proper stack unwinding when
   // handling exceptions. So it can close and delete files on Cancel.
   if (Fmt==RARFMT15)
   {
     RecVolumes3 RecVol(false);
     return RecVol.Restore(Cmd,Name,Silent);
   }
   else
   {
     RecVolumes5 RecVol(false);
     return RecVol.Restore(Cmd,Name,Silent);
   }
 }
 
 
 void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name)
 {
   wchar RevName[NM];
   *RevName=0;
   if (Arc!=NULL)
   {
     // We received .rar or .exe volume as a parameter, trying to find
     // the matching .rev file number 1.
     bool NewNumbering=Arc->NewNumbering;
 
     wchar ArcName[NM];
     wcsncpyz(ArcName,Name,ASIZE(ArcName));
 
     wchar *VolNumStart=VolNameToFirstName(ArcName,ArcName,ASIZE(ArcName),NewNumbering);
     wchar RecVolMask[NM];
     wcsncpyz(RecVolMask,ArcName,ASIZE(RecVolMask));
     size_t BaseNamePartLength=VolNumStart-ArcName;
     wcsncpyz(RecVolMask+BaseNamePartLength,L"*.rev",ASIZE(RecVolMask)-BaseNamePartLength);
 
     FindFile Find;
     Find.SetMask(RecVolMask);
     FindData RecData;
 
     while (Find.Next(&RecData))
     {
       wchar *Num=GetVolNumPart(RecData.Name);
       if (*Num!='1') // Name must have "0...01" numeric part.
         continue;
       bool FirstVol=true;
       while (--Num>=RecData.Name && IsDigit(*Num))
         if (*Num!='0')
         {
           FirstVol=false;
           break;
         }
       if (FirstVol)
       {
         wcsncpyz(RevName,RecData.Name,ASIZE(RevName));
         Name=RevName;
         break;
       }
     }
     if (*RevName==0) // First .rev file not found.
       return;
   }
   
   File RevFile;
   if (!RevFile.Open(Name))
   {
     ErrHandler.OpenErrorMsg(Name); // It also sets RARX_OPEN.
     return;
   }
   mprintf(L"\n");
   byte Sign[REV5_SIGN_SIZE];
   bool Rev5=RevFile.Read(Sign,REV5_SIGN_SIZE)==REV5_SIGN_SIZE && memcmp(Sign,REV5_SIGN,REV5_SIGN_SIZE)==0;
   RevFile.Close();
   if (Rev5)
   {
     RecVolumes5 RecVol(true);
     RecVol.Test(Cmd,Name);
   }
   else
   {
     RecVolumes3 RecVol(true);
     RecVol.Test(Cmd,Name);
   }
 }