"Fossies" - the Fresh Open Source Software Archive

Member "unrar/rdwrfn.cpp" (4 May 2022, 8233 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 "rdwrfn.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 6.1.2_vs_6.1.3.

    1 #include "rar.hpp"
    2 
    3 ComprDataIO::ComprDataIO()
    4 {
    5 #ifndef RAR_NOCRYPT
    6   Crypt=new CryptData;
    7   Decrypt=new CryptData;
    8 #endif
    9 
   10   Init();
   11 }
   12 
   13 
   14 void ComprDataIO::Init()
   15 {
   16   UnpackFromMemory=false;
   17   UnpackToMemory=false;
   18   UnpPackedSize=0;
   19   UnpPackedLeft=0;
   20   ShowProgress=true;
   21   TestMode=false;
   22   SkipUnpCRC=false;
   23   NoFileHeader=false;
   24   PackVolume=false;
   25   UnpVolume=false;
   26   NextVolumeMissing=false;
   27   SrcFile=NULL;
   28   DestFile=NULL;
   29   UnpWrAddr=NULL;
   30   UnpWrSize=0;
   31   Command=NULL;
   32   Encryption=false;
   33   Decryption=false;
   34   CurPackRead=CurPackWrite=CurUnpRead=CurUnpWrite=0;
   35   LastPercent=-1;
   36   SubHead=NULL;
   37   SubHeadPos=NULL;
   38   CurrentCommand=0;
   39   ProcessedArcSize=0;
   40   LastArcSize=0;
   41   TotalArcSize=0;
   42 }
   43 
   44 
   45 ComprDataIO::~ComprDataIO()
   46 {
   47 #ifndef RAR_NOCRYPT
   48   delete Crypt;
   49   delete Decrypt;
   50 #endif
   51 }
   52 
   53 
   54 
   55 
   56 int ComprDataIO::UnpRead(byte *Addr,size_t Count)
   57 {
   58 #ifndef RAR_NOCRYPT
   59   // In case of encryption we need to align read size to encryption 
   60   // block size. We can do it by simple masking, because unpack read code
   61   // always reads more than CRYPT_BLOCK_SIZE, so we do not risk to make it 0.
   62   if (Decryption)
   63     Count &= ~CRYPT_BLOCK_MASK;
   64 #endif
   65   
   66   int ReadSize=0,TotalRead=0;
   67   byte *ReadAddr;
   68   ReadAddr=Addr;
   69   while (Count > 0)
   70   {
   71     Archive *SrcArc=(Archive *)SrcFile;
   72 
   73     if (UnpackFromMemory)
   74     {
   75       memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize);
   76       ReadSize=(int)UnpackFromMemorySize;
   77       UnpackFromMemorySize=0;
   78     }
   79     else
   80     {
   81       size_t SizeToRead=((int64)Count>UnpPackedLeft) ? (size_t)UnpPackedLeft:Count;
   82       if (SizeToRead > 0)
   83       {
   84         if (UnpVolume && Decryption && (int64)Count>UnpPackedLeft)
   85         {
   86           // We need aligned blocks for decryption and we want "Keep broken
   87           // files" to work efficiently with missing encrypted volumes.
   88           // So for last data block in volume we adjust the size to read to
   89           // next equal or smaller block producing aligned total block size.
   90           // So we'll ask for next volume only when processing few unaligned
   91           // bytes left in the end, when most of data is already extracted.
   92           size_t NewTotalRead = TotalRead + SizeToRead;
   93           size_t Adjust = NewTotalRead - (NewTotalRead  & ~CRYPT_BLOCK_MASK);
   94           size_t NewSizeToRead = SizeToRead - Adjust;
   95           if ((int)NewSizeToRead > 0)
   96             SizeToRead = NewSizeToRead;
   97         }
   98 
   99         if (!SrcFile->IsOpened())
  100           return -1;
  101         ReadSize=SrcFile->Read(ReadAddr,SizeToRead);
  102         FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead;
  103         if (!NoFileHeader && hd->SplitAfter)
  104           PackedDataHash.Update(ReadAddr,ReadSize);
  105       }
  106     }
  107     CurUnpRead+=ReadSize;
  108     TotalRead+=ReadSize;
  109 #ifndef NOVOLUME
  110     // These variable are not used in NOVOLUME mode, so it is better
  111     // to exclude commands below to avoid compiler warnings.
  112     ReadAddr+=ReadSize;
  113     Count-=ReadSize;
  114 #endif
  115     UnpPackedLeft-=ReadSize;
  116 
  117     // Do not ask for next volume if we read something from current volume.
  118     // If next volume is missing, we need to process all data from current
  119     // volume before aborting. It helps to recover all possible data
  120     // in "Keep broken files" mode. But if we process encrypted data,
  121     // we ask for next volume also if we have non-aligned encryption block.
  122     // Since we adjust data size for decryption earlier above,
  123     // it does not hurt "Keep broken files" mode efficiency.
  124     if (UnpVolume && UnpPackedLeft == 0 && 
  125         (ReadSize==0 || Decryption && (TotalRead & CRYPT_BLOCK_MASK) != 0) )
  126     {
  127 #ifndef NOVOLUME
  128       if (!MergeArchive(*SrcArc,this,true,CurrentCommand))
  129 #endif
  130       {
  131         NextVolumeMissing=true;
  132         return -1;
  133       }
  134     }
  135     else
  136       break;
  137   }
  138   Archive *SrcArc=(Archive *)SrcFile;
  139   if (SrcArc!=NULL)
  140     ShowUnpRead(SrcArc->NextBlockPos-UnpPackedSize+CurUnpRead,TotalArcSize);
  141   if (ReadSize!=-1)
  142   {
  143     ReadSize=TotalRead;
  144 #ifndef RAR_NOCRYPT
  145     if (Decryption)
  146       Decrypt->DecryptBlock(Addr,ReadSize);
  147 #endif
  148   }
  149   Wait();
  150   return ReadSize;
  151 }
  152 
  153 
  154 void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
  155 {
  156 
  157 #ifdef RARDLL
  158   RAROptions *Cmd=((Archive *)SrcFile)->GetRAROptions();
  159   if (Cmd->DllOpMode!=RAR_SKIP)
  160   {
  161     if (Cmd->Callback!=NULL &&
  162         Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LPARAM)Addr,Count)==-1)
  163       ErrHandler.Exit(RARX_USERBREAK);
  164     if (Cmd->ProcessDataProc!=NULL)
  165     {
  166       int RetCode=Cmd->ProcessDataProc(Addr,(int)Count);
  167       if (RetCode==0)
  168         ErrHandler.Exit(RARX_USERBREAK);
  169     }
  170   }
  171 #endif // RARDLL
  172 
  173   UnpWrAddr=Addr;
  174   UnpWrSize=Count;
  175   if (UnpackToMemory)
  176   {
  177     if (Count <= UnpackToMemorySize)
  178     {
  179       memcpy(UnpackToMemoryAddr,Addr,Count);
  180       UnpackToMemoryAddr+=Count;
  181       UnpackToMemorySize-=Count;
  182     }
  183   }
  184   else
  185     if (!TestMode)
  186       DestFile->Write(Addr,Count);
  187   CurUnpWrite+=Count;
  188   if (!SkipUnpCRC)
  189     UnpHash.Update(Addr,Count);
  190   ShowUnpWrite();
  191   Wait();
  192 }
  193 
  194 
  195 
  196 
  197 
  198 
  199 void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
  200 {
  201   if (ShowProgress && SrcFile!=NULL)
  202   {
  203     // Important when processing several archives or multivolume archive.
  204     ArcPos+=ProcessedArcSize;
  205 
  206     Archive *SrcArc=(Archive *)SrcFile;
  207     RAROptions *Cmd=SrcArc->GetRAROptions();
  208 
  209     int CurPercent=ToPercent(ArcPos,ArcSize);
  210     if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
  211     {
  212       uiExtractProgress(CurUnpWrite,SrcArc->FileHead.UnpSize,ArcPos,ArcSize);
  213       LastPercent=CurPercent;
  214     }
  215   }
  216 }
  217 
  218 
  219 void ComprDataIO::ShowUnpWrite()
  220 {
  221 }
  222 
  223 
  224 
  225 
  226 
  227 
  228 
  229 
  230 
  231 
  232 void ComprDataIO::SetFiles(File *SrcFile,File *DestFile)
  233 {
  234   if (SrcFile!=NULL)
  235     ComprDataIO::SrcFile=SrcFile;
  236   if (DestFile!=NULL)
  237     ComprDataIO::DestFile=DestFile;
  238   LastPercent=-1;
  239 }
  240 
  241 
  242 void ComprDataIO::GetUnpackedData(byte **Data,size_t *Size)
  243 {
  244   *Data=UnpWrAddr;
  245   *Size=UnpWrSize;
  246 }
  247 
  248 
  249 void ComprDataIO::SetEncryption(bool Encrypt,CRYPT_METHOD Method,
  250      SecPassword *Password,const byte *Salt,const byte *InitV,
  251      uint Lg2Cnt,byte *HashKey,byte *PswCheck)
  252 {
  253 #ifndef RAR_NOCRYPT
  254   if (Encrypt)
  255     Encryption=Crypt->SetCryptKeys(true,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
  256   else
  257     Decryption=Decrypt->SetCryptKeys(false,Method,Password,Salt,InitV,Lg2Cnt,HashKey,PswCheck);
  258 #endif
  259 }
  260 
  261 
  262 #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
  263 void ComprDataIO::SetAV15Encryption()
  264 {
  265   Decryption=true;
  266   Decrypt->SetAV15Encryption();
  267 }
  268 #endif
  269 
  270 
  271 #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
  272 void ComprDataIO::SetCmt13Encryption()
  273 {
  274   Decryption=true;
  275   Decrypt->SetCmt13Encryption();
  276 }
  277 #endif
  278 
  279 
  280 
  281 
  282 void ComprDataIO::SetUnpackToMemory(byte *Addr,uint Size)
  283 {
  284   UnpackToMemory=true;
  285   UnpackToMemoryAddr=Addr;
  286   UnpackToMemorySize=Size;
  287 }
  288 
  289 
  290 // Extraction progress is based on the position in archive and we adjust 
  291 // the total archives size here, so trailing blocks do not prevent progress
  292 // reaching 100% at the end of extraction. Alternatively we could print "100%"
  293 // after completing the entire archive extraction, but then we would need
  294 // to take into account possible messages like the checksum error after
  295 // last file percent progress.
  296 void ComprDataIO::AdjustTotalArcSize(Archive *Arc)
  297 {
  298   // If we know a position of QO or RR blocks, use them to adjust the total
  299   // packed size to beginning of these blocks. Earlier we already calculated
  300   // the total size based on entire archive sizes. We also set LastArcSize
  301   // to start of first trailing block, to add it later to ProcessedArcSize.
  302   int64 ArcLength=Arc->IsSeekable() ? Arc->FileLength() : 0;
  303   if (Arc->MainHead.QOpenOffset!=0) // QO is always preceding RR record.
  304     LastArcSize=Arc->MainHead.QOpenOffset;
  305   else
  306     if (Arc->MainHead.RROffset!=0)
  307       LastArcSize=Arc->MainHead.RROffset;
  308     else
  309     {
  310       // If neither QO nor RR are found, exclude the approximate size of
  311       // end of archive block.
  312       // We select EndBlock to be larger than typical 8 bytes HEAD_ENDARC,
  313       // but to not exceed the smallest 22 bytes HEAD_FILE with 1 byte file
  314       // name, so we do not have two files with 100% at the end of archive.
  315       const uint EndBlock=23;
  316 
  317       if (ArcLength>EndBlock)
  318         LastArcSize=ArcLength-EndBlock;
  319     }
  320 
  321   TotalArcSize-=ArcLength-LastArcSize;
  322 }