aboutsummaryrefslogtreecommitdiff
path: root/lib/UnrarXLib/extract.cpp
diff options
context:
space:
mode:
authortheuni <theuni-nospam-@xbmc.org>2011-01-24 16:05:21 -0500
committertheuni <theuni-nospam-@xbmc.org>2011-01-24 16:05:21 -0500
commitc51b1189e3d5353e842991f5859ddcea0f73e426 (patch)
treeef2cb8a6184699aa614f3655dca4ce661cdc108e /lib/UnrarXLib/extract.cpp
parentbe61ebdc9e897fe40c6f371111724de79ddee8d5 (diff)
Merged cptspiff's code-reshuffle branch.
Squashed commit due to build breakage during code-reshuffle history. Conflicts: xbmc/Util.cpp xbmc/cdrip/CDDARipper.cpp xbmc/filesystem/Directory.cpp xbmc/filesystem/File.cpp
Diffstat (limited to 'lib/UnrarXLib/extract.cpp')
-rw-r--r--lib/UnrarXLib/extract.cpp897
1 files changed, 897 insertions, 0 deletions
diff --git a/lib/UnrarXLib/extract.cpp b/lib/UnrarXLib/extract.cpp
new file mode 100644
index 0000000000..17e5052d6a
--- /dev/null
+++ b/lib/UnrarXLib/extract.cpp
@@ -0,0 +1,897 @@
+#include "rar.hpp"
+#include "Util.h"
+#ifdef _LINUX
+#include "XSyncUtils.h"
+#include "XEventUtils.h"
+#endif
+
+CmdExtract::CmdExtract()
+{
+ TotalFileCount=0;
+ *Password=0;
+ Unp = NULL;
+}
+
+
+CmdExtract::~CmdExtract()
+{
+ delete Unp;
+ memset(Password,0,sizeof(Password));
+}
+
+
+void CmdExtract::DoExtract(CommandData *Cmd)
+{
+ if (!Unp)
+ {
+ Unp=new Unpack(&DataIO);
+ Unp->Init(NULL);
+ }
+ DataIO.SetCurrentCommand(*Cmd->Command);
+
+ struct FindData FD;
+ while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
+ if (FindFile::FastFind(ArcName,ArcNameW,&FD))
+ DataIO.TotalArcSize+=FD.Size;
+ Cmd->ArcNames->Rewind();
+ while (Cmd->GetArcName(ArcName,ArcNameW,sizeof(ArcName)))
+ {
+ while (ExtractArchive(Cmd)==EXTRACT_ARC_REPEAT)
+ ;
+ if (FindFile::FastFind(ArcName,ArcNameW,&FD))
+ DataIO.ProcessedArcSize+=FD.Size;
+ }
+
+ if (TotalFileCount==0 && *Cmd->Command!='I')
+ {
+ if (!PasswordCancelled)
+ {
+ mprintf(St(MExtrNoFiles));
+ }
+ ErrHandler.SetErrorCode(WARNING);
+ }
+#ifndef GUI
+ else if (!Cmd->DisableDone)
+ {
+ if (*Cmd->Command=='I')
+ {
+ mprintf(St(MDone));
+ }
+ else
+ {
+ if (ErrHandler.GetErrorCount()==0)
+ {
+ mprintf(St(MExtrAllOk));
+ }
+ else
+ {
+ mprintf(St(MExtrTotalErr),ErrHandler.GetErrorCount());
+ }
+ }
+ }
+#endif
+}
+
+
+void CmdExtract::ExtractArchiveInit(CommandData *Cmd,Archive &Arc)
+{
+ if (!Unp)
+ {
+ Unp=new Unpack(&DataIO);
+ Unp->Init(NULL);
+ }
+
+ DataIO.UnpArcSize=Arc.FileLength();
+
+ FileCount=0;
+ MatchedArgs=0;
+#ifndef SFX_MODULE
+ FirstFile=true;
+#endif
+
+ if (*Cmd->Password!=0)
+ strcpy(Password,Cmd->Password);
+ PasswordAll=(*Cmd->Password!=0);
+
+ DataIO.UnpVolume=false;
+
+ PrevExtracted=false;
+ SignatureFound=false;
+ AllMatchesExact=true;
+ ReconstructDone=false;
+}
+
+
+EXTRACT_ARC_CODE CmdExtract::ExtractArchive(CommandData *Cmd)
+{
+ Archive Arc(Cmd);
+ if (!Arc.WOpen(ArcName,ArcNameW))
+ {
+ ErrHandler.SetErrorCode(OPEN_ERROR);
+ return(EXTRACT_ARC_NEXT);
+ }
+
+ if (!Arc.IsArchive(true))
+ {
+#ifndef GUI
+ mprintf(St(MNotRAR),ArcName);
+#endif
+ if (CmpExt(ArcName,"rar"))
+ ErrHandler.SetErrorCode(WARNING);
+ return(EXTRACT_ARC_NEXT);
+ }
+
+ if (!Arc.IsOpened())
+ return(EXTRACT_ARC_NEXT);
+
+#ifndef SFX_MODULE
+ if (Arc.Volume && Arc.NotFirstVolume)
+ {
+ char FirstVolName[NM];
+
+ VolNameToFirstName(ArcName,FirstVolName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING));
+ if (stricomp(ArcName,FirstVolName)!=0 && FileExist(FirstVolName) &&
+ Cmd->ArcNames->Search(FirstVolName,NULL,false))
+ return(EXTRACT_ARC_NEXT);
+ }
+#endif
+ ExtractArchiveInit(Cmd,Arc);
+
+ if (*Cmd->Command=='T' || *Cmd->Command=='I')
+ Cmd->Test=true;
+
+#ifndef GUI
+ if (*Cmd->Command=='I')
+ Cmd->DisablePercentage=true;
+ else
+ if (Cmd->Test)
+ {
+ mprintf(St(MExtrTest),ArcName);
+ }
+ else
+ {
+ mprintf(St(MExtracting),ArcName);
+ }
+#endif
+
+ Arc.ViewComment();
+
+ while (1)
+ {
+ int Size=Arc.ReadHeader();
+ bool Repeat=false;
+ if (!ExtractCurrentFile(Cmd,Arc,Size,Repeat))
+ {
+ if (Repeat)
+ {
+ return(EXTRACT_ARC_REPEAT);
+ }
+ else
+ break;
+ }
+ }
+ return(EXTRACT_ARC_NEXT);
+}
+
+
+bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,bool &Repeat)
+{
+ if (!Unp)
+ {
+ Unp=new Unpack(&DataIO);
+ Unp->Init(NULL);
+ }
+ char Command=*Cmd->Command;
+
+ if (HeaderSize<=0)
+ {
+ if (DataIO.UnpVolume)
+ {
+//#ifdef NOVOLUME
+// return(false);
+//#else
+ if (!MergeArchive(Arc,NULL,false,Command))
+ {
+ ErrHandler.SetErrorCode(WARNING);
+ return(false);
+ }
+ SignatureFound=false;
+//#endif
+ }
+ else
+ return(false);
+ }
+ int HeadType=Arc.GetHeaderType();
+ if (HeadType!=FILE_HEAD)
+ {
+ if (HeadType==AV_HEAD || HeadType==SIGN_HEAD)
+ SignatureFound=true;
+#if !defined(SFX_MODULE) && !defined(_WIN_CE)
+ if (HeadType==SUB_HEAD && PrevExtracted)
+ SetExtraInfo(Cmd,Arc,DestFileName,*DestFileNameW ? DestFileNameW:NULL);
+#endif
+ if (HeadType==NEWSUB_HEAD)
+ {
+ if (Arc.SubHead.CmpName(SUBHEAD_TYPE_AV))
+ SignatureFound=true;
+#if !defined(NOSUBBLOCKS) && !defined(_WIN_CE)
+ if (PrevExtracted)
+ SetExtraInfoNew(Cmd,Arc,DestFileName,*DestFileNameW ? DestFileNameW:NULL);
+#endif
+ }
+ if (HeadType==ENDARC_HEAD)
+ {
+ if (Arc.EndArcHead.Flags & EARC_NEXT_VOLUME)
+ {
+#ifndef NOVOLUME
+ if (!MergeArchive(Arc,NULL,false,Command))
+ {
+ ErrHandler.SetErrorCode(WARNING);
+ return(false);
+ }
+ SignatureFound=false;
+#endif
+ Arc.Seek(Arc.CurBlockPos,SEEK_SET);
+ return(true);
+ }
+ else
+ return(false);
+ }
+ Arc.SeekToNext();
+ return(true);
+ }
+ PrevExtracted=false;
+
+ if (SignatureFound ||
+ (!Cmd->Recurse && MatchedArgs>=(int)Cmd->FileArgs->ItemsCount() && AllMatchesExact))
+ return(false);
+
+ char ArcFileName[NM];
+
+ IntToExt(Arc.NewLhd.FileName,Arc.NewLhd.FileName);
+ strcpy(ArcFileName,Arc.NewLhd.FileName);
+
+ wchar ArcFileNameW[NM];
+ *ArcFileNameW=0;
+
+ int MatchType=MATCH_WILDSUBPATH;
+
+ bool EqualNames=false;
+ int MatchNumber=Cmd->IsProcessFile(Arc.NewLhd,&EqualNames,MatchType);
+ bool ExactMatch=MatchNumber!=0;
+#if !defined(SFX_MODULE) && !defined(_WIN_CE)
+ if (Cmd->ExclPath==EXCL_BASEPATH)
+ {
+ *Cmd->ArcPath=0;
+ if (ExactMatch)
+ {
+ Cmd->FileArgs->Rewind();
+ if (Cmd->FileArgs->GetString(Cmd->ArcPath,NULL,sizeof(Cmd->ArcPath),MatchNumber-1))
+ *PointToName(Cmd->ArcPath)=0;
+ }
+ }
+#endif
+ if (ExactMatch && !EqualNames)
+ AllMatchesExact=false;
+
+#ifdef UNICODE_SUPPORTED
+ bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
+#else
+ bool WideName=false;
+#endif
+
+#ifdef _APPLE
+ if (WideName)
+ {
+ WideToUtf(Arc.NewLhd.FileNameW,ArcFileName,sizeof(ArcFileName));
+ WideName=false;
+ }
+#endif
+
+ wchar *DestNameW=WideName ? DestFileNameW:NULL;
+
+#ifdef UNICODE_SUPPORTED
+ if (WideName)
+ {
+ ConvertPath(Arc.NewLhd.FileNameW,ArcFileNameW);
+ char Name[NM];
+ WideToChar(ArcFileNameW,Name);
+ if (IsNameUsable(Name))
+ strcpy(ArcFileName,Name);
+ }
+#endif
+
+ ConvertPath(ArcFileName,ArcFileName);
+
+ if (Arc.IsArcLabel())
+ return(true);
+
+ if (Arc.NewLhd.Flags & LHD_VERSION)
+ {
+ if (Cmd->VersionControl!=1 && !EqualNames)
+ {
+ if (Cmd->VersionControl==0)
+ ExactMatch=false;
+ int Version=ParseVersionFileName(ArcFileName,ArcFileNameW,false);
+ if (Cmd->VersionControl-1==Version)
+ ParseVersionFileName(ArcFileName,ArcFileNameW,true);
+ else
+ ExactMatch=false;
+ }
+ }
+ else
+ if (!Arc.IsArcDir() && Cmd->VersionControl>1)
+ ExactMatch=false;
+
+ Arc.ConvertAttributes();
+
+#ifndef SFX_MODULE
+ if ((Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/)) && FirstFile)
+ {
+ char CurVolName[NM];
+ strcpy(CurVolName,ArcName);
+
+ VolNameToFirstName(ArcName,ArcName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING) != 0);
+ if (stricomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
+ {
+ *ArcNameW=0;
+ Repeat=true;
+ return(false);
+ }
+#if !defined(RARDLL) && !defined(_WIN_CE)
+ if (!ReconstructDone)
+ {
+ ReconstructDone=true;
+
+ RecVolumes RecVol;
+ if (RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true))
+ {
+ Repeat=true;
+ return(false);
+ }
+ }
+#endif
+ strcpy(ArcName,CurVolName);
+ }
+#endif
+
+ DataIO.UnpVolume=(Arc.NewLhd.Flags & LHD_SPLIT_AFTER);
+ DataIO.NextVolumeMissing=false;
+
+ Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
+
+ bool TestMode=false;
+ bool ExtrFile=false;
+ bool SkipSolid=false;
+
+#ifndef SFX_MODULE
+ if (FirstFile && (ExactMatch || Arc.Solid) && (Arc.NewLhd.Flags & (LHD_SPLIT_BEFORE/*|LHD_SOLID*/))!=0)
+ {
+ if (ExactMatch)
+ {
+ Log(Arc.FileName,St(MUnpCannotMerge),(char*) ArcFileName);
+#ifdef RARDLL
+ Cmd->DllError=ERAR_BAD_DATA;
+#endif
+ ErrHandler.SetErrorCode(WARNING);
+ }
+ ExactMatch=false;
+ }
+
+ FirstFile=false;
+#endif
+
+ if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
+ {
+ if (Arc.NewLhd.Flags & LHD_PASSWORD)
+#ifndef RARDLL
+ if (*Password==0)
+#endif
+ {
+#ifdef RARDLL
+ if (*Cmd->Password==0)
+ if (Cmd->Callback==NULL ||
+ Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LONG)Cmd->Password,sizeof(Cmd->Password))==-1)
+ return(false);
+ strcpy(Password,Cmd->Password);
+
+#else
+ if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password)))
+ {
+ PasswordCancelled=true;
+ return(false);
+ }
+#endif
+ }
+#if !defined(GUI) && !defined(SILENT)
+ else
+ if (!PasswordAll && (!Arc.Solid || Arc.NewLhd.UnpVer>=20 && (Arc.NewLhd.Flags & LHD_SOLID)==0))
+ {
+ eprintf(St(MUseCurPsw),(char*) ArcFileName);
+ switch(Cmd->AllYes ? 1:Ask(St(MYesNoAll)))
+ {
+ case -1:
+ ErrHandler.Exit(USER_BREAK);
+ case 2:
+ if (!GetPassword(PASSWORD_FILE,ArcFileName,Password,sizeof(Password)))
+ {
+ return(false);
+ }
+ break;
+ case 3:
+ PasswordAll=true;
+ break;
+ }
+ }
+#endif
+
+#ifndef SFX_MODULE
+ if (*Cmd->ExtrPath==0 && *Cmd->ExtrPathW!=0)
+ WideToChar(Cmd->ExtrPathW,DestFileName);
+ else
+#endif
+ strcpy(DestFileName,Cmd->ExtrPath);
+
+
+#ifndef SFX_MODULE
+ if (Cmd->AppendArcNameToPath)
+ {
+ AddEndSlash(DestFileName);
+ strcat(DestFileName,PointToName(Arc.FileName));
+ SetExt(DestFileName,NULL);
+ AddEndSlash(DestFileName);
+ }
+#endif
+
+ char *ExtrName=ArcFileName;
+
+ bool EmptyName=false;
+#ifndef SFX_MODULE
+ int Length=strlen(Cmd->ArcPath);
+ if (Length>1 && IsPathDiv(Cmd->ArcPath[Length-1]) &&
+ strlen(ArcFileName)==((unsigned int)Length-1))
+ Length--;
+ if (Length>0 && strnicomp(Cmd->ArcPath,ArcFileName,Length)==0)
+ {
+ ExtrName+=Length;
+ while (*ExtrName==CPATHDIVIDER)
+ ExtrName++;
+ if (*ExtrName==0)
+ EmptyName=true;
+ }
+#endif
+
+ bool AbsPaths=Cmd->ExclPath==EXCL_ABSPATH && Command=='X' && IsDriveDiv(':');
+ if (AbsPaths)
+ *DestFileName=0;
+
+ if (DestFileName[strlen(DestFileName)-1] != '\\' && DestFileName[strlen(DestFileName)-1] != '/')
+ strcat(DestFileName,"\\");
+
+ if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
+ {
+ strcat(DestFileName,PointToName(ExtrName));
+ }
+ else
+ strcat(DestFileName,ExtrName);
+
+ if (AbsPaths && DestFileName[1]=='_' && IsPathDiv(DestFileName[2]))
+ DestFileName[1]=':';
+
+#ifndef SFX_MODULE
+ if (!WideName && *Cmd->ExtrPathW!=0)
+ {
+ DestNameW=DestFileNameW;
+ WideName=true;
+ CharToWide(ArcFileName,ArcFileNameW);
+ }
+#endif
+
+ if (WideName)
+ {
+ if (*Cmd->ExtrPathW!=0)
+ strcpyw(DestFileNameW,Cmd->ExtrPathW);
+ else
+ CharToWide(Cmd->ExtrPath,DestFileNameW);
+
+#ifndef SFX_MODULE
+ if (Cmd->AppendArcNameToPath)
+ {
+ wchar FileNameW[NM];
+ if (*Arc.FileNameW!=0)
+ strcpyw(FileNameW,Arc.FileNameW);
+ else
+ CharToWide(Arc.FileName,FileNameW);
+ strcatw(DestFileNameW,PointToName(FileNameW));
+ SetExt(DestFileNameW,NULL);
+ AddEndSlash(DestFileNameW);
+ }
+#endif
+ wchar *ExtrNameW=ArcFileNameW;
+#ifndef SFX_MODULE
+ if (Length>0)
+ {
+ wchar ArcPathW[NM];
+ CharToWide(Cmd->ArcPath,ArcPathW);
+ Length=strlenw(ArcPathW);
+ }
+ ExtrNameW+=Length;
+ while (*ExtrNameW==CPATHDIVIDER)
+ ExtrNameW++;
+#endif
+
+ if (AbsPaths)
+ *DestFileNameW=0;
+
+ if (Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
+ strcatw(DestFileNameW,PointToName(ExtrNameW));
+ else
+ strcatw(DestFileNameW,ExtrNameW);
+
+ if (AbsPaths && DestFileNameW[1]=='_' && IsPathDiv(DestFileNameW[2]))
+ DestFileNameW[1]=':';
+ }
+ else
+ *DestFileNameW=0;
+
+ ExtrFile=!SkipSolid && !EmptyName && (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0/* && *ExtrName*/;
+ if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X'))
+ {
+ struct FindData FD;
+ if (FindFile::FastFind(DestFileName,DestNameW,&FD))
+ {
+ if (FD.mtime >= Arc.NewLhd.mtime)
+ ExtrFile=false;
+ }
+ else
+ if (Cmd->FreshFiles)
+ ExtrFile=false;
+ }
+
+#ifdef RARDLL
+ if (*Cmd->DllDestName)
+ {
+ strncpy(DestFileName,Cmd->DllDestName,sizeof(DestFileName));
+ *DestFileNameW=0;
+ if (Cmd->DllOpMode!=RAR_EXTRACT)
+ ExtrFile=false;
+ }
+ if (*Cmd->DllDestNameW)
+ {
+ strncpyw(DestFileNameW,Cmd->DllDestNameW,sizeof(DestFileNameW)/sizeof(DestFileNameW[0]));
+ DestNameW=DestFileNameW;
+ if (Cmd->DllOpMode!=RAR_EXTRACT)
+ ExtrFile=false;
+ }
+#endif
+
+#ifdef SFX_MODULE
+ if (Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.Method!=0x30)
+#else
+ if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER)
+#endif
+ {
+#ifndef SILENT
+ Log(Arc.FileName,St(MUnknownMeth),(char*) ArcFileName);
+#ifndef SFX_MODULE
+ Log(Arc.FileName,St(MVerRequired),Arc.NewLhd.UnpVer/10,Arc.NewLhd.UnpVer%10);
+#endif
+#endif
+ ExtrFile=false;
+ ErrHandler.SetErrorCode(WARNING);
+#ifdef RARDLL
+ Cmd->DllError=ERAR_UNKNOWN_FORMAT;
+#endif
+ }
+
+ File CurFile;
+
+ if (!IsLink(Arc.NewLhd.FileAttr))
+ {
+ if (Arc.IsArcDir())
+ {
+ if (!ExtrFile || Command=='P' || Command=='E' || Cmd->ExclPath==EXCL_SKIPWHOLEPATH)
+ return(true);
+ if (SkipSolid)
+ {
+#ifndef GUI
+ mprintf(St(MExtrSkipFile),(char*) ArcFileName);
+#endif
+ return(true);
+ }
+ TotalFileCount++;
+ if (Cmd->Test)
+ {
+#ifndef GUI
+ mprintf(St(MExtrTestFile),(char*) ArcFileName);
+ mprintf(" %s",St(MOk));
+#endif
+ return(true);
+ }
+ if (CUtil::CreateDirectoryEx(DestFileName))
+ {
+#ifndef GUI
+ mprintf(St(MCreatDir),DestFileName);
+ mprintf(" %s",St(MOk));
+#endif
+ PrevExtracted=true;
+ SetFileAttr(DestFileName,DestNameW,Arc.NewLhd.FileAttr);
+ PrevExtracted=true;
+ }
+ else
+ {
+ Log(Arc.FileName,St(MExtrErrMkDir),DestFileName);
+ ErrHandler.SysErrMsg();
+#ifdef RARDLL
+ Cmd->DllError=ERAR_ECREATE;
+#endif
+ ErrHandler.SetErrorCode(CREATE_ERROR);
+ }
+ if (PrevExtracted)
+ SetDirTime(DestFileName,
+ Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
+ Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime,
+ Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
+ return(true);
+ }
+ else
+ {
+ if (Cmd->Test && ExtrFile)
+ TestMode=true;
+#if !defined(GUI) && !defined(SFX_MODULE)
+ if (Command=='P' && ExtrFile)
+ CurFile.SetHandleType(FILE_HANDLESTD);
+#endif
+ if ((Command=='E' || Command=='X') && ExtrFile && !Cmd->Test)
+ {
+ bool UserReject;
+
+ if (GetDataIO().UnpackToMemorySize == -1)
+ {
+ if (!FileCreate(Cmd,&CurFile,DestFileName,DestNameW,Cmd->Overwrite,&UserReject,Arc.NewLhd.UnpSize,Arc.NewLhd.FileTime))
+ {
+ ExtrFile=false;
+ if (!UserReject)
+ {
+ ErrHandler.CreateErrorMsg(Arc.FileName,DestFileName);
+ ErrHandler.SetErrorCode(CREATE_ERROR);
+#ifdef RARDLL
+ Cmd->DllError=ERAR_ECREATE;
+#endif
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!ExtrFile && Arc.Solid)
+ {
+ SkipSolid=true;
+ TestMode=true;
+ ExtrFile=true;
+ }
+ if (ExtrFile)
+ {
+ if (!SkipSolid)
+ {
+ if (!TestMode && Command!='P' && CurFile.IsDevice())
+ {
+ Log(Arc.FileName,St(MInvalidName),DestFileName);
+ ErrHandler.WriteError(Arc.FileName,DestFileName);
+ }
+ TotalFileCount++;
+ }
+ FileCount++;
+#ifndef GUI
+ if (Command!='I')
+ {
+ if (SkipSolid)
+ mprintf(St(MExtrSkipFile),(char*) ArcFileName);
+ else
+ {
+ switch(Cmd->Test ? 'T':Command)
+ {
+ case 'T':
+ mprintf(St(MExtrTestFile),(char*) ArcFileName);
+ break;
+#ifndef SFX_MODULE
+ case 'P':
+ mprintf(St(MExtrPrinting),(char*) ArcFileName);
+ break;
+#endif
+ case 'X':
+ case 'E':
+ mprintf(St(MExtrFile),DestFileName);
+ break;
+ }
+ }
+ }
+ if (!Cmd->DisablePercentage)
+ {
+ mprintf(" ");
+ }
+#endif
+ DataIO.CurUnpRead=0;
+ DataIO.CurUnpWrite=0;
+ DataIO.UnpFileCRC=Arc.OldFormat ? 0 : 0xffffffff;
+ DataIO.PackedCRC=0xffffffff;
+ DataIO.SetEncryption(
+ (Arc.NewLhd.Flags & LHD_PASSWORD) ? Arc.NewLhd.UnpVer:0,Password,
+ (Arc.NewLhd.Flags & LHD_SALT) ? Arc.NewLhd.Salt:NULL,false);
+ DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize);
+ DataIO.SetFiles(&Arc,&CurFile);
+ DataIO.SetTestMode(TestMode);
+ DataIO.SetSkipUnpCRC(SkipSolid);
+
+#ifndef _WIN_CE
+ if (!TestMode && !Arc.BrokenFileHeader &&
+ (Arc.NewLhd.FullPackSize<<11)>Arc.NewLhd.FullUnpSize &&
+ (Arc.NewLhd.FullUnpSize<100000000 || Arc.FileLength()>Arc.NewLhd.FullPackSize))
+ CurFile.Prealloc(Arc.NewLhd.FullUnpSize);
+#endif
+ CurFile.SetAllowDelete(!Cmd->KeepBroken);
+
+ bool LinkCreateMode=!Cmd->Test && !SkipSolid;
+ if (ExtractLink(DataIO,Arc,DestFileName,DataIO.UnpFileCRC,LinkCreateMode))
+ PrevExtracted=LinkCreateMode;
+ else if ((Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0)
+ {
+ if (Arc.NewLhd.Method==0x30)
+ UnstoreFile(DataIO,Arc.NewLhd.FullUnpSize);
+ else
+ {
+ Unp->SetDestSize(Arc.NewLhd.FullUnpSize);
+#ifndef SFX_MODULE
+ if (Arc.NewLhd.UnpVer<=15)
+ Unp->DoUnpack(15,FileCount>1 && Arc.Solid);
+ else
+#endif
+ Unp->DoUnpack(Arc.NewLhd.UnpVer,(Arc.NewLhd.Flags & LHD_SOLID));
+ }
+ }
+
+ if (DataIO.UnpackToMemorySize > -1)
+ if (WaitForSingleObject(DataIO.hQuit,1) == WAIT_OBJECT_0)
+ {
+ return false;
+ }
+
+ if (Arc.IsOpened())
+ Arc.SeekToNext();
+
+ bool BrokenFile=false;
+/* if (!SkipSolid)
+ {
+ if (Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC) ||
+ !Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC^0xffffffff))
+ {
+#ifndef GUI
+ if (Command!='P' && Command!='I')
+ mprintf("%s%s ",Cmd->DisablePercentage ? " ":"\b\b\b\b\b ",St(MOk));
+#endif
+ }
+ else
+ {
+ char *BadArcName=(Arc.NewLhd.Flags & LHD_SPLIT_BEFORE) ? NULL:Arc.FileName;
+ if (Arc.NewLhd.Flags & LHD_PASSWORD)
+ {
+ Log(BadArcName,St(MEncrBadCRC),ArcFileName);
+ }
+ else
+ {
+ Log(BadArcName,St(MCRCFailed),ArcFileName);
+ }
+ BrokenFile=true;
+ ErrHandler.SetErrorCode(CRC_ERROR);
+#ifdef RARDLL
+ Cmd->DllError=ERAR_BAD_DATA;
+#endif
+ Alarm();
+ }
+ }*/
+#ifndef GUI
+// else
+// mprintf("\b\b\b\b\b ");
+#endif
+
+ if (!TestMode && (Command=='X' || Command=='E') &&
+ !IsLink(Arc.NewLhd.FileAttr))
+ {
+#if defined(_WIN_32) || defined(_EMX)
+ if (Cmd->ClearArc)
+ Arc.NewLhd.FileAttr&=~FA_ARCH;
+#endif
+ if (!BrokenFile || Cmd->KeepBroken)
+ {
+ if (BrokenFile)
+ CurFile.Truncate();
+ CurFile.SetOpenFileStat(
+ Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
+ Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.NewLhd.ctime,
+ Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime);
+ CurFile.Close();
+ CurFile.SetCloseFileStat(
+ Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.NewLhd.mtime,
+ Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.NewLhd.atime,
+ Arc.NewLhd.FileAttr);
+ PrevExtracted=true;
+ }
+ }
+ }
+ }
+ if (ExactMatch)
+ MatchedArgs++;
+ if (DataIO.NextVolumeMissing || !Arc.IsOpened())
+ return(false);
+ if (!ExtrFile)
+ {
+ if (!Arc.Solid)
+ Arc.SeekToNext();
+ else if (!SkipSolid)
+ return(false);
+ }
+ return(true);
+}
+
+
+void CmdExtract::UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize)
+{
+ Array<byte> Buffer(0x40000);
+ if (DataIO.UnpackToMemorySize > -1)
+ {
+ while (1)
+ {
+ if (WaitForSingleObject(DataIO.hQuit,1) == WAIT_OBJECT_0)
+ {
+ return;
+ }
+ int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
+ if (DataIO.UnpackToMemorySize > -1 && !DataIO.NextVolumeMissing)
+ {
+ if (WaitForSingleObject(DataIO.hSeek,1) == WAIT_OBJECT_0)
+ continue;
+ }
+ if (Code > 0)
+ {
+ Code=Code<DestUnpSize ? Code:int64to32(DestUnpSize);
+ DataIO.UnpWrite(&Buffer[0],Code);
+ if (DestUnpSize>=0)
+ DestUnpSize-=Code;
+ }
+ else
+ {
+ if (DataIO.NextVolumeMissing)
+ SetEvent(DataIO.hSeekDone);
+ else
+ if (WaitForSingleObject(DataIO.hSeek,1) == WAIT_OBJECT_0)
+ continue;
+ ResetEvent(DataIO.hBufferFilled);
+ SetEvent(DataIO.hBufferEmpty);
+ while (WaitForSingleObject(DataIO.hBufferFilled,1) != WAIT_OBJECT_0)
+ if (WaitForSingleObject(DataIO.hQuit,1) == WAIT_OBJECT_0)
+ return;
+ }
+ }
+ }
+ else
+ {
+ while (1)
+ {
+ int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
+ if (Code > 0)
+ {
+ Code=Code<DestUnpSize ? Code:int64to32(DestUnpSize);
+ DataIO.UnpWrite(&Buffer[0],Code);
+ if (DestUnpSize>=0)
+ DestUnpSize-=Code;
+ }
+ else if (Code == -1)
+ {
+ DataIO.NextVolumeMissing = true;
+ return;
+ }
+ else
+ return;
+ }
+ }
+}